@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,111 @@
1
+ # ScaledPreview
2
+
3
+ > 파운데이션 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 실제 컴포넌트를 높이가 고정된 무대 가운데에 작게 줄여 보여 줘요. 갤러리 카드 · 템플릿 고르기 · 썸네일처럼 "이렇게 생겼어요"를 보여 줄 때 써요. 내용은 contentWidth 폭으로 배치한 뒤 무대에 맞게 줄고(최대 maxScale), 누르기 · 포커스 · 화면 읽기가 막힌 inert 상태예요. 왼쪽 위 흰 칩(label)과 오른쪽 위 회색 칩(meta)을 얹을 수 있고, lazy면 화면 근처에 있을 때만 실행해서 보이지 않는 미리보기가 타이머를 돌리지 않아요.
6
+
7
+ ```tsx
8
+ import { ScaledPreview } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 실제 컴포넌트를 작게 줄여 보여 주는 썸네일(갤러리 카드 · 템플릿 고르기)은 `ScaledPreview`(고정 높이 무대, 맞춰 줄이기, inert, `label` 흰 칩 · `meta` 회색 칩, 타이머가 도는 내용은 `lazy`로 보일 때만). 필터로 바뀌는 카드 격자는 `Grid stagger` + 필터 값을 `key`로.
14
+
15
+ ## API
16
+
17
+ ### ScaledPreview
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `children` (필수) | `ReactNode` | | 줄여 보여 줄 실제 내용. inert · aria-hidden이라 누를 수 없어요. |
22
+ | `height` | `number` | `320` | 무대 높이(px). |
23
+ | `contentWidth` | `number` | `520` | 줄이기 전 내용이 배치되는 폭(px). width: 100%인 내용이 자리를 갖게. |
24
+ | `maxScale` | `number` | `0.8` | 가장 큰 배율. 무대에 안 맞으면 더 줄어요. |
25
+ | `minScale` | `number` | `0.3` | 가장 작은 배율. 그래도 넘치면 무대 가장자리에서 잘려요. |
26
+ | `inset` | `number` | `24` | 줄인 내용과 무대 가장자리 사이 여백(px). |
27
+ | `label` | `ReactNode` | | 왼쪽 위 흰 칩(분류). |
28
+ | `meta` | `ReactNode` | | 오른쪽 위 회색 칩(개수 · 버전). |
29
+ | `lazy` | `boolean` | `false` | 화면 근처에 있을 때만 내용을 붙여요(IntersectionObserver). |
30
+ | `fallback` | `ReactNode` | `Skeleton` | lazy 미리보기가 화면 밖일 때 보여 줄 것. |
31
+ | `tone` | `'subtle' \| 'surface'` | `'subtle'` | subtle = 가장 옅은 회색 무대 · surface = 흰 무대(회색 판 안에서). |
32
+
33
+ ## 예제
34
+
35
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
36
+
37
+ ### 갤러리 카드
38
+
39
+ Card padding="sm" 안에 ScaledPreview + 제목 · 설명 · CopyButton. label = 분류, meta = 예제 개수.
40
+
41
+ ```tsx
42
+ import { Bell } from 'lucide-react'
43
+ import { Badge, Button, CopyButton, Inline, Stack, Text, Card, CardBody, CardHeader, ScaledPreview } from '@iamfiro/design'
44
+
45
+ export default function Example() {
46
+ return (
47
+ <Card padding="sm" style={{ width: '100%', maxWidth: 340 }}>
48
+ <CardBody>
49
+ <Stack gap={3}>
50
+ <ScaledPreview height={240} label="피드백" meta="예제 3개">
51
+ <Card variant="raised" style={{ width: 360 }}>
52
+ <CardHeader
53
+ icon={<Bell />}
54
+ title="새 댓글 3개"
55
+ description="김민지 님 외 2명이 3분기 메모에 댓글을 남겼어요."
56
+ actions={<Badge tone="accent">새 글</Badge>}
57
+ />
58
+ <CardBody>
59
+ <Inline gap={2} justify="end">
60
+ <Button size="sm" variant="secondary">
61
+ 나중에
62
+ </Button>
63
+ <Button size="sm" variant="primary">
64
+ 보기
65
+ </Button>
66
+ </Inline>
67
+ </CardBody>
68
+ </Card>
69
+ </ScaledPreview>
70
+ <Inline gap={2} justify="between" wrap={false}>
71
+ <Stack gap={0}>
72
+ <Text variant="label-lg">알림 카드</Text>
73
+ <Text variant="body-sm" tone="tertiary" truncate>
74
+ 새 소식을 알리고 바로 행동하게 하는 카드
75
+ </Text>
76
+ </Stack>
77
+ <CopyButton value={``} variant="secondary" />
78
+ </Inline>
79
+ </Stack>
80
+ </CardBody>
81
+ </Card>
82
+ )
83
+ }
84
+ ```
85
+
86
+ ### 보일 때만 실행
87
+
88
+ lazy면 무대가 화면에서 200px 안으로 들어올 때 내용을 붙이고, 멀어지면 떼어 내요. 그동안엔 Skeleton(또는 fallback)을 보여 줘요. 실시간 차트처럼 타이머가 도는 예제를 여러 개 늘어놓을 때 써요.
89
+
90
+ ```tsx
91
+ import { Grid, ScaledPreview, Sparkbar } from '@iamfiro/design'
92
+
93
+ const SERIES = [
94
+ [4, 6, 5, 8, 7, 9, 12, 10, 13, 15],
95
+ [9, 8, 10, 7, 6, 8, 5, 6, 4, 3],
96
+ [3, 5, 4, 6, 9, 8, 7, 10, 9, 11],
97
+ [6, 6, 7, 5, 8, 9, 7, 8, 10, 9],
98
+ ]
99
+
100
+ export default function Example() {
101
+ return (
102
+ <Grid minItemWidth={180} gap={3} style={{ width: '100%' }}>
103
+ {SERIES.map((data, i) => (
104
+ <ScaledPreview key={i} lazy height={140} contentWidth={240} meta={`#${i + 1}`}>
105
+ <Sparkbar data={data} />
106
+ </ScaledPreview>
107
+ ))}
108
+ </Grid>
109
+ )
110
+ }
111
+ ```
@@ -0,0 +1,160 @@
1
+ # ScatterChart
2
+
3
+ > 차트 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 두 값의 관계를 점으로 보여주는 산점도. sizeKey를 주면 넓이가 값에 비례하는 버블 차트가 되고, categoryKey로 점을 분류별 색으로 나눠요. 포인터에서 가장 가까운 점이 커지고 나머지는 흐려지며, 옆의 Card 툴팁에 분류와 x · y · 크기 값을 보여줘요. 점은 왼쪽부터 차례로 나타나요.
6
+
7
+ ```tsx
8
+ import { ScatterChart, type ScatterCategory } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 두 값의 관계는 `ScatterChart`(가장 가까운 점이 커지고 나머지는 흐려짐, 범례 클릭 = 분류 숨김 · 보임은 제자리에서 줄며 사라지기), 단계 전환은 `FunnelChart`(빠진 만큼은 앞 단계 색의 옅은 빗금, 한 색조 단계는 `gradient` = `--chart-seq-*`).
14
+
15
+ ## API
16
+
17
+ ### ScatterChart
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `data` (필수) | `ScatterChartRow[]` | | 행 목록. 한 행 = 점 하나. x · y가 숫자가 아닌 행은 건너뛰어요. |
22
+ | `xKey / yKey` (필수) | `string` | | x · y 값이 든 필드. |
23
+ | `sizeKey` | `string` | | 버블 크기 필드. 넓이가 값에 비례해요. |
24
+ | `sizeRange` | `[number, number]` | `[4, 22]` | 버블 반지름(px)의 최소 · 최대. |
25
+ | `pointRadius` | `number` | `5` | sizeKey가 없을 때 점 반지름(px). |
26
+ | `categoryKey` | `string` | | 점의 분류 필드. 분류마다 색이 달라요. |
27
+ | `categories` | `ScatterCategory[]` | | 분류 순서 · 이름 · 색. 생략하면 categoryKey 값이 나온 순서대로 --chart-1부터. |
28
+ | `labelKey` | `string` | | 점 이름 필드(툴팁 제목). 생략하면 분류 이름. |
29
+ | `xLabel / yLabel / sizeLabel` | `string` | | 축 제목이자 툴팁 행 이름. |
30
+ | `height` | `number` | `280` | 축 라벨을 포함한 높이(px). |
31
+ | `xTickCount / yTickCount` | `number` | `5 / 4` | 축 라벨 개수(대략). |
32
+ | `xDomain / yDomain` | `[number, number]` | | 축이 덮을 범위. 둥근 눈금으로 넓혀요. 생략하면 데이터 범위(0에 가까우면 0부터). |
33
+ | `trendLine` | `boolean \| 'category'` | `false` | 점선 추세선(최소제곱). category는 분류마다 하나씩. |
34
+ | `referenceLines` | `ScatterReferenceLine[]` | | { axis: 'x' \| 'y', value, label?, tone? } 점선 기준선. |
35
+ | `formatX / formatY / formatSize` | `(value, row) => string` | `'1,234'` | 툴팁 값 형식. |
36
+ | `formatAxisX / formatAxisY` | `(value) => string` | `'6천'` | 축 라벨 형식. |
37
+ | `legend` | `boolean` | `true` | 아래 범례(categoryKey가 있을 때). 누르면 분류를 숨기고 · 보이고, 올리면 강조해요. |
38
+ | `hiddenCategories / defaultHiddenCategories / onHiddenCategoriesChange` | `string[]` | | 숨긴 분류 key(제어/비제어). |
39
+ | `activeIndex / defaultActiveIndex / onActiveIndexChange` | `number \| null` | | 하이라이트한 점. 보이는 점을 x 순서로 센 번호(제어/비제어). |
40
+ | `aria-label` | `string` | `'산점도'` | 차트 이름. |
41
+
42
+ ## 예제
43
+
44
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
45
+
46
+ ### 버블 · 고객사별 매출 대비 사용량
47
+
48
+ 버블 크기는 좌석 수, 색은 요금제예요. 범례를 누르면 그 요금제가 제자리에서 줄어들며 사라지고, 다시 누르면 돌아와요. trendLine은 보이는 점 전체의 추세선이에요. ←/→, Home/End로 점을 왼쪽부터 옮기고 Esc로 닫아요.
49
+
50
+ ```tsx
51
+ import { ScatterChart, type ScatterCategory } from '@iamfiro/design'
52
+
53
+ const PLANS: ScatterCategory[] = [
54
+ { key: 'starter', label: '스타터', color: '--chart-3' },
55
+ { key: 'team', label: '팀', color: '--chart-2' },
56
+ { key: 'enterprise', label: '엔터프라이즈', color: '--chart-4' },
57
+ ]
58
+
59
+ // 고객사별 월 사용량(만 회) · 연 매출(만 원) · 좌석 수
60
+ const CUSTOMERS = [
61
+ { name: '한빛상사', plan: 'starter', usage: 12, revenue: 480, seats: 8 },
62
+ { name: '누리테크', plan: 'starter', usage: 18, revenue: 620, seats: 12 },
63
+ { name: '바른물류', plan: 'starter', usage: 9, revenue: 360, seats: 5 },
64
+ { name: '소담커머스', plan: 'starter', usage: 26, revenue: 840, seats: 15 },
65
+ { name: '다온랩', plan: 'starter', usage: 31, revenue: 760, seats: 10 },
66
+ { name: '새봄디자인', plan: 'team', usage: 42, revenue: 1850, seats: 34 },
67
+ { name: '온결헬스', plan: 'team', usage: 58, revenue: 2300, seats: 48 },
68
+ { name: '한결금융', plan: 'team', usage: 36, revenue: 2100, seats: 40 },
69
+ { name: '푸른교육', plan: 'team', usage: 71, revenue: 2650, seats: 55 },
70
+ { name: '미래모빌리티', plan: 'team', usage: 64, revenue: 3100, seats: 62 },
71
+ { name: '가람제약', plan: 'team', usage: 49, revenue: 1720, seats: 28 },
72
+ { name: '대한전자', plan: 'enterprise', usage: 118, revenue: 7800, seats: 240 },
73
+ { name: '세종에너지', plan: 'enterprise', usage: 96, revenue: 6200, seats: 180 },
74
+ { name: '하늘항공', plan: 'enterprise', usage: 142, revenue: 9400, seats: 320 },
75
+ { name: '우리리테일', plan: 'enterprise', usage: 87, revenue: 5100, seats: 150 },
76
+ { name: '나래통신', plan: 'enterprise', usage: 128, revenue: 6900, seats: 210 },
77
+ ]
78
+
79
+ export default function Example() {
80
+ return (
81
+ <ScatterChart
82
+ data={CUSTOMERS}
83
+ xKey="usage"
84
+ yKey="revenue"
85
+ sizeKey="seats"
86
+ categoryKey="plan"
87
+ categories={PLANS}
88
+ labelKey="name"
89
+ xLabel="월 사용량"
90
+ yLabel="연 매출"
91
+ sizeLabel="좌석 수"
92
+ trendLine
93
+ formatX={(v) => `${v.toLocaleString('ko-KR')}만 회`}
94
+ formatY={(v) => `${v.toLocaleString('ko-KR')}만 원`}
95
+ formatSize={(v) => `${v.toLocaleString('ko-KR')}석`}
96
+ formatAxisX={(v) => `${v}만`}
97
+ aria-label="고객사별 매출 대비 사용량"
98
+ style={{ width: '100%', maxWidth: 620 }}
99
+ />
100
+ )
101
+ }
102
+ ```
103
+
104
+ ### 두 분류 · 기준선
105
+
106
+ trendLine="category"는 분류마다 자기 색의 추세선을 그려요. referenceLines로 목표선을, yDomain으로 축 범위를 정해요.
107
+
108
+ ```tsx
109
+ import { ScatterChart, type ScatterCategory } from '@iamfiro/design'
110
+
111
+ const GROUPS: ScatterCategory[] = [
112
+ { key: 'a', label: '기존 화면' },
113
+ { key: 'b', label: '새 화면' },
114
+ ]
115
+
116
+ // 응답 시간(초)과 만족도(점) — 사용자 한 명이 점 하나
117
+ const RESPONSES = [
118
+ { group: 'a', time: 4.2, score: 62 },
119
+ { group: 'a', time: 5.1, score: 55 },
120
+ { group: 'a', time: 3.6, score: 70 },
121
+ { group: 'a', time: 6.4, score: 48 },
122
+ { group: 'a', time: 4.8, score: 58 },
123
+ { group: 'a', time: 5.7, score: 51 },
124
+ { group: 'a', time: 3.9, score: 66 },
125
+ { group: 'a', time: 7.1, score: 42 },
126
+ { group: 'a', time: 4.5, score: 64 },
127
+ { group: 'b', time: 1.8, score: 84 },
128
+ { group: 'b', time: 2.4, score: 78 },
129
+ { group: 'b', time: 1.2, score: 91 },
130
+ { group: 'b', time: 3.1, score: 72 },
131
+ { group: 'b', time: 2.0, score: 86 },
132
+ { group: 'b', time: 2.7, score: 75 },
133
+ { group: 'b', time: 1.5, score: 88 },
134
+ { group: 'b', time: 3.4, score: 69 },
135
+ { group: 'b', time: 2.2, score: 81 },
136
+ ]
137
+
138
+ export default function Example() {
139
+ return (
140
+ <ScatterChart
141
+ data={RESPONSES}
142
+ xKey="time"
143
+ yKey="score"
144
+ categoryKey="group"
145
+ categories={GROUPS}
146
+ xLabel="응답 시간"
147
+ yLabel="만족도"
148
+ trendLine="category"
149
+ referenceLines={[{ axis: 'y', value: 70, label: '목표 70점', tone: 'accent' }]}
150
+ formatX={(v) => `${v}초`}
151
+ formatY={(v) => `${v}점`}
152
+ formatAxisX={(v) => `${v}초`}
153
+ yDomain={[40, 100]}
154
+ height={260}
155
+ aria-label="응답 시간과 만족도"
156
+ style={{ width: '100%', maxWidth: 560 }}
157
+ />
158
+ )
159
+ }
160
+ ```
@@ -0,0 +1,271 @@
1
+ # ScrollArea
2
+
3
+ > 파운데이션 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 어느 브라우저에서나 같은 스크롤바를 그리는 스크롤 영역. 스크롤은 그대로 네이티브(휠 · 터치 · 키보드)이고, 막대만 위에 얹어요. 막대는 .ds-scroll과 같은 규격(12px 영역 · 4px 막대 · 양 끝 6px)으로, 올려 두거나 스크롤하는 동안 나타났다가 잠시 뒤 사라져요. 막대를 끌면 따라오고(끄는 중 Esc는 원래 자리로), 빈 트랙을 누르면 한 화면씩 넘어가요. fade를 주면 더 읽을 내용이 남은 쪽 가장자리만 부드럽게 흐려져요.
6
+
7
+ ```tsx
8
+ import { ScrollArea } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## API
12
+
13
+ ### ScrollArea
14
+
15
+ | prop | 타입 | 기본값 | 설명 |
16
+ | --- | --- | --- | --- |
17
+ | `children` | `ReactNode` | | 스크롤할 내용. |
18
+ | `orientation` | `'vertical' \| 'horizontal' \| 'both'` | `'vertical'` | 스크롤 방향. 가로 · 양방향이면 내용은 자기 너비(max-content)를 유지해요. |
19
+ | `maxHeight` | `number \| string` | | 이 높이까지는 내용만큼 자라고, 넘으면 스크롤. 고정 높이는 style 또는 부모(flex: 1)로. |
20
+ | `scrollbars` | `'auto' \| 'always'` | `'auto'` | auto: 올려 두거나 스크롤하는 동안만 보이고 사라짐 · always: 넘칠 때 항상. |
21
+ | `fade` | `boolean \| number` | | 아직 스크롤할 수 있는 쪽 가장자리를 흐리게(mask). 숫자는 흐림 길이 px(기본 28). |
22
+ | `stickToBottom` | `boolean` | | 맨 아래에서 시작하고, 내용이 늘어도 아래에 붙음. 사용자가 위로 올렸으면 그대로 둠. |
23
+ | `onAtBottomChange` | `(atBottom: boolean) => void` | | 맨 아래(8px 안)에 닿거나 벗어날 때. |
24
+ | `viewportRef` | `Ref<HTMLDivElement>` | | 실제로 스크롤되는 요소. scrollTo · scrollTop에. |
25
+ | `focusable` | `boolean` | | Tab으로 갈 수 있는 영역인지. 기본: 넘치는데 안에 포커스할 요소가 없을 때만. |
26
+ | `aria-label / aria-labelledby` | `string` | | 주면 영역이 role="region"이 돼요. 키보드로 스크롤할 영역이면 꼭. |
27
+ | `onScroll` | `(e) => void` | | 스크롤될 때(viewport의 scroll 이벤트). |
28
+ | `viewportClassName / className / style` | `string / CSSProperties` | | style · className은 바깥 요소에. 부모가 세로 flex면 style={{ flex: 1, minHeight: 0 }}. |
29
+
30
+ ## 예제
31
+
32
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
33
+
34
+ ### 최대 높이 + 가장자리 흐림
35
+
36
+ maxHeight까지는 내용만큼 자라고 그 뒤로 스크롤돼요. fade는 위 · 아래 중 아직 내용이 숨어 있는 쪽만 흐려서, 맨 위에선 아래만, 중간에선 양쪽이 흐려져요.
37
+
38
+ ```tsx
39
+ import { FileText, GitMerge, MessageSquare, UserPlus } from 'lucide-react'
40
+ import { Avatar, IconTile, Card, CardHeader, List, ListItem, ScrollArea } from '@iamfiro/design'
41
+
42
+ const PEOPLE = ['김민지', '이도현', '박서연', '정하늘', '한지우', '오세훈']
43
+ const KINDS = [
44
+ { icon: <MessageSquare />, text: '디자인 리뷰에 댓글을 남겼어요' },
45
+ { icon: <GitMerge />, text: '결제 화면 개선을 병합했어요' },
46
+ { icon: <FileText />, text: '4분기 로드맵 문서를 고쳤어요' },
47
+ { icon: <UserPlus />, text: '새 팀원을 초대했어요' },
48
+ ]
49
+
50
+ const ACTIVITY = Array.from({ length: 18 }, (_, i) => ({
51
+ id: i,
52
+ who: PEOPLE[i % PEOPLE.length],
53
+ ...KINDS[i % KINDS.length],
54
+ time: i === 0 ? '방금' : i < 6 ? `${i * 7}분 전` : `${Math.floor(i / 3)}시간 전`,
55
+ }))
56
+
57
+ export default function Example() {
58
+ return (
59
+ <Card padding="sm" style={{ width: '100%', maxWidth: 420 }}>
60
+ <CardHeader title="최근 활동" description="오늘 18건" />
61
+ <ScrollArea maxHeight={300} fade aria-label="최근 활동">
62
+ <List density="compact" aria-label="활동 기록">
63
+ {ACTIVITY.map((a) => (
64
+ <ListItem
65
+ key={a.id}
66
+ leading={<Avatar name={a.who} size={28} />}
67
+ title={a.who}
68
+ description={a.text}
69
+ meta={a.time}
70
+ trailing={
71
+ <IconTile size={24} tone="surface">
72
+ {a.icon}
73
+ </IconTile>
74
+ }
75
+ />
76
+ ))}
77
+ </List>
78
+ </ScrollArea>
79
+ </Card>
80
+ )
81
+ }
82
+ ```
83
+
84
+ ### 대화 기록 (아래에 붙기)
85
+
86
+ stickToBottom이면 맨 아래에서 시작하고, 새 메시지가 와도 아래에 붙어 있어요. 위로 올려 읽는 중이면 끌어내리지 않고, onAtBottomChange로 "맨 아래로" 버튼을 켜요. viewportRef로 scrollTo를 부를 수 있어요.
87
+
88
+ ```tsx
89
+ import { useRef, useState } from 'react'
90
+ import { ArrowDown, Send } from 'lucide-react'
91
+ import { Box, Button, Inline, Card, Comment, CommentThread, ScrollArea } from '@iamfiro/design'
92
+
93
+ interface Message {
94
+ id: number
95
+ author: string
96
+ text: string
97
+ date: Date
98
+ }
99
+
100
+ const ago = (m: number) => new Date(Date.now() - m * 60_000)
101
+
102
+ const START: Message[] = [
103
+ { id: 1, author: '김민지', text: '오늘 배포 일정 다시 한번 확인할게요. 오후 4시 맞죠?', date: ago(42) },
104
+ { id: 2, author: '이도현', text: '네, 4시에 시작해서 30분 안에 끝낼 예정이에요.', date: ago(40) },
105
+ { id: 3, author: '이도현', text: '결제 모듈은 마지막에 따로 올릴게요.', date: ago(39) },
106
+ { id: 4, author: '박서연', text: '변경 사항 안내 문구는 제가 정리해 둘게요.', date: ago(31) },
107
+ { id: 5, author: '김민지', text: '좋아요. 롤백 절차도 문서에 같이 넣어 주세요.', date: ago(25) },
108
+ { id: 6, author: '정하늘', text: '모니터링 대시보드 링크 공유드려요. 오류율 0.2% 넘으면 알림이 와요.', date: ago(18) },
109
+ { id: 7, author: '이도현', text: '스테이징 확인 끝났어요. 문제 없어요.', date: ago(9) },
110
+ ]
111
+
112
+ const REPLIES = [
113
+ { author: '박서연', text: '안내 문구 초안 올렸어요. 한번 봐 주세요.' },
114
+ { author: '정하늘', text: '지금 오류율 0.05%로 안정적이에요.' },
115
+ { author: '김민지', text: '확인했어요. 고마워요!' },
116
+ { author: '이도현', text: '결제 모듈도 올라갔어요. 배포 끝!' },
117
+ ]
118
+
119
+ export default function Example() {
120
+ const [messages, setMessages] = useState(START)
121
+ const [atBottom, setAtBottom] = useState(true)
122
+ const viewport = useRef<HTMLDivElement>(null)
123
+
124
+ const receive = () => {
125
+ const reply = REPLIES[(messages.length - START.length) % REPLIES.length]
126
+ const date = new Date()
127
+ setMessages((m) => [...m, { id: m.length + 1, ...reply, date }])
128
+ }
129
+ const toBottom = () => viewport.current?.scrollTo({ top: viewport.current.scrollHeight, behavior: 'smooth' })
130
+
131
+ return (
132
+ <Card padding="none" style={{ width: '100%', maxWidth: 520, height: 400 }}>
133
+ <ScrollArea
134
+ stickToBottom
135
+ fade
136
+ onAtBottomChange={setAtBottom}
137
+ viewportRef={viewport}
138
+ aria-label="배포 채널 대화"
139
+ style={{ flex: 1, minHeight: 0 }}
140
+ >
141
+ <Box padding={4}>
142
+ <CommentThread>
143
+ {messages.map((m, i) => (
144
+ <Comment key={m.id} author={m.author} date={m.date} continued={messages[i - 1]?.author === m.author}>
145
+ {m.text}
146
+ </Comment>
147
+ ))}
148
+ </CommentThread>
149
+ </Box>
150
+ </ScrollArea>
151
+ <Box paddingX={4} paddingY={3}>
152
+ <Inline justify="between">
153
+ <Button size="sm" variant="secondary" icon={<ArrowDown />} disabled={atBottom} onClick={toBottom}>
154
+ 맨 아래로
155
+ </Button>
156
+ <Button size="sm" variant="primary" icon={<Send />} onClick={receive}>
157
+ 새 메시지 받기
158
+ </Button>
159
+ </Inline>
160
+ </Box>
161
+ </Card>
162
+ )
163
+ }
164
+ ```
165
+
166
+ ### 가로 스크롤
167
+
168
+ orientation="horizontal"이면 아래에 가로 막대가 생기고, fade는 왼쪽 · 오른쪽 가장자리에 걸려요. 트랙패드 · Shift+휠로 넘겨 보세요.
169
+
170
+ ```tsx
171
+ import { Box, FileIcon, Inline, Stack, Text, Card, ScrollArea } from '@iamfiro/design'
172
+
173
+ const FILES = [
174
+ { name: '4분기 로드맵.pptx', who: '김민지', when: '10분 전' },
175
+ { name: '10월 매출 정리.xlsx', who: '이도현', when: '1시간 전' },
176
+ { name: '브랜드 가이드.pdf', who: '박서연', when: '어제' },
177
+ { name: '랜딩 페이지 시안.png', who: '정하늘', when: '어제' },
178
+ { name: '사용자 인터뷰 정리.docx', who: '한지우', when: '10월 22일' },
179
+ { name: '아이콘 세트.zip', who: '오세훈', when: '10월 21일' },
180
+ { name: '2027 예산안.xlsx', who: '김민지', when: '10월 20일' },
181
+ ]
182
+
183
+ export default function Example() {
184
+ return (
185
+ <Stack gap={2} style={{ width: '100%', maxWidth: 560 }}>
186
+ <Text variant="label-md">최근 파일</Text>
187
+ <ScrollArea orientation="horizontal" fade aria-label="최근 파일">
188
+ <Box paddingX={1} paddingY={3}>
189
+ <Inline gap={3} wrap={false}>
190
+ {FILES.map((f) => (
191
+ <Card key={f.name} as="button" interactive padding="sm" style={{ width: 168, flex: 'none', textAlign: 'start' }}>
192
+ <Stack gap={3}>
193
+ <FileIcon name={f.name} size={28} />
194
+ <Stack gap={1}>
195
+ <Text variant="label-sm" truncate>
196
+ {f.name}
197
+ </Text>
198
+ <Text variant="caption" tone="tertiary">
199
+ {f.who} · {f.when}
200
+ </Text>
201
+ </Stack>
202
+ </Stack>
203
+ </Card>
204
+ ))}
205
+ </Inline>
206
+ </Box>
207
+ </ScrollArea>
208
+ </Stack>
209
+ )
210
+ }
211
+ ```
212
+
213
+ ### 키보드로 읽는 영역
214
+
215
+ 안에 포커스할 요소가 없으면 영역 자체가 Tab으로 갈 수 있는 region이 되어 ↑ ↓ · Page Up / Down · Space로 읽을 수 있어요(aria-label 필수). scrollbars="always"는 넘칠 때 막대를 항상 보여 줘요. 끝까지 읽어야 동의 버튼이 켜져요.
216
+
217
+ ```tsx
218
+ import { useState } from 'react'
219
+ import { Box, Button, Inline, Prose, Stack, Text, Card, ScrollArea } from '@iamfiro/design'
220
+
221
+ const SECTIONS = [
222
+ ['제1조 (목적)', '이 약관은 회사가 제공하는 협업 서비스의 이용 조건과 절차, 회사와 이용자의 권리 · 의무를 정하는 것을 목적으로 해요.'],
223
+ ['제2조 (계정)', '이용자는 하나의 이메일로 하나의 계정을 만들 수 있어요. 계정 정보는 본인이 직접 관리하고, 다른 사람에게 빌려주지 않아요.'],
224
+ ['제3조 (요금)', '유료 요금제는 매월 같은 날 자동으로 결제돼요. 결제일 7일 전까지 해지하면 다음 달부터 청구되지 않아요.'],
225
+ ['제4조 (데이터)', '이용자가 올린 문서와 파일의 권리는 이용자에게 있어요. 회사는 서비스 제공에 필요한 범위에서만 데이터를 처리해요.'],
226
+ ['제5조 (서비스 변경)', '기능을 바꾸거나 끝낼 때는 30일 전에 공지해요. 이용자에게 불리한 변경은 이메일로도 따로 알려요.'],
227
+ ['제6조 (해지)', '언제든 설정에서 해지할 수 있어요. 해지 후 30일 동안은 데이터를 내려받을 수 있고, 그 뒤에는 완전히 삭제돼요.'],
228
+ ] as const
229
+
230
+ export default function Example() {
231
+ const [read, setRead] = useState(false)
232
+ return (
233
+ <Card padding="none" style={{ width: '100%', maxWidth: 460 }}>
234
+ <Box padding={4}>
235
+ <Stack gap={1}>
236
+ <Text variant="heading-xs">서비스 이용 약관</Text>
237
+ <Text variant="caption" tone="tertiary">
238
+ 끝까지 읽으면 동의할 수 있어요. 본문을 Tab으로 고른 뒤 ↑ ↓ · Page Up / Down으로도 읽을 수 있어요.
239
+ </Text>
240
+ </Stack>
241
+ </Box>
242
+ <ScrollArea
243
+ maxHeight={220}
244
+ scrollbars="always"
245
+ fade
246
+ aria-label="이용 약관 본문"
247
+ onAtBottomChange={(bottom) => bottom && setRead(true)}
248
+ >
249
+ <Box paddingX={4} paddingY={2}>
250
+ <Prose size="sm">
251
+ {SECTIONS.map(([title, body]) => (
252
+ <section key={title}>
253
+ <h4>{title}</h4>
254
+ <p>{body}</p>
255
+ </section>
256
+ ))}
257
+ </Prose>
258
+ </Box>
259
+ </ScrollArea>
260
+ <Box padding={4}>
261
+ <Inline justify="end" gap={2}>
262
+ <Button variant="ghost">나중에</Button>
263
+ <Button variant="primary" disabled={!read}>
264
+ 동의하고 계속
265
+ </Button>
266
+ </Inline>
267
+ </Box>
268
+ </Card>
269
+ )
270
+ }
271
+ ```
@@ -0,0 +1,105 @@
1
+ # SearchInput
2
+
3
+ > 텍스트 입력 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 돋보기 아이콘이 붙은 검색 입력창. shortcutKey를 주면 오른쪽에 키캡이 보이고, 어디서든 ⌘(Mac) 또는 Ctrl + 그 키로 바로 포커스돼요. Input의 다른 props는 모두 그대로 쓸 수 있어요.
6
+
7
+ ```tsx
8
+ import { SearchInput } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## API
12
+
13
+ ### SearchInput
14
+
15
+ Input의 props(size · invalid · disabled · value · onChange 등)를 그대로 받아요. leading · trailing · type은 정해져 있어요.
16
+
17
+ | prop | 타입 | 기본값 | 설명 |
18
+ | --- | --- | --- | --- |
19
+ | `shortcutKey` | `string` | | ⌘(Mac) / Ctrl과 함께 누르면 포커스되는 키. 키캡으로 표시돼요. 한 화면에서 같은 키를 두 번 쓰지 마세요. |
20
+ | `placeholder` | `string` | `'검색'` | 빈 칸 안내 문구. |
21
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 높이 36 / 44 / 52px. |
22
+ | `wrapperClassName` | `string` | | 바깥 칸에 붙일 클래스. |
23
+
24
+ ## 예제
25
+
26
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
27
+
28
+ ### 단축키
29
+
30
+ ⌘/Ctrl + / 를 눌러 보세요. 포커스와 함께 입력된 글자가 전체 선택돼요. 이 문서 사이트는 ⌘K를 이미 쓰고 있어서 예시에서는 /를 썼어요.
31
+
32
+ ```tsx
33
+ import { SearchInput } from '@iamfiro/design'
34
+
35
+ export default function Example() {
36
+ return (
37
+ <div style={{ width: 320 }}>
38
+ <SearchInput placeholder="문서 검색" shortcutKey="/" aria-label="문서 검색" />
39
+ </div>
40
+ )
41
+ }
42
+ ```
43
+
44
+ ### 목록 필터링
45
+
46
+ value / onChange로 제어하며 목록을 바로 걸러요. 결과가 없으면 EmptyState로 알려 주세요.
47
+
48
+ ```tsx
49
+ import { useState } from 'react'
50
+ import { SearchX } from 'lucide-react'
51
+ import { Avatar, SearchInput, Text, EmptyState } from '@iamfiro/design'
52
+
53
+ const MEMBERS = [
54
+ { name: '김민지', role: '디자이너' },
55
+ { name: '이도현', role: '프론트엔드 개발자' },
56
+ { name: '최서연', role: '프로덕트 매니저' },
57
+ { name: '정우진', role: '백엔드 개발자' },
58
+ { name: '한지수', role: '데이터 분석가' },
59
+ ]
60
+
61
+ export default function Example() {
62
+ const [query, setQuery] = useState('')
63
+ const results = MEMBERS.filter((m) => m.name.includes(query.trim()) || m.role.includes(query.trim()))
64
+
65
+ return (
66
+ <div style={{ display: 'grid', gap: 12, width: 320 }}>
67
+ <SearchInput size="sm" placeholder="이름이나 역할로 찾기" value={query} onChange={(e) => setQuery(e.target.value)} aria-label="멤버 찾기" />
68
+ {results.length > 0 ? (
69
+ <div style={{ display: 'grid', gap: 10 }}>
70
+ {results.map((m) => (
71
+ <div key={m.name} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
72
+ <Avatar name={m.name} size={28} />
73
+ <Text variant="label-md">{m.name}</Text>
74
+ <Text as="span" variant="body-sm" tone="tertiary">
75
+ {m.role}
76
+ </Text>
77
+ </div>
78
+ ))}
79
+ </div>
80
+ ) : (
81
+ <EmptyState size="sm" icon={<SearchX />} title="찾는 멤버가 없어요" description={`'${query}'와 일치하는 이름이나 역할이 없어요.`} />
82
+ )}
83
+ </div>
84
+ )
85
+ }
86
+ ```
87
+
88
+ ### 크기와 상태
89
+
90
+ Input과 같은 size(36 / 44 / 52px)와 disabled를 받아요.
91
+
92
+ ```tsx
93
+ import { SearchInput } from '@iamfiro/design'
94
+
95
+ export default function Example() {
96
+ return (
97
+ <div style={{ display: 'grid', gap: 12, width: 320 }}>
98
+ <SearchInput size="sm" placeholder="작게 (sm)" aria-label="검색 sm" />
99
+ <SearchInput placeholder="기본 (md)" aria-label="검색 md" />
100
+ <SearchInput size="lg" placeholder="크게 (lg)" aria-label="검색 lg" />
101
+ <SearchInput placeholder="검색할 수 없어요" disabled aria-label="검색 비활성" />
102
+ </div>
103
+ )
104
+ }
105
+ ```