@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,305 @@
1
+ # Tabs
2
+
3
+ > 내비게이션 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 같은 자리에서 여러 패널을 바꿔 보여줘요. Tabs 안에 TabList · Tab · TabPanel을 조합하고, 선택 표시는 탭 사이를 미끄러지듯 이동해요. ← → · Home / End로 탭을 옮기고, 무거운 패널은 manual 활성화로 Enter / Space를 누를 때만 바꿔요.
6
+
7
+ ```tsx
8
+ import { Tab, TabList, TabPanel, Tabs } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 탭은 `Tabs`(패널 연결). `SegmentedControl`은 같은 화면 안의 보기 전환에만.
14
+
15
+ ## API
16
+
17
+ ### Tabs
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `value` | `string` | | 선택된 탭(제어). |
22
+ | `defaultValue` | `string` | `''` | 처음 선택된 탭(비제어). |
23
+ | `onValueChange` | `(value: string) => void` | | 선택이 바뀔 때. |
24
+ | `activation` | `'auto' \| 'manual'` | `'auto'` | auto: 화살표로 옮기면 바로 선택 · manual: 화살표는 포커스만, Enter / Space로 선택. |
25
+ | `className` | `string` | | 바깥 요소에 전달. |
26
+
27
+ ### TabList
28
+
29
+ Tabs.List로도 쓸 수 있어요.
30
+
31
+ | prop | 타입 | 기본값 | 설명 |
32
+ | --- | --- | --- | --- |
33
+ | `variant` | `'underline' \| 'pill'` | `'underline'` | underline: 선택 탭 아래 선 · pill: 회색 트랙 위 흰 칩. |
34
+ | `size` | `'sm' \| 'md'` | `'md'` | 탭 크기. |
35
+ | `fitted` | `boolean` | | 탭이 줄 전체를 같은 폭으로 채워요. |
36
+ | `aria-label` | `string` | | 탭 목록의 접근성 이름. |
37
+ | `className` | `string` | | tablist 요소에 전달. |
38
+
39
+ ### Tab
40
+
41
+ Tabs.Tab으로도 쓸 수 있어요.
42
+
43
+ | prop | 타입 | 기본값 | 설명 |
44
+ | --- | --- | --- | --- |
45
+ | `value` (필수) | `string` | | 이 탭의 값. 같은 value의 TabPanel과 연결돼요. |
46
+ | `children` (필수) | `ReactNode` | | 탭 이름. |
47
+ | `icon` | `ReactNode` | | 이름 앞 아이콘. |
48
+ | `count` | `number` | | 이름 뒤 작은 숫자. |
49
+ | `disabled` | `boolean` | | 비활성. 키보드 이동에서도 건너뛰어요. |
50
+
51
+ ### TabPanel
52
+
53
+ Tabs.Panel로도 쓸 수 있어요.
54
+
55
+ | prop | 타입 | 기본값 | 설명 |
56
+ | --- | --- | --- | --- |
57
+ | `value` (필수) | `string` | | 연결할 Tab의 value. |
58
+ | `children` (필수) | `ReactNode` | | 패널 내용. |
59
+ | `keepMounted` | `boolean` | | 숨겨져도 DOM에 남겨 폼 상태·스크롤을 유지해요. |
60
+ | `className` | `string` | | tabpanel 요소에 전달. |
61
+
62
+ ## 예제
63
+
64
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
65
+
66
+ ### 기본 (underline)
67
+
68
+ 선택된 탭 아래 선이 움직여요. value를 생략하면 defaultValue로 비제어 사용.
69
+
70
+ ```tsx
71
+ import { Box, Stack, Text, Tab, TabList, TabPanel, Tabs } from '@iamfiro/design'
72
+
73
+ export default function Example() {
74
+ return (
75
+ <Tabs defaultValue="overview">
76
+ <Box style={{ width: 480 }}>
77
+ <TabList aria-label="프로젝트">
78
+ <Tab value="overview">개요</Tab>
79
+ <Tab value="activity">활동</Tab>
80
+ <Tab value="settings">설정</Tab>
81
+ </TabList>
82
+ <TabPanel value="overview">
83
+ <Stack gap={1}>
84
+ <Text variant="label-md">Lumen 리디자인</Text>
85
+ <Text variant="body-sm" tone="secondary">
86
+ 10월 31일 출시를 목표로 디자인 시스템과 랜딩 페이지를 새로 만들고 있어요.
87
+ </Text>
88
+ </Stack>
89
+ </TabPanel>
90
+ <TabPanel value="activity">
91
+ <Text variant="body-sm" tone="secondary">
92
+ 이도현님이 2분 전에 ‘버튼 상태 정리’ 작업을 완료했어요.
93
+ </Text>
94
+ </TabPanel>
95
+ <TabPanel value="settings">
96
+ <Text variant="body-sm" tone="secondary">
97
+ 프로젝트 이름, 공개 범위, 보관 설정을 바꿀 수 있어요.
98
+ </Text>
99
+ </TabPanel>
100
+ </Box>
101
+ </Tabs>
102
+ )
103
+ }
104
+ ```
105
+
106
+ ### pill
107
+
108
+ 회색 트랙 위 흰 칩. 화면 안의 작은 보기 전환에 어울려요. size="sm"으로 더 작게.
109
+
110
+ ```tsx
111
+ import { Box, Stack, Text, Tab, TabList, TabPanel, Tabs } from '@iamfiro/design'
112
+
113
+ const RANGES = [
114
+ { value: 'day', label: '오늘', visitors: '1,284' },
115
+ { value: 'week', label: '이번 주', visitors: '8,903' },
116
+ { value: 'month', label: '이번 달', visitors: '32,410' },
117
+ ]
118
+
119
+ export default function Example() {
120
+ return (
121
+ <Stack gap={8} align="start">
122
+ <Tabs defaultValue="week">
123
+ <Box>
124
+ <TabList variant="pill" aria-label="기간">
125
+ {RANGES.map((r) => (
126
+ <Tab key={r.value} value={r.value}>
127
+ {r.label}
128
+ </Tab>
129
+ ))}
130
+ </TabList>
131
+ {RANGES.map((r) => (
132
+ <TabPanel key={r.value} value={r.value}>
133
+ <Stack gap={1}>
134
+ <Text variant="caption" tone="tertiary">
135
+ {r.label} 방문자
136
+ </Text>
137
+ <Text variant="number-lg">{r.visitors}</Text>
138
+ </Stack>
139
+ </TabPanel>
140
+ ))}
141
+ </Box>
142
+ </Tabs>
143
+ <Tabs defaultValue="code">
144
+ <TabList variant="pill" size="sm" aria-label="보기">
145
+ <Tab value="preview">미리 보기</Tab>
146
+ <Tab value="code">코드</Tab>
147
+ </TabList>
148
+ </Tabs>
149
+ </Stack>
150
+ )
151
+ }
152
+ ```
153
+
154
+ ### 아이콘과 개수
155
+
156
+ icon과 count로 탭 옆에 아이콘·숫자를 붙여요. disabled 탭은 키보드 이동에서도 건너뛰어요.
157
+
158
+ ```tsx
159
+ import { Archive, CircleDot, GitPullRequest, Inbox } from 'lucide-react'
160
+ import { Box, Text, Tab, TabList, TabPanel, Tabs } from '@iamfiro/design'
161
+
162
+ export default function Example() {
163
+ return (
164
+ <Tabs defaultValue="inbox">
165
+ <Box style={{ width: 520 }}>
166
+ <TabList aria-label="받은 항목">
167
+ <Tab value="inbox" icon={<Inbox />} count={12}>
168
+ 받은 편지함
169
+ </Tab>
170
+ <Tab value="issues" icon={<CircleDot />} count={4}>
171
+ 이슈
172
+ </Tab>
173
+ <Tab value="reviews" icon={<GitPullRequest />} count={2}>
174
+ 리뷰 요청
175
+ </Tab>
176
+ <Tab value="archive" icon={<Archive />} disabled>
177
+ 보관함
178
+ </Tab>
179
+ </TabList>
180
+ <TabPanel value="inbox">
181
+ <Text variant="body-sm" tone="secondary">
182
+ 읽지 않은 알림 12개가 있어요.
183
+ </Text>
184
+ </TabPanel>
185
+ <TabPanel value="issues">
186
+ <Text variant="body-sm" tone="secondary">
187
+ 나에게 배정된 열린 이슈 4개.
188
+ </Text>
189
+ </TabPanel>
190
+ <TabPanel value="reviews">
191
+ <Text variant="body-sm" tone="secondary">
192
+ 김민지님과 박서연님이 리뷰를 요청했어요.
193
+ </Text>
194
+ </TabPanel>
195
+ </Box>
196
+ </Tabs>
197
+ )
198
+ }
199
+ ```
200
+
201
+ ### 꽉 채우기
202
+
203
+ fitted를 주면 탭이 줄 전체를 같은 폭으로 나눠 가져요.
204
+
205
+ ```tsx
206
+ import { Stack, Tab, TabList, Tabs } from '@iamfiro/design'
207
+
208
+ export default function Example() {
209
+ return (
210
+ <Stack gap={6} style={{ width: 400 }}>
211
+ <Tabs defaultValue="login">
212
+ <TabList fitted aria-label="계정">
213
+ <Tab value="login">로그인</Tab>
214
+ <Tab value="signup">회원가입</Tab>
215
+ </TabList>
216
+ </Tabs>
217
+ <Tabs defaultValue="monthly">
218
+ <TabList variant="pill" fitted aria-label="결제 주기">
219
+ <Tab value="monthly">월간</Tab>
220
+ <Tab value="yearly">연간</Tab>
221
+ <Tab value="custom">맞춤</Tab>
222
+ </TabList>
223
+ </Tabs>
224
+ </Stack>
225
+ )
226
+ }
227
+ ```
228
+
229
+ ### 수동 활성화
230
+
231
+ activation="manual"이면 화살표는 포커스만 옮기고 Enter / Space로 선택해요. 패널을 그리는 비용이 클 때. 제어(value / onValueChange) 예시이기도 해요.
232
+
233
+ ```tsx
234
+ import { useState } from 'react'
235
+ import { Box, Kbd, Stack, Text, Tab, TabList, TabPanel, Tabs } from '@iamfiro/design'
236
+
237
+ const REPORTS = [
238
+ { value: 'sales', label: '매출', summary: '10월 매출은 지난달보다 12% 늘었어요.' },
239
+ { value: 'users', label: '사용자', summary: '주간 활성 사용자는 8,903명이에요.' },
240
+ { value: 'retention', label: '리텐션', summary: '4주 리텐션은 41%예요.' },
241
+ ]
242
+
243
+ export default function Example() {
244
+ const [report, setReport] = useState('sales')
245
+ return (
246
+ <Tabs value={report} onValueChange={setReport} activation="manual">
247
+ <Stack gap={5} style={{ width: 460 }}>
248
+ <Box>
249
+ <TabList aria-label="리포트">
250
+ {REPORTS.map((r) => (
251
+ <Tab key={r.value} value={r.value}>
252
+ {r.label}
253
+ </Tab>
254
+ ))}
255
+ </TabList>
256
+ {REPORTS.map((r) => (
257
+ <TabPanel key={r.value} value={r.value}>
258
+ <Text variant="body-sm">{r.summary}</Text>
259
+ </TabPanel>
260
+ ))}
261
+ </Box>
262
+ <Text variant="caption" tone="tertiary">
263
+ <Kbd>←</Kbd> <Kbd>→</Kbd>로 포커스를 옮기고 <Kbd>Enter</Kbd>로 열어요.
264
+ </Text>
265
+ </Stack>
266
+ </Tabs>
267
+ )
268
+ }
269
+ ```
270
+
271
+ ### 숨겨도 상태 유지
272
+
273
+ keepMounted 패널은 숨겨져도 DOM에 남아서, 탭을 오가도 입력한 내용이 지워지지 않아요.
274
+
275
+ ```tsx
276
+ import { Box, Field, Input, Stack, Textarea, Tab, TabList, TabPanel, Tabs } from '@iamfiro/design'
277
+
278
+ export default function Example() {
279
+ return (
280
+ <Tabs defaultValue="basic">
281
+ <Box style={{ width: 440 }}>
282
+ <TabList aria-label="새 일정">
283
+ <Tab value="basic">기본 정보</Tab>
284
+ <Tab value="detail">상세 설명</Tab>
285
+ </TabList>
286
+ <TabPanel value="basic" keepMounted>
287
+ <Stack gap={4}>
288
+ <Field label="일정 이름" htmlFor="event-name">
289
+ <Input id="event-name" placeholder="예: 디자인 리뷰" />
290
+ </Field>
291
+ <Field label="날짜" htmlFor="event-date">
292
+ <Input id="event-date" placeholder="10월 25일" />
293
+ </Field>
294
+ </Stack>
295
+ </TabPanel>
296
+ <TabPanel value="detail" keepMounted>
297
+ <Field label="설명" htmlFor="event-desc">
298
+ <Textarea id="event-desc" rows={4} placeholder="탭을 바꿔도 입력한 내용이 남아 있어요." />
299
+ </Field>
300
+ </TabPanel>
301
+ </Box>
302
+ </Tabs>
303
+ )
304
+ }
305
+ ```
@@ -0,0 +1,246 @@
1
+ # TagInput
2
+
3
+ > 텍스트 입력 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 자유롭게 친 글자를 태그로 모으는 입력 칸. Enter · 쉼표 · Tab으로 추가하고, 붙여넣은 글은 구분자로 나눠 한꺼번에 넣어요. 빈 칸에서 Backspace는 처음엔 마지막 태그를 표시만 하고 두 번째에 지워서, 한 번 잘못 눌러 지워지는 일이 없어요. 중복·규칙 위반은 흔들어서 알리고, 지운 태그는 폭이 접히며 나머지가 미끄러져 와요. 한글 조합 중의 키는 무시해요. 태그 모양·여백은 MultiSelect · Combobox와 같아요(왼쪽 8, 높이 28, 간격 6).
6
+
7
+ ```tsx
8
+ import { TagInput, type TagRejectReason } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## API
12
+
13
+ ### TagInput
14
+
15
+ | prop | 타입 | 기본값 | 설명 |
16
+ | --- | --- | --- | --- |
17
+ | `value` | `string[]` | | 태그 목록(제어). |
18
+ | `defaultValue` | `string[]` | `[]` | 처음 태그(비제어). |
19
+ | `onValueChange` | `(tags: string[]) => void` | | 추가 · 삭제 · 수정할 때. |
20
+ | `delimiters` | `string[]` | `['Enter', 'Tab', ',']` | 태그를 만드는 키. 'Enter' · 'Tab' 또는 한 글자(',' ';' ' '). 붙여넣기는 이 글자(와 줄바꿈 · 탭)로 나눠요. |
21
+ | `validate` | `(tag, tags) => boolean \| string` | | true면 통과, false나 메시지면 거절(칸이 흔들림). |
22
+ | `allowInvalid` | `boolean` | | validate에 걸린 태그도 빨간 톤으로 남겨요. |
23
+ | `allowDuplicates` | `boolean` | `false` | 중복 허용. 기본은 대소문자 · 앞뒤 공백 무시하고 거절, 기존 태그가 흔들려요. |
24
+ | `transform` | `(text: string) => string` | | 태그가 되기 전에 다듬기(앞의 # 제거, 소문자 등). |
25
+ | `max` | `number` | | 최대 개수. 넘치면 칸이 흔들려요. |
26
+ | `onReject` | `(text, reason: 'duplicate' \| 'invalid' \| 'max', message?) => void` | | 거절될 때마다. 이유를 hint에 보여줄 때. |
27
+ | `suggestions` | `string[]` | | 치는 동안 보여줄 추천. ↓로 골라 Enter, 그냥 Enter는 친 글자 그대로. |
28
+ | `editable` | `boolean` | `true` | 더블클릭 · 표시 후 Enter로 그 자리 수정. 비우고 확정하면 삭제. |
29
+ | `placeholder` | `string` | `'입력 후 Enter'` | 태그가 없을 때 문구. |
30
+ | `leading` | `ReactNode` | | 앞쪽 아이콘. |
31
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 최소 높이 36 / 44 / 52px. 태그가 많으면 줄을 바꿔 늘어나요. |
32
+ | `invalid / disabled` | `boolean` | | 오류 · 비활성. |
33
+ | `name` | `string` | | 폼 제출용. 태그마다 hidden input. |
34
+
35
+ ## 예제
36
+
37
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
38
+
39
+ ### 기본
40
+
41
+ 제어 모드(value + onValueChange). ×로 지우고, 태그를 한 번 누르면 표시, 더블클릭하면 그 자리에서 고쳐요.
42
+
43
+ ```tsx
44
+ import { useState } from 'react'
45
+ import { Field, Stack, Text, TagInput } from '@iamfiro/design'
46
+
47
+ export default function Example() {
48
+ const [tags, setTags] = useState(['디자인 시스템', '접근성', '모션'])
49
+ return (
50
+ <Stack gap={2} style={{ width: 360 }}>
51
+ <Field label="관심 주제" htmlFor="topics" hint="Enter · 쉼표 · Tab으로 추가해요. 쉼표로 이어 붙여넣어도 나눠져요.">
52
+ <TagInput id="topics" value={tags} onValueChange={setTags} placeholder="주제 입력 후 Enter" />
53
+ </Field>
54
+ <Text variant="caption" tone="tertiary">
55
+ {tags.length}개: {tags.join(' · ') || '없음'}
56
+ </Text>
57
+ </Stack>
58
+ )
59
+ }
60
+ ```
61
+
62
+ ### 키보드
63
+
64
+ 입력 칸에 포커스를 둔 채 태그를 오가요. 표시된 태그는 한 단계 진한 회색이에요.
65
+
66
+ ```tsx
67
+ import { Field, Inline, Kbd, Stack, Text, TagInput } from '@iamfiro/design'
68
+
69
+ const KEYS: { keys: string[]; label: string }[] = [
70
+ { keys: ['backspace'], label: '빈 칸에서 한 번: 마지막 태그 표시 · 한 번 더: 삭제' },
71
+ { keys: ['left', 'right'], label: '태그 사이 이동 (맨 오른쪽 다음은 입력 칸)' },
72
+ { keys: ['enter'], label: '표시한 태그 수정 · 더블클릭도 같아요' },
73
+ { keys: ['esc'], label: '표시 해제 · 수정 취소' },
74
+ ]
75
+
76
+ export default function Example() {
77
+ return (
78
+ <Stack gap={4} style={{ width: 400 }}>
79
+ <Field label="라벨" htmlFor="labels" hint="한글을 조합하는 중의 Enter · 쉼표는 글자를 끝내는 데만 쓰여요.">
80
+ <TagInput id="labels" defaultValue={['버그', '긴급', '디자인 검토', '백엔드']} placeholder="라벨 추가" />
81
+ </Field>
82
+ <Stack gap={2}>
83
+ {KEYS.map((k) => (
84
+ <Inline key={k.label} gap={2} align="center">
85
+ <Kbd keys={k.keys} size="sm" />
86
+ <Text variant="body-sm" tone="secondary">
87
+ {k.label}
88
+ </Text>
89
+ </Inline>
90
+ ))}
91
+ </Stack>
92
+ </Stack>
93
+ )
94
+ }
95
+ ```
96
+
97
+ ### 규칙 · 최대 개수
98
+
99
+ validate · max · 중복 거절. onReject로 이유를 받아 Field hint에 보여줘요.
100
+
101
+ ```tsx
102
+ import { useState } from 'react'
103
+ import { Field, TagInput, type TagRejectReason } from '@iamfiro/design'
104
+
105
+ const MAX = 5
106
+
107
+ const MESSAGES: Record<TagRejectReason, string> = {
108
+ duplicate: '이미 있는 키워드예요.',
109
+ invalid: '키워드는 12자까지 쓸 수 있어요.',
110
+ max: `키워드는 ${MAX}개까지예요.`,
111
+ }
112
+
113
+ export default function Example() {
114
+ const [keywords, setKeywords] = useState(['봄 신상', '린넨'])
115
+ const [error, setError] = useState<string | null>(null)
116
+ return (
117
+ <div style={{ width: 380 }}>
118
+ <Field
119
+ label={`검색 키워드 (${keywords.length}/${MAX})`}
120
+ htmlFor="keywords"
121
+ invalid={!!error}
122
+ hint={error ?? '같은 키워드를 다시 넣으면 기존 태그가 흔들려요. 12자를 넘거나 5개를 넘기면 칸이 흔들려요.'}
123
+ >
124
+ <TagInput
125
+ id="keywords"
126
+ value={keywords}
127
+ onValueChange={(next) => {
128
+ setKeywords(next)
129
+ setError(null)
130
+ }}
131
+ max={MAX}
132
+ validate={(text) => text.length <= 12}
133
+ onReject={(_, reason) => setError(MESSAGES[reason])}
134
+ placeholder="키워드 입력"
135
+ />
136
+ </Field>
137
+ </div>
138
+ )
139
+ }
140
+ ```
141
+
142
+ ### 형식이 틀린 태그 남기기
143
+
144
+ allowInvalid면 validate에 걸린 태그도 빨간 톤으로 남겨요(받는 사람 칸). 마우스를 올리면 이유가 보여요.
145
+
146
+ ```tsx
147
+ import { Field, TagInput } from '@iamfiro/design'
148
+ import { Mail } from 'lucide-react'
149
+
150
+ const isEmail = (text: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(text) || '이메일 형식이 아니에요'
151
+
152
+ export default function Example() {
153
+ return (
154
+ <div style={{ width: 420 }}>
155
+ <Field label="받는 사람" htmlFor="recipients" hint="스페이스 · 쉼표 · 세미콜론으로 나눠요. 형식이 틀린 주소는 빨간 태그로 남아 바로 고칠 수 있어요(더블클릭).">
156
+ <TagInput
157
+ id="recipients"
158
+ leading={<Mail />}
159
+ defaultValue={['minji.kim@lumen.app', 'dohyun.lee@lumen', 'seoyeon@lumen.app']}
160
+ delimiters={['Enter', 'Tab', ',', ';', ' ']}
161
+ validate={isEmail}
162
+ allowInvalid
163
+ transform={(text) => text.toLowerCase()}
164
+ placeholder="이메일 주소"
165
+ />
166
+ </Field>
167
+ </div>
168
+ )
169
+ }
170
+ ```
171
+
172
+ ### 추천 목록
173
+
174
+ suggestions를 주면 치는 동안 Listbox가 떠요. 이미 넣은 것은 빠져요.
175
+
176
+ ```tsx
177
+ import { Field, TagInput } from '@iamfiro/design'
178
+
179
+ const SKILLS = ['React', 'React Native', 'TypeScript', 'JavaScript', 'Next.js', 'Vite', 'Node.js', 'GraphQL', 'Figma', 'Storybook', '접근성', '애니메이션', '디자인 토큰', '테스트 자동화']
180
+
181
+ export default function Example() {
182
+ return (
183
+ <div style={{ width: 380 }}>
184
+ <Field label="기술 스택" htmlFor="skills" hint="치는 동안 추천이 떠요. ↓로 골라 Enter, 그냥 Enter는 친 글자 그대로 추가해요. 앞의 #은 지워져요.">
185
+ <TagInput
186
+ id="skills"
187
+ suggestions={SKILLS}
188
+ defaultValue={['React', 'TypeScript']}
189
+ transform={(text) => text.replace(/^#+/, '')}
190
+ placeholder="#태그 또는 이름"
191
+ />
192
+ </Field>
193
+ </div>
194
+ )
195
+ }
196
+ ```
197
+
198
+ ### 크기 · 상태 · 폼
199
+
200
+ size · invalid · disabled. name을 주면 태그마다 hidden input으로 제출돼요.
201
+
202
+ ```tsx
203
+ import { useState, type FormEvent } from 'react'
204
+ import { Button, Field, Grid, Stack, Text, TagInput } from '@iamfiro/design'
205
+
206
+ export default function Example() {
207
+ const [sent, setSent] = useState<string[] | null>(null)
208
+ const submit = (e: FormEvent<HTMLFormElement>) => {
209
+ e.preventDefault()
210
+ setSent(new FormData(e.currentTarget).getAll('tags').map(String))
211
+ }
212
+ return (
213
+ <Stack gap={5} style={{ width: 520 }}>
214
+ <Grid columns={2} gap={4}>
215
+ <Field label="작게 (sm)" htmlFor="ti-sm">
216
+ <TagInput id="ti-sm" size="sm" defaultValue={['기획', '리서치']} />
217
+ </Field>
218
+ <Field label="크게 (lg)" htmlFor="ti-lg">
219
+ <TagInput id="ti-lg" size="lg" defaultValue={['출시']} />
220
+ </Field>
221
+ <Field label="태그" invalid hint="태그를 하나 이상 넣어 주세요." htmlFor="ti-err">
222
+ <TagInput id="ti-err" invalid />
223
+ </Field>
224
+ <Field label="잠긴 태그" htmlFor="ti-off">
225
+ <TagInput id="ti-off" defaultValue={['보관됨', '읽기 전용']} disabled />
226
+ </Field>
227
+ </Grid>
228
+ <form onSubmit={submit}>
229
+ <Stack gap={2}>
230
+ <Field label="폼으로 보내기 (name=&quot;tags&quot;)" htmlFor="ti-form">
231
+ <TagInput id="ti-form" name="tags" defaultValue={['서울', '부산']} />
232
+ </Field>
233
+ <Button type="submit" size="sm" style={{ alignSelf: 'flex-start' }}>
234
+ 제출
235
+ </Button>
236
+ {sent && (
237
+ <Text variant="caption" tone="tertiary">
238
+ 보낸 값: {sent.join(', ') || '없음'}
239
+ </Text>
240
+ )}
241
+ </Stack>
242
+ </form>
243
+ </Stack>
244
+ )
245
+ }
246
+ ```