@iamfiro/design 0.0.0-stage → 0.3.0

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 (416) hide show
  1. package/AGENTS.md +82 -0
  2. package/README.md +15 -2
  3. package/agents/INDEX.md +157 -0
  4. package/agents/accordion/AGENTS.md +279 -0
  5. package/agents/action-bar/AGENTS.md +90 -0
  6. package/agents/alert/AGENTS.md +212 -0
  7. package/agents/alert-dialog/AGENTS.md +193 -0
  8. package/agents/app-shell/AGENTS.md +409 -0
  9. package/agents/area-chart/AGENTS.md +183 -0
  10. package/agents/aspect-ratio/AGENTS.md +143 -0
  11. package/agents/avatar/AGENTS.md +130 -0
  12. package/agents/badge/AGENTS.md +217 -0
  13. package/agents/bar-chart/AGENTS.md +386 -0
  14. package/agents/bar-list/AGENTS.md +223 -0
  15. package/agents/brand-icon/AGENTS.md +82 -0
  16. package/agents/breadcrumb/AGENTS.md +133 -0
  17. package/agents/button/AGENTS.md +195 -0
  18. package/agents/card/AGENTS.md +141 -0
  19. package/agents/card-frame/AGENTS.md +227 -0
  20. package/agents/chat-bubble/AGENTS.md +266 -0
  21. package/agents/chat-composer/AGENTS.md +251 -0
  22. package/agents/checkbox/AGENTS.md +113 -0
  23. package/agents/code-block/AGENTS.md +144 -0
  24. package/agents/color-dot/AGENTS.md +120 -0
  25. package/agents/color-picker/AGENTS.md +224 -0
  26. package/agents/colors/AGENTS.md +168 -0
  27. package/agents/combobox/AGENTS.md +218 -0
  28. package/agents/command-menu/AGENTS.md +169 -0
  29. package/agents/comment/AGENTS.md +206 -0
  30. package/agents/context-menu/AGENTS.md +303 -0
  31. package/agents/copy-button/AGENTS.md +84 -0
  32. package/agents/count-badge/AGENTS.md +115 -0
  33. package/agents/countdown/AGENTS.md +101 -0
  34. package/agents/data-grid/AGENTS.md +460 -0
  35. package/agents/date-picker/AGENTS.md +197 -0
  36. package/agents/delta/AGENTS.md +114 -0
  37. package/agents/description-list/AGENTS.md +251 -0
  38. package/agents/dialog/AGENTS.md +391 -0
  39. package/agents/drawer/AGENTS.md +471 -0
  40. package/agents/dropdown-menu/AGENTS.md +322 -0
  41. package/agents/dropzone/AGENTS.md +116 -0
  42. package/agents/elapsed/AGENTS.md +160 -0
  43. package/agents/empty-state/AGENTS.md +203 -0
  44. package/agents/file-chip/AGENTS.md +79 -0
  45. package/agents/file-icon/AGENTS.md +66 -0
  46. package/agents/file-upload/AGENTS.md +168 -0
  47. package/agents/filter-chips/AGENTS.md +167 -0
  48. package/agents/flag/AGENTS.md +67 -0
  49. package/agents/funnel-chart/AGENTS.md +131 -0
  50. package/agents/highlight/AGENTS.md +119 -0
  51. package/agents/hover-card/AGENTS.md +271 -0
  52. package/agents/icon-stack/AGENTS.md +120 -0
  53. package/agents/icon-tile/AGENTS.md +94 -0
  54. package/agents/inline-diff/AGENTS.md +211 -0
  55. package/agents/input/AGENTS.md +261 -0
  56. package/agents/kanban/AGENTS.md +352 -0
  57. package/agents/kbd/AGENTS.md +160 -0
  58. package/agents/layout/AGENTS.md +351 -0
  59. package/agents/line-chart/AGENTS.md +393 -0
  60. package/agents/link/AGENTS.md +53 -0
  61. package/agents/list/AGENTS.md +392 -0
  62. package/agents/marker/AGENTS.md +142 -0
  63. package/agents/masked-text/AGENTS.md +127 -0
  64. package/agents/menubar/AGENTS.md +276 -0
  65. package/agents/multi-select/AGENTS.md +159 -0
  66. package/agents/navigation-menu/AGENTS.md +315 -0
  67. package/agents/notice-stack/AGENTS.md +101 -0
  68. package/agents/number-stepper/AGENTS.md +96 -0
  69. package/agents/otp-input/AGENTS.md +162 -0
  70. package/agents/pagination/AGENTS.md +189 -0
  71. package/agents/phone-input/AGENTS.md +131 -0
  72. package/agents/pie-chart/AGENTS.md +243 -0
  73. package/agents/popover/AGENTS.md +190 -0
  74. package/agents/progress/AGENTS.md +273 -0
  75. package/agents/progress-tracker/AGENTS.md +305 -0
  76. package/agents/rating/AGENTS.md +165 -0
  77. package/agents/relative-time/AGENTS.md +103 -0
  78. package/agents/resizable/AGENTS.md +390 -0
  79. package/agents/scaled-preview/AGENTS.md +111 -0
  80. package/agents/scatter-chart/AGENTS.md +160 -0
  81. package/agents/scroll-area/AGENTS.md +271 -0
  82. package/agents/search-input/AGENTS.md +105 -0
  83. package/agents/segmented-control/AGENTS.md +153 -0
  84. package/agents/select/AGENTS.md +159 -0
  85. package/agents/selector-button/AGENTS.md +122 -0
  86. package/agents/sidebar/AGENTS.md +201 -0
  87. package/agents/skeleton/AGENTS.md +166 -0
  88. package/agents/slider/AGENTS.md +181 -0
  89. package/agents/social-login-button/AGENTS.md +156 -0
  90. package/agents/spark-chart/AGENTS.md +257 -0
  91. package/agents/sparkbar/AGENTS.md +92 -0
  92. package/agents/spinner/AGENTS.md +123 -0
  93. package/agents/split-view/AGENTS.md +290 -0
  94. package/agents/stat/AGENTS.md +138 -0
  95. package/agents/status-icon/AGENTS.md +243 -0
  96. package/agents/step-list/AGENTS.md +313 -0
  97. package/agents/table/AGENTS.md +286 -0
  98. package/agents/tabs/AGENTS.md +305 -0
  99. package/agents/tag-input/AGENTS.md +246 -0
  100. package/agents/time-picker/AGENTS.md +228 -0
  101. package/agents/timeline/AGENTS.md +1018 -0
  102. package/agents/toast/AGENTS.md +266 -0
  103. package/agents/toggle-group/AGENTS.md +216 -0
  104. package/agents/toolbar/AGENTS.md +277 -0
  105. package/agents/tooltip/AGENTS.md +154 -0
  106. package/agents/tracker/AGENTS.md +158 -0
  107. package/agents/tree-diagram/AGENTS.md +260 -0
  108. package/agents/tree-view/AGENTS.md +329 -0
  109. package/agents/typography/AGENTS.md +396 -0
  110. package/lib/components/Accordion/Accordion2.js +135 -0
  111. package/lib/components/ActionBar/ActionBar2.js +65 -0
  112. package/lib/components/Alert/Alert2.js +131 -0
  113. package/lib/components/AppShell/AppShell2.js +94 -0
  114. package/lib/components/AreaChart/AreaChart.js +59 -0
  115. package/lib/components/BarChart/BarChart2.js +243 -0
  116. package/lib/components/BarList/BarList2.js +172 -0
  117. package/lib/components/Breadcrumb/Breadcrumb2.js +87 -0
  118. package/lib/components/Calendar/Calendar2.js +309 -0
  119. package/lib/components/Calendar/DatePicker2.js +229 -0
  120. package/lib/components/Calendar/date.js +121 -0
  121. package/lib/components/Card/Card2.js +104 -0
  122. package/lib/components/CardFrame/CardFrame2.js +72 -0
  123. package/lib/components/Chart/ChartParts.js +150 -0
  124. package/lib/components/Chart/chart2.js +96 -0
  125. package/lib/components/Chart/useChartInteraction.js +94 -0
  126. package/lib/components/ChatBubble/ChatBubble2.js +174 -0
  127. package/lib/components/ChatBubble/formatChatTime.js +53 -0
  128. package/lib/components/ChatComposer/ChatComposer2.js +153 -0
  129. package/lib/components/CodeBlock/CodeBlock2.js +93 -0
  130. package/lib/components/CodeBlock/highlight.js +114 -0
  131. package/lib/components/ColorPicker/ColorPicker2.js +610 -0
  132. package/lib/components/ColorPicker/color.js +180 -0
  133. package/lib/components/ColorPicker/presets.js +75 -0
  134. package/lib/components/Combobox/Combobox2.js +229 -0
  135. package/lib/components/CommandMenu/CommandMenu.js +267 -0
  136. package/lib/components/Comment/Comment2.js +134 -0
  137. package/lib/components/ContextMenu/ContextMenu2.js +168 -0
  138. package/lib/components/DataGrid/DataGrid2.js +1996 -0
  139. package/lib/components/DataGrid/GridPopover.js +154 -0
  140. package/lib/components/DataGrid/anchor.js +50 -0
  141. package/lib/components/DataGrid/model.js +558 -0
  142. package/lib/components/DataGrid/panels.js +703 -0
  143. package/lib/components/DataGrid/typeMeta.js +76 -0
  144. package/lib/components/DataGrid/types.js +54 -0
  145. package/lib/components/DescriptionList/DescriptionList2.js +180 -0
  146. package/lib/components/Dialog/AlertDialog.js +118 -0
  147. package/lib/components/Dialog/Dialog2.js +109 -0
  148. package/lib/components/Dialog/modal.js +92 -0
  149. package/lib/components/Drawer/Drawer2.js +244 -0
  150. package/lib/components/DropdownMenu/DropdownMenu2.js +394 -0
  151. package/lib/components/DropdownMenu/menuCore.js +63 -0
  152. package/lib/components/Dropzone/Dropzone2.js +144 -0
  153. package/lib/components/EmptyState/EmptyState2.js +72 -0
  154. package/lib/components/FileChip/FileChip2.js +118 -0
  155. package/lib/components/FileUpload/FileUpload.js +258 -0
  156. package/lib/components/FilterChips/FilterChips2.js +101 -0
  157. package/lib/components/FunnelChart/FunnelChart2.js +283 -0
  158. package/lib/components/FunnelChart/funnel.js +69 -0
  159. package/lib/components/Highlight/Highlight2.js +100 -0
  160. package/lib/components/HoverCard/HoverCard.js +134 -0
  161. package/lib/components/InlineDiff/InlineDiff2.js +215 -0
  162. package/lib/components/InlineDiff/diff.js +126 -0
  163. package/lib/components/InlineDiff/useDiffReview.js +109 -0
  164. package/lib/components/Kanban/Kanban2.js +691 -0
  165. package/lib/components/Kanban/KanbanCard.js +159 -0
  166. package/lib/components/Kanban/move.js +69 -0
  167. package/lib/components/LineChart/LineChart2.js +342 -0
  168. package/lib/components/List/List2.js +133 -0
  169. package/lib/components/Listbox/Listbox2.js +163 -0
  170. package/lib/components/Marker/Marker2.js +82 -0
  171. package/lib/components/Menubar/Menubar2.js +223 -0
  172. package/lib/components/MultiSelect/MultiSelect2.js +204 -0
  173. package/lib/components/NavigationMenu/NavigationMenu2.js +481 -0
  174. package/lib/components/NoticeStack/NoticeStack2.js +178 -0
  175. package/lib/components/NumberStepper/NumberStepper2.js +129 -0
  176. package/lib/components/OtpInput/OtpInput2.js +122 -0
  177. package/lib/components/Pagination/Pagination2.js +210 -0
  178. package/lib/components/Pagination/paginationRange.js +53 -0
  179. package/lib/components/PhoneInput/PhoneInput.js +175 -0
  180. package/lib/components/PieChart/PieChart2.js +246 -0
  181. package/lib/components/PieChart/arc.js +66 -0
  182. package/lib/components/PieChart/useArcTween.js +94 -0
  183. package/lib/components/Popover/Popover2.js +112 -0
  184. package/lib/components/ProgressTracker/ProgressTracker2.js +226 -0
  185. package/lib/components/Rating/Rating2.js +186 -0
  186. package/lib/components/Resizable/Resizable2.js +236 -0
  187. package/lib/components/Resizable/layout.js +115 -0
  188. package/lib/components/ScaledPreview/ScaledPreview2.js +100 -0
  189. package/lib/components/ScatterChart/ScatterChart2.js +356 -0
  190. package/lib/components/ScatterChart/scatter.js +83 -0
  191. package/lib/components/ScrollArea/ScrollArea2.js +218 -0
  192. package/lib/components/Select/Select2.js +153 -0
  193. package/lib/components/Sidebar/Sidebar2.js +127 -0
  194. package/lib/components/Skeleton/Skeleton2.js +91 -0
  195. package/lib/components/Slider/Slider2.js +142 -0
  196. package/lib/components/SocialLoginButton/SocialLoginButton.js +85 -0
  197. package/lib/components/SparkChart/SparkChart2.js +217 -0
  198. package/lib/components/SparkChart/spark.js +76 -0
  199. package/lib/components/Sparkbar/Sparkbar2.js +111 -0
  200. package/lib/components/SplitView/SplitView2.js +95 -0
  201. package/lib/components/Stat/Stat2.js +164 -0
  202. package/lib/components/StepList/StepList2.js +131 -0
  203. package/lib/components/Table/Table2.js +104 -0
  204. package/lib/components/Tabs/Tabs2.js +131 -0
  205. package/lib/components/TagInput/TagInput2.js +360 -0
  206. package/lib/components/TimePicker/TimePicker2.js +388 -0
  207. package/lib/components/TimePicker/time.js +83 -0
  208. package/lib/components/Timeline/Timeline2.js +369 -0
  209. package/lib/components/Timeline/scale.js +83 -0
  210. package/lib/components/Toast/Toaster.js +212 -0
  211. package/lib/components/Toast/store.js +129 -0
  212. package/lib/components/ToggleGroup/ToggleGroup2.js +125 -0
  213. package/lib/components/Toolbar/Toolbar2.js +281 -0
  214. package/lib/components/Tracker/Tracker2.js +172 -0
  215. package/lib/components/TreeDiagram/TreeDiagram2.js +223 -0
  216. package/lib/components/TreeView/TreeView2.js +284 -0
  217. package/lib/hooks/timing.js +55 -0
  218. package/lib/hooks/useControllableState.js +49 -0
  219. package/lib/hooks/useCountdown.js +80 -0
  220. package/lib/hooks/useDigitInput.js +105 -0
  221. package/lib/hooks/useDismiss.js +71 -0
  222. package/lib/hooks/useElapsed.js +83 -0
  223. package/lib/hooks/useFloating.js +70 -0
  224. package/lib/hooks/useFocusTrap.js +61 -0
  225. package/lib/hooks/usePresence.js +60 -0
  226. package/lib/hooks/usePressToOpen.js +69 -0
  227. package/lib/hooks/useScrollLock.js +70 -0
  228. package/lib/hooks/useSelection.js +68 -0
  229. package/lib/index.js +178 -0
  230. package/lib/primitives/AspectRatio2.js +80 -0
  231. package/lib/primitives/BrandIcon.js +245 -0
  232. package/lib/primitives/ColorDot2.js +70 -0
  233. package/lib/primitives/CopyButton2.js +85 -0
  234. package/lib/primitives/CountBadge2.js +78 -0
  235. package/lib/primitives/Countdown2.js +65 -0
  236. package/lib/primitives/Delta2.js +67 -0
  237. package/lib/primitives/Elapsed.js +62 -0
  238. package/lib/primitives/FileIcon2.js +125 -0
  239. package/lib/primitives/Flag2.js +263 -0
  240. package/lib/primitives/IconStack2.js +85 -0
  241. package/lib/primitives/IconTile2.js +68 -0
  242. package/lib/primitives/Kbd2.js +88 -0
  243. package/lib/primitives/Layout2.js +118 -0
  244. package/lib/primitives/Link2.js +53 -0
  245. package/lib/primitives/MaskedText2.js +120 -0
  246. package/lib/primitives/Progress2.js +137 -0
  247. package/lib/primitives/RelativeTime.js +84 -0
  248. package/lib/primitives/SearchInput2.js +84 -0
  249. package/lib/primitives/SelectorButton2.js +97 -0
  250. package/lib/primitives/Spinner2.js +98 -0
  251. package/lib/primitives/StatusIcon2.js +126 -0
  252. package/lib/primitives/Swatch2.js +79 -0
  253. package/lib/primitives/Tooltip2.js +132 -0
  254. package/lib/primitives/Typography2.js +97 -0
  255. package/lib/primitives/formatCountdown.js +51 -0
  256. package/lib/primitives/formatElapsed.js +66 -0
  257. package/lib/primitives/formatRelativeTime.js +64 -0
  258. package/lib/primitives/hotkey.js +94 -0
  259. package/lib/primitives/index.js +352 -0
  260. package/lib/primitives/maskValue.js +65 -0
  261. package/lib/style.css +2 -0
  262. package/lib/types/components/Accordion/Accordion.d.ts +57 -0
  263. package/lib/types/components/ActionBar/ActionBar.d.ts +24 -0
  264. package/lib/types/components/Alert/Alert.d.ts +36 -0
  265. package/lib/types/components/AppShell/AppShell.d.ts +38 -0
  266. package/lib/types/components/AreaChart/AreaChart.d.ts +17 -0
  267. package/lib/types/components/BarChart/BarChart.d.ts +57 -0
  268. package/lib/types/components/BarList/BarList.d.ts +56 -0
  269. package/lib/types/components/Breadcrumb/Breadcrumb.d.ts +15 -0
  270. package/lib/types/components/Calendar/Calendar.d.ts +34 -0
  271. package/lib/types/components/Calendar/DatePicker.d.ts +45 -0
  272. package/lib/types/components/Calendar/date.d.ts +32 -0
  273. package/lib/types/components/Card/Card.d.ts +64 -0
  274. package/lib/types/components/CardFrame/CardFrame.d.ts +15 -0
  275. package/lib/types/components/Chart/ChartParts.d.ts +38 -0
  276. package/lib/types/components/Chart/chart.d.ts +46 -0
  277. package/lib/types/components/Chart/useChartInteraction.d.ts +39 -0
  278. package/lib/types/components/ChatBubble/ChatBubble.d.ts +61 -0
  279. package/lib/types/components/ChatBubble/formatChatTime.d.ts +2 -0
  280. package/lib/types/components/ChatComposer/ChatComposer.d.ts +42 -0
  281. package/lib/types/components/CodeBlock/CodeBlock.d.ts +18 -0
  282. package/lib/types/components/CodeBlock/highlight.d.ts +10 -0
  283. package/lib/types/components/ColorPicker/ColorPicker.d.ts +61 -0
  284. package/lib/types/components/ColorPicker/color.d.ts +48 -0
  285. package/lib/types/components/ColorPicker/presets.d.ts +7 -0
  286. package/lib/types/components/Combobox/Combobox.d.ts +48 -0
  287. package/lib/types/components/CommandMenu/CommandMenu.d.ts +51 -0
  288. package/lib/types/components/Comment/Comment.d.ts +45 -0
  289. package/lib/types/components/ContextMenu/ContextMenu.d.ts +40 -0
  290. package/lib/types/components/DataGrid/DataGrid.d.ts +43 -0
  291. package/lib/types/components/DataGrid/GridPopover.d.ts +43 -0
  292. package/lib/types/components/DataGrid/anchor.d.ts +5 -0
  293. package/lib/types/components/DataGrid/model.d.ts +61 -0
  294. package/lib/types/components/DataGrid/panels.d.ts +63 -0
  295. package/lib/types/components/DataGrid/typeMeta.d.ts +6 -0
  296. package/lib/types/components/DataGrid/types.d.ts +77 -0
  297. package/lib/types/components/DescriptionList/DescriptionList.d.ts +77 -0
  298. package/lib/types/components/Dialog/AlertDialog.d.ts +26 -0
  299. package/lib/types/components/Dialog/Dialog.d.ts +42 -0
  300. package/lib/types/components/Dialog/modal.d.ts +38 -0
  301. package/lib/types/components/Drawer/Drawer.d.ts +62 -0
  302. package/lib/types/components/DropdownMenu/DropdownMenu.d.ts +97 -0
  303. package/lib/types/components/DropdownMenu/menuCore.d.ts +23 -0
  304. package/lib/types/components/Dropzone/Dropzone.d.ts +30 -0
  305. package/lib/types/components/EmptyState/EmptyState.d.ts +26 -0
  306. package/lib/types/components/FileChip/FileChip.d.ts +32 -0
  307. package/lib/types/components/FileUpload/FileUpload.d.ts +52 -0
  308. package/lib/types/components/FilterChips/FilterChips.d.ts +37 -0
  309. package/lib/types/components/FunnelChart/FunnelChart.d.ts +38 -0
  310. package/lib/types/components/FunnelChart/funnel.d.ts +25 -0
  311. package/lib/types/components/Highlight/Highlight.d.ts +35 -0
  312. package/lib/types/components/HoverCard/HoverCard.d.ts +47 -0
  313. package/lib/types/components/InlineDiff/InlineDiff.d.ts +36 -0
  314. package/lib/types/components/InlineDiff/diff.d.ts +42 -0
  315. package/lib/types/components/InlineDiff/useDiffReview.d.ts +57 -0
  316. package/lib/types/components/Kanban/Kanban.d.ts +64 -0
  317. package/lib/types/components/Kanban/KanbanCard.d.ts +35 -0
  318. package/lib/types/components/Kanban/move.d.ts +25 -0
  319. package/lib/types/components/LineChart/LineChart.d.ts +85 -0
  320. package/lib/types/components/List/List.d.ts +62 -0
  321. package/lib/types/components/Listbox/Listbox.d.ts +60 -0
  322. package/lib/types/components/Marker/Marker.d.ts +28 -0
  323. package/lib/types/components/Menubar/Menubar.d.ts +50 -0
  324. package/lib/types/components/MultiSelect/MultiSelect.d.ts +38 -0
  325. package/lib/types/components/NavigationMenu/NavigationMenu.d.ts +101 -0
  326. package/lib/types/components/NoticeStack/NoticeStack.d.ts +41 -0
  327. package/lib/types/components/NumberStepper/NumberStepper.d.ts +32 -0
  328. package/lib/types/components/OtpInput/OtpInput.d.ts +31 -0
  329. package/lib/types/components/Pagination/Pagination.d.ts +54 -0
  330. package/lib/types/components/Pagination/paginationRange.d.ts +7 -0
  331. package/lib/types/components/PhoneInput/PhoneInput.d.ts +47 -0
  332. package/lib/types/components/PieChart/PieChart.d.ts +67 -0
  333. package/lib/types/components/PieChart/arc.d.ts +26 -0
  334. package/lib/types/components/PieChart/useArcTween.d.ts +15 -0
  335. package/lib/types/components/Popover/Popover.d.ts +28 -0
  336. package/lib/types/components/ProgressTracker/ProgressTracker.d.ts +64 -0
  337. package/lib/types/components/Rating/Rating.d.ts +42 -0
  338. package/lib/types/components/Resizable/Resizable.d.ts +50 -0
  339. package/lib/types/components/Resizable/layout.d.ts +31 -0
  340. package/lib/types/components/ScaledPreview/ScaledPreview.d.ts +38 -0
  341. package/lib/types/components/ScatterChart/ScatterChart.d.ts +81 -0
  342. package/lib/types/components/ScatterChart/scatter.d.ts +14 -0
  343. package/lib/types/components/ScrollArea/ScrollArea.d.ts +34 -0
  344. package/lib/types/components/Select/Select.d.ts +39 -0
  345. package/lib/types/components/Sidebar/Sidebar.d.ts +39 -0
  346. package/lib/types/components/Skeleton/Skeleton.d.ts +47 -0
  347. package/lib/types/components/Slider/Slider.d.ts +36 -0
  348. package/lib/types/components/SocialLoginButton/SocialLoginButton.d.ts +10 -0
  349. package/lib/types/components/SparkChart/SparkChart.d.ts +55 -0
  350. package/lib/types/components/SparkChart/spark.d.ts +16 -0
  351. package/lib/types/components/Sparkbar/Sparkbar.d.ts +39 -0
  352. package/lib/types/components/SplitView/SplitView.d.ts +31 -0
  353. package/lib/types/components/Stat/Stat.d.ts +58 -0
  354. package/lib/types/components/StepList/StepList.d.ts +61 -0
  355. package/lib/types/components/Table/Table.d.ts +39 -0
  356. package/lib/types/components/Tabs/Tabs.d.ts +47 -0
  357. package/lib/types/components/TagInput/TagInput.d.ts +46 -0
  358. package/lib/types/components/TimePicker/TimePicker.d.ts +43 -0
  359. package/lib/types/components/TimePicker/time.d.ts +15 -0
  360. package/lib/types/components/Timeline/Timeline.d.ts +154 -0
  361. package/lib/types/components/Timeline/scale.d.ts +22 -0
  362. package/lib/types/components/Toast/Toaster.d.ts +19 -0
  363. package/lib/types/components/Toast/index.d.ts +4 -0
  364. package/lib/types/components/Toast/store.d.ts +75 -0
  365. package/lib/types/components/ToggleGroup/ToggleGroup.d.ts +28 -0
  366. package/lib/types/components/Toolbar/Toolbar.d.ts +70 -0
  367. package/lib/types/components/Tracker/Tracker.d.ts +43 -0
  368. package/lib/types/components/TreeDiagram/TreeDiagram.d.ts +68 -0
  369. package/lib/types/components/TreeView/TreeView.d.ts +107 -0
  370. package/lib/types/components/index.d.ts +188 -0
  371. package/lib/types/hooks/index.d.ts +17 -0
  372. package/lib/types/hooks/timing.d.ts +29 -0
  373. package/lib/types/hooks/useControllableState.d.ts +5 -0
  374. package/lib/types/hooks/useCountdown.d.ts +19 -0
  375. package/lib/types/hooks/useDigitInput.d.ts +24 -0
  376. package/lib/types/hooks/useDismiss.d.ts +3 -0
  377. package/lib/types/hooks/useElapsed.d.ts +28 -0
  378. package/lib/types/hooks/useFloating.d.ts +21 -0
  379. package/lib/types/hooks/useFocusTrap.d.ts +7 -0
  380. package/lib/types/hooks/usePresence.d.ts +8 -0
  381. package/lib/types/hooks/usePressToOpen.d.ts +20 -0
  382. package/lib/types/hooks/useScrollLock.d.ts +2 -0
  383. package/lib/types/hooks/useSelection.d.ts +29 -0
  384. package/lib/types/index.d.ts +5 -0
  385. package/lib/types/primitives/AspectRatio.d.ts +14 -0
  386. package/lib/types/primitives/BrandIcon.d.ts +12 -0
  387. package/lib/types/primitives/ColorDot.d.ts +20 -0
  388. package/lib/types/primitives/CopyButton.d.ts +12 -0
  389. package/lib/types/primitives/CountBadge.d.ts +28 -0
  390. package/lib/types/primitives/Countdown.d.ts +21 -0
  391. package/lib/types/primitives/Delta.d.ts +33 -0
  392. package/lib/types/primitives/Elapsed.d.ts +23 -0
  393. package/lib/types/primitives/FileIcon.d.ts +17 -0
  394. package/lib/types/primitives/Flag.d.ts +15 -0
  395. package/lib/types/primitives/IconStack.d.ts +27 -0
  396. package/lib/types/primitives/IconTile.d.ts +24 -0
  397. package/lib/types/primitives/Kbd.d.ts +19 -0
  398. package/lib/types/primitives/Layout.d.ts +64 -0
  399. package/lib/types/primitives/Link.d.ts +12 -0
  400. package/lib/types/primitives/MaskedText.d.ts +28 -0
  401. package/lib/types/primitives/Progress.d.ts +52 -0
  402. package/lib/types/primitives/RelativeTime.d.ts +22 -0
  403. package/lib/types/primitives/SearchInput.d.ts +8 -0
  404. package/lib/types/primitives/SelectorButton.d.ts +23 -0
  405. package/lib/types/primitives/Spinner.d.ts +15 -0
  406. package/lib/types/primitives/StatusIcon.d.ts +40 -0
  407. package/lib/types/primitives/Swatch.d.ts +11 -0
  408. package/lib/types/primitives/Tooltip.d.ts +17 -0
  409. package/lib/types/primitives/Typography.d.ts +48 -0
  410. package/lib/types/primitives/formatCountdown.d.ts +2 -0
  411. package/lib/types/primitives/formatElapsed.d.ts +8 -0
  412. package/lib/types/primitives/formatRelativeTime.d.ts +16 -0
  413. package/lib/types/primitives/hotkey.d.ts +10 -0
  414. package/lib/types/primitives/index.d.ts +188 -0
  415. package/lib/types/primitives/maskValue.d.ts +24 -0
  416. package/package.json +55 -4
