@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,409 @@
1
+ # AppShell
2
+
3
+ > 내비게이션 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 앱의 뼈대. 왼쪽에 고정된 사이드바와 스크롤되는 본문 영역, 그 위의 헤더를 배치해요. 화면 너비가 900px 이하이면 사이드바가 왼쪽에서 밀려 나오는 드로어로 바뀌어요.
6
+
7
+ ```tsx
8
+ import { AppShell, Sidebar, SidebarGroup, SidebarItem } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 예외는 앱 뼈대 하나: `AppShell variant="inset"`은 사이드바가 옅은 회색 바탕(`--canvas`) 위에 놓이고, 본문은 그 옆에 흰 패널(`--r-lg` + `--shadow-panel`, 바깥 여백 8px)로 떠 있다. 본문은 패널 안에서만 스크롤. 회색 바탕 위의 hover·선택 채움은 `--canvas-hover` / `--canvas-active`(AppShell이 사이드바 안에서 `--surface-hover/active`를 이것으로 바꿔 준다). 선택된 사이드바 항목은 어둡게 채우지 않고 **흰 칩 + `--shadow-chip`**(옅은 윤곽 + 그림자)으로 떠오르게. docs 사이트가 이 구조.
14
+
15
+ ## API
16
+
17
+ ### AppShell
18
+
19
+ | prop | 타입 | 기본값 | 설명 |
20
+ | --- | --- | --- | --- |
21
+ | `sidebar` (필수) | `ReactNode` | | 왼쪽 영역. 보통 <Sidebar>. |
22
+ | `header` | `ReactNode` | | 본문 위에 붙는 상단 바(검색, 액션 등). |
23
+ | `children` (필수) | `ReactNode` | | 본문. |
24
+ | `variant` | `'plain' \| 'inset'` | `'plain'` | plain: 흰 한 장, 창 전체가 스크롤. inset: 회색 바탕 위 흰 패널로 떠 있는 본문, 패널 안에서만 스크롤. |
25
+ | `sidebarWidth` | `number` | `264` | 넓은 화면에서 사이드바 너비(px). 드로어는 최대 화면의 86%. |
26
+ | `sidebarCollapsed` | `boolean` | `false` | 넓은 화면에서 사이드바를 접어요. 사이드바가 밀려 나가며 본문이 넓어져요. |
27
+ | `mobileSidebarOpen` | `boolean` | `false` | 좁은 화면(≤ 900px)에서 드로어 열림 여부. |
28
+ | `onMobileSidebarOpenChange` | `(open: boolean) => void` | | 바깥 클릭이나 Esc로 닫힐 때 false로 호출돼요. |
29
+ | `aside` | `ReactNode` | | 오른쪽 패널(도구, 상세 정보). 패널 안만 따로 스크롤되고, 900px 이하에선 숨어요. |
30
+ | `asideWidth` | `number` | `320` | 오른쪽 패널 너비(px). |
31
+ | `asideOpen` | `boolean` | `true` | 패널 열림. 닫으면 패널이 밀려 나가며 본문이 넓어져요. |
32
+ | `asideLabel` | `string` | `'패널'` | 패널(<aside>)의 접근성 이름. |
33
+ | `scrollKey` | `unknown` | | 바뀌면(새 페이지) 본문을 맨 위로 스크롤해요. inset이면 패널을, plain이면 창을. |
34
+ | `className` | `string` | | 루트에 붙일 클래스. |
35
+
36
+ ## 예제
37
+
38
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
39
+
40
+ ### 기본
41
+
42
+ sidebar에는 보통 Sidebar를, header에는 Breadcrumb와 액션 버튼을 넣어요. 사이드바와 헤더는 페이지를 스크롤해도 제자리에 붙어 있어요.
43
+
44
+ ```tsx
45
+ import { useState } from 'react'
46
+ import { Bell, FolderKanban, House, Inbox, Plus } from 'lucide-react'
47
+ import { Badge, Button, Text, AppShell, Breadcrumb, Card, Sidebar, SidebarGroup, SidebarItem } from '@iamfiro/design'
48
+
49
+ const MENU = [
50
+ { id: 'home', label: '홈', icon: <House /> },
51
+ { id: 'inbox', label: '받은 편지함', icon: <Inbox />, badge: <Badge tone="accent">3</Badge> },
52
+ { id: 'projects', label: '프로젝트', icon: <FolderKanban /> },
53
+ ]
54
+
55
+ export default function Example() {
56
+ const [page, setPage] = useState('projects')
57
+ const current = MENU.find((m) => m.id === page)!
58
+
59
+ const sidebar = (
60
+ <Sidebar header={<Text variant="label-lg">Lumen</Text>}>
61
+ <SidebarGroup>
62
+ {MENU.map((m) => (
63
+ <SidebarItem key={m.id} icon={m.icon} badge={m.badge} active={m.id === page} onClick={() => setPage(m.id)}>
64
+ {m.label}
65
+ </SidebarItem>
66
+ ))}
67
+ </SidebarGroup>
68
+ </Sidebar>
69
+ )
70
+
71
+ const header = (
72
+ <>
73
+ <Breadcrumb items={[{ label: '워크스페이스', onClick: () => setPage('home') }, { label: current.label }]} />
74
+ <div style={{ display: 'flex', gap: 8, marginLeft: 'auto' }}>
75
+ <Button iconOnly variant="ghost" icon={<Bell />} aria-label="알림" />
76
+ <Button variant="primary" size="sm" icon={<Plus />}>
77
+ 새로 만들기
78
+ </Button>
79
+ </div>
80
+ </>
81
+ )
82
+
83
+ // 미리보기용 상자예요. 실제 앱에서는 AppShell을 최상단에 두면 화면 전체를 채워요.
84
+ return (
85
+ <Card padding="none" style={{ width: '100%', maxWidth: 760, height: 420, overflow: 'hidden', contain: 'layout paint' }}>
86
+ <AppShell sidebar={sidebar} header={header} sidebarWidth={220}>
87
+ <div style={{ padding: '8px 24px 24px' }}>
88
+ <Text variant="heading-md">{current.label}</Text>
89
+ <Text tone="secondary" style={{ marginTop: 8 }}>
90
+ 사이드바는 제자리에 고정되고, 본문만 스크롤돼요.
91
+ </Text>
92
+ </div>
93
+ </AppShell>
94
+ </Card>
95
+ )
96
+ }
97
+ ```
98
+
99
+ ### 떠 있는 본문 (inset)
100
+
101
+ variant="inset"이면 사이드바는 옅은 회색 바탕(--canvas)에 놓이고, 본문은 그 위에 흰 패널로 떠서 패널 안에서만 스크롤돼요. 사이드바 머리는 SelectorButton + 검색 · 접기 아이콘 버튼으로, 접으면 sidebarCollapsed로 사이드바가 밀려 나가고 헤더에 여는 버튼이 생겨요. scrollKey가 바뀌면 본문이 맨 위로 돌아가요.
102
+
103
+ ```tsx
104
+ import { useState, type CSSProperties } from 'react'
105
+ import { FolderKanban, House, Inbox, PanelLeft, Plus, Search, SquarePen } from 'lucide-react'
106
+ import { Badge, Button, IconTile, Inline, SelectorButton, Text, Tooltip, AppShell, Breadcrumb, Card, Sidebar, SidebarGroup, SidebarItem } from '@iamfiro/design'
107
+
108
+ const MENU = [
109
+ { id: 'new', label: '새 대화', icon: <SquarePen /> },
110
+ { id: 'home', label: '홈', icon: <House /> },
111
+ { id: 'inbox', label: '받은 편지함', icon: <Inbox />, badge: <Badge tone="accent">3</Badge> },
112
+ { id: 'projects', label: '프로젝트', icon: <FolderKanban /> },
113
+ ]
114
+
115
+ export default function Example() {
116
+ const [page, setPage] = useState('projects')
117
+ const [collapsed, setCollapsed] = useState(false)
118
+ const current = MENU.find((m) => m.id === page)!
119
+
120
+ const sidebar = (
121
+ <Sidebar
122
+ header={
123
+ <Inline justify="between" gap={1} wrap={false}>
124
+ <SelectorButton
125
+ leading={
126
+ <IconTile tone="surface" size={24}>
127
+ A
128
+ </IconTile>
129
+ }
130
+ label="Acme"
131
+ />
132
+ <Inline gap={1} wrap={false}>
133
+ <Tooltip content="검색">
134
+ <Button iconOnly variant="ghost" size="sm" icon={<Search />} aria-label="검색" />
135
+ </Tooltip>
136
+ <Tooltip content="사이드바 접기">
137
+ <Button iconOnly variant="ghost" size="sm" icon={<PanelLeft />} aria-label="사이드바 접기" onClick={() => setCollapsed(true)} />
138
+ </Tooltip>
139
+ </Inline>
140
+ </Inline>
141
+ }
142
+ >
143
+ <SidebarGroup>
144
+ {MENU.map((m) => (
145
+ <SidebarItem key={m.id} icon={m.icon} badge={m.badge} active={m.id === page} onClick={() => setPage(m.id)}>
146
+ {m.label}
147
+ </SidebarItem>
148
+ ))}
149
+ </SidebarGroup>
150
+ </Sidebar>
151
+ )
152
+
153
+ const header = (
154
+ <>
155
+ <Inline gap={2} wrap={false}>
156
+ {collapsed && (
157
+ <Tooltip content="사이드바 열기">
158
+ <Button iconOnly variant="ghost" size="sm" icon={<PanelLeft />} aria-label="사이드바 열기" onClick={() => setCollapsed(false)} />
159
+ </Tooltip>
160
+ )}
161
+ <Breadcrumb items={[{ label: 'Acme', onClick: () => setPage('home') }, { label: current.label }]} />
162
+ </Inline>
163
+ <Button variant="primary" size="sm" icon={<Plus />} style={{ marginLeft: 'auto' }}>
164
+ 새로 만들기
165
+ </Button>
166
+ </>
167
+ )
168
+
169
+ // 미리보기용 상자예요. 실제 앱에서는 AppShell을 최상단에 두면 화면 전체를 채워요.
170
+ return (
171
+ <Card padding="none" style={{ width: '100%', maxWidth: 760, height: 420, overflow: 'hidden', contain: 'layout paint', '--shell-height': '420px' } as CSSProperties}>
172
+ <AppShell variant="inset" sidebar={sidebar} header={header} sidebarWidth={220} sidebarCollapsed={collapsed} scrollKey={page}>
173
+ <div style={{ padding: '8px 20px 24px' }}>
174
+ <Text variant="heading-md">{current.label}</Text>
175
+ <Text tone="secondary" style={{ marginTop: 8 }}>
176
+ 회색 바탕 위에 본문이 흰 패널로 떠 있어요. 본문만 패널 안에서 스크롤돼요.
177
+ </Text>
178
+ </div>
179
+ </AppShell>
180
+ </Card>
181
+ )
182
+ }
183
+ ```
184
+
185
+ ### 모바일 드로어
186
+
187
+ 좁은 화면에서는 mobileSidebarOpen / onMobileSidebarOpenChange로 드로어를 열고 닫아요. 바깥의 어두운 영역을 누르거나 Esc를 누르면 닫혀요. 항목을 고른 뒤에도 직접 닫아 주세요.
188
+
189
+ ```tsx
190
+ import { useState } from 'react'
191
+ import { ChartColumn, House, Menu, Settings } from 'lucide-react'
192
+ import { Button, Text, AppShell, Card, Sidebar, SidebarGroup, SidebarItem } from '@iamfiro/design'
193
+
194
+ const MENU = [
195
+ { id: 'home', label: '홈', icon: <House /> },
196
+ { id: 'reports', label: '리포트', icon: <ChartColumn /> },
197
+ { id: 'settings', label: '설정', icon: <Settings /> },
198
+ ]
199
+
200
+ export default function Example() {
201
+ const [page, setPage] = useState('home')
202
+ const [drawerOpen, setDrawerOpen] = useState(false)
203
+
204
+ const go = (id: string) => {
205
+ setPage(id)
206
+ setDrawerOpen(false)
207
+ }
208
+
209
+ const sidebar = (
210
+ <Sidebar header={<Text variant="label-lg">Lumen</Text>}>
211
+ <SidebarGroup>
212
+ {MENU.map((m) => (
213
+ <SidebarItem key={m.id} icon={m.icon} active={m.id === page} onClick={() => go(m.id)}>
214
+ {m.label}
215
+ </SidebarItem>
216
+ ))}
217
+ </SidebarGroup>
218
+ </Sidebar>
219
+ )
220
+
221
+ // contain은 미리보기용이에요. 드로어가 화면 대신 이 상자 안에서 열리게 해요.
222
+ return (
223
+ <Card padding="none" style={{ width: '100%', maxWidth: 760, height: 420, overflow: 'hidden', contain: 'layout paint' }}>
224
+ <AppShell
225
+ sidebar={sidebar}
226
+ mobileSidebarOpen={drawerOpen}
227
+ onMobileSidebarOpenChange={setDrawerOpen}
228
+ header={<Button iconOnly variant="ghost" icon={<Menu />} aria-label="메뉴 열기" onClick={() => setDrawerOpen(true)} />}
229
+ >
230
+ <div style={{ padding: '8px 24px 24px' }}>
231
+ <Text variant="heading-md">{MENU.find((m) => m.id === page)?.label}</Text>
232
+ <Text tone="secondary" style={{ marginTop: 8 }}>
233
+ 창 너비를 900px 이하로 줄이면 사이드바가 숨고, 메뉴 버튼으로 열 수 있어요.
234
+ </Text>
235
+ </div>
236
+ </AppShell>
237
+ </Card>
238
+ )
239
+ }
240
+ ```
241
+
242
+ ### 세 칸 (오른쪽 패널)
243
+
244
+ aside로 오른쪽 패널을 붙이고 asideOpen으로 열고 닫아요(본문 폭이 함께 부드럽게 바뀌어요). 사이드바는 SelectorButton(워크스페이스 · 사용자), NoticeStack, ProgressTracker collapsible로, 헤더는 SelectorButton size="lg" 제목과 아이콘 버튼으로, 패널은 SearchInput · Card+List(IconTile · Kbd) · 세로 ToggleGroup으로 조립했어요. 패널은 900px 이하 화면에서 숨어요.
245
+
246
+ ```tsx
247
+ import { useState, type CSSProperties } from 'react'
248
+ import {
249
+ Bookmark,
250
+ ChevronRight,
251
+ FileText,
252
+ FolderClosed,
253
+ History,
254
+ House,
255
+ Inbox,
256
+ MoreHorizontal,
257
+ Moon,
258
+ PanelLeft,
259
+ PanelRight,
260
+ Plus,
261
+ Search,
262
+ Settings,
263
+ Share,
264
+ Sun,
265
+ } from 'lucide-react'
266
+ import { Avatar, Box, Button, IconTile, Inline, Kbd, SearchInput, SelectorButton, Stack, Text, AppShell, Card, DropdownMenu, DropdownMenuItem, DropdownMenuSeparator, EmptyState, List, ListItem, NoticeStack, ProgressTracker, Sidebar, SidebarGroup, SidebarItem, ToggleGroup, ToggleGroupItem, type NoticeItem, type TrackerStep } from '@iamfiro/design'
267
+
268
+ const NOTICES: NoticeItem[] = [
269
+ {
270
+ id: 'shared-folders',
271
+ eyebrow: '10월 새 기능',
272
+ title: '공유 폴더',
273
+ footer: (
274
+ <Button variant="ghost" size="sm" iconRight={<ChevronRight />}>
275
+ 전체 변경 기록
276
+ </Button>
277
+ ),
278
+ },
279
+ { id: 'templates', eyebrow: '새 기능', title: '문서 템플릿' },
280
+ ]
281
+
282
+ const STEPS: TrackerStep[] = ['프로필 사진 올리기', '팀원 초대하기', '첫 문서 만들기', '폴더 정리하기', '문서 공유하기', '알림 켜기', '모바일 앱 받기', '테마 고르기'].map(
283
+ (label, i) => ({ id: String(i), label }),
284
+ )
285
+
286
+ const TOOLS = [
287
+ { id: 'bookmark', label: '북마크', icon: <Bookmark />, keys: ['mod', 'shift', 'B'] },
288
+ { id: 'history', label: '방문 기록', icon: <History />, keys: ['mod', 'Y'] },
289
+ ]
290
+
291
+ const SUGGESTED = [
292
+ { id: 'wiki', title: '팀 위키', domain: 'wiki.lumen.app' },
293
+ { id: 'design', title: '디자인 가이드', domain: 'design.lumen.app' },
294
+ ]
295
+
296
+ export default function Example() {
297
+ const [page, setPage] = useState('home')
298
+ const [notices, setNotices] = useState(NOTICES)
299
+ const [panelOpen, setPanelOpen] = useState(true)
300
+ const [theme, setTheme] = useState<'light' | 'dark'>('light')
301
+ const item = (id: string) => ({ active: page === id, onClick: () => setPage(id) })
302
+
303
+ const sidebar = (
304
+ <Sidebar
305
+ header={
306
+ <Stack gap={2}>
307
+ <Inline gap={1} justify="end">
308
+ <Button variant="ghost" size="sm" iconOnly icon={<PanelLeft />} aria-label="사이드바 접기" />
309
+ <Button variant="ghost" size="sm" iconOnly icon={<Search />} aria-label="검색" />
310
+ </Inline>
311
+ <DropdownMenu trigger={<SelectorButton block leading={<Avatar name="L" square size={24} />} label="루멘 디자인팀" />}>
312
+ <DropdownMenuItem>루멘 디자인팀</DropdownMenuItem>
313
+ <DropdownMenuItem>사이드 프로젝트</DropdownMenuItem>
314
+ <DropdownMenuSeparator />
315
+ <DropdownMenuItem icon={<Plus />}>새 워크스페이스</DropdownMenuItem>
316
+ </DropdownMenu>
317
+ </Stack>
318
+ }
319
+ footer={
320
+ <Stack gap={3}>
321
+ <NoticeStack items={notices} onDismiss={(id) => setNotices((prev) => prev.filter((n) => n.id !== id))} />
322
+ <ProgressTracker
323
+ collapsible
324
+ title="시작하기"
325
+ steps={STEPS}
326
+ defaultCompleted={['0']}
327
+ summary={(done, total) => `${Math.round((done / total) * 100)}% 완료 · 좋은 출발이에요!`}
328
+ />
329
+ <DropdownMenu minWidth={220} trigger={<SelectorButton block leading={<Avatar name="김민지" size={24} />} label="김민지" />}>
330
+ <DropdownMenuItem icon={<Settings />}>설정</DropdownMenuItem>
331
+ </DropdownMenu>
332
+ </Stack>
333
+ }
334
+ >
335
+ <SidebarGroup>
336
+ <SidebarItem icon={<House />} {...item('home')}>
337
+ 홈
338
+ </SidebarItem>
339
+ <SidebarItem icon={<Inbox />} {...item('inbox')}>
340
+ 받은 편지함
341
+ </SidebarItem>
342
+ </SidebarGroup>
343
+ <SidebarGroup label="프로젝트">
344
+ <SidebarItem icon={<FolderClosed />} {...item('brand')}>
345
+ 브랜드 리뉴얼
346
+ </SidebarItem>
347
+ <SidebarItem icon={<FolderClosed />} {...item('retro')}>
348
+ 3분기 회고
349
+ </SidebarItem>
350
+ </SidebarGroup>
351
+ </Sidebar>
352
+ )
353
+
354
+ const header = (
355
+ <>
356
+ <DropdownMenu trigger={<SelectorButton size="lg" label="새 문서" />}>
357
+ <DropdownMenuItem>이름 바꾸기</DropdownMenuItem>
358
+ <DropdownMenuItem>복제</DropdownMenuItem>
359
+ </DropdownMenu>
360
+ <Inline gap={1} style={{ marginLeft: 'auto' }}>
361
+ <Button variant="ghost" iconOnly icon={<Share />} aria-label="공유" />
362
+ <Button variant="ghost" iconOnly icon={<MoreHorizontal />} aria-label="더 보기" />
363
+ {!panelOpen && <Button variant="ghost" iconOnly icon={<PanelRight />} aria-label="패널 열기" onClick={() => setPanelOpen(true)} />}
364
+ </Inline>
365
+ </>
366
+ )
367
+
368
+ const aside = (
369
+ <Box padding={3}>
370
+ <Stack gap={3}>
371
+ <Inline justify="between" wrap={false}>
372
+ <Text variant="label-lg">워크스페이스</Text>
373
+ <Button variant="ghost" size="sm" iconOnly icon={<PanelRight />} aria-label="패널 닫기" onClick={() => setPanelOpen(false)} />
374
+ </Inline>
375
+ <SearchInput placeholder="검색하거나 URL 입력" size="sm" />
376
+ <Card padding="sm">
377
+ <List label="도구" density="compact">
378
+ {TOOLS.map((t) => (
379
+ <ListItem key={t.id} leading={<IconTile>{t.icon}</IconTile>} title={t.label} onClick={() => {}} trailing={<Kbd keys={t.keys} size="sm" />} />
380
+ ))}
381
+ </List>
382
+ </Card>
383
+ <Card padding="sm">
384
+ <List label="추천" density="compact">
385
+ {SUGGESTED.map((s) => (
386
+ <ListItem key={s.id} leading={<IconTile>{s.title.slice(0, 1)}</IconTile>} title={s.title} description={s.domain} href="#" />
387
+ ))}
388
+ </List>
389
+ </Card>
390
+ <Inline justify="end">
391
+ <ToggleGroup type="single" required orientation="vertical" size="sm" value={theme} onValueChange={(v) => v && setTheme(v)} aria-label="테마">
392
+ <ToggleGroupItem value="light" icon={<Sun />} aria-label="밝게" />
393
+ <ToggleGroupItem value="dark" icon={<Moon />} aria-label="어둡게" />
394
+ </ToggleGroup>
395
+ </Inline>
396
+ </Stack>
397
+ </Box>
398
+ )
399
+
400
+ // 미리보기용 상자예요. 오른쪽 패널은 화면 너비가 900px보다 넓을 때만 보여요.
401
+ return (
402
+ <Card padding="none" style={{ width: '100%', maxWidth: 1080, height: 640, overflow: 'hidden', contain: 'layout paint', '--shell-height': '640px' } as CSSProperties}>
403
+ <AppShell sidebar={sidebar} header={header} sidebarWidth={240} aside={aside} asideWidth={280} asideOpen={panelOpen} asideLabel="워크스페이스">
404
+ <EmptyState icon={<FileText />} title="여기에 페이지가 들어가요" description="왼쪽에서 문서를 고르거나 새로 만들어 보세요." />
405
+ </AppShell>
406
+ </Card>
407
+ )
408
+ }
409
+ ```
@@ -0,0 +1,183 @@
1
+ # AreaChart
2
+
3
+ > 차트 · `@iamfiro/design` · 직접 만들지 말고 이 컴포넌트를 쓴다.
4
+
5
+ 양의 크기와 구성을 함께 보여 주는 영역 차트. LineChart 위에 쌓기 모드를 더한 것이라 축 · Card 툴팁 · 범례 · 키보드 안내선 · bands · referenceLines · endDot · streaming이 그대로 동작해요. default는 시리즈가 바닥에서 겹치는 반투명 영역, stacked는 위로 쌓아 맨 위 선이 합계, percent는 행마다 100%로 맞춘 비율이에요. 데이터가 바뀌면 영역이 새 모양으로 미끄러져요.
6
+
7
+ ```tsx
8
+ import { AreaChart, type LineSeries } from '@iamfiro/design'
9
+ ```
10
+
11
+ ## 디자인 규칙
12
+
13
+ - 영역 차트는 `AreaChart`(= LineChart `area` + `stack`), 따로 만들지 않는다. 겹침(default)은 반투명, 쌓기(`stacked`)는 맨 위 선이 합계이고 툴팁은 위층부터 + 합계 줄, 100%(`percent`)는 툴팁에 몫, 합계 줄엔 실제 수. 층은 위 · 아래 가장자리를 같은 명령으로 그려(`bandPath`) 모드 · 데이터가 바뀌어도 모양이 미끄러진다.
14
+
15
+ ## API
16
+
17
+ ### AreaChart
18
+
19
+ LineChart의 props를 모두 받아요(area · stack 제외). 아래는 AreaChart에서 더하거나 의미가 바뀐 것.
20
+
21
+ | prop | 타입 | 기본값 | 설명 |
22
+ | --- | --- | --- | --- |
23
+ | `type` | `'default' \| 'stacked' \| 'percent'` | `'default'` | 겹침 · 쌓기 · 100% 쌓기. 쌓을 땐 빠진 값(null)을 0으로 셈해요. |
24
+ | `fill` | `'gradient' \| 'solid'` | `'gradient'` | 아래로 옅어지는 채움 또는 한 겹의 옅은 색. 쌓기 모드는 층이 구분되게 조금 더 진해요. |
25
+ | `curve` | `'linear' \| 'smooth'` | `'linear'` | 직선 또는 튀어 오르지 않는 단조 곡선. 층의 위 · 아래 가장자리 모두에 적용돼요. |
26
+ | `connectNulls` | `boolean` | | null을 건너 이어 그려요(default type). |
27
+ | `showTotal` | `boolean` | `stacked · percent면 true` | 툴팁 마지막 줄에 합계. |
28
+ | `tooltipSort` | `'value' \| 'series' \| 'reverse'` | `쌓기 'reverse' · 그 외 'value'` | 툴팁 행 순서. reverse = 위에 쌓인 층부터. |
29
+ | `formatAxisValue` | `(value) => string` | `'6천' · percent '45%'` | y축 라벨. percent에선 값이 0–1 비율이에요. |
30
+ | `yTicks / referenceLines` | `number[] / LineChartReferenceLine[]` | | percent에선 0–1 비율로 적어요(0.5 = 50%). |
31
+ | `aria-label` | `string` | `'영역 차트'` | 차트 이름. 하이라이트한 값과 합계를 aria-live로 읽어요. |
32
+
33
+ ## 예제
34
+
35
+ 예제를 감싼 `style={{ ... }}` div는 미리보기 배치용이다. 실제 화면 배치는 `Stack` · `Inline` · `Grid`로 한다.
36
+
37
+ ### 채널별 방문 (stacked)
38
+
39
+ 쌓인 영역의 맨 위가 하루 합계예요. 툴팁은 위에 쌓인 시리즈부터 나오고 마지막 줄에 합계가 붙어요. 범례에 마우스를 올리면 그 층만 강조돼요.
40
+
41
+ ```tsx
42
+ import { AreaChart, type LineSeries } from '@iamfiro/design'
43
+
44
+ const CHANNELS: LineSeries[] = [
45
+ { key: 'search', label: '검색' },
46
+ { key: 'direct', label: '직접 방문' },
47
+ { key: 'social', label: '소셜' },
48
+ { key: 'email', label: '이메일' },
49
+ ]
50
+
51
+ const DATA = [
52
+ { day: '10월 13일', search: 4200, direct: 2100, social: 1300, email: 600 },
53
+ { day: '10월 14일', search: 4500, direct: 2250, social: 1180, email: 720 },
54
+ { day: '10월 15일', search: 4380, direct: 2400, social: 1420, email: 680 },
55
+ { day: '10월 16일', search: 4920, direct: 2310, social: 1610, email: 910 },
56
+ { day: '10월 17일', search: 5100, direct: 2520, social: 1550, email: 840 },
57
+ { day: '10월 18일', search: 3900, direct: 1980, social: 1890, email: 420 },
58
+ { day: '10월 19일', search: 3700, direct: 1850, social: 2010, email: 390 },
59
+ { day: '10월 20일', search: 5300, direct: 2640, social: 1720, email: 1020 },
60
+ { day: '10월 21일', search: 5480, direct: 2700, social: 1680, email: 960 },
61
+ { day: '10월 22일', search: 5620, direct: 2810, social: 1840, email: 1110 },
62
+ { day: '10월 23일', search: 5750, direct: 2760, social: 1930, email: 1040 },
63
+ { day: '10월 24일', search: 6010, direct: 2920, social: 2080, email: 1180 },
64
+ ]
65
+
66
+ export default function Example() {
67
+ return (
68
+ <AreaChart
69
+ type="stacked"
70
+ data={DATA}
71
+ xKey="day"
72
+ series={CHANNELS}
73
+ curve="smooth"
74
+ height={260}
75
+ formatValue={(v) => `${v.toLocaleString('ko-KR')}명`}
76
+ aria-label="채널별 방문자"
77
+ style={{ width: '100%', maxWidth: 640 }}
78
+ />
79
+ )
80
+ }
81
+ ```
82
+
83
+ ### 비율 (percent)
84
+
85
+ y축은 0–100%, 툴팁 값은 그 행에서의 몫이고 합계 줄은 실제 수예요. fill="solid"는 한 겹의 옅은 색. 연도를 바꾸면 층 경계가 새 위치로 미끄러져요.
86
+
87
+ ```tsx
88
+ import { useState } from 'react'
89
+ import { Button, Inline, Stack, AreaChart, type LineSeries } from '@iamfiro/design'
90
+
91
+ const DEVICES: LineSeries[] = [
92
+ { key: 'mobile', label: '모바일' },
93
+ { key: 'desktop', label: '데스크톱' },
94
+ { key: 'tablet', label: '태블릿' },
95
+ ]
96
+
97
+ const BY_MONTH = [
98
+ { month: '5월', mobile: 5200, desktop: 4100, tablet: 700 },
99
+ { month: '6월', mobile: 5800, desktop: 4000, tablet: 760 },
100
+ { month: '7월', mobile: 6400, desktop: 3900, tablet: 820 },
101
+ { month: '8월', mobile: 7100, desktop: 3700, tablet: 780 },
102
+ { month: '9월', mobile: 7600, desktop: 3800, tablet: 900 },
103
+ { month: '10월', mobile: 8300, desktop: 3600, tablet: 950 },
104
+ ]
105
+
106
+ const LAST_YEAR = [
107
+ { month: '5월', mobile: 3900, desktop: 4800, tablet: 900 },
108
+ { month: '6월', mobile: 4100, desktop: 4700, tablet: 880 },
109
+ { month: '7월', mobile: 4600, desktop: 4500, tablet: 860 },
110
+ { month: '8월', mobile: 4800, desktop: 4600, tablet: 820 },
111
+ { month: '9월', mobile: 5100, desktop: 4400, tablet: 800 },
112
+ { month: '10월', mobile: 5400, desktop: 4300, tablet: 790 },
113
+ ]
114
+
115
+ export default function Example() {
116
+ const [year, setYear] = useState<2025 | 2026>(2026)
117
+ return (
118
+ <Stack gap={4} style={{ width: '100%', maxWidth: 640 }}>
119
+ <AreaChart
120
+ type="percent"
121
+ data={year === 2026 ? BY_MONTH : LAST_YEAR}
122
+ xKey="month"
123
+ series={DEVICES}
124
+ fill="solid"
125
+ yTickCount={5}
126
+ height={240}
127
+ formatValue={(v) => `${v.toLocaleString('ko-KR')}명`}
128
+ aria-label={`${year}년 기기별 방문 비율`}
129
+ />
130
+ <Inline gap={2}>
131
+ <Button size="sm" variant={year === 2025 ? 'primary' : 'secondary'} onClick={() => setYear(2025)}>
132
+ 2025년
133
+ </Button>
134
+ <Button size="sm" variant={year === 2026 ? 'primary' : 'secondary'} onClick={() => setYear(2026)}>
135
+ 2026년
136
+ </Button>
137
+ </Inline>
138
+ </Stack>
139
+ )
140
+ }
141
+ ```
142
+
143
+ ### 겹친 두 시리즈 (default)
144
+
145
+ 두 시리즈를 바닥에서 반투명하게 겹쳐요. connectNulls는 빠진 날(null)을 건너 이어 그리고, referenceLines는 목표선이에요. 포커스한 뒤 ←/→, Home/End, Esc로도 움직여요.
146
+
147
+ ```tsx
148
+ import { AreaChart, type LineSeries } from '@iamfiro/design'
149
+
150
+ const SERIES: LineSeries[] = [
151
+ { key: 'thisWeek', label: '이번 주', color: '--chart-2' },
152
+ { key: 'lastWeek', label: '지난주', color: '--chart-5' },
153
+ ]
154
+
155
+ // 이번 주는 금요일까지만 기록이 있고, 수요일은 집계가 빠졌어요(null → connectNulls로 이어 그림).
156
+ const DATA = [
157
+ { day: '월', thisWeek: 1820, lastWeek: 1640 },
158
+ { day: '화', thisWeek: 2140, lastWeek: 1710 },
159
+ { day: '수', thisWeek: null, lastWeek: 1880 },
160
+ { day: '목', thisWeek: 2480, lastWeek: 1920 },
161
+ { day: '금', thisWeek: 2610, lastWeek: 2050 },
162
+ { day: '토', thisWeek: null, lastWeek: 1420 },
163
+ { day: '일', thisWeek: null, lastWeek: 1290 },
164
+ ]
165
+
166
+ export default function Example() {
167
+ return (
168
+ <AreaChart
169
+ data={DATA}
170
+ xKey="day"
171
+ series={SERIES}
172
+ curve="smooth"
173
+ connectNulls
174
+ referenceLines={[{ value: 2400, label: '목표 2,400건', tone: 'accent' }]}
175
+ height={240}
176
+ tooltipSort="series"
177
+ formatValue={(v) => `${v.toLocaleString('ko-KR')}건`}
178
+ aria-label="요일별 주문 · 이번 주와 지난주"
179
+ style={{ width: '100%', maxWidth: 560 }}
180
+ />
181
+ )
182
+ }
183
+ ```