sellmate-design-system-react 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/components/SBarcodeInput/SBarcodeInput.cjs +1 -1
  2. package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
  3. package/dist/components/SBarcodeInput/SBarcodeInput.js +1 -1
  4. package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
  5. package/dist/components/SChipInput/SChipInput.cjs +1 -1
  6. package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
  7. package/dist/components/SChipInput/SChipInput.js +1 -1
  8. package/dist/components/SChipInput/SChipInput.js.map +1 -1
  9. package/dist/components/SCircleProgress/SCircleProgress.cjs +69 -50
  10. package/dist/components/SCircleProgress/SCircleProgress.cjs.map +1 -1
  11. package/dist/components/SCircleProgress/SCircleProgress.d.ts +2 -0
  12. package/dist/components/SCircleProgress/SCircleProgress.js +69 -50
  13. package/dist/components/SCircleProgress/SCircleProgress.js.map +1 -1
  14. package/dist/components/SDatePicker/SDatePicker.cjs +1 -1
  15. package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
  16. package/dist/components/SDatePicker/SDatePicker.js +1 -1
  17. package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
  18. package/dist/components/SDateRangePicker/SDateRangePicker.cjs +1 -1
  19. package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
  20. package/dist/components/SDateRangePicker/SDateRangePicker.js +1 -1
  21. package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
  22. package/dist/components/SField/SField.cjs +1 -1
  23. package/dist/components/SField/SField.cjs.map +1 -1
  24. package/dist/components/SField/SField.js +1 -1
  25. package/dist/components/SField/SField.js.map +1 -1
  26. package/dist/components/SFilePicker/SFilePicker.cjs +36 -17
  27. package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
  28. package/dist/components/SFilePicker/SFilePicker.d.ts +1 -1
  29. package/dist/components/SFilePicker/SFilePicker.js +35 -17
  30. package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
  31. package/dist/components/SInput/SInput.cjs +1 -1
  32. package/dist/components/SInput/SInput.cjs.map +1 -1
  33. package/dist/components/SInput/SInput.js +1 -1
  34. package/dist/components/SInput/SInput.js.map +1 -1
  35. package/dist/components/SKeyValueTable/SKeyValueTable.cjs +43 -22
  36. package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
  37. package/dist/components/SKeyValueTable/SKeyValueTable.js +43 -22
  38. package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
  39. package/dist/components/SLoadingContainer/SLoadingContainer.cjs +69 -50
  40. package/dist/components/SLoadingContainer/SLoadingContainer.cjs.map +1 -1
  41. package/dist/components/SLoadingContainer/SLoadingContainer.js +69 -50
  42. package/dist/components/SLoadingContainer/SLoadingContainer.js.map +1 -1
  43. package/dist/components/SLoadingContainer/loading.cjs +69 -50
  44. package/dist/components/SLoadingContainer/loading.cjs.map +1 -1
  45. package/dist/components/SLoadingContainer/loading.js +69 -50
  46. package/dist/components/SLoadingContainer/loading.js.map +1 -1
  47. package/dist/components/SLoadingModal/SLoadingModal.cjs +72 -50
  48. package/dist/components/SLoadingModal/SLoadingModal.cjs.map +1 -1
  49. package/dist/components/SLoadingModal/SLoadingModal.d.ts +3 -1
  50. package/dist/components/SLoadingModal/SLoadingModal.js +72 -50
  51. package/dist/components/SLoadingModal/SLoadingModal.js.map +1 -1
  52. package/dist/components/SNumberInput/SNumberInput.cjs +1 -1
  53. package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
  54. package/dist/components/SNumberInput/SNumberInput.js +1 -1
  55. package/dist/components/SNumberInput/SNumberInput.js.map +1 -1
  56. package/dist/components/SRadio/SRadioGroup.cjs +1 -1
  57. package/dist/components/SRadio/SRadioGroup.cjs.map +1 -1
  58. package/dist/components/SRadio/SRadioGroup.js +1 -1
  59. package/dist/components/SRadio/SRadioGroup.js.map +1 -1
  60. package/dist/components/SSelect/SSelect.cjs +8 -4
  61. package/dist/components/SSelect/SSelect.cjs.map +1 -1
  62. package/dist/components/SSelect/SSelect.js +8 -4
  63. package/dist/components/SSelect/SSelect.js.map +1 -1
  64. package/dist/components/STable/STable.cjs +82 -56
  65. package/dist/components/STable/STable.cjs.map +1 -1
  66. package/dist/components/STable/STable.js +82 -56
  67. package/dist/components/STable/STable.js.map +1 -1
  68. package/dist/components/STextarea/STextarea.cjs +1 -1
  69. package/dist/components/STextarea/STextarea.cjs.map +1 -1
  70. package/dist/components/STextarea/STextarea.js +1 -1
  71. package/dist/components/STextarea/STextarea.js.map +1 -1
  72. package/dist/components/STooltip/STooltip.cjs +1 -1
  73. package/dist/components/STooltip/STooltip.cjs.map +1 -1
  74. package/dist/components/STooltip/STooltip.js +1 -1
  75. package/dist/components/STooltip/STooltip.js.map +1 -1
  76. package/dist/index.cjs +120 -74
  77. package/dist/index.cjs.map +1 -1
  78. package/dist/index.js +120 -74
  79. package/dist/index.js.map +1 -1
  80. package/dist/styles.css +62 -21
  81. package/dist/theme.css +45 -21
  82. package/package.json +1 -1
@@ -30,12 +30,35 @@ var COLOR_MAP = {
30
30
  };
31
31
  var clamp = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