@@ -0,0 +1,290 @@
1
+ # SplitView
2
+
3
+ > 컨테이너 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 목록 – 상세(master–detail) 두 칸 레이아웃. 왼쪽 목록과 오른쪽 상세가 각자 스크롤되고, 목록은 옅은 회색 판 위에 놓여 ListItem variant="raised"로 고른 행이 흰 카드처럼 떠올라요. resizable이면 가운데 경계를 끌거나, 포커스한 뒤 ← → 로 목록 너비를 바꿔요. 높이는 부모가 정해요.
6
+
7
+ ```tsx
8
+ import { SplitView } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 목록–상세는 `SplitView`(칸마다 스크롤, 경계는 `role="separator"`). 회색 판 위의 선택 행은 `ListItem variant="raised"`.
14
+
15
+ ## API
16
+
17
+ ### SplitView
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `list` (필수) | `ReactNode` | | 왼쪽 목록 칸. |
22
+ | `children` (필수) | `ReactNode` | | 오른쪽 상세 칸. 세로 flex라 ActionBar가 아래에 붙어요. |
23
+ | `listWidth` | `number` | | 목록 너비 px(제어). |
24
+ | `defaultListWidth` | `number` | `300` | 처음 너비(비제어). 더블 클릭 · Enter로 돌아가는 너비. |
25
+ | `onListWidthChange` | `(width: number) => void` | | 끌거나 키로 바꿀 때. |
26
+ | `minListWidth / maxListWidth` | `number` | `220 / 520` | 너비 범위. |
27
+ | `resizable` | `boolean` | | 경계를 끌어 너비 조절. role="separator"(aria-valuenow), ← → (Shift는 크게) · Home / End. |
28
+ | `listTone` | `'soft' \| 'plain'` | `'soft'` | soft: 목록 칸이 옅은 회색 판 · plain: 흰 바탕. |
29
+ | `listLabel / detailLabel` | `string` | `'목록' / '상세'` | 두 칸(section)의 접근성 이름. |
30
+ | `className / style` | `string / CSSProperties` | | 바깥 요소에 전달. 부모가 flex 세로면 style={{ flex: 1, minHeight: 0 }}. |
31
+
32
+ ## 예제
33
+
34
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
35
+
36
+ ### 검토 대기열
37
+
38
+ 위쪽은 제목 · 작은 진행 막대 · "26 / 33 검토" · 실행 취소(Z). 왼쪽은 개수가 붙은 Tabs와 요청 목록, 오른쪽은 요청 내용과 아래에 붙은 ActionBar(승인 A · 수정 E · 거절 R · 건너뛰기 S). 처리 중엔 버튼과 단축키가 잠기고, 끝나면 다음 요청이 골라져요.
39
+
40
+ ```tsx
41
+ import { useEffect, useState, type ReactNode } from 'react'
42
+ import { Check, ChevronsRight, CircleCheck, FileSignature, KeyRound, Pencil, Receipt, Undo2, UserPlus, X } from 'lucide-react'
43
+ import { Badge, Box, Button, Grid, IconTile, Inline, Progress, Stack, Text, ActionBar, Card, List, ListItem, SplitView, Tab, TabList, TabPanel, Tabs } from '@iamfiro/design'
44
+
45
+ interface ReviewItem {
46
+ id: string
47
+ icon: ReactNode
48
+ title: string
49
+ kind: string
50
+ time: string
51
+ from: string
52
+ risk?: boolean
53
+ note: string
54
+ amount: string
55
+ due: string
56
+ }
57
+
58
+ const REQUESTS: ReviewItem[] = [
59
+ { id: 'r1', icon: <Receipt />, title: '10월 법인 카드 정산', kind: '경비', time: '방금', from: '김민지', risk: true, note: '영수증 12장 중 2장의 금액이 카드 내역과 달라요.', amount: '1,248,000원', due: '10월 27일' },
60
+ { id: 'r2', icon: <UserPlus />, title: '이도현 님 관리자 권한 요청', kind: '권한', time: '14분', from: '이도현', note: '디자인팀 워크스페이스의 관리자 권한을 요청했어요.', amount: '—', due: '10월 26일' },
61
+ { id: 'r3', icon: <FileSignature />, title: '협력사 계약서 갱신', kind: '계약', time: '1시간', from: '김민지', note: '단가가 작년보다 4% 올랐어요. 나머지 조건은 같아요.', amount: '32,000,000원', due: '10월 31일' },
62
+ { id: 'r4', icon: <KeyRound />, title: '외부 공유 링크 허용', kind: '보안', time: '2시간', from: '이도현', risk: true, note: '고객사에 보낼 폴더를 링크로 공유하려고 해요.', amount: '—', due: '10월 25일' },
63
+ ]
64
+
65
+ const REVIEWED_BEFORE = 26
66
+ const TOTAL = REVIEWED_BEFORE + REQUESTS.length
67
+
68
+ export default function Example() {
69
+ const [queue, setQueue] = useState(REQUESTS)
70
+ const [done, setDone] = useState<ReviewItem[]>([])
71
+ const [tab, setTab] = useState('all')
72
+ const [selectedId, setSelectedId] = useState(REQUESTS[0].id)
73
+ const [pending, setPending] = useState(false)
74
+
75
+ const shown = tab === 'risk' ? queue.filter((r) => r.risk) : queue
76
+ const selected = queue.find((r) => r.id === selectedId) ?? shown[0]
77
+
78
+ // 데모용 처리: 0.6초 동안 잠갔다가 목록에서 빼고 다음 요청을 골라요.
79
+ useEffect(() => {
80
+ if (!pending || !selected) return
81
+ const id = window.setTimeout(() => {
82
+ const rest = queue.filter((r) => r.id !== selected.id)
83
+ setQueue(rest)
84
+ setDone((d) => [selected, ...d])
85
+ setSelectedId(rest[0]?.id ?? '')
86
+ setPending(false)
87
+ }, 600)
88
+ return () => window.clearTimeout(id)
89
+ }, [pending, selected, queue])
90
+
91
+ const undo = () => {
92
+ const [last, ...older] = done
93
+ if (!last) return
94
+ setDone(older)
95
+ setQueue((q) => REQUESTS.filter((r) => r.id === last.id || q.some((x) => x.id === r.id)))
96
+ setSelectedId(last.id)
97
+ }
98
+
99
+ const act = () => setPending(true)
100
+ const reviewed = REVIEWED_BEFORE + done.length
101
+
102
+ const rows = (items: ReviewItem[]) => (
103
+ <List density="compact" aria-label="검토할 요청">
104
+ {items.map((r) => (
105
+ <ListItem
106
+ key={r.id}
107
+ variant="raised"
108
+ selected={selected?.id === r.id}
109
+ onClick={() => setSelectedId(r.id)}
110
+ leading={<IconTile tone="surface">{r.icon}</IconTile>}
111
+ title={r.title}
112
+ description={r.kind}
113
+ meta={r.time}
114
+ />
115
+ ))}
116
+ </List>
117
+ )
118
+
119
+ return (
120
+ <Card padding="none" style={{ width: '100%', maxWidth: 880, height: 520 }}>
121
+ <Box paddingX={4} paddingY={3}>
122
+ <Inline justify="between" wrap={false}>
123
+ <Inline gap={2} wrap={false}>
124
+ <IconTile tone="accent" size={24}>
125
+ <CircleCheck />
126
+ </IconTile>
127
+ <Text variant="label-md">검토 센터</Text>
128
+ <Progress value={reviewed} max={TOTAL} size="sm" tone="accent" aria-label="검토 진행률" style={{ width: 72 }} />
129
+ <Text variant="label-sm" numeric>
130
+ {reviewed} / {TOTAL} 검토
131
+ </Text>
132
+ <Text variant="caption" tone="tertiary">
133
+ 가장 오래된 요청 2시간
134
+ </Text>
135
+ </Inline>
136
+ <Button variant="ghost" size="sm" icon={<Undo2 />} shortcut="Z" hotkey disabled={done.length === 0 || pending} onClick={undo}>
137
+ 실행 취소
138
+ </Button>
139
+ </Inline>
140
+ </Box>
141
+
142
+ <SplitView
143
+ resizable
144
+ defaultListWidth={300}
145
+ listLabel="요청 목록"
146
+ detailLabel="요청 내용"
147
+ style={{ flex: 1, minHeight: 0 }}
148
+ list={
149
+ <Tabs value={tab} onValueChange={setTab}>
150
+ <TabList size="sm" aria-label="요청 거르기">
151
+ <Tab value="all" count={queue.length}>
152
+ 전체
153
+ </Tab>
154
+ <Tab value="risk" count={queue.filter((r) => r.risk).length}>
155
+ 위험 높음
156
+ </Tab>
157
+ </TabList>
158
+ <TabPanel value="all">{rows(queue)}</TabPanel>
159
+ <TabPanel value="risk">{rows(queue.filter((r) => r.risk))}</TabPanel>
160
+ </Tabs>
161
+ }
162
+ >
163
+ {selected ? (
164
+ <>
165
+ <Box padding={5}>
166
+ <Stack gap={4}>
167
+ <Inline gap={2}>
168
+ <Text variant="label-md">{selected.from}</Text>
169
+ {selected.risk && (
170
+ <Badge tone="danger" size="sm">
171
+ 위험 높음
172
+ </Badge>
173
+ )}
174
+ <Text variant="caption" tone="tertiary">
175
+ {selected.kind} · {selected.time} 전
176
+ </Text>
177
+ </Inline>
178
+ <Text variant="heading-sm">{selected.title}</Text>
179
+ <Text variant="body-md" tone="secondary">
180
+ {selected.note}
181
+ </Text>
182
+ <Grid columns={2} gap={4} style={{ maxWidth: 360 }}>
183
+ <Stack gap={1}>
184
+ <Text variant="caption" tone="tertiary">
185
+ 금액
186
+ </Text>
187
+ <Text variant="label-md" numeric>
188
+ {selected.amount}
189
+ </Text>
190
+ </Stack>
191
+ <Stack gap={1}>
192
+ <Text variant="caption" tone="tertiary">
193
+ 기한
194
+ </Text>
195
+ <Text variant="label-md">{selected.due}</Text>
196
+ </Stack>
197
+ </Grid>
198
+ </Stack>
199
+ </Box>
200
+ <ActionBar pending={pending} aria-label="요청 처리">
201
+ <Button variant="primary" icon={<Check />} shortcut="A" hotkey loading={pending} onClick={act}>
202
+ 승인
203
+ </Button>
204
+ <Button variant="ghost" icon={<Pencil />} shortcut="E" hotkey onClick={act}>
205
+ 수정
206
+ </Button>
207
+ <Button variant="ghost" icon={<X />} shortcut="R" hotkey onClick={act}>
208
+ 거절
209
+ </Button>
210
+ <Button variant="ghost" icon={<ChevronsRight />} shortcut="S" hotkey onClick={act}>
211
+ 건너뛰기
212
+ </Button>
213
+ </ActionBar>
214
+ </>
215
+ ) : (
216
+ <Box padding={6}>
217
+ <Text variant="body-md" tone="tertiary" align="center">
218
+ 모든 요청을 검토했어요.
219
+ </Text>
220
+ </Box>
221
+ )}
222
+ </SplitView>
223
+ </Card>
224
+ )
225
+ }
226
+ ```
227
+
228
+ ### 너비 제어
229
+
230
+ listWidth / onListWidthChange로 제어해요. 경계를 끄는 동안엔 포인터를 그대로 따르고, 키보드 · 버튼으로 바꾸면 부드럽게 움직여요. 끄는 중 Esc는 원래 너비로, 더블 클릭 · Enter는 기본 너비로 돌아가요.
231
+
232
+ ```tsx
233
+ import { useState } from 'react'
234
+ import { Bell, Lock, User } from 'lucide-react'
235
+ import { Box, Button, Inline, Stack, Text, Card, List, ListItem, SplitView } from '@iamfiro/design'
236
+
237
+ const SECTIONS = [
238
+ { id: 'profile', icon: <User />, title: '프로필', body: '이름, 사진, 소개를 바꿔요. 김민지 님의 프로필은 팀원 모두에게 보여요.' },
239
+ { id: 'alarm', icon: <Bell />, title: '알림', body: '멘션과 승인 요청만 바로 알려 드리고, 나머지는 하루 한 번 모아서 보내요.' },
240
+ { id: 'security', icon: <Lock />, title: '보안', body: '2단계 인증이 켜져 있어요. 마지막 로그인은 10월 25일 오전 9시예요.' },
241
+ ]
242
+
243
+ export default function Example() {
244
+ const [width, setWidth] = useState(220)
245
+ const [selected, setSelected] = useState('profile')
246
+ const section = SECTIONS.find((s) => s.id === selected) ?? SECTIONS[0]
247
+ return (
248
+ <Stack gap={3} style={{ width: '100%', maxWidth: 640 }}>
249
+ <Inline gap={2}>
250
+ <Text variant="caption" tone="tertiary" numeric>
251
+ 목록 너비 {width}px
252
+ </Text>
253
+ <Button size="sm" variant="ghost" onClick={() => setWidth(180)}>
254
+ 좁게
255
+ </Button>
256
+ <Button size="sm" variant="ghost" onClick={() => setWidth(300)}>
257
+ 넓게
258
+ </Button>
259
+ </Inline>
260
+ <Card padding="none" style={{ height: 280 }}>
261
+ <SplitView
262
+ resizable
263
+ listWidth={width}
264
+ onListWidthChange={setWidth}
265
+ minListWidth={160}
266
+ maxListWidth={360}
267
+ listLabel="설정 목록"
268
+ detailLabel="설정 내용"
269
+ list={
270
+ <List aria-label="설정">
271
+ {SECTIONS.map((s) => (
272
+ <ListItem key={s.id} variant="raised" leading={s.icon} title={s.title} selected={selected === s.id} onClick={() => setSelected(s.id)} />
273
+ ))}
274
+ </List>
275
+ }
276
+ >
277
+ <Box padding={5}>
278
+ <Stack gap={2}>
279
+ <Text variant="heading-sm">{section.title}</Text>
280
+ <Text variant="body-md" tone="secondary">
281
+ {section.body}
282
+ </Text>
283
+ </Stack>
284
+ </Box>
285
+ </SplitView>
286
+ </Card>
287
+ </Stack>
288
+ )
289
+ }
290
+ ```
@@ -0,0 +1,138 @@
1
+ # Stat
2
+
3
+ > 데이터 표시 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 라벨과 숫자 하나. 옅은 라벨, 굵은 값, 옅은 "/ 전체"나 단위, 그리고 증감(Delta) 자리로 이뤄져요. 한 줄(inline)로 행 안에 넣거나, 라벨 위 큰 숫자(stacked)로 지표 띠를 만들어요. StatGroup은 여러 Stat을 옅은 세로선으로 나눠 한 줄에 놓고, 좁아지면 줄을 바꿔요.
6
+
7
+ ```tsx
8
+ import { Stat, StatGroup } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 표 칸 · KPI 카드의 작은 추이는 `SparkLine` · `SparkArea` · `Sparkbar`(같은 props, 하나로 고르면 `SparkChart type`). 축 없음, 실제 픽셀 크기로 그려 24–40px에서도 또렷하게, 값 범위는 0이 아니라 최솟값–최댓값. 색은 `tone="trend"` + `higherIs`(Delta와 같은 규칙), 마지막 값은 `endDot`. 긴 표에선 `tooltip={false}`로 이벤트 없는 정적 그림(`role="img"`). KPI 카드는 Card 안 `Stat` + `Delta` + `SparkArea`.
14
+ - 라벨 + 숫자는 `Stat`(한 줄 "시간 1:52 / 2:55" 또는 오버라인 라벨 위 큰 숫자), 지표 띠는 `StatGroup`(칸 사이 `Separator`, 줄이 바뀌어도 줄 첫 칸 앞엔 선 없음).
15
+ - 단독 개수 타일("완료 137 / 실패 3")은 `Stat tile icon iconTone`. 카드 · 팝오버 안의 옅은 회색 패널은 모서리 `--r-panel`(12px) + 여백 12px.
16
+
17
+ ## API
18
+
19
+ ### Stat
20
+
21
+ | prop | 타입 | 기본값 | 설명 |
22
+ | --- | --- | --- | --- |
23
+ | `label` (필수) | `ReactNode` | | 무엇을 잰 값인지. |
24
+ | `value` (필수) | `ReactNode` | | 형식을 맞춘 값("1:52", "₩8,500"). |
25
+ | `total` | `ReactNode` | | 값이 속한 전체. 옅게 "/ 전체"로 붙어요. |
26
+ | `unit` | `ReactNode` | | 값 뒤 옅은 단위("초", "건"). |
27
+ | `delta` | `ReactNode` | | 값 뒤 증감 자리. 보통 <Delta>. |
28
+ | `caption` | `ReactNode` | | 값 아래 옅은 한 줄(stacked). |
29
+ | `layout` | `'stacked' \| 'inline'` | `'stacked'` | 라벨 위 큰 숫자 / 한 줄. |
30
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 값 크기(number-sm · md · lg 역할). |
31
+ | `tone` | `TextTone` | `'default'` | 값 색. 오류가 있으면 danger 같은 식으로. |
32
+ | `tile` | `boolean` | | 옅은 회색 패널(--surface-active, 모서리 12, 여백 12)로 감싼 단독 타일. |
33
+ | `icon` | `ReactNode` | | 라벨 앞 작은 아이콘. IconTile 네모 안에 들어가요. |
34
+ | `iconTone` | `'neutral' \| 'accent' \| 'success' \| 'warning' \| 'danger'` | `'neutral'` | 아이콘 네모의 색. |
35
+ | `className` | `string` | | 추가 클래스. |
36
+ | `style` | `CSSProperties` | | 인라인 스타일. |
37
+
38
+ ### StatGroup
39
+
40
+ | prop | 타입 | 기본값 | 설명 |
41
+ | --- | --- | --- | --- |
42
+ | `children` (필수) | `ReactNode` | | Stat들(또는 아무 칸). |
43
+ | `gap` | `Space` | `6` | 칸 사이 간격. 세로선은 그 가운데에 놓여요. |
44
+ | `minItemWidth` | `number` | `96` | 칸의 최소 폭(px). 모자라면 줄을 바꿔요. |
45
+ | `fill` | `boolean` | `true` | 칸이 폭을 똑같이 나눠 가질지, 내용 폭만 쓸지. |
46
+ | `dividers` | `boolean` | `true` | 칸 사이 옅은 세로선. |
47
+ | `aria-label` | `string` | | 묶음 이름("배포 지표"). |
48
+
49
+ ## 예제
50
+
51
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
52
+
53
+ ### 한 줄
54
+
55
+ layout="inline": "시간 1:52 / 2:55"처럼 행 · 카드 아래쪽에 넣는 짧은 지표.
56
+
57
+ ```tsx
58
+ import { Delta, Inline, Stack, Stat } from '@iamfiro/design'
59
+
60
+ export default function Example() {
61
+ return (
62
+ <Stack gap={4}>
63
+ <Inline gap={5}>
64
+ <Stat layout="inline" label="시간" value="1:52" total="2:55" />
65
+ <Stat layout="inline" label="비용" value="₩8,500" total="₩10,300" />
66
+ <Stat layout="inline" label="완료" value="7" total="12" />
67
+ </Inline>
68
+ <Inline gap={5}>
69
+ <Stat layout="inline" size="sm" label="빌드" value="48" unit="초" delta={<Delta value={-6} higherIs="worse" format={(n) => `${n}초`} size="sm" />} />
70
+ <Stat layout="inline" size="sm" label="경고" value="3" unit="건" tone="warning" />
71
+ </Inline>
72
+ </Stack>
73
+ )
74
+ }
75
+ ```
76
+
77
+ ### 라벨 위 숫자
78
+
79
+ layout="stacked"(기본): 오버라인 라벨 + 큰 숫자. size로 숫자 크기를, delta로 증감을 붙여요.
80
+
81
+ ```tsx
82
+ import { Delta, Grid, Stat } from '@iamfiro/design'
83
+
84
+ export default function Example() {
85
+ return (
86
+ <Grid minItemWidth={160} gap={6} style={{ width: '100%' }}>
87
+ <Stat size="sm" label="이번 주 배포" value="14" unit="회" />
88
+ <Stat label="평균 리뷰 시간" value="3.2" unit="시간" delta={<Delta value={-0.8} higherIs="worse" format={(n) => `${n}시간`} size="sm" />} />
89
+ <Stat size="lg" label="활성 사용자" value="12,480" delta={<Delta value={4.2} format={(n) => `${n}%`} arrow size="sm" />} caption="지난주 11,977명" />
90
+ </Grid>
91
+ )
92
+ }
93
+ ```
94
+
95
+ ### 타일
96
+
97
+ tile: 옅은 회색 패널(모서리 12, 촘촘한 여백) 안의 Stat. icon은 라벨 앞 색 네모(IconTile)로 들어가고, iconTone으로 상태색을 고르며, 숫자 색은 tone으로 따로 정해요.
98
+
99
+ ```tsx
100
+ import { Check, Clock, X } from 'lucide-react'
101
+ import { Grid, Stat } from '@iamfiro/design'
102
+
103
+ export default function Example() {
104
+ return (
105
+ <Grid columns={3} gap={2} style={{ width: '100%', maxWidth: 420 }}>
106
+ <Stat tile icon={<Check />} iconTone="success" label="완료" value="137" />
107
+ <Stat tile icon={<X />} iconTone="danger" label="실패" value="3" tone="danger" />
108
+ <Stat tile icon={<Clock />} label="대기" value="12" unit="건" />
109
+ </Grid>
110
+ )
111
+ }
112
+ ```
113
+
114
+ ### StatGroup
115
+
116
+ 지표 띠. 칸 사이 세로선은 Separator이고, 줄이 바뀌어도 각 줄의 첫 칸 앞에는 선이 생기지 않아요. 미리보기 폭을 줄여 보세요.
117
+
118
+ ```tsx
119
+ import { Delta, Card, CardBody, CardHeader, Stat, StatGroup } from '@iamfiro/design'
120
+
121
+ export default function Example() {
122
+ return (
123
+ <Card style={{ width: '100%' }}>
124
+ <CardHeader title="배포 #1284" description="main · 10월 25일 오후 2:14" />
125
+ <CardBody>
126
+ <StatGroup aria-label="배포 지표">
127
+ <Stat label="소요 시간" value="25" unit="초" />
128
+ <Stat label="비용" value="₩2,500" />
129
+ <Stat label="요청" value="128" />
130
+ <Stat label="캐시 적중" value="92%" />
131
+ <Stat label="재시도" value="3" delta={<Delta value={2} higherIs="worse" size="sm" />} />
132
+ <Stat label="오류" value="0" />
133
+ </StatGroup>
134
+ </CardBody>
135
+ </Card>
136
+ )
137
+ }
138
+ ```
@@ -0,0 +1,243 @@
1
+ # StatusIcon
2
+
3
+ > 아이콘 & 아바타 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 체크리스트 · 일정 행 앞에 붙는 작은 단계 아이콘. 대기는 회색 점선 원, 진행 중은 파란 링(돌거나 채워짐), 완료는 회색 체크, 오류는 빨간 ×, 확인 필요는 주황 !예요. 모든 상태가 svg 하나에 들어 있어 상태가 바뀌면 링이 차오르고 체크가 그려지며 자연스럽게 넘어가요.
6
+
7
+ ```tsx
8
+ import { StatusIcon } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 단계 행 앞 아이콘은 `StatusIcon`(대기 = 회색 점선 원, 진행 = 파란 링, 완료 = 회색 체크, 오류 · 확인 필요). 상태마다 아이콘을 바꿔 끼우지 않고 한 svg 안에서 전환한다.
14
+ - 읽기 전용 단계 타임라인(계획 · 활동 기록 · 승인 흐름)은 `StepList`(`ol`, 마커 + 연결선, `meta` 시간, 아래 내용엔 Collapsible inline). 번호 원은 `StatusIcon number`(`persistNumber`면 모든 상태에서 번호). 사용자가 체크하는 목록은 `ProgressTracker`. 카드 아래 상태 띠는 `CardFooter band`.
15
+
16
+ ## API
17
+
18
+ ### StatusIcon
19
+
20
+ | prop | 타입 | 기본값 | 설명 |
21
+ | --- | --- | --- | --- |
22
+ | `status` (필수) | `'pending' \| 'active' \| 'done' \| 'error' \| 'warning'` | | 단계 상태. |
23
+ | `size` | `'sm' \| 'md' \| 'lg' \| number` | `'md'` | 크기(px 숫자도 가능). |
24
+ | `progress` | `number` | | active일 때 0–100. 생략하면 링이 계속 돌아요. |
25
+ | `colored` | `boolean` | | 완료를 회색 대신 초록으로. |
26
+ | `number` | `number \| string` | | 대기 상태를 회색 실선 원 + 번호("5")로. 다른 상태에선 링 · 기호로 넘어가요. |
27
+ | `persistNumber` | `boolean` | | number와 함께: 모든 상태에서 번호를 남기고 테두리가 상태 색(완료 회색 · 진행 파랑 · 오류 빨강 · 확인 주황)이 돼요. |
28
+ | `label` | `string` | | 스크린 리더가 읽을 이름. 기본은 "완료", "진행 중 40%"처럼 상태 이름이에요. |
29
+ | `decorative` | `boolean` | | 옆 글자가 이미 상태를 말할 때 스크린 리더에서 숨겨요. |
30
+ | `className` | `string` | | 추가 클래스. |
31
+ | `style` | `CSSProperties` | | 인라인 스타일. |
32
+
33
+ ## 예제
34
+
35
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
36
+
37
+ ### 상태
38
+
39
+ pending · active · done · error · warning. colored를 주면 완료가 초록이 돼요.
40
+
41
+ ```tsx
42
+ import { Inline, StatusIcon, Text, type StatusIconStatus } from '@iamfiro/design'
43
+
44
+ const STATES: Array<{ status: StatusIconStatus; label: string }> = [
45
+ { status: 'pending', label: '대기' },
46
+ { status: 'active', label: '진행 중' },
47
+ { status: 'done', label: '완료' },
48
+ { status: 'error', label: '오류' },
49
+ { status: 'warning', label: '확인 필요' },
50
+ ]
51
+
52
+ export default function Example() {
53
+ return (
54
+ <Inline gap={6}>
55
+ {STATES.map((s) => (
56
+ <Inline key={s.status} gap={2} wrap={false}>
57
+ <StatusIcon status={s.status} decorative />
58
+ <Text variant="label-sm">{s.label}</Text>
59
+ </Inline>
60
+ ))}
61
+ <Inline gap={2} wrap={false}>
62
+ <StatusIcon status="done" colored decorative />
63
+ <Text variant="label-sm">완료 (colored)</Text>
64
+ </Inline>
65
+ </Inline>
66
+ )
67
+ }
68
+ ```
69
+
70
+ ### 작업 단계
71
+
72
+ ListItem의 leading에 놓아 단계 목록을 만들어요. 버튼을 눌러 상태가 바뀌는 움직임을 확인해 보세요.
73
+
74
+ ```tsx
75
+ import { useState } from 'react'
76
+ import { Button, Inline, Stack, StatusIcon, type StatusIconStatus, List, ListItem } from '@iamfiro/design'
77
+
78
+ const STEPS = [
79
+ { id: 'lint', title: '코드 검사', description: '규칙 위반 0건' },
80
+ { id: 'test', title: '테스트', description: '412개 통과' },
81
+ { id: 'build', title: '빌드', description: '번들 크기 확인 중' },
82
+ { id: 'deploy', title: '운영 배포', description: '서울 리전' },
83
+ { id: 'notify', title: '팀에 알리기', description: '#release 채널' },
84
+ ]
85
+
86
+ export default function Example() {
87
+ // Index of the step in progress; steps before it are done.
88
+ const [current, setCurrent] = useState(2)
89
+ const [failed, setFailed] = useState(false)
90
+
91
+ const statusOf = (i: number): StatusIconStatus => {
92
+ if (i < current) return 'done'
93
+ if (i === current) return failed ? 'error' : 'active'
94
+ return 'pending'
95
+ }
96
+
97
+ return (
98
+ <Stack gap={4} style={{ width: '100%', maxWidth: 420 }}>
99
+ <List label="배포 단계">
100
+ {STEPS.map((s, i) => (
101
+ <ListItem
102
+ key={s.id}
103
+ leading={<StatusIcon status={statusOf(i)} />}
104
+ title={s.title}
105
+ description={i === current && failed ? '빌드 스크립트가 종료 코드 1로 끝났어요' : s.description}
106
+ />
107
+ ))}
108
+ </List>
109
+ <Inline gap={2}>
110
+ <Button
111
+ variant="primary"
112
+ size="sm"
113
+ disabled={current >= STEPS.length}
114
+ onClick={() => {
115
+ setFailed(false)
116
+ setCurrent((c) => c + 1)
117
+ }}
118
+ >
119
+ 다음 단계
120
+ </Button>
121
+ <Button size="sm" disabled={current >= STEPS.length} onClick={() => setFailed((f) => !f)}>
122
+ {failed ? '다시 시도' : '실패로 표시'}
123
+ </Button>
124
+ <Button
125
+ variant="ghost"
126
+ size="sm"
127
+ onClick={() => {
128
+ setFailed(false)
129
+ setCurrent(0)
130
+ }}
131
+ >
132
+ 처음부터
133
+ </Button>
134
+ </Inline>
135
+ </Stack>
136
+ )
137
+ }
138
+ ```
139
+
140
+ ### 번호
141
+
142
+ number를 주면 대기 상태가 점선 원 대신 회색 실선 원 + 번호가 돼요. 시작하면 링으로, 끝나면 체크로 넘어가요. persistNumber면 모든 상태에서 번호가 남고 테두리 색만 상태를 따라가요(번호 타임라인).
143
+
144
+ ```tsx
145
+ import { useState } from 'react'
146
+ import { Button, Inline, Stack, StatusIcon, Text, type StatusIconStatus } from '@iamfiro/design'
147
+
148
+ const ORDER: StatusIconStatus[] = ['pending', 'active', 'done']
149
+
150
+ export default function Example() {
151
+ const [step, setStep] = useState(0)
152
+ const status = ORDER[step]
153
+ return (
154
+ <Stack gap={5}>
155
+ <Inline gap={6}>
156
+ <Inline gap={2} wrap={false}>
157
+ <StatusIcon status="pending" number={5} size="lg" decorative />
158
+ <Text variant="label-sm">대기 (number)</Text>
159
+ </Inline>
160
+ <Inline gap={2} wrap={false}>
161
+ <StatusIcon status="pending" number={12} size="lg" decorative />
162
+ <Text variant="label-sm">두 자리</Text>
163
+ </Inline>
164
+ </Inline>
165
+ <Inline gap={4}>
166
+ {(['pending', 'active', 'done', 'error', 'warning'] as const).map((s, i) => (
167
+ <StatusIcon key={s} status={s} number={i + 1} persistNumber size="lg" />
168
+ ))}
169
+ <Text variant="label-sm" tone="secondary">
170
+ persistNumber
171
+ </Text>
172
+ </Inline>
173
+ <Inline gap={3}>
174
+ <StatusIcon status={status} number={3} size="lg" />
175
+ <Button size="sm" onClick={() => setStep((s) => (s + 1) % ORDER.length)}>
176
+ {status === 'pending' ? '시작하기' : status === 'active' ? '완료하기' : '처음으로'}
177
+ </Button>
178
+ </Inline>
179
+ </Stack>
180
+ )
181
+ }
182
+ ```
183
+
184
+ ### 진행률
185
+
186
+ active에 progress(0–100)를 주면 링이 그만큼 채워지고, 없으면 Spinner처럼 돌아요.
187
+
188
+ ```tsx
189
+ import { useState } from 'react'
190
+ import { Button, Inline, Stack, StatusIcon, Text } from '@iamfiro/design'
191
+
192
+ export default function Example() {
193
+ const [progress, setProgress] = useState(35)
194
+ const done = progress >= 100
195
+
196
+ return (
197
+ <Stack gap={4} align="start">
198
+ <Inline gap={6}>
199
+ <Inline gap={2} wrap={false}>
200
+ <StatusIcon status="active" size="lg" />
201
+ <Text variant="label-sm">파일 정리 중</Text>
202
+ </Inline>
203
+ <Inline gap={2} wrap={false}>
204
+ <StatusIcon status={done ? 'done' : 'active'} progress={progress} size="lg" />
205
+ <Text variant="label-sm" numeric>
206
+ {done ? '업로드 완료' : `업로드 ${progress}%`}
207
+ </Text>
208
+ </Inline>
209
+ </Inline>
210
+ <Inline gap={2}>
211
+ <Button size="sm" disabled={done} onClick={() => setProgress((p) => Math.min(100, p + 25))}>
212
+ 25% 올리기
213
+ </Button>
214
+ <Button variant="ghost" size="sm" onClick={() => setProgress(0)}>
215
+ 초기화
216
+ </Button>
217
+ </Inline>
218
+ </Stack>
219
+ )
220
+ }
221
+ ```
222
+
223
+ ### 크기
224
+
225
+ sm 14 · md 16 · lg 20px, 또는 px 숫자. 텍스트 옆에서도 찌그러지지 않아요(flex: none).
226
+
227
+ ```tsx
228
+ import { Inline, StatusIcon } from '@iamfiro/design'
229
+
230
+ export default function Example() {
231
+ return (
232
+ <Inline gap={6}>
233
+ {(['sm', 'md', 'lg', 28] as const).map((size) => (
234
+ <Inline key={size} gap={2} wrap={false}>
235
+ <StatusIcon status="done" size={size} />
236
+ <StatusIcon status="active" progress={60} size={size} />
237
+ <StatusIcon status="pending" size={size} />
238
+ </Inline>
239
+ ))}
240
+ </Inline>
241
+ )
242
+ }
243
+ ```