@conscience-technology/ctds 0.0.0-stage → 0.1.1

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 (289) hide show
  1. package/README.md +128 -2
  2. package/assets/components/AppFrame/AppFrame.module.css +177 -0
  3. package/assets/components/AppFrame/AppFrame.tsx +93 -0
  4. package/assets/components/AppFrame/index.ts +6 -0
  5. package/assets/components/AttachmentChip/AttachmentChip.module.css +71 -0
  6. package/assets/components/AttachmentChip/AttachmentChip.tsx +74 -0
  7. package/assets/components/AttachmentChip/index.ts +2 -0
  8. package/assets/components/AttachmentThumb/AttachmentThumb.module.css +107 -0
  9. package/assets/components/AttachmentThumb/AttachmentThumb.tsx +91 -0
  10. package/assets/components/AttachmentThumb/index.ts +2 -0
  11. package/assets/components/Avatar/Avatar.module.css +167 -0
  12. package/assets/components/Avatar/Avatar.tsx +228 -0
  13. package/assets/components/Avatar/index.ts +2 -0
  14. package/assets/components/AvatarUpload/AvatarUpload.module.css +130 -0
  15. package/assets/components/AvatarUpload/AvatarUpload.tsx +139 -0
  16. package/assets/components/AvatarUpload/index.ts +2 -0
  17. package/assets/components/Badge/Badge.module.css +76 -0
  18. package/assets/components/Badge/Badge.tsx +68 -0
  19. package/assets/components/Badge/index.ts +2 -0
  20. package/assets/components/Breadcrumb/Breadcrumb.module.css +213 -0
  21. package/assets/components/Breadcrumb/Breadcrumb.tsx +279 -0
  22. package/assets/components/Breadcrumb/index.ts +8 -0
  23. package/assets/components/Button/Button.module.css +216 -0
  24. package/assets/components/Button/Button.tsx +149 -0
  25. package/assets/components/Button/index.ts +2 -0
  26. package/assets/components/Callout/Callout.module.css +146 -0
  27. package/assets/components/Callout/Callout.tsx +138 -0
  28. package/assets/components/Callout/index.ts +2 -0
  29. package/assets/components/ChatInput/ChatInput.module.css +254 -0
  30. package/assets/components/ChatInput/ChatInput.tsx +322 -0
  31. package/assets/components/ChatInput/ModelSelector.tsx +40 -0
  32. package/assets/components/ChatInput/SendButton.tsx +41 -0
  33. package/assets/components/ChatInput/index.ts +10 -0
  34. package/assets/components/Checkbox/Checkbox.module.css +66 -0
  35. package/assets/components/Checkbox/Checkbox.tsx +36 -0
  36. package/assets/components/Checkbox/index.ts +2 -0
  37. package/assets/components/Chip/Chip.module.css +128 -0
  38. package/assets/components/Chip/Chip.tsx +103 -0
  39. package/assets/components/Chip/index.ts +2 -0
  40. package/assets/components/ChoiceCard/ChoiceCard.module.css +142 -0
  41. package/assets/components/ChoiceCard/ChoiceCard.tsx +132 -0
  42. package/assets/components/ChoiceCard/index.ts +2 -0
  43. package/assets/components/ContextMenu/ContextMenu.module.css +102 -0
  44. package/assets/components/ContextMenu/ContextMenu.tsx +392 -0
  45. package/assets/components/ContextMenu/index.ts +9 -0
  46. package/assets/components/DatePicker/Calendar.tsx +234 -0
  47. package/assets/components/DatePicker/DESIGN_NOTES.md +106 -0
  48. package/assets/components/DatePicker/DESIGN_NOTES_TIME.md +125 -0
  49. package/assets/components/DatePicker/DatePicker.module.css +295 -0
  50. package/assets/components/DatePicker/DatePicker.tsx +387 -0
  51. package/assets/components/DatePicker/TimeSelector.tsx +69 -0
  52. package/assets/components/DatePicker/index.ts +8 -0
  53. package/assets/components/DatePicker/presets.ts +80 -0
  54. package/assets/components/DatePicker/utils.ts +148 -0
  55. package/assets/components/Disclosure/Disclosure.module.css +73 -0
  56. package/assets/components/Disclosure/Disclosure.tsx +129 -0
  57. package/assets/components/Disclosure/index.ts +6 -0
  58. package/assets/components/Drawer/Drawer.module.css +257 -0
  59. package/assets/components/Drawer/Drawer.tsx +126 -0
  60. package/assets/components/Drawer/index.ts +7 -0
  61. package/assets/components/EmptyState/EmptyState.module.css +102 -0
  62. package/assets/components/EmptyState/EmptyState.tsx +80 -0
  63. package/assets/components/EmptyState/index.ts +2 -0
  64. package/assets/components/FileIcon/FileIcon.module.css +66 -0
  65. package/assets/components/FileIcon/FileIcon.tsx +84 -0
  66. package/assets/components/FileIcon/fileExtMap.ts +112 -0
  67. package/assets/components/FileIcon/index.ts +9 -0
  68. package/assets/components/FilterButton/FilterButton.module.css +130 -0
  69. package/assets/components/FilterButton/FilterButton.tsx +94 -0
  70. package/assets/components/FilterButton/index.ts +2 -0
  71. package/assets/components/GalleryItem/GalleryItem.module.css +220 -0
  72. package/assets/components/GalleryItem/GalleryItem.tsx +163 -0
  73. package/assets/components/GalleryItem/index.ts +7 -0
  74. package/assets/components/Icon/Icon.tsx +616 -0
  75. package/assets/components/Icon/context.tsx +39 -0
  76. package/assets/components/Icon/index.ts +4 -0
  77. package/assets/components/IconButton/IconButton.module.css +109 -0
  78. package/assets/components/IconButton/IconButton.tsx +110 -0
  79. package/assets/components/IconButton/index.ts +2 -0
  80. package/assets/components/Input/Input.module.css +338 -0
  81. package/assets/components/Input/Input.tsx +371 -0
  82. package/assets/components/Input/index.ts +2 -0
  83. package/assets/components/ListItem/ListItem.module.css +318 -0
  84. package/assets/components/ListItem/ListItem.tsx +262 -0
  85. package/assets/components/ListItem/index.ts +9 -0
  86. package/assets/components/MenuItem/MenuItem.module.css +437 -0
  87. package/assets/components/MenuItem/MenuItem.tsx +529 -0
  88. package/assets/components/MenuItem/index.ts +8 -0
  89. package/assets/components/MetricCard/MetricCard.module.css +153 -0
  90. package/assets/components/MetricCard/MetricCard.tsx +140 -0
  91. package/assets/components/MetricCard/index.ts +2 -0
  92. package/assets/components/Modal/Modal.module.css +175 -0
  93. package/assets/components/Modal/Modal.tsx +98 -0
  94. package/assets/components/Modal/index.ts +2 -0
  95. package/assets/components/Onboarding/DocsIndex.tsx +82 -0
  96. package/assets/components/Onboarding/LayoutBuilder.tsx +160 -0
  97. package/assets/components/Onboarding/Onboarding.module.css +1394 -0
  98. package/assets/components/Onboarding/OnboardingAxisPanel.tsx +515 -0
  99. package/assets/components/Onboarding/OnboardingPage.tsx +1193 -0
  100. package/assets/components/Onboarding/PresetsGallery.tsx +65 -0
  101. package/assets/components/Onboarding/actions.ts +250 -0
  102. package/assets/components/Onboarding/index.ts +8 -0
  103. package/assets/components/Onboarding/palette.css +40 -0
  104. package/assets/components/Onboarding/wizardData.ts +265 -0
  105. package/assets/components/Pagination/Pagination.module.css +82 -0
  106. package/assets/components/Pagination/Pagination.tsx +248 -0
  107. package/assets/components/Pagination/index.ts +6 -0
  108. package/assets/components/ProgressBar/ProgressBar.module.css +64 -0
  109. package/assets/components/ProgressBar/ProgressBar.tsx +54 -0
  110. package/assets/components/ProgressBar/index.ts +2 -0
  111. package/assets/components/QuotationBar/QuotationBar.module.css +61 -0
  112. package/assets/components/QuotationBar/QuotationBar.tsx +48 -0
  113. package/assets/components/QuotationBar/index.ts +2 -0
  114. package/assets/components/Radio/Radio.module.css +63 -0
  115. package/assets/components/Radio/Radio.tsx +33 -0
  116. package/assets/components/Radio/index.ts +2 -0
  117. package/assets/components/Select/Select.module.css +151 -0
  118. package/assets/components/Select/Select.tsx +425 -0
  119. package/assets/components/Select/index.ts +10 -0
  120. package/assets/components/SelectableCard/SelectableCard.module.css +177 -0
  121. package/assets/components/SelectableCard/SelectableCard.tsx +83 -0
  122. package/assets/components/SelectableCard/index.ts +2 -0
  123. package/assets/components/Shortcut/Shortcut.module.css +56 -0
  124. package/assets/components/Shortcut/Shortcut.tsx +156 -0
  125. package/assets/components/Shortcut/index.ts +2 -0
  126. package/assets/components/Sidebar/Sidebar.module.css +242 -0
  127. package/assets/components/Sidebar/Sidebar.tsx +264 -0
  128. package/assets/components/Sidebar/index.ts +7 -0
  129. package/assets/components/SidebarSplit/SidebarSplit.module.css +126 -0
  130. package/assets/components/SidebarSplit/SidebarSplit.tsx +222 -0
  131. package/assets/components/SidebarSplit/index.ts +6 -0
  132. package/assets/components/Slider/Slider.module.css +120 -0
  133. package/assets/components/Slider/Slider.tsx +88 -0
  134. package/assets/components/Slider/index.ts +2 -0
  135. package/assets/components/SplitButton/SplitButton.module.css +190 -0
  136. package/assets/components/SplitButton/SplitButton.tsx +145 -0
  137. package/assets/components/SplitButton/index.ts +6 -0
  138. package/assets/components/Stepper/Stepper.module.css +182 -0
  139. package/assets/components/Stepper/Stepper.tsx +185 -0
  140. package/assets/components/Stepper/index.ts +2 -0
  141. package/assets/components/Switch/Switch.module.css +116 -0
  142. package/assets/components/Switch/Switch.tsx +58 -0
  143. package/assets/components/Switch/index.ts +2 -0
  144. package/assets/components/TableCell/TableCell.module.css +137 -0
  145. package/assets/components/TableCell/TableCellAvatar.tsx +42 -0
  146. package/assets/components/TableCell/TableCellBadge.tsx +23 -0
  147. package/assets/components/TableCell/TableCellIcon.tsx +39 -0
  148. package/assets/components/TableCell/TableCellImage.tsx +49 -0
  149. package/assets/components/TableCell/TableCellLink.tsx +33 -0
  150. package/assets/components/TableCell/TableCellMeter.tsx +55 -0
  151. package/assets/components/TableCell/TableCellNumber.tsx +43 -0
  152. package/assets/components/TableCell/TableCellText.tsx +30 -0
  153. package/assets/components/TableCell/index.ts +23 -0
  154. package/assets/components/TableHeader/TableHeader.module.css +287 -0
  155. package/assets/components/TableHeader/TableHeader.tsx +590 -0
  156. package/assets/components/TableHeader/index.ts +9 -0
  157. package/assets/components/TableRow/TableRow.module.css +290 -0
  158. package/assets/components/TableRow/TableRow.tsx +253 -0
  159. package/assets/components/TableRow/index.ts +8 -0
  160. package/assets/components/TableRowEdit/TableRowEdit.module.css +126 -0
  161. package/assets/components/TableRowEdit/TableRowEdit.tsx +247 -0
  162. package/assets/components/TableRowEdit/index.ts +2 -0
  163. package/assets/components/TableRowSelect/TableRowSelect.module.css +23 -0
  164. package/assets/components/TableRowSelect/TableRowSelect.tsx +175 -0
  165. package/assets/components/TableRowSelect/index.ts +2 -0
  166. package/assets/components/Tabs/Tabs.module.css +234 -0
  167. package/assets/components/Tabs/Tabs.tsx +426 -0
  168. package/assets/components/Tabs/index.ts +9 -0
  169. package/assets/components/Textarea/Textarea.module.css +318 -0
  170. package/assets/components/Textarea/Textarea.tsx +426 -0
  171. package/assets/components/Textarea/index.ts +7 -0
  172. package/assets/components/ThemeController.tsx +271 -0
  173. package/assets/components/TimePicker/TimePicker.module.css +317 -0
  174. package/assets/components/TimePicker/TimePicker.tsx +821 -0
  175. package/assets/components/TimePicker/index.ts +8 -0
  176. package/assets/components/TimePicker/utils.ts +115 -0
  177. package/assets/components/Toast/Toast.module.css +264 -0
  178. package/assets/components/Toast/Toast.tsx +243 -0
  179. package/assets/components/Toast/index.ts +15 -0
  180. package/assets/components/Toolbar/Toolbar.module.css +72 -0
  181. package/assets/components/Toolbar/Toolbar.tsx +75 -0
  182. package/assets/components/Toolbar/index.ts +2 -0
  183. package/assets/components/Tooltip/Tooltip.module.css +42 -0
  184. package/assets/components/Tooltip/Tooltip.tsx +332 -0
  185. package/assets/components/Tooltip/index.ts +2 -0
  186. package/assets/components/Topbar/Topbar.module.css +26 -0
  187. package/assets/components/Topbar/Topbar.tsx +47 -0
  188. package/assets/components/Topbar/index.ts +2 -0
  189. package/assets/components/_cn.ts +3 -0
  190. package/assets/components/_color.ts +48 -0
  191. package/assets/components/_data.ts +659 -0
  192. package/assets/components/_utils.css +19 -0
  193. package/assets/components/axisOptions.ts +24 -0
  194. package/assets/components/tokens.css +742 -0
  195. package/assets/prompts/GUIDE.md +251 -0
  196. package/assets/prompts/OVERRIDE.md +170 -0
  197. package/assets/prompts/PRINCIPLES.md +130 -0
  198. package/assets/prompts/axes/density.md +38 -0
  199. package/assets/prompts/axes/font.md +36 -0
  200. package/assets/prompts/axes/hue.md +36 -0
  201. package/assets/prompts/axes/icon.md +48 -0
  202. package/assets/prompts/axes/mode.md +50 -0
  203. package/assets/prompts/axes/motion.md +77 -0
  204. package/assets/prompts/axes/palette.md +35 -0
  205. package/assets/prompts/axes/shape.md +33 -0
  206. package/assets/prompts/axes/voice.md +54 -0
  207. package/assets/prompts/components/README.md +84 -0
  208. package/assets/prompts/components/app-frame.md +94 -0
  209. package/assets/prompts/components/attachment-chip.md +46 -0
  210. package/assets/prompts/components/attachment-thumb.md +49 -0
  211. package/assets/prompts/components/avatar.md +86 -0
  212. package/assets/prompts/components/badge.md +104 -0
  213. package/assets/prompts/components/breadcrumb.md +77 -0
  214. package/assets/prompts/components/button.md +99 -0
  215. package/assets/prompts/components/callout.md +81 -0
  216. package/assets/prompts/components/chat-input.md +84 -0
  217. package/assets/prompts/components/checkbox.md +46 -0
  218. package/assets/prompts/components/chip.md +84 -0
  219. package/assets/prompts/components/choice-card.md +127 -0
  220. package/assets/prompts/components/context-menu.md +145 -0
  221. package/assets/prompts/components/date-picker.md +104 -0
  222. package/assets/prompts/components/drawer.md +152 -0
  223. package/assets/prompts/components/empty-state.md +69 -0
  224. package/assets/prompts/components/file-icon.md +73 -0
  225. package/assets/prompts/components/filter-button.md +42 -0
  226. package/assets/prompts/components/form-field.md +74 -0
  227. package/assets/prompts/components/gallery-item.md +158 -0
  228. package/assets/prompts/components/icon-button.md +82 -0
  229. package/assets/prompts/components/icon.md +68 -0
  230. package/assets/prompts/components/input.md +95 -0
  231. package/assets/prompts/components/list-item.md +235 -0
  232. package/assets/prompts/components/menu-item.md +234 -0
  233. package/assets/prompts/components/metric-card.md +132 -0
  234. package/assets/prompts/components/modal.md +131 -0
  235. package/assets/prompts/components/pagination.md +92 -0
  236. package/assets/prompts/components/progress-bar.md +61 -0
  237. package/assets/prompts/components/quotation-bar.md +39 -0
  238. package/assets/prompts/components/radio.md +41 -0
  239. package/assets/prompts/components/select.md +104 -0
  240. package/assets/prompts/components/selectable-card.md +67 -0
  241. package/assets/prompts/components/shortcut.md +76 -0
  242. package/assets/prompts/components/sidebar.md +107 -0
  243. package/assets/prompts/components/slider.md +89 -0
  244. package/assets/prompts/components/split-button.md +71 -0
  245. package/assets/prompts/components/stepper.md +93 -0
  246. package/assets/prompts/components/switch.md +86 -0
  247. package/assets/prompts/components/table-cell.md +87 -0
  248. package/assets/prompts/components/table-header.md +157 -0
  249. package/assets/prompts/components/table-row-edit.md +129 -0
  250. package/assets/prompts/components/table-row-select.md +82 -0
  251. package/assets/prompts/components/table-row.md +156 -0
  252. package/assets/prompts/components/tabs.md +122 -0
  253. package/assets/prompts/components/textarea.md +105 -0
  254. package/assets/prompts/components/toast.md +149 -0
  255. package/assets/prompts/components/tooltip.md +71 -0
  256. package/assets/prompts/components/topbar.md +148 -0
  257. package/assets/prompts/primitives/emerge.md +43 -0
  258. package/assets/prompts/primitives/fade.md +31 -0
  259. package/assets/prompts/primitives/scale.md +32 -0
  260. package/assets/prompts/primitives/scroll.md +75 -0
  261. package/assets/prompts/primitives/slide.md +31 -0
  262. package/assets/prompts/themes/_SCHEMA.md +135 -0
  263. package/assets/prompts/themes/_TEMPLATE.md +73 -0
  264. package/assets/prompts/themes/expressive.md +118 -0
  265. package/assets/prompts/themes/pure.md +87 -0
  266. package/assets/prompts/themes/spare.md +73 -0
  267. package/assets/prompts/tokens/breakpoint.md +29 -0
  268. package/assets/prompts/tokens/color.md +78 -0
  269. package/assets/prompts/tokens/radius.md +33 -0
  270. package/assets/prompts/tokens/shadow.md +35 -0
  271. package/assets/prompts/tokens/spacing.md +86 -0
  272. package/assets/prompts/tokens/typography.md +76 -0
  273. package/assets/prompts/tokens/z-index.md +35 -0
  274. package/assets/public/expressive.png +0 -0
  275. package/assets/public/pure.png +0 -0
  276. package/assets/public/spare.png +0 -0
  277. package/assets/skill/SKILL.md +36 -0
  278. package/bin/ctds.js +76 -0
  279. package/package.json +35 -4
  280. package/src/commands/init.js +215 -0
  281. package/src/commands/update.js +275 -0
  282. package/src/utils/assets.js +78 -0
  283. package/src/utils/deps.js +51 -0
  284. package/src/utils/detect.js +47 -0
  285. package/src/utils/diff.js +52 -0
  286. package/src/utils/hash.js +16 -0
  287. package/src/utils/log.js +41 -0
  288. package/src/utils/meta.js +73 -0
  289. package/src/utils/prompt.js +28 -0