32
32
  var SCircleProgress = react.forwardRef(
33
- function SCircleProgress2({ value = 0, type = "primary", indeterminate = false, label, className, style }, ref) {
33
+ function SCircleProgress2({
34
+ value = 0,
35
+ type = "primary",
36
+ indeterminate = false,
37
+ label,
38
+ innerValue = false,
39
+ className,
40
+ style
41
+ }, ref) {
34
42
  const v = clamp(value);
35
43
  const colors = COLOR_MAP[type];
36
44
  const c = VIEWBOX / 2;
37
45
  const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
38
46
  const filled = v / 100 * CIRCUMFERENCE;
47
+ const showPercent = !indeterminate;
48
+ const percentNode = /* @__PURE__ */ jsxRuntime.jsxs(
49
+ "span",
50
+ {
51
+ className: cn(
52
+ "text-center text-[16px] font-bold leading-[26px]",
53
+ innerValue && "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
54
+ ),
55
+ style: { color: percentColor },
56
+ children: [
57
+ Math.round(v),
58
+ "%"
59
+ ]
60
+ }
61
+ );
39
62
  return /* @__PURE__ */ jsxRuntime.jsxs(
40
63
  "div",
41
64
  {
@@ -46,57 +69,53 @@ var SCircleProgress = react.forwardRef(
46
69
  ),
47
70
  style,
48
71
  children: [
49
- /* @__PURE__ */ jsxRuntime.jsxs(
50
- "svg",
51
- {
52
- viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
53
- xmlns: "http://www.w3.org/2000/svg",
54
- className: cn("h-[80px] w-[80px]", indeterminate && "origin-center animate-circle-spin"),
55
- children: [
56
- /* @__PURE__ */ jsxRuntime.jsx(
57
- "circle",
58
- {
59
- cx: c,
60
- cy: c,
61
- r: RADIUS,
62
- fill: "none",
63
- strokeWidth: STROKE,
64
- style: { stroke: colors.track }
65
- }
72
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(innerValue && "relative"), children: [
73
+ /* @__PURE__ */ jsxRuntime.jsxs(
74
+ "svg",
75
+ {
76
+ viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
77
+ xmlns: "http://www.w3.org/2000/svg",
78
+ className: cn(
79
+ "h-[80px] w-[80px]",
80
+ indeterminate && "origin-center animate-circle-spin"
66
81
  ),
67
- /* @__PURE__ */ jsxRuntime.jsx(
68
- "circle",
69
- {
70
- cx: c,
71
- cy: c,
72
- r: RADIUS,
73
- fill: "none",
74
- strokeWidth: STROKE,
75
- strokeLinecap: "round",
76
- className: cn(
77
- "origin-center",
78
- indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
79
- ),
80
- style: {
81
- stroke: colors.arc,
82
- ...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
82
+ children: [
83
+ /* @__PURE__ */ jsxRuntime.jsx(
84
+ "circle",
85
+ {
86
+ cx: c,
87
+ cy: c,
88
+ r: RADIUS,
89
+ fill: "none",
90
+ strokeWidth: STROKE,
91
+ style: { stroke: colors.track }
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsxRuntime.jsx(
95
+ "circle",
96
+ {
97
+ cx: c,
98
+ cy: c,
99
+ r: RADIUS,
100
+ fill: "none",
101
+ strokeWidth: STROKE,
102
+ strokeLinecap: "round",
103
+ className: cn(
104
+ "origin-center",
105
+ indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
106
+ ),
107
+ style: {
108
+ stroke: colors.arc,
109
+ ...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
110
+ }
83
111
  }
84
- }
85
- )
86
- ]
87
- }
88
- ),
89
- !indeterminate && /* @__PURE__ */ jsxRuntime.jsxs(
90
- "span",
91
- {
92
- className: "text-center text-[16px] font-bold leading-[26px]",
93
- style: { color: percentColor },
94
- children: [
95
- Math.round(v),
96
- "%"
97
- ]
98
- }
99
- ),
112
+ )
113
+ ]
114
+ }
115
+ ),
116
+ showPercent && innerValue && percentNode
117
+ ] }),
118
+ showPercent && !innerValue && percentNode,
100
119
  label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
101
120
  ]
102
121
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/cn.ts","../../../src/components/SCircleProgress/SCircleProgress.tsx","../../../src/components/SLoadingContainer/SLoadingContainer.tsx"],"names":["extendTailwindMerge","clsx","forwardRef","SCircleProgress","jsxs","jsx","SLoadingContainer","useState","useEffect","useRef","useCallback","createPortal"],"mappings":"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","file":"SLoadingContainer.cjs","sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { extendTailwindMerge } from 'tailwind-merge';\n\n/**\n * theme.css 의 --text-* 는 기본 Tailwind 폰트사이즈 스케일(xs/sm/base...)이 아닌\n * 숫자 스케일(10~32)이라, 확장 없이는 tailwind-merge 가 이를 텍스트 컬러 그룹으로\n * 오인해 text-12 같은 클래스를 text-(--color-var) 뒤에서 충돌 제거해버린다.\n */\nconst twMerge = extendTailwindMerge({\n extend: {\n classGroups: {\n 'font-size': [{ text: ['10', '11', '12', '13', '14', '16', '18', '20', '24', '28', '32'] }],\n },\n },\n});\n\n/**\n * className 병합 유틸.\n * clsx로 조건부 클래스를 합치고, tailwind-merge로 Tailwind 클래스 충돌을 해소한다.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { forwardRef, type CSSProperties } from 'react';\nimport { cn } from '../../lib/cn';\n\nexport type SCircleProgressType = 'primary' | 'inverse' | 'error' | 'complete';\n\nconst VIEWBOX = 80;\nconst RADIUS = 34;\nconst STROKE = 12;\nconst CIRCUMFERENCE = 2 * Math.PI * RADIUS;\n\nconst COLOR_MAP: Record<SCircleProgressType, { arc: string; track: string }> = {\n primary: { arc: 'var(--cmp-progress-active-color)', track: 'var(--cmp-progress-color-track)' },\n // inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)\n inverse: { arc: 'var(--color-white)', track: 'rgba(255,255,255,0.4)' },\n error: { arc: 'var(--color-red-75)', track: 'var(--cmp-progress-color-track)' },\n complete: { arc: '#01BB4B', track: 'var(--cmp-progress-color-track)' },\n};\n\nexport interface SCircleProgressProps {\n /** 진행률 (0–100) */\n value?: number;\n /** 색상 테마 */\n type?: SCircleProgressType;\n /** 불확정(스피너) 모드 — value 무시 */\n indeterminate?: boolean;\n /** 하단 레이블 */\n label?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst clamp = (v: number) => (Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0);\n\n/** SCircleProgress — sd-circle-progress 포팅. determinate=진행률 arc, indeterminate=스피너. */\nexport const SCircleProgress = forwardRef<HTMLDivElement, SCircleProgressProps>(\n function SCircleProgress(\n { value = 0, type = 'primary', indeterminate = false, label, className, style },\n ref,\n ) {\n const v = clamp(value);\n const colors = COLOR_MAP[type];\n const c = VIEWBOX / 2;\n const percentColor = v === 0 ? 'var(--sys-color-fg-tertiary, #888888)' : colors.arc;\n const filled = (v / 100) * CIRCUMFERENCE;\n\n return (\n <div\n ref={ref}\n className={cn(\n 'inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]',\n className,\n )}\n style={style}\n >\n <svg\n viewBox={`0 0 ${VIEWBOX} ${VIEWBOX}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn('h-[80px] w-[80px]', indeterminate && 'origin-center animate-circle-spin')}\n >\n <circle\n cx={c}\n cy={c}\n r={RADIUS}\n fill=\"none\"\n strokeWidth={STROKE}\n style={{ stroke: colors.track }}\n />\n <circle\n cx={c}\n cy={c}\n r={RADIUS}\n fill=\"none\"\n strokeWidth={STROKE}\n strokeLinecap=\"round\"\n className={cn(\n 'origin-center',\n indeterminate\n ? 'animate-circle-arc'\n : '-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear',\n )}\n style={{\n stroke: colors.arc,\n ...(indeterminate\n ? {}\n : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }),\n }}\n />\n </svg>\n {/* percent 는 원(ring) 아래에 표시 */}\n {!indeterminate && (\n <span\n className=\"text-center text-[16px] font-bold leading-[26px]\"\n style={{ color: percentColor }}\n >\n {Math.round(v)}%\n </span>\n )}\n {label && (\n <span className=\"text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]\">\n {label}\n </span>\n )}\n </div>\n );\n },\n);\n","'use client';\n\nimport { forwardRef, useCallback, useEffect, useRef, useState, type CSSProperties } from 'react';\nimport { createPortal } from 'react-dom';\nimport { cn } from '../../lib/cn';\nimport { SCircleProgress } from '../SCircleProgress';\n\nexport interface SLoadingContainerProps {\n /** 오버레이 표시 여부 (Stencil의 show()/hide() 명령형 API → 제어 prop으로 대체) */\n open?: boolean;\n /** 스피너 하단 메시지 */\n message?: string;\n /** z-index. 기본값(1200)은 토스트(1100)·모달(1000/1001) 위 — 전체 화면을 막는 최상단 블로킹 오버레이 */\n zIndex?: number;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * SLoadingContainer — sd-loading-container 포팅.\n * 전체 화면 딤 오버레이 + inverse 스피너. React에서는 `open` 제어 prop 사용.\n * body 로 portal 해 조상의 스태킹 컨텍스트에 갇히지 않고 항상 최상단에 뜨게 한다.\n */\nexport const SLoadingContainer = forwardRef<HTMLDivElement, SLoadingContainerProps>(\n function SLoadingContainer({ open = false, message, zIndex = 1200, className, style }, ref) {\n // portal 은 클라이언트에서만 (SSR 시 document 없음) — 마운트 후 body 로 렌더\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n\n // 오버레이 표시 중 배경 스크롤 차단\n useEffect(() => {\n if (!open) return;\n const prev = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => {\n document.body.style.overflow = prev;\n };\n }, [open]);\n\n // body 로 portal 된 블로킹 오버레이라, 클릭이 document 까지 전파되면 Radix Dialog 의\n // \"바깥 클릭\" 감지에 걸려 열려있는 모달이 닫힌다. 오버레이 요소에 네이티브 pointerdown\n // 리스너를 직접 붙여(요소 자신에서 가장 먼저 발화) 전파를 끊어 document 리스너를 차단한다.\n const innerRef = useRef<HTMLDivElement | null>(null);\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n innerRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref],\n );\n useEffect(() => {\n const el = innerRef.current;\n if (!el) return;\n const stop = (e: Event) => e.stopPropagation();\n el.addEventListener('pointerdown', stop);\n el.addEventListener('mousedown', stop);\n return () => {\n el.removeEventListener('pointerdown', stop);\n el.removeEventListener('mousedown', stop);\n };\n }, [mounted]);\n\n const overlay = (\n <div\n ref={setRef}\n aria-hidden={!open}\n className={cn(\n 'fixed inset-0 flex items-center justify-center transition-opacity duration-200',\n open\n ? 'pointer-events-auto visible opacity-100'\n : 'pointer-events-none invisible opacity-0',\n className,\n )}\n style={{ zIndex, ...style }}\n >\n <div className=\"absolute inset-0 bg-black/40\" />\n <div className=\"relative flex flex-col items-center gap-[16px]\">\n <SCircleProgress indeterminate type=\"inverse\" />\n {message && (\n <p className=\"m-0 max-w-[400px] break-keep text-center text-[14px] font-medium leading-[22px] text-[color:var(--color-white)]\">\n {message}\n </p>\n )}\n </div>\n </div>\n );\n\n if (!mounted) return null;\n return createPortal(overlay, document.body);\n },\n);\n"]}
1
+ {"version":3,"sources":["../../../src/lib/cn.ts","../../../src/components/SCircleProgress/SCircleProgress.tsx","../../../src/components/SLoadingContainer/SLoadingContainer.tsx"],"names":["extendTailwindMerge","clsx","forwardRef","SCircleProgress","jsxs","jsx","SLoadingContainer","useState","useEffect","useRef","useCallback","createPortal"],"mappings":"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","file":"SLoadingContainer.cjs","sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { extendTailwindMerge } from 'tailwind-merge';\n\n/**\n * theme.css 의 --text-* 는 기본 Tailwind 폰트사이즈 스케일(xs/sm/base...)이 아닌\n * 숫자 스케일(10~32)이라, 확장 없이는 tailwind-merge 가 이를 텍스트 컬러 그룹으로\n * 오인해 text-12 같은 클래스를 text-(--color-var) 뒤에서 충돌 제거해버린다.\n */\nconst twMerge = extendTailwindMerge({\n extend: {\n classGroups: {\n 'font-size': [{ text: ['10', '11', '12', '13', '14', '16', '18', '20', '24', '28', '32'] }],\n },\n },\n});\n\n/**\n * className 병합 유틸.\n * clsx로 조건부 클래스를 합치고, tailwind-merge로 Tailwind 클래스 충돌을 해소한다.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { forwardRef, type CSSProperties } from 'react';\nimport { cn } from '../../lib/cn';\n\nexport type SCircleProgressType = 'primary' | 'inverse' | 'error' | 'complete';\n\nconst VIEWBOX = 80;\nconst RADIUS = 34;\nconst STROKE = 12;\nconst CIRCUMFERENCE = 2 * Math.PI * RADIUS;\n\nconst COLOR_MAP: Record<SCircleProgressType, { arc: string; track: string }> = {\n primary: { arc: 'var(--cmp-progress-active-color)', track: 'var(--cmp-progress-color-track)' },\n // inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)\n inverse: { arc: 'var(--color-white)', track: 'rgba(255,255,255,0.4)' },\n error: { arc: 'var(--color-red-75)', track: 'var(--cmp-progress-color-track)' },\n complete: { arc: '#01BB4B', track: 'var(--cmp-progress-color-track)' },\n};\n\nexport interface SCircleProgressProps {\n /** 진행률 (0–100) */\n value?: number;\n /** 색상 테마 */\n type?: SCircleProgressType;\n /** 불확정(스피너) 모드 — value 무시 */\n indeterminate?: boolean;\n /** 하단 레이블 */\n label?: string;\n /** true면 퍼센트를 원 아래가 아닌 원 가운데에 표시 */\n innerValue?: boolean;\n className?: string;\n style?: CSSProperties;\n}\n\nconst clamp = (v: number) => (Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0);\n\n/** SCircleProgress — sd-circle-progress 포팅. determinate=진행률 arc, indeterminate=스피너. */\nexport const SCircleProgress = forwardRef<HTMLDivElement, SCircleProgressProps>(\n function SCircleProgress(\n {\n value = 0,\n type = 'primary',\n indeterminate = false,\n label,\n innerValue = false,\n className,\n style,\n },\n ref,\n ) {\n const v = clamp(value);\n const colors = COLOR_MAP[type];\n const c = VIEWBOX / 2;\n const percentColor = v === 0 ? 'var(--sys-color-fg-tertiary, #888888)' : colors.arc;\n const filled = (v / 100) * CIRCUMFERENCE;\n const showPercent = !indeterminate;\n const percentNode = (\n <span\n className={cn(\n 'text-center text-[16px] font-bold leading-[26px]',\n innerValue && 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',\n )}\n style={{ color: percentColor }}\n >\n {Math.round(v)}%\n </span>\n );\n\n return (\n <div\n ref={ref}\n className={cn(\n 'inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]',\n className,\n )}\n style={style}\n >\n <div className={cn(innerValue && 'relative')}>\n <svg\n viewBox={`0 0 ${VIEWBOX} ${VIEWBOX}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn(\n 'h-[80px] w-[80px]',\n indeterminate && 'origin-center animate-circle-spin',\n )}\n >\n <circle\n cx={c}\n cy={c}\n r={RADIUS}\n fill=\"none\"\n strokeWidth={STROKE}\n style={{ stroke: colors.track }}\n />\n <circle\n cx={c}\n cy={c}\n r={RADIUS}\n fill=\"none\"\n strokeWidth={STROKE}\n strokeLinecap=\"round\"\n className={cn(\n 'origin-center',\n indeterminate\n ? 'animate-circle-arc'\n : '-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear',\n )}\n style={{\n stroke: colors.arc,\n ...(indeterminate\n ? {}\n : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }),\n }}\n />\n </svg>\n {/* innerValue: 원 가운데에 퍼센트 오버레이 */}\n {showPercent && innerValue && percentNode}\n </div>\n {/* 기본: 퍼센트를 원(ring) 아래에 표시 */}\n {showPercent && !innerValue && percentNode}\n {label && (\n <span className=\"text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]\">\n {label}\n </span>\n )}\n </div>\n );\n },\n);\n","'use client';\n\nimport { forwardRef, useCallback, useEffect, useRef, useState, type CSSProperties } from 'react';\nimport { createPortal } from 'react-dom';\nimport { cn } from '../../lib/cn';\nimport { SCircleProgress } from '../SCircleProgress';\n\nexport interface SLoadingContainerProps {\n /** 오버레이 표시 여부 (Stencil의 show()/hide() 명령형 API → 제어 prop으로 대체) */\n open?: boolean;\n /** 스피너 하단 메시지 */\n message?: string;\n /** z-index. 기본값(1200)은 토스트(1100)·모달(1000/1001) 위 — 전체 화면을 막는 최상단 블로킹 오버레이 */\n zIndex?: number;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * SLoadingContainer — sd-loading-container 포팅.\n * 전체 화면 딤 오버레이 + inverse 스피너. React에서는 `open` 제어 prop 사용.\n * body 로 portal 해 조상의 스태킹 컨텍스트에 갇히지 않고 항상 최상단에 뜨게 한다.\n */\nexport const SLoadingContainer = forwardRef<HTMLDivElement, SLoadingContainerProps>(\n function SLoadingContainer({ open = false, message, zIndex = 1200, className, style }, ref) {\n // portal 은 클라이언트에서만 (SSR 시 document 없음) — 마운트 후 body 로 렌더\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n\n // 오버레이 표시 중 배경 스크롤 차단\n useEffect(() => {\n if (!open) return;\n const prev = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => {\n document.body.style.overflow = prev;\n };\n }, [open]);\n\n // body 로 portal 된 블로킹 오버레이라, 클릭이 document 까지 전파되면 Radix Dialog 의\n // \"바깥 클릭\" 감지에 걸려 열려있는 모달이 닫힌다. 오버레이 요소에 네이티브 pointerdown\n // 리스너를 직접 붙여(요소 자신에서 가장 먼저 발화) 전파를 끊어 document 리스너를 차단한다.\n const innerRef = useRef<HTMLDivElement | null>(null);\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n innerRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref],\n );\n useEffect(() => {\n const el = innerRef.current;\n if (!el) return;\n const stop = (e: Event) => e.stopPropagation();\n el.addEventListener('pointerdown', stop);\n el.addEventListener('mousedown', stop);\n return () => {\n el.removeEventListener('pointerdown', stop);\n el.removeEventListener('mousedown', stop);\n };\n }, [mounted]);\n\n const overlay = (\n <div\n ref={setRef}\n aria-hidden={!open}\n className={cn(\n 'fixed inset-0 flex items-center justify-center transition-opacity duration-200',\n open\n ? 'pointer-events-auto visible opacity-100'\n : 'pointer-events-none invisible opacity-0',\n className,\n )}\n style={{ zIndex, ...style }}\n >\n <div className=\"absolute inset-0 bg-black/40\" />\n <div className=\"relative flex flex-col items-center gap-[16px]\">\n <SCircleProgress indeterminate type=\"inverse\" />\n {message && (\n <p className=\"m-0 max-w-[400px] break-keep text-center text-[14px] font-medium leading-[22px] text-[color:var(--color-white)]\">\n {message}\n </p>\n )}\n </div>\n </div>\n );\n\n if (!mounted) return null;\n return createPortal(overlay, document.body);\n },\n);\n"]}
@@ -28,12 +28,35 @@ var COLOR_MAP = {
28
28
  };
29
29
  var clamp = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
30
30
  var SCircleProgress = forwardRef(
31
- function SCircleProgress2({ value = 0, type = "primary", indeterminate = false, label, className, style }, ref) {
31
+ function SCircleProgress2({
32
+ value = 0,
33
+ type = "primary",
34
+ indeterminate = false,
35
+ label,
36
+ innerValue = false,
37
+ className,
38
+ style
39
+ }, ref) {
32
40
  const v = clamp(value);
33
41
  const colors = COLOR_MAP[type];
34
42
  const c = VIEWBOX / 2;
35
43
  const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
36
44
  const filled = v / 100 * CIRCUMFERENCE;
45
+ const showPercent = !indeterminate;
46
+ const percentNode = /* @__PURE__ */ jsxs(
47
+ "span",
48
+ {
49
+ className: cn(
50
+ "text-center text-[16px] font-bold leading-[26px]",
51
+ innerValue && "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
52
+ ),
53
+ style: { color: percentColor },
54
+ children: [
55
+ Math.round(v),
56
+ "%"
57
+ ]
58
+ }
59
+ );
37
60
  return /* @__PURE__ */ jsxs(
38
61
  "div",
39
62
  {
@@ -44,57 +67,53 @@ var SCircleProgress = forwardRef(
44
67
  ),
45
68
  style,
46
69
  children: [
47
- /* @__PURE__ */ jsxs(
48
- "svg",
49
- {
50
- viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
51
- xmlns: "http://www.w3.org/2000/svg",
52
- className: cn("h-[80px] w-[80px]", indeterminate && "origin-center animate-circle-spin"),
53
- children: [
54
- /* @__PURE__ */ jsx(
55
- "circle",
56
- {
57
- cx: c,
58
- cy: c,
59
- r: RADIUS,
60
- fill: "none",
61
- strokeWidth: STROKE,
62
- style: { stroke: colors.track }
63
- }
70
+ /* @__PURE__ */ jsxs("div", { className: cn(innerValue && "relative"), children: [
71
+ /* @__PURE__ */ jsxs(
72
+ "svg",
73
+ {
74
+ viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
75
+ xmlns: "http://www.w3.org/2000/svg",
76
+ className: cn(
77
+ "h-[80px] w-[80px]",
78
+ indeterminate && "origin-center animate-circle-spin"
64
79
  ),
65
- /* @__PURE__ */ jsx(
66
- "circle",
67
- {
68
- cx: c,
69
- cy: c,
70
- r: RADIUS,
71
- fill: "none",
72
- strokeWidth: STROKE,
73
- strokeLinecap: "round",
74
- className: cn(
75
- "origin-center",
76
- indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
77
- ),
78
- style: {
79
- stroke: colors.arc,
80
- ...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
80
+ children: [
81
+ /* @__PURE__ */ jsx(
82
+ "circle",
83
+ {
84
+ cx: c,
85
+ cy: c,
86
+ r: RADIUS,
87
+ fill: "none",
88
+ strokeWidth: STROKE,
89
+ style: { stroke: colors.track }
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsx(
93
+ "circle",
94
+ {
95
+ cx: c,
96
+ cy: c,
97
+ r: RADIUS,
98
+ fill: "none",
99
+ strokeWidth: STROKE,
100
+ strokeLinecap: "round",
101
+ className: cn(
102
+ "origin-center",
103
+ indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
104
+ ),
105
+ style: {
106
+ stroke: colors.arc,
107
+ ...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
108
+ }
81
109
  }
82
- }
83
- )
84
- ]
85
- }
86
- ),
87
- !indeterminate && /* @__PURE__ */ jsxs(
88
- "span",
89
- {
90
- className: "text-center text-[16px] font-bold leading-[26px]",
91
- style: { color: percentColor },
92
- children: [
93
- Math.round(v),
94
- "%"
95
- ]
96
- }
97
- ),
110
+ )
111
+ ]
112
+ }
113
+ ),
114
+ showPercent && innerValue && percentNode
115
+ ] }),
116
+ showPercent && !innerValue && percentNode,
98
117
  label && /* @__PURE__ */ jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
99
118
  ]
100
119
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/cn.ts","../../../src/components/SCircleProgress/SCircleProgress.tsx","../../../src/components/SLoadingContainer/SLoadingContainer.tsx"],"names":["SCircleProgress","forwardRef","SLoadingContainer","jsxs","jsx"],"mappings":"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","file":"SLoadingContainer.js","sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { extendTailwindMerge } from 'tailwind-merge';\n\n/**\n * theme.css 의 --text-* 는 기본 Tailwind 폰트사이즈 스케일(xs/sm/base...)이 아닌\n * 숫자 스케일(10~32)이라, 확장 없이는 tailwind-merge 가 이를 텍스트 컬러 그룹으로\n * 오인해 text-12 같은 클래스를 text-(--color-var) 뒤에서 충돌 제거해버린다.\n */\nconst twMerge = extendTailwindMerge({\n extend: {\n classGroups: {\n 'font-size': [{ text: ['10', '11', '12', '13', '14', '16', '18', '20', '24', '28', '32'] }],\n },\n },\n});\n\n/**\n * className 병합 유틸.\n * clsx로 조건부 클래스를 합치고, tailwind-merge로 Tailwind 클래스 충돌을 해소한다.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { forwardRef, type CSSProperties } from 'react';\nimport { cn } from '../../lib/cn';\n\nexport type SCircleProgressType = 'primary' | 'inverse' | 'error' | 'complete';\n\nconst VIEWBOX = 80;\nconst RADIUS = 34;\nconst STROKE = 12;\nconst CIRCUMFERENCE = 2 * Math.PI * RADIUS;\n\nconst COLOR_MAP: Record<SCircleProgressType, { arc: string; track: string }> = {\n primary: { arc: 'var(--cmp-progress-active-color)', track: 'var(--cmp-progress-color-track)' },\n // inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)\n inverse: { arc: 'var(--color-white)', track: 'rgba(255,255,255,0.4)' },\n error: { arc: 'var(--color-red-75)', track: 'var(--cmp-progress-color-track)' },\n complete: { arc: '#01BB4B', track: 'var(--cmp-progress-color-track)' },\n};\n\nexport interface SCircleProgressProps {\n /** 진행률 (0–100) */\n value?: number;\n /** 색상 테마 */\n type?: SCircleProgressType;\n /** 불확정(스피너) 모드 — value 무시 */\n indeterminate?: boolean;\n /** 하단 레이블 */\n label?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst clamp = (v: number) => (Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0);\n\n/** SCircleProgress — sd-circle-progress 포팅. determinate=진행률 arc, indeterminate=스피너. */\nexport const SCircleProgress = forwardRef<HTMLDivElement, SCircleProgressProps>(\n function SCircleProgress(\n { value = 0, type = 'primary', indeterminate = false, label, className, style },\n ref,\n ) {\n const v = clamp(value);\n const colors = COLOR_MAP[type];\n const c = VIEWBOX / 2;\n const percentColor = v === 0 ? 'var(--sys-color-fg-tertiary, #888888)' : colors.arc;\n const filled = (v / 100) * CIRCUMFERENCE;\n\n return (\n <div\n ref={ref}\n className={cn(\n 'inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]',\n className,\n )}\n style={style}\n >\n <svg\n viewBox={`0 0 ${VIEWBOX} ${VIEWBOX}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn('h-[80px] w-[80px]', indeterminate && 'origin-center animate-circle-spin')}\n >\n <circle\n cx={c}\n cy={c}\n r={RADIUS}\n fill=\"none\"\n strokeWidth={STROKE}\n style={{ stroke: colors.track }}\n />\n <circle\n cx={c}\n cy={c}\n r={RADIUS}\n fill=\"none\"\n strokeWidth={STROKE}\n strokeLinecap=\"round\"\n className={cn(\n 'origin-center',\n indeterminate\n ? 'animate-circle-arc'\n : '-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear',\n )}\n style={{\n stroke: colors.arc,\n ...(indeterminate\n ? {}\n : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }),\n }}\n />\n </svg>\n {/* percent 는 원(ring) 아래에 표시 */}\n {!indeterminate && (\n <span\n className=\"text-center text-[16px] font-bold leading-[26px]\"\n style={{ color: percentColor }}\n >\n {Math.round(v)}%\n </span>\n )}\n {label && (\n <span className=\"text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]\">\n {label}\n </span>\n )}\n </div>\n );\n },\n);\n","'use client';\n\nimport { forwardRef, useCallback, useEffect, useRef, useState, type CSSProperties } from 'react';\nimport { createPortal } from 'react-dom';\nimport { cn } from '../../lib/cn';\nimport { SCircleProgress } from '../SCircleProgress';\n\nexport interface SLoadingContainerProps {\n /** 오버레이 표시 여부 (Stencil의 show()/hide() 명령형 API → 제어 prop으로 대체) */\n open?: boolean;\n /** 스피너 하단 메시지 */\n message?: string;\n /** z-index. 기본값(1200)은 토스트(1100)·모달(1000/1001) 위 — 전체 화면을 막는 최상단 블로킹 오버레이 */\n zIndex?: number;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * SLoadingContainer — sd-loading-container 포팅.\n * 전체 화면 딤 오버레이 + inverse 스피너. React에서는 `open` 제어 prop 사용.\n * body 로 portal 해 조상의 스태킹 컨텍스트에 갇히지 않고 항상 최상단에 뜨게 한다.\n */\nexport const SLoadingContainer = forwardRef<HTMLDivElement, SLoadingContainerProps>(\n function SLoadingContainer({ open = false, message, zIndex = 1200, className, style }, ref) {\n // portal 은 클라이언트에서만 (SSR 시 document 없음) — 마운트 후 body 로 렌더\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n\n // 오버레이 표시 중 배경 스크롤 차단\n useEffect(() => {\n if (!open) return;\n const prev = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => {\n document.body.style.overflow = prev;\n };\n }, [open]);\n\n // body 로 portal 된 블로킹 오버레이라, 클릭이 document 까지 전파되면 Radix Dialog 의\n // \"바깥 클릭\" 감지에 걸려 열려있는 모달이 닫힌다. 오버레이 요소에 네이티브 pointerdown\n // 리스너를 직접 붙여(요소 자신에서 가장 먼저 발화) 전파를 끊어 document 리스너를 차단한다.\n const innerRef = useRef<HTMLDivElement | null>(null);\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n innerRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref],\n );\n useEffect(() => {\n const el = innerRef.current;\n if (!el) return;\n const stop = (e: Event) => e.stopPropagation();\n el.addEventListener('pointerdown', stop);\n el.addEventListener('mousedown', stop);\n return () => {\n el.removeEventListener('pointerdown', stop);\n el.removeEventListener('mousedown', stop);\n };\n }, [mounted]);\n\n const overlay = (\n <div\n ref={setRef}\n aria-hidden={!open}\n className={cn(\n 'fixed inset-0 flex items-center justify-center transition-opacity duration-200',\n open\n ? 'pointer-events-auto visible opacity-100'\n : 'pointer-events-none invisible opacity-0',\n className,\n )}\n style={{ zIndex, ...style }}\n >\n <div className=\"absolute inset-0 bg-black/40\" />\n <div className=\"relative flex flex-col items-center gap-[16px]\">\n <SCircleProgress indeterminate type=\"inverse\" />\n {message && (\n <p className=\"m-0 max-w-[400px] break-keep text-center text-[14px] font-medium leading-[22px] text-[color:var(--color-white)]\">\n {message}\n </p>\n )}\n </div>\n </div>\n );\n\n if (!mounted) return null;\n return createPortal(overlay, document.body);\n },\n);\n"]}
1
+ {"version":3,"sources":["../../../src/lib/cn.ts","../../../src/components/SCircleProgress/SCircleProgress.tsx","../../../src/components/SLoadingContainer/SLoadingContainer.tsx"],"names":["SCircleProgress","forwardRef","SLoadingContainer","jsxs","jsx"],"mappings":"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","file":"SLoadingContainer.js","sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { extendTailwindMerge } from 'tailwind-merge';\n\n/**\n * theme.css 의 --text-* 는 기본 Tailwind 폰트사이즈 스케일(xs/sm/base...)이 아닌\n * 숫자 스케일(10~32)이라, 확장 없이는 tailwind-merge 가 이를 텍스트 컬러 그룹으로\n * 오인해 text-12 같은 클래스를 text-(--color-var) 뒤에서 충돌 제거해버린다.\n */\nconst twMerge = extendTailwindMerge({\n extend: {\n classGroups: {\n 'font-size': [{ text: ['10', '11', '12', '13', '14', '16', '18', '20', '24', '28', '32'] }],\n },\n },\n});\n\n/**\n * className 병합 유틸.\n * clsx로 조건부 클래스를 합치고, tailwind-merge로 Tailwind 클래스 충돌을 해소한다.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { forwardRef, type CSSProperties } from 'react';\nimport { cn } from '../../lib/cn';\n\nexport type SCircleProgressType = 'primary' | 'inverse' | 'error' | 'complete';\n\nconst VIEWBOX = 80;\nconst RADIUS = 34;\nconst STROKE = 12;\nconst CIRCUMFERENCE = 2 * Math.PI * RADIUS;\n\nconst COLOR_MAP: Record<SCircleProgressType, { arc: string; track: string }> = {\n primary: { arc: 'var(--cmp-progress-active-color)', track: 'var(--cmp-progress-color-track)' },\n // inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)\n inverse: { arc: 'var(--color-white)', track: 'rgba(255,255,255,0.4)' },\n error: { arc: 'var(--color-red-75)', track: 'var(--cmp-progress-color-track)' },\n complete: { arc: '#01BB4B', track: 'var(--cmp-progress-color-track)' },\n};\n\nexport interface SCircleProgressProps {\n /** 진행률 (0–100) */\n value?: number;\n /** 색상 테마 */\n type?: SCircleProgressType;\n /** 불확정(스피너) 모드 — value 무시 */\n indeterminate?: boolean;\n /** 하단 레이블 */\n label?: string;\n /** true면 퍼센트를 원 아래가 아닌 원 가운데에 표시 */\n innerValue?: boolean;\n className?: string;\n style?: CSSProperties;\n}\n\nconst clamp = (v: number) => (Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0);\n\n/** SCircleProgress — sd-circle-progress 포팅. determinate=진행률 arc, indeterminate=스피너. */\nexport const SCircleProgress = forwardRef<HTMLDivElement, SCircleProgressProps>(\n function SCircleProgress(\n {\n value = 0,\n type = 'primary',\n indeterminate = false,\n label,\n innerValue = false,\n className,\n style,\n },\n ref,\n ) {\n const v = clamp(value);\n const colors = COLOR_MAP[type];\n const c = VIEWBOX / 2;\n const percentColor = v === 0 ? 'var(--sys-color-fg-tertiary, #888888)' : colors.arc;\n const filled = (v / 100) * CIRCUMFERENCE;\n const showPercent = !indeterminate;\n const percentNode = (\n <span\n className={cn(\n 'text-center text-[16px] font-bold leading-[26px]',\n innerValue && 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',\n )}\n style={{ color: percentColor }}\n >\n {Math.round(v)}%\n </span>\n );\n\n return (\n <div\n ref={ref}\n className={cn(\n 'inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]',\n className,\n )}\n style={style}\n >\n <div className={cn(innerValue && 'relative')}>\n <svg\n viewBox={`0 0 ${VIEWBOX} ${VIEWBOX}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn(\n 'h-[80px] w-[80px]',\n indeterminate && 'origin-center animate-circle-spin',\n )}\n >\n <circle\n cx={c}\n cy={c}\n r={RADIUS}\n fill=\"none\"\n strokeWidth={STROKE}\n style={{ stroke: colors.track }}\n />\n <circle\n cx={c}\n cy={c}\n r={RADIUS}\n fill=\"none\"\n strokeWidth={STROKE}\n strokeLinecap=\"round\"\n className={cn(\n 'origin-center',\n indeterminate\n ? 'animate-circle-arc'\n : '-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear',\n )}\n style={{\n stroke: colors.arc,\n ...(indeterminate\n ? {}\n : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }),\n }}\n />\n </svg>\n {/* innerValue: 원 가운데에 퍼센트 오버레이 */}\n {showPercent && innerValue && percentNode}\n </div>\n {/* 기본: 퍼센트를 원(ring) 아래에 표시 */}\n {showPercent && !innerValue && percentNode}\n {label && (\n <span className=\"text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]\">\n {label}\n </span>\n )}\n </div>\n );\n },\n);\n","'use client';\n\nimport { forwardRef, useCallback, useEffect, useRef, useState, type CSSProperties } from 'react';\nimport { createPortal } from 'react-dom';\nimport { cn } from '../../lib/cn';\nimport { SCircleProgress } from '../SCircleProgress';\n\nexport interface SLoadingContainerProps {\n /** 오버레이 표시 여부 (Stencil의 show()/hide() 명령형 API → 제어 prop으로 대체) */\n open?: boolean;\n /** 스피너 하단 메시지 */\n message?: string;\n /** z-index. 기본값(1200)은 토스트(1100)·모달(1000/1001) 위 — 전체 화면을 막는 최상단 블로킹 오버레이 */\n zIndex?: number;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * SLoadingContainer — sd-loading-container 포팅.\n * 전체 화면 딤 오버레이 + inverse 스피너. React에서는 `open` 제어 prop 사용.\n * body 로 portal 해 조상의 스태킹 컨텍스트에 갇히지 않고 항상 최상단에 뜨게 한다.\n */\nexport const SLoadingContainer = forwardRef<HTMLDivElement, SLoadingContainerProps>(\n function SLoadingContainer({ open = false, message, zIndex = 1200, className, style }, ref) {\n // portal 은 클라이언트에서만 (SSR 시 document 없음) — 마운트 후 body 로 렌더\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n\n // 오버레이 표시 중 배경 스크롤 차단\n useEffect(() => {\n if (!open) return;\n const prev = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => {\n document.body.style.overflow = prev;\n };\n }, [open]);\n\n // body 로 portal 된 블로킹 오버레이라, 클릭이 document 까지 전파되면 Radix Dialog 의\n // \"바깥 클릭\" 감지에 걸려 열려있는 모달이 닫힌다. 오버레이 요소에 네이티브 pointerdown\n // 리스너를 직접 붙여(요소 자신에서 가장 먼저 발화) 전파를 끊어 document 리스너를 차단한다.\n const innerRef = useRef<HTMLDivElement | null>(null);\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n innerRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref],\n );\n useEffect(() => {\n const el = innerRef.current;\n if (!el) return;\n const stop = (e: Event) => e.stopPropagation();\n el.addEventListener('pointerdown', stop);\n el.addEventListener('mousedown', stop);\n return () => {\n el.removeEventListener('pointerdown', stop);\n el.removeEventListener('mousedown', stop);\n };\n }, [mounted]);\n\n const overlay = (\n <div\n ref={setRef}\n aria-hidden={!open}\n className={cn(\n 'fixed inset-0 flex items-center justify-center transition-opacity duration-200',\n open\n ? 'pointer-events-auto visible opacity-100'\n : 'pointer-events-none invisible opacity-0',\n className,\n )}\n style={{ zIndex, ...style }}\n >\n <div className=\"absolute inset-0 bg-black/40\" />\n <div className=\"relative flex flex-col items-center gap-[16px]\">\n <SCircleProgress indeterminate type=\"inverse\" />\n {message && (\n <p className=\"m-0 max-w-[400px] break-keep text-center text-[14px] font-medium leading-[22px] text-[color:var(--color-white)]\">\n {message}\n </p>\n )}\n </div>\n </div>\n );\n\n if (!mounted) return null;\n return createPortal(overlay, document.body);\n },\n);\n"]}
@@ -31,12 +31,35 @@ var COLOR_MAP = {
31
31
  };
32
32
  var clamp = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
33
33
  var SCircleProgress = react.forwardRef(
34
- function SCircleProgress2({ value = 0, type = "primary", indeterminate = false, label, className, style }, ref) {
34
+ function SCircleProgress2({
35
+ value = 0,
36
+ type = "primary",
37
+ indeterminate = false,
38
+ label,
39
+ innerValue = false,
40
+ className,
41
+ style
42
+ }, ref) {
35
43
  const v = clamp(value);
36
44
  const colors = COLOR_MAP[type];
37
45
  const c = VIEWBOX / 2;
38
46
  const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
39
47
  const filled = v / 100 * CIRCUMFERENCE;
48
+ const showPercent = !indeterminate;
49
+ const percentNode = /* @__PURE__ */ jsxRuntime.jsxs(
50
+ "span",
51
+ {
52
+ className: cn(
53
+ "text-center text-[16px] font-bold leading-[26px]",
54
+ innerValue && "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
55
+ ),
56
+ style: { color: percentColor },
57
+ children: [
58
+ Math.round(v),
59
+ "%"
60
+ ]
61
+ }
62
+ );
40
63
  return /* @__PURE__ */ jsxRuntime.jsxs(
41
64
  "div",
42
65
  {
@@ -47,57 +70,53 @@ var SCircleProgress = react.forwardRef(
47
70
  ),
48
71
  style,
49
72
  children: [
50
- /* @__PURE__ */ jsxRuntime.jsxs(
51
- "svg",
52
- {
53
- viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
54
- xmlns: "http://www.w3.org/2000/svg",
55
- className: cn("h-[80px] w-[80px]", indeterminate && "origin-center animate-circle-spin"),
56
- children: [
57
- /* @__PURE__ */ jsxRuntime.jsx(
58
- "circle",
59
- {
60
- cx: c,
61
- cy: c,
62
- r: RADIUS,
63
- fill: "none",
64
- strokeWidth: STROKE,
65
- style: { stroke: colors.track }
66
- }
73
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(innerValue && "relative"), children: [
74
+ /* @__PURE__ */ jsxRuntime.jsxs(
75
+ "svg",
76
+ {
77
+ viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
78
+ xmlns: "http://www.w3.org/2000/svg",
79
+ className: cn(
80
+ "h-[80px] w-[80px]",
81
+ indeterminate && "origin-center animate-circle-spin"
67
82
  ),
68
- /* @__PURE__ */ jsxRuntime.jsx(
69
- "circle",
70
- {
71
- cx: c,
72
- cy: c,
73
- r: RADIUS,
74
- fill: "none",
75
- strokeWidth: STROKE,
76
- strokeLinecap: "round",
77
- className: cn(
78
- "origin-center",
79
- indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
80
- ),
81
- style: {
82
- stroke: colors.arc,
83
- ...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
83
+ children: [
84
+ /* @__PURE__ */ jsxRuntime.jsx(
85
+ "circle",
86
+ {
87
+ cx: c,
88
+ cy: c,
89
+ r: RADIUS,
90
+ fill: "none",
91
+ strokeWidth: STROKE,
92
+ style: { stroke: colors.track }
93
+ }
94
+ ),
95
+ /* @__PURE__ */ jsxRuntime.jsx(
96
+ "circle",
97
+ {
98
+ cx: c,
99
+ cy: c,
100
+ r: RADIUS,
101
+ fill: "none",
102
+ strokeWidth: STROKE,
103
+ strokeLinecap: "round",
104
+ className: cn(
105
+ "origin-center",
106
+ indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
107
+ ),
108
+ style: {
109
+ stroke: colors.arc,
110
+ ...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
111
+ }
84
112
  }
85
- }
86
- )
87
- ]
88
- }
89
- ),
90
- !indeterminate && /* @__PURE__ */ jsxRuntime.jsxs(
91
- "span",
92
- {
93
- className: "text-center text-[16px] font-bold leading-[26px]",
94
- style: { color: percentColor },
95
- children: [
96
- Math.round(v),
97
- "%"
98
- ]
99
- }
100
- ),
113
+ )
114
+ ]
115
+ }
116
+ ),
117
+ showPercent && innerValue && percentNode
118
+ ] }),
119
+ showPercent && !innerValue && percentNode,
101
120
  label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
102
121
  ]
103
122
  }