/* ============================================================================ * 서명전에 — TDS Paragraph 컴포넌트 * · 한 단락 안에 텍스트/아이콘/뱃지/링크를 자연스럽게 섞을 수 있어요. * · 4 서브: * Paragraph.Text — 인라인 텍스트 (typography/fontWeight/color 부분 오버라이드) * Paragraph.Icon — 인라인 아이콘 (URL 또는 IOSIcon name, mono 마스크) * Paragraph.Badge — 인라인 뱃지 (style fill/weak × type blue/teal/green/red/yellow/elephant) * Paragraph.Link — 인라인 링크 (type underline/clear, as 다른 태그 가능) * * · root props (ParagraphProps): * typography * "t1"~"t7" | "st1"~"st13" 필수 * display "block" | "inline" 기본 "block" * ellipsisAfterLines number webkit-line-clamp 줄 수 * textAlign CSS text-align * fontWeight "regular"|"medium"|"semibold"|"bold" 기본 "regular" * color string CSS 색상 * children, className, style, id 패스스루 * * · 서브들도 typography/fontWeight/color 등을 부분 오버라이드 가능 (자기만 다른 스타일). * ========================================================================== */ // ----- typography → utility class 매핑 ----- function __pgTypoClass(typo) { if (!typo || typeof typo !== "string") return ""; let m = typo.match(/^t(\d+)$/i); if (m) { const n = parseInt(m[1], 10); if (n >= 1 && n <= 7) return `ty-${n}`; } m = typo.match(/^st(\d+)$/i); if (m) { const n = parseInt(m[1], 10); if (n >= 1 && n <= 13) return `sub-ty-${n}`; } if (window.console && console.warn) { console.warn( `[Paragraph] \`typography\` 는 t1~t7 또는 st1~st13 만 가능해요. 받은 값: ${typo}` ); } return ""; } // ----- fontWeight → utility class 매핑 ----- const __PG_FW_CLASS = { regular: "w-regular", medium: "w-medium", semibold: "w-semibold", bold: "w-bold", }; function __pgFwClass(fw) { if (!fw) return ""; return __PG_FW_CLASS[fw] || ""; } // ----- 아이콘 URL 감지 ----- function __pgIsIconUrl(name) { if (!name) return false; return ( /^(https?:|\/|\.{1,2}\/)/i.test(name) || /\.(svg|png|jpe?g|gif|webp)(?:\?|#|$)/i.test(name) ); } function __pgIsMonoIcon(name) { if (!name) return false; return /-mono(?:\.[^/?#]+)?(?:\?[^#]*)?(?:#.*)?$/i.test(name); } // ============================================================================= // Root Paragraph // ============================================================================= function Paragraph({ typography, display = "block", ellipsisAfterLines, textAlign, fontWeight = "regular", color, className = "", style, id, children, ...rest }) { // typography 필수 if (!typography) { if (window.console && console.warn) { console.warn("[Paragraph] `typography` 는 필수 prop 이에요."); } } const cls = [ "tds-paragraph", display === "inline" ? "tds-paragraph--display-inline" : "", typeof ellipsisAfterLines === "number" && ellipsisAfterLines > 0 ? "tds-paragraph--clamp" : "", __pgTypoClass(typography), __pgFwClass(fontWeight), className, ].filter(Boolean).join(" "); const mergedStyle = Object.assign({}, style || {}); if (textAlign) mergedStyle.textAlign = textAlign; if (color) mergedStyle.color = color; if (typeof ellipsisAfterLines === "number" && ellipsisAfterLines > 0) { mergedStyle["--tds-paragraph-clamp"] = String(ellipsisAfterLines); } // display=inline 일 땐 root 도 inline 요소가 자연스러우니 , 아니면

const Tag = display === "inline" ? "span" : "p"; return ( {children} ); } // ============================================================================= // Paragraph.Text — 인라인 텍스트 // ============================================================================= function ParagraphText({ typography, fontWeight, color, className = "", style, id, children, ...rest }) { const cls = [ "tds-paragraph__text", __pgTypoClass(typography), __pgFwClass(fontWeight), className, ].filter(Boolean).join(" "); const mergedStyle = color ? Object.assign({ color: color }, style || {}) : style; return ( {children} ); } // ============================================================================= // Paragraph.Icon — 인라인 아이콘 // ============================================================================= function ParagraphIcon({ name, mono, typography, // 아이콘 높이 제어 — 부모와 다르게 줄 때 className = "", style, id, ...rest }) { if (!name) return null; const isUrl = __pgIsIconUrl(name); const inferredMono = typeof mono === "boolean" ? mono : (isUrl && __pgIsMonoIcon(name)); const cls = [ "tds-paragraph__icon", inferredMono ? "tds-paragraph__icon--mono" : "", __pgTypoClass(typography), className, ].filter(Boolean).join(" "); if (isUrl) { if (inferredMono) { const maskStyle = Object.assign( { WebkitMaskImage: `url("${name}")`, maskImage: `url("${name}")`, }, style || {} ); return ( ); } return ( ); } // IOSIcon 위임 — name 이 라이브러리 키 if (window.IOSIcon) { return ( ); } return