@@ -0,0 +1,137 @@
1
+ /* TableCell*
2
+ ───────────────────────────────────────────────────────────────
3
+ TableRow 셀 안쪽에 꽂히는 "콘텐츠 포맷터"들. 공통 레이아웃만.
4
+ 폭·정렬·padding은 상위 TableRow .cell에서 통제한다.
5
+
6
+ 토큰만 사용 — 색/시간/폰트 리터럴 금지.
7
+ */
8
+
9
+ /* 공용 inline-flex 베이스 — 모든 셀 포맷터가 상속.
10
+ overflow/mask는 상위 TableRow .cellInner가 책임 — 포맷터는 clipping을 두지 않는다.
11
+ (여기서 overflow:hidden을 주면 자식 mask가 중첩되어 fade가 깨짐). */
12
+ .base {
13
+ display: inline-flex;
14
+ align-items: center;
15
+ min-width: 0;
16
+ max-width: 100%;
17
+ gap: var(--space-1);
18
+ white-space: nowrap;
19
+ }
20
+
21
+ /* Text ─────────────────────────────────────────────────── */
22
+ .text {
23
+ white-space: nowrap;
24
+ color: inherit;
25
+ }
26
+
27
+ .textMuted { color: var(--fg-muted); }
28
+ .textStrong { color: var(--fg-strong); font-weight: var(--font-weight-medium); }
29
+ .textSubtle { color: var(--fg-subtle); }
30
+
31
+ /* Number — 숫자 셀. tabular-nums로 자릿수 정렬 안정. */
32
+ .number {
33
+ font-variant-numeric: tabular-nums;
34
+ white-space: nowrap;
35
+ }
36
+
37
+ /* 통화/단위 접미사는 fg-muted로 한 톤 약하게. */
38
+ .numberUnit {
39
+ color: var(--fg-muted);
40
+ margin-inline-start: var(--space-0_5);
41
+ }
42
+
43
+ /* 음수 하이라이트 — destructive 톤. */
44
+ .numberNegative {
45
+ color: var(--destructive);
46
+ }
47
+
48
+ /* Image cell — 썸네일 + 라벨.
49
+ 썸네일 ↔ 라벨 사이는 공용 base(--space-1)보다 넉넉하게 --space-2.
50
+ 아이콘·이미지 자리에 라벨이 바짝 붙으면 "그릇과 내용"의 리듬이 깨짐. */
51
+ .imageCell {
52
+ gap: var(--space-2);
53
+ }
54
+
55
+ /* Image thumb — 정사각/radius-sm 기본. src 없거나 로드 실패 시 빈 회색박스로 노출.
56
+ 셀 min-height를 넘기지 않도록 size로 받은 px 그대로 적용. */
57
+ .image {
58
+ display: inline-flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ overflow: hidden;
62
+ background: var(--bg-muted);
63
+ color: var(--fg-subtle);
64
+ flex-shrink: 0;
65
+ }
66
+
67
+ .imageImg {
68
+ display: block;
69
+ width: 100%;
70
+ height: 100%;
71
+ object-fit: cover;
72
+ }
73
+
74
+ /* Icon ───────────────────────────────────────────────────
75
+ 아이콘 ↔ 라벨 사이도 image/avatar와 같은 리듬으로 --space-2. */
76
+ .icon {
77
+ color: var(--fg);
78
+ gap: var(--space-2);
79
+ }
80
+
81
+ .iconMuted { color: var(--fg-muted); }
82
+ .iconSubtle { color: var(--fg-subtle); }
83
+ .iconStrong { color: var(--fg-strong); }
84
+ .iconAccent { color: var(--primary); }
85
+
86
+ /* Avatar ───────────────────────────────────────────────── */
87
+ .avatar {
88
+ /* 아바타 ↔ 이름 사이 간격 — 다른 리딩 요소(image/icon)보다 한 단계 넓게.
89
+ 사람 식별 셀은 "얼굴"과 "이름"이 분리된 두 정보라 숨 쉴 공간이 필요. */
90
+ gap: var(--space-3);
91
+ }
92
+
93
+ .avatarText {
94
+ display: inline-flex;
95
+ flex-direction: column;
96
+ min-width: 0;
97
+ line-height: var(--lh-sm);
98
+ }
99
+
100
+ .avatarSublabel {
101
+ color: var(--fg-muted);
102
+ font-size: var(--text-xs);
103
+ line-height: var(--lh-xs);
104
+ }
105
+
106
+ /* Meter ────────────────────────────────────────────────── */
107
+ .meter {
108
+ gap: var(--space-2);
109
+ }
110
+
111
+ .meterTrack {
112
+ position: relative;
113
+ display: inline-block;
114
+ height: var(--space-1_5);
115
+ background: var(--bg-muted);
116
+ border-radius: var(--radius-full);
117
+ overflow: hidden;
118
+ flex-shrink: 0;
119
+ }
120
+
121
+ .meterFill {
122
+ position: absolute;
123
+ inset-block: 0;
124
+ inset-inline-start: 0;
125
+ background: var(--primary);
126
+ border-radius: inherit;
127
+ }
128
+
129
+ .meterSuccess .meterFill { background: var(--success); }
130
+ .meterWarning .meterFill { background: var(--warning); }
131
+ .meterDestructive .meterFill { background: var(--destructive); }
132
+
133
+ .meterLabel {
134
+ color: var(--fg-muted);
135
+ font-variant-numeric: tabular-nums;
136
+ flex-shrink: 0;
137
+ }
@@ -0,0 +1,42 @@
1
+ import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
2
+
3
+ import { Avatar, type AvatarShape, type AvatarStatus } from "../Avatar";
4
+ import styles from "./TableCell.module.css";
5
+
6
+ export type TableCellAvatarProps = HTMLAttributes<HTMLSpanElement> & {
7
+ /** 이미지 URL. 로드 실패 시 이니셜/아이콘 폴백. */
8
+ src?: string;
9
+ /** 이름 — 이니셜 추출·tint seed·aria 라벨 공용. */
10
+ name?: string;
11
+ /** 이니셜 직접 지정 — name보다 우선. */
12
+ initials?: string;
13
+ /** circle(기본, 사람) / rounded(팀·조직·봇). */
14
+ shape?: AvatarShape;
15
+ /** 접속 상태 뱃지. 미지정 시 뱃지 없음. */
16
+ status?: AvatarStatus;
17
+ /** 아바타 오른쪽 라벨 — 보통 name 재사용. 다른 표시가 필요하면 ReactNode로. */
18
+ label?: ReactNode;
19
+ /** 라벨 아래쪽 보조 텍스트 — 이메일·역할 등. */
20
+ sublabel?: ReactNode;
21
+ };
22
+
23
+ export const TableCellAvatar = forwardRef<HTMLSpanElement, TableCellAvatarProps>(
24
+ function TableCellAvatar(
25
+ { className, src, name, initials, shape = "circle", status, label, sublabel, ...rest },
26
+ ref,
27
+ ) {
28
+ const cls = [styles.base, styles.avatar, className ?? ""].filter(Boolean).join(" ");
29
+ const resolvedLabel = label ?? name;
30
+ return (
31
+ <span ref={ref} className={cls} {...rest}>
32
+ <Avatar size="md" shape={shape} src={src} name={name} initials={initials} status={status} />
33
+ {(resolvedLabel != null || sublabel != null) && (
34
+ <span className={styles.avatarText}>
35
+ {resolvedLabel != null && <span className={styles.text}>{resolvedLabel}</span>}
36
+ {sublabel != null && <span className={styles.avatarSublabel}>{sublabel}</span>}
37
+ </span>
38
+ )}
39
+ </span>
40
+ );
41
+ },
42
+ );
@@ -0,0 +1,23 @@
1
+ import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
2
+
3
+ import { Badge, type BadgeStatus, type BadgeVariant } from "../Badge";
4
+ import styles from "./TableCell.module.css";
5
+
6
+ export type TableCellBadgeProps = HTMLAttributes<HTMLSpanElement> & {
7
+ children?: ReactNode;
8
+ status?: BadgeStatus;
9
+ variant?: BadgeVariant;
10
+ };
11
+
12
+ export const TableCellBadge = forwardRef<HTMLSpanElement, TableCellBadgeProps>(
13
+ function TableCellBadge({ className, children, status, variant = "soft", ...rest }, ref) {
14
+ const cls = [styles.base, className ?? ""].filter(Boolean).join(" ");
15
+ return (
16
+ <span ref={ref} className={cls} {...rest}>
17
+ <Badge size="sm" variant={variant} status={status}>
18
+ {children}
19
+ </Badge>
20
+ </span>
21
+ );
22
+ },
23
+ );
@@ -0,0 +1,39 @@
1
+ import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
2
+
3
+ import { Icon, type IconName } from "../Icon";
4
+ import styles from "./TableCell.module.css";
5
+
6
+ export type TableCellIconTone = "default" | "muted" | "subtle" | "strong" | "accent";
7
+
8
+ export type TableCellIconProps = HTMLAttributes<HTMLSpanElement> & {
9
+ /** 아이콘 이름. CTDS Icon 세트 기준. */
10
+ name: IconName;
11
+ /** 아이콘 옆 라벨. 미지정 시 아이콘만. */
12
+ label?: ReactNode;
13
+ /** 아이콘 톤. 셀 전반의 색을 결정. */
14
+ tone?: TableCellIconTone;
15
+ /** 아이콘 크기(px). 기본 16 — 셀 min-height 안쪽. */
16
+ size?: number;
17
+ };
18
+
19
+ const toneClass: Record<TableCellIconTone, string> = {
20
+ default: "",
21
+ muted: styles.iconMuted,
22
+ subtle: styles.iconSubtle,
23
+ strong: styles.iconStrong,
24
+ accent: styles.iconAccent,
25
+ };
26
+
27
+ export const TableCellIcon = forwardRef<HTMLSpanElement, TableCellIconProps>(
28
+ function TableCellIcon({ className, name, label, tone = "default", size = 16, ...rest }, ref) {
29
+ const cls = [styles.base, styles.icon, toneClass[tone], className ?? ""]
30
+ .filter(Boolean)
31
+ .join(" ");
32
+ return (
33
+ <span ref={ref} className={cls} {...rest}>
34
+ <Icon name={name} size={size} />
35
+ {label != null && <span className={styles.text}>{label}</span>}
36
+ </span>
37
+ );
38
+ },
39
+ );
@@ -0,0 +1,49 @@
1
+ import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
2
+
3
+ import styles from "./TableCell.module.css";
4
+
5
+ export type TableCellImageProps = HTMLAttributes<HTMLSpanElement> & {
6
+ src?: string;
7
+ alt?: string;
8
+ /** px 단위 정사각 썸네일 크기. 기본 24. 셀 min-height 안쪽에 들어가도록 상위에서 조정. */
9
+ size?: number;
10
+ /** 모양 — square(기본, radius-sm) / rounded(radius-md) / circle. */
11
+ shape?: "square" | "rounded" | "circle";
12
+ /** src 없을 때 또는 로드 실패 폴백 노드. 미지정 시 빈 회색박스(bg-muted). */
13
+ fallback?: ReactNode;
14
+ /** 썸네일 오른쪽 라벨 — 파일명·설명 등. */
15
+ label?: ReactNode;
16
+ };
17
+
18
+ const shapeRadius: Record<NonNullable<TableCellImageProps["shape"]>, string> = {
19
+ square: "var(--radius-sm)",
20
+ rounded: "var(--radius-md)",
21
+ /* circle은 전용 토큰 경유 — Shape soft 축에서 2xl로 캡된다(완전 원 과함 방지). */
22
+ circle: "var(--radius-image-circle)",
23
+ };
24
+
25
+ export const TableCellImage = forwardRef<HTMLSpanElement, TableCellImageProps>(
26
+ function TableCellImage(
27
+ { className, src, alt, size = 24, shape = "square", fallback, label, ...rest },
28
+ ref,
29
+ ) {
30
+ const cls = [styles.base, styles.imageCell, className ?? ""].filter(Boolean).join(" ");
31
+ const thumbStyle = {
32
+ width: size,
33
+ height: size,
34
+ borderRadius: shapeRadius[shape],
35
+ };
36
+ return (
37
+ <span ref={ref} className={cls} {...rest}>
38
+ <span className={styles.image} style={thumbStyle} aria-hidden={!alt || undefined}>
39
+ {src ? (
40
+ <img className={styles.imageImg} src={src} alt={alt ?? ""} />
41
+ ) : (
42
+ fallback
43
+ )}
44
+ </span>
45
+ {label != null && <span className={styles.text}>{label}</span>}
46
+ </span>
47
+ );
48
+ },
49
+ );
@@ -0,0 +1,33 @@
1
+ "use client";
2
+
3
+ import { forwardRef, type AnchorHTMLAttributes, type ReactNode } from "react";
4
+
5
+ import { Button } from "../Button";
6
+ import { Icon } from "../Icon";
7
+
8
+ export type TableCellLinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
9
+ children?: ReactNode;
10
+ /** 외부 링크 — target="_blank"·external 아이콘 자동 추가. */
11
+ external?: boolean;
12
+ };
13
+
14
+ /* 셀 안쪽 inline 링크. Button(ghost·xs) + asChild로 anchor를 감싸 — 셀의 "작은 액션"
15
+ 형태를 유지하면서 Button 토큰(hover·focus·ring)을 그대로 받는다.
16
+ xs size는 ghost 전용 제약 준수.
17
+ asChild 모드의 Slot은 자식이 정확히 하나여야 해서 Button의 rightIcon prop을 쓸 수 없음.
18
+ external 아이콘은 anchor 내부에 직접 꽂아 single child 조건을 지킨다.
19
+ ⚠ Navigate 모드 TableRow(href·onClick 있음) 안에서는 쓰지 않는다 — nested interactive. */
20
+ export const TableCellLink = forwardRef<HTMLAnchorElement, TableCellLinkProps>(
21
+ function TableCellLink({ children, external, href, target, rel, ...rest }, ref) {
22
+ const resolvedTarget = external ? (target ?? "_blank") : target;
23
+ const resolvedRel = external ? (rel ?? "noreferrer noopener") : rel;
24
+ return (
25
+ <Button asChild size="xs" variant="ghost">
26
+ <a ref={ref} href={href} target={resolvedTarget} rel={resolvedRel} {...rest}>
27
+ {children}
28
+ {external && <Icon name="arrow-square-out" aria-hidden />}
29
+ </a>
30
+ </Button>
31
+ );
32
+ },
33
+ );
@@ -0,0 +1,55 @@
1
+ import { forwardRef, type HTMLAttributes } from "react";
2
+
3
+ import styles from "./TableCell.module.css";
4
+
5
+ export type TableCellMeterTone = "default" | "success" | "warning" | "destructive";
6
+
7
+ export type TableCellMeterProps = HTMLAttributes<HTMLSpanElement> & {
8
+ /** 0~100. 범위 밖은 clamp. */
9
+ value: number;
10
+ /** 트랙 폭(px). 기본 80. 셀 폭에 맞춰 조정. */
11
+ width?: number;
12
+ /** 수치 라벨 위치 — right(기본), none. */
13
+ labelPosition?: "right" | "none";
14
+ /** 수치 표기 포맷. 기본 `{value}%`. */
15
+ format?: (value: number) => string;
16
+ /** 톤 — 상태 전달용. */
17
+ tone?: TableCellMeterTone;
18
+ };
19
+
20
+ const toneClass: Record<TableCellMeterTone, string> = {
21
+ default: "",
22
+ success: styles.meterSuccess,
23
+ warning: styles.meterWarning,
24
+ destructive: styles.meterDestructive,
25
+ };
26
+
27
+ export const TableCellMeter = forwardRef<HTMLSpanElement, TableCellMeterProps>(
28
+ function TableCellMeter(
29
+ { className, value, width = 80, labelPosition = "right", format, tone = "default", style, ...rest },
30
+ ref,
31
+ ) {
32
+ const clamped = Math.max(0, Math.min(100, value));
33
+ const text = (format ?? ((v: number) => `${Math.round(v)}%`))(clamped);
34
+ const cls = [styles.base, styles.meter, toneClass[tone], className ?? ""]
35
+ .filter(Boolean)
36
+ .join(" ");
37
+ return (
38
+ <span
39
+ ref={ref}
40
+ className={cls}
41
+ role="meter"
42
+ aria-valuemin={0}
43
+ aria-valuemax={100}
44
+ aria-valuenow={clamped}
45
+ style={style}
46
+ {...rest}
47
+ >
48
+ <span className={styles.meterTrack} style={{ width }}>
49
+ <span className={styles.meterFill} style={{ width: `${clamped}%` }} />
50
+ </span>
51
+ {labelPosition === "right" && <span className={styles.meterLabel}>{text}</span>}
52
+ </span>
53
+ );
54
+ },
55
+ );
@@ -0,0 +1,43 @@
1
+ import { forwardRef, type HTMLAttributes } from "react";
2
+
3
+ import styles from "./TableCell.module.css";
4
+
5
+ export type TableCellNumberProps = Omit<HTMLAttributes<HTMLSpanElement>, "children"> & {
6
+ value: number | string;
7
+ /** Intl.NumberFormat 옵션. value가 number일 때 적용. */
8
+ format?: Intl.NumberFormatOptions;
9
+ /** 로케일. 지정 안 하면 브라우저 기본. */
10
+ locale?: string;
11
+ /** 숫자 뒤에 붙는 단위(원·%·ms 등). fg-muted 톤으로 렌더. */
12
+ unit?: string;
13
+ /** 음수 하이라이트 — destructive 톤. */
14
+ highlightNegative?: boolean;
15
+ };
16
+
17
+ export const TableCellNumber = forwardRef<HTMLSpanElement, TableCellNumberProps>(
18
+ function TableCellNumber(
19
+ { className, value, format, locale, unit, highlightNegative, ...rest },
20
+ ref,
21
+ ) {
22
+ const numeric = typeof value === "number" ? value : Number(value);
23
+ const isNegative = highlightNegative && !Number.isNaN(numeric) && numeric < 0;
24
+ const text =
25
+ typeof value === "number"
26
+ ? new Intl.NumberFormat(locale, format).format(value)
27
+ : String(value);
28
+ const cls = [
29
+ styles.base,
30
+ styles.number,
31
+ isNegative ? styles.numberNegative : "",
32
+ className ?? "",
33
+ ]
34
+ .filter(Boolean)
35
+ .join(" ");
36
+ return (
37
+ <span ref={ref} className={cls} {...rest}>
38
+ <span>{text}</span>
39
+ {unit && <span className={styles.numberUnit}>{unit}</span>}
40
+ </span>
41
+ );
42
+ },
43
+ );
@@ -0,0 +1,30 @@
1
+ import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
2
+
3
+ import styles from "./TableCell.module.css";
4
+
5
+ export type TableCellTextTone = "default" | "strong" | "muted" | "subtle";
6
+
7
+ export type TableCellTextProps = HTMLAttributes<HTMLSpanElement> & {
8
+ tone?: TableCellTextTone;
9
+ children?: ReactNode;
10
+ };
11
+
12
+ const toneClass: Record<TableCellTextTone, string> = {
13
+ default: "",
14
+ strong: styles.textStrong,
15
+ muted: styles.textMuted,
16
+ subtle: styles.textSubtle,
17
+ };
18
+
19
+ export const TableCellText = forwardRef<HTMLSpanElement, TableCellTextProps>(
20
+ function TableCellText({ className, tone = "default", children, ...rest }, ref) {
21
+ const cls = [styles.base, styles.text, toneClass[tone], className ?? ""]
22
+ .filter(Boolean)
23
+ .join(" ");
24
+ return (
25
+ <span ref={ref} className={cls} {...rest}>
26
+ {children}
27
+ </span>
28
+ );
29
+ },
30
+ );
@@ -0,0 +1,23 @@
1
+ export { TableCellText } from "./TableCellText";
2
+ export type { TableCellTextProps, TableCellTextTone } from "./TableCellText";
3
+
4
+ export { TableCellNumber } from "./TableCellNumber";
5
+ export type { TableCellNumberProps } from "./TableCellNumber";
6
+
7
+ export { TableCellImage } from "./TableCellImage";
8
+ export type { TableCellImageProps } from "./TableCellImage";
9
+
10
+ export { TableCellBadge } from "./TableCellBadge";
11
+ export type { TableCellBadgeProps } from "./TableCellBadge";
12
+
13
+ export { TableCellIcon } from "./TableCellIcon";
14
+ export type { TableCellIconProps, TableCellIconTone } from "./TableCellIcon";
15
+
16
+ export { TableCellAvatar } from "./TableCellAvatar";
17
+ export type { TableCellAvatarProps } from "./TableCellAvatar";
18
+
19
+ export { TableCellLink } from "./TableCellLink";
20
+ export type { TableCellLinkProps } from "./TableCellLink";
21
+
22
+ export { TableCellMeter } from "./TableCellMeter";
23
+ export type { TableCellMeterProps, TableCellMeterTone } from "./TableCellMeter";