dishui 0.0.106 → 0.0.110

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 (388) hide show
  1. package/dist/.release-verified.json +3 -2
  2. package/dist/components/Accordion/index.js.map +1 -1
  3. package/dist/components/Avatar/index.js.map +1 -1
  4. package/dist/components/Badge/index.js.map +1 -1
  5. package/dist/components/Button/index.js.map +1 -1
  6. package/dist/components/ButtonMenu/index.js.map +1 -1
  7. package/dist/components/Card/Metric2.js.map +1 -1
  8. package/dist/components/Card/Ticket2.js.map +1 -1
  9. package/dist/components/Card/index.js.map +1 -1
  10. package/dist/components/Chart/Chart.js.map +1 -1
  11. package/dist/components/Checkbox/index.js.map +1 -1
  12. package/dist/components/ChoicePicker/index.js.map +1 -1
  13. package/dist/components/Column/index.js.map +1 -1
  14. package/dist/components/ConfirmDialog/index.js.map +1 -1
  15. package/dist/components/DateTimeInput/index.js.map +1 -1
  16. package/dist/components/Demo/index.js.map +1 -1
  17. package/dist/components/Demo/source.js.map +1 -1
  18. package/dist/components/Divider/index.js.map +1 -1
  19. package/dist/components/EmptyState/index.js.map +1 -1
  20. package/dist/components/Field/index.js.map +1 -1
  21. package/dist/components/FileUploader/DropZone.js.map +1 -1
  22. package/dist/components/FileUploader/FileItem.js.map +1 -1
  23. package/dist/components/FileUploader/FileUploader.js.map +1 -1
  24. package/dist/components/FileUploader/UploadQueue.js.map +1 -1
  25. package/dist/components/GroupButton/index.js.map +1 -1
  26. package/dist/components/GroupedTable/index.js.map +1 -1
  27. package/dist/components/Icon/index.js.map +1 -1
  28. package/dist/components/Image/index.js.map +1 -1
  29. package/dist/components/Input/index.js.map +1 -1
  30. package/dist/components/Label/index.js.map +1 -1
  31. package/dist/components/Layout/index.js.map +1 -1
  32. package/dist/components/LayoutSuite/DashboardSuite.js.map +1 -1
  33. package/dist/components/LayoutSuite/index.js.map +1 -1
  34. package/dist/components/List/index.js.map +1 -1
  35. package/dist/components/Markdown/Markdown.js.map +1 -1
  36. package/dist/components/Markdown/codeThemes.js.map +1 -1
  37. package/dist/components/Markdown/markdownComponents.js.map +1 -1
  38. package/dist/components/Markdown/parseCodeBlockMeta.js.map +1 -1
  39. package/dist/components/Markdown/useMarkdownSource.js.map +1 -1
  40. package/dist/components/Markdown/useMarkmapRenderer.js.map +1 -1
  41. package/dist/components/Markdown/useMermaidRenderer.js.map +1 -1
  42. package/dist/components/Modal/focusScope.js.map +1 -1
  43. package/dist/components/Modal/index.js.map +1 -1
  44. package/dist/components/MultipleChoice/index.js.map +1 -1
  45. package/dist/components/NavigationList/index.js.map +1 -1
  46. package/dist/components/Page/Float2.js.map +1 -1
  47. package/dist/components/Page/index.js.map +1 -1
  48. package/dist/components/Page/resize2.js.map +1 -1
  49. package/dist/components/PageHeader/index.js.map +1 -1
  50. package/dist/components/PagePanel/index.js.map +1 -1
  51. package/dist/components/ProtectedRoute/index.js.map +1 -1
  52. package/dist/components/Resizable/ResizeGrip.js.map +1 -1
  53. package/dist/components/Resizable/index.js.map +1 -1
  54. package/dist/components/Resizable/useResize.js.map +1 -1
  55. package/dist/components/Row/index.js.map +1 -1
  56. package/dist/components/Section/index.js.map +1 -1
  57. package/dist/components/Select/index.js.map +1 -1
  58. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  59. package/dist/components/Skeleton/index.js.map +1 -1
  60. package/dist/components/Slider/index.js.map +1 -1
  61. package/dist/components/Switch/index.js.map +1 -1
  62. package/dist/components/Tab/index.js.map +1 -1
  63. package/dist/components/Table/index.js.map +1 -1
  64. package/dist/components/Tabs/index.js.map +1 -1
  65. package/dist/components/Tabs/tabNavigation.js.map +1 -1
  66. package/dist/components/Text/index.js.map +1 -1
  67. package/dist/components/Textarea/index.js.map +1 -1
  68. package/dist/components/Tooltip/index.js.map +1 -1
  69. package/dist/components/Tree/Tree.js.map +1 -1
  70. package/dist/components/ai/AgentChat/index.js.map +1 -1
  71. package/dist/components/ai/AgentRunCard/index.js.map +1 -1
  72. package/dist/components/ai/AgentScreen/index.js.map +1 -1
  73. package/dist/components/ai/ApprovalCard/index.js.map +1 -1
  74. package/dist/components/ai/CodeView/index.js.map +1 -1
  75. package/dist/components/ai/CommandSearch/index.js.map +1 -1
  76. package/dist/components/ai/ContextCards/index.js.map +1 -1
  77. package/dist/components/ai/DiffTable/index.js.map +1 -1
  78. package/dist/components/ai/FilterTable/index.js.map +1 -1
  79. package/dist/components/ai/FineTuneCard/index.js.map +1 -1
  80. package/dist/components/ai/InsightCards/index.js.map +1 -1
  81. package/dist/components/ai/IssueCard/index.js.map +1 -1
  82. package/dist/components/ai/LoadingState/index.js.map +1 -1
  83. package/dist/components/ai/PromptBar/index.js.map +1 -1
  84. package/dist/components/ai/RecommendationCard/index.js.map +1 -1
  85. package/dist/components/ai/RecordsTable/index.js.map +1 -1
  86. package/dist/components/ai/SelectionActions/index.js.map +1 -1
  87. package/dist/components/ai/StateFlow/index.js.map +1 -1
  88. package/dist/components/ai/StreamingText/index.js.map +1 -1
  89. package/dist/components/ai/TaskRows/index.js.map +1 -1
  90. package/dist/components/ai/Thinking/index.js.map +1 -1
  91. package/dist/components/ai/ToolChips/index.js.map +1 -1
  92. package/dist/components/ai/shared.js.map +1 -1
  93. package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
  94. package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
  95. package/dist/components/pro/ArticleControl/buildHeadingTree.js.map +1 -1
  96. package/dist/components/pro/ArticleControl/useArticleToc.js.map +1 -1
  97. package/dist/components/pro/Calendar/Calendar.js +165 -160
  98. package/dist/components/pro/Calendar/Calendar.js.map +1 -1
  99. package/dist/components/pro/Calendar/hooks/useCalendarDrag.js.map +1 -1
  100. package/dist/components/pro/Calendar/hooks/useCalendarState.js +31 -31
  101. package/dist/components/pro/Calendar/hooks/useCalendarState.js.map +1 -1
  102. package/dist/components/pro/Calendar/utils.js.map +1 -1
  103. package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
  104. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
  105. package/dist/components/pro/CodeEditor/editors/markdownExtensions.js.map +1 -1
  106. package/dist/components/pro/CodeEditor/extensions/contextMenu.js.map +1 -1
  107. package/dist/components/pro/CodeEditor/extensions/index.js.map +1 -1
  108. package/dist/components/pro/CodeEditor/langs/index.js.map +1 -1
  109. package/dist/components/pro/CodeEditor/langs/javascript.js.map +1 -1
  110. package/dist/components/pro/CodeEditor/langs/python.js.map +1 -1
  111. package/dist/components/pro/CodeEditor/langs/snippets.js.map +1 -1
  112. package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
  113. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js +65 -59
  114. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
  115. package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
  116. package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
  117. package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
  118. package/dist/components/pro/CodeEditor/themes.js.map +1 -1
  119. package/dist/components/pro/CodeEditor/utils.js.map +1 -1
  120. package/dist/components/pro/DataTable/DataTable.js.map +1 -1
  121. package/dist/components/pro/DataTable/Filters.js.map +1 -1
  122. package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
  123. package/dist/components/pro/DataTable/PivotView.js.map +1 -1
  124. package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
  125. package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
  126. package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
  127. package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
  128. package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
  129. package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
  130. package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
  131. package/dist/components/pro/DataTable/extension.js.map +1 -1
  132. package/dist/components/pro/DataTable/pivotEngine.js.map +1 -1
  133. package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
  134. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  135. package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
  136. package/dist/components/pro/DataTable/treeDataUtils.js.map +1 -1
  137. package/dist/components/pro/DataTable/useColumnDragReorder.js.map +1 -1
  138. package/dist/components/pro/DataTable/useDataTableModel.js +119 -104
  139. package/dist/components/pro/DataTable/useDataTableModel.js.map +1 -1
  140. package/dist/components/pro/DataTable/utils.js.map +1 -1
  141. package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
  142. package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
  143. package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
  144. package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
  145. package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
  146. package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
  147. package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
  148. package/dist/components/pro/Flow/Flow.js.map +1 -1
  149. package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
  150. package/dist/components/pro/Flow/archify/build.js.map +1 -1
  151. package/dist/components/pro/Flow/archify/convert.js.map +1 -1
  152. package/dist/components/pro/Flow/archify/palette.js.map +1 -1
  153. package/dist/components/pro/Flow/archify/presets.js.map +1 -1
  154. package/dist/components/pro/Flow/archify/spec.js.map +1 -1
  155. package/dist/components/pro/Flow/canvas/AlignmentGuides.js.map +1 -1
  156. package/dist/components/pro/Flow/canvas/GridRenderer.js.map +1 -1
  157. package/dist/components/pro/Flow/canvas/MiniMapRenderer.js.map +1 -1
  158. package/dist/components/pro/Flow/canvas/PixiApp.js.map +1 -1
  159. package/dist/components/pro/Flow/canvas/SelectionOverlay.js.map +1 -1
  160. package/dist/components/pro/Flow/canvas/ViewportContainer.js.map +1 -1
  161. package/dist/components/pro/Flow/constants.js.map +1 -1
  162. package/dist/components/pro/Flow/context/FlowAIContext.js.map +1 -1
  163. package/dist/components/pro/Flow/context/FlowContext.js.map +1 -1
  164. package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
  165. package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
  166. package/dist/components/pro/Flow/edges/edgeMarkers.js.map +1 -1
  167. package/dist/components/pro/Flow/edges/edgePaths.js.map +1 -1
  168. package/dist/components/pro/Flow/hooks/useAlignmentGuides.js.map +1 -1
  169. package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
  170. package/dist/components/pro/Flow/hooks/useCompactMode.js.map +1 -1
  171. package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
  172. package/dist/components/pro/Flow/hooks/useDraggablePanel.js.map +1 -1
  173. package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
  174. package/dist/components/pro/Flow/hooks/useFlowImportExport.js.map +1 -1
  175. package/dist/components/pro/Flow/hooks/useKeyboardShortcuts.js.map +1 -1
  176. package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
  177. package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
  178. package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
  179. package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
  180. package/dist/components/pro/Flow/hooks/usePdfExport.js.map +1 -1
  181. package/dist/components/pro/Flow/hooks/usePixiApp.js.map +1 -1
  182. package/dist/components/pro/Flow/hooks/useResizablePanel.js.map +1 -1
  183. package/dist/components/pro/Flow/hooks/useSelection.js.map +1 -1
  184. package/dist/components/pro/Flow/hooks/useUndoRedo.js.map +1 -1
  185. package/dist/components/pro/Flow/hooks/useViewport.js.map +1 -1
  186. package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
  187. package/dist/components/pro/Flow/lines/GeometricLineTool.js.map +1 -1
  188. package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
  189. package/dist/components/pro/Flow/lines/lineSmoothing.js.map +1 -1
  190. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  191. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  192. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  193. package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
  194. package/dist/components/pro/Flow/nodes/NodeHandles.js.map +1 -1
  195. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  196. package/dist/components/pro/Flow/nodes/NodeText.js.map +1 -1
  197. package/dist/components/pro/Flow/nodes/aiClient.js.map +1 -1
  198. package/dist/components/pro/Flow/nodes/animAnchors.js.map +1 -1
  199. package/dist/components/pro/Flow/nodes/chartGeometryBudget.js.map +1 -1
  200. package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
  201. package/dist/components/pro/Flow/nodes/demandRender.js.map +1 -1
  202. package/dist/components/pro/Flow/nodes/nodeUtils.js.map +1 -1
  203. package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
  204. package/dist/components/pro/Flow/nodes/svgIconTexture.js.map +1 -1
  205. package/dist/components/pro/Flow/nodes/svgIcons.js.map +1 -1
  206. package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
  207. package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
  208. package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
  209. package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
  210. package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
  211. package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
  212. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  213. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  214. package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
  215. package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
  216. package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
  217. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  218. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  219. package/dist/components/pro/Flow/types.js.map +1 -1
  220. package/dist/components/pro/Flow/utils/dashedLine.js.map +1 -1
  221. package/dist/components/pro/Flow/utils/gradient.js.map +1 -1
  222. package/dist/components/pro/Flow/utils/pdfExport.js.map +1 -1
  223. package/dist/components/pro/Flow/utils/themeColor.js.map +1 -1
  224. package/dist/components/pro/Gantt/Gantt.js.map +1 -1
  225. package/dist/components/pro/Gantt/hooks/useGanttDrag.js.map +1 -1
  226. package/dist/components/pro/Gantt/hooks/useGanttState.js +79 -71
  227. package/dist/components/pro/Gantt/hooks/useGanttState.js.map +1 -1
  228. package/dist/components/pro/Gantt/utils.js.map +1 -1
  229. package/dist/components/pro/Kanban/Kanban.js.map +1 -1
  230. package/dist/components/pro/Kanban/Swimlanes.js.map +1 -1
  231. package/dist/components/pro/Kanban/useKanbanDrag.js.map +1 -1
  232. package/dist/components/pro/Kanban/utils.js.map +1 -1
  233. package/dist/components/pro/RichTextEditor/AIRewrite.d.ts +1 -0
  234. package/dist/components/pro/RichTextEditor/AIRewrite.js +109 -88
  235. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  236. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  237. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  238. package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
  239. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  240. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  241. package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
  242. package/dist/components/pro/RichTextEditor/RichTextEditor.js +133 -132
  243. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  244. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  245. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  246. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  247. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  248. package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
  249. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
  250. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  251. package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js.map +1 -1
  252. package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js.map +1 -1
  253. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  254. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js.map +1 -1
  255. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  256. package/dist/components/pro/RichTextEditor/extensions/FontSize.js.map +1 -1
  257. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  258. package/dist/components/pro/RichTextEditor/extensions/ResizableImage.js.map +1 -1
  259. package/dist/components/pro/RichTextEditor/extensions/legacyMermaid.js.map +1 -1
  260. package/dist/components/pro/RichTextEditor/types.d.ts +2 -0
  261. package/dist/components/pro/RichTextEditor/types.js.map +1 -1
  262. package/dist/components/pro/Sprite/Molly/animations.d.ts +6 -0
  263. package/dist/components/pro/Sprite/Molly/animations.js +52 -0
  264. package/dist/components/pro/Sprite/Molly/animations.js.map +1 -0
  265. package/dist/components/pro/Sprite/Molly/events.d.ts +2 -0
  266. package/dist/components/pro/Sprite/Molly/events.js +46 -0
  267. package/dist/components/pro/Sprite/Molly/events.js.map +1 -0
  268. package/dist/components/pro/Sprite/Molly/index.d.ts +1 -0
  269. package/dist/components/pro/Sprite/Molly/index.js +12 -0
  270. package/dist/components/pro/Sprite/Molly/index.js.map +1 -0
  271. package/dist/components/pro/Sprite/Molly/legFlexion.d.ts +3 -0
  272. package/dist/components/pro/Sprite/Molly/legFlexion.js +48 -0
  273. package/dist/components/pro/Sprite/Molly/legFlexion.js.map +1 -0
  274. package/dist/components/pro/Sprite/Molly/locomotion.d.ts +4 -0
  275. package/dist/components/pro/Sprite/Molly/locomotion.js +51 -0
  276. package/dist/components/pro/Sprite/Molly/locomotion.js.map +1 -0
  277. package/dist/components/pro/Sprite/Molly/model.d.ts +23 -0
  278. package/dist/components/pro/Sprite/Molly/model.js +614 -0
  279. package/dist/components/pro/Sprite/Molly/model.js.map +1 -0
  280. package/dist/components/pro/Sprite/Molly/rig.d.ts +25 -0
  281. package/dist/components/pro/Sprite/Molly/rig.js +102 -0
  282. package/dist/components/pro/Sprite/Molly/rig.js.map +1 -0
  283. package/dist/components/pro/Sprite/Ruby/animations.d.ts +6 -0
  284. package/dist/components/pro/Sprite/Ruby/animations.js +58 -0
  285. package/dist/components/pro/Sprite/Ruby/animations.js.map +1 -0
  286. package/dist/components/pro/Sprite/Ruby/events.d.ts +2 -0
  287. package/dist/components/pro/Sprite/Ruby/events.js +46 -0
  288. package/dist/components/pro/Sprite/Ruby/events.js.map +1 -0
  289. package/dist/components/pro/Sprite/Ruby/index.d.ts +1 -0
  290. package/dist/components/pro/Sprite/Ruby/index.js +12 -0
  291. package/dist/components/pro/Sprite/Ruby/index.js.map +1 -0
  292. package/dist/components/pro/Sprite/Ruby/locomotion.d.ts +4 -0
  293. package/dist/components/pro/Sprite/Ruby/locomotion.js +41 -0
  294. package/dist/components/pro/Sprite/Ruby/locomotion.js.map +1 -0
  295. package/dist/components/pro/Sprite/Ruby/model.d.ts +23 -0
  296. package/dist/components/pro/Sprite/Ruby/model.js +605 -0
  297. package/dist/components/pro/Sprite/Ruby/model.js.map +1 -0
  298. package/dist/components/pro/Sprite/Ruby/rig.d.ts +26 -0
  299. package/dist/components/pro/Sprite/Ruby/rig.js +112 -0
  300. package/dist/components/pro/Sprite/Ruby/rig.js.map +1 -0
  301. package/dist/components/pro/Sprite/Sprite.d.ts +23 -0
  302. package/dist/components/pro/Sprite/Sprite2.js +224 -0
  303. package/dist/components/pro/Sprite/Sprite2.js.map +1 -0
  304. package/dist/components/pro/Sprite/actions.d.ts +3 -0
  305. package/dist/components/pro/Sprite/actions.js +16 -0
  306. package/dist/components/pro/Sprite/actions.js.map +1 -0
  307. package/dist/components/pro/Sprite/createSpriteScene.d.ts +4 -0
  308. package/dist/components/pro/Sprite/createSpriteScene.js +14 -0
  309. package/dist/components/pro/Sprite/createSpriteScene.js.map +1 -0
  310. package/dist/components/pro/Sprite/index.d.ts +4 -0
  311. package/dist/components/pro/Sprite/shared/animation.d.ts +33 -0
  312. package/dist/components/pro/Sprite/shared/animation.js +39 -0
  313. package/dist/components/pro/Sprite/shared/animation.js.map +1 -0
  314. package/dist/components/pro/Sprite/shared/createSpriteStage.d.ts +14 -0
  315. package/dist/components/pro/Sprite/shared/createSpriteStage.js +127 -0
  316. package/dist/components/pro/Sprite/shared/createSpriteStage.js.map +1 -0
  317. package/dist/components/pro/Sprite/shared/events.d.ts +5 -0
  318. package/dist/components/pro/Sprite/shared/events.js +21 -0
  319. package/dist/components/pro/Sprite/shared/events.js.map +1 -0
  320. package/dist/components/pro/Sprite/shared/face.d.ts +15 -0
  321. package/dist/components/pro/Sprite/shared/face.js +33 -0
  322. package/dist/components/pro/Sprite/shared/face.js.map +1 -0
  323. package/dist/components/pro/Sprite/shared/faceSurface.d.ts +6 -0
  324. package/dist/components/pro/Sprite/shared/faceSurface.js +66 -0
  325. package/dist/components/pro/Sprite/shared/faceSurface.js.map +1 -0
  326. package/dist/components/pro/Sprite/shared/gait.d.ts +5 -0
  327. package/dist/components/pro/Sprite/shared/gait.js +19 -0
  328. package/dist/components/pro/Sprite/shared/gait.js.map +1 -0
  329. package/dist/components/pro/Sprite/shared/geometry.d.ts +8 -0
  330. package/dist/components/pro/Sprite/shared/geometry.js +59 -0
  331. package/dist/components/pro/Sprite/shared/geometry.js.map +1 -0
  332. package/dist/components/pro/Sprite/shared/magicEffect.d.ts +27 -0
  333. package/dist/components/pro/Sprite/shared/magicEffect.js +61 -0
  334. package/dist/components/pro/Sprite/shared/magicEffect.js.map +1 -0
  335. package/dist/components/pro/Sprite/shared/playback.d.ts +8 -0
  336. package/dist/components/pro/Sprite/shared/playback.js +74 -0
  337. package/dist/components/pro/Sprite/shared/playback.js.map +1 -0
  338. package/dist/components/pro/Sprite/shared/rig.d.ts +6 -0
  339. package/dist/components/pro/Sprite/shared/rig.js +48 -0
  340. package/dist/components/pro/Sprite/shared/rig.js.map +1 -0
  341. package/dist/components/pro/Sprite/shared/scene.d.ts +9 -0
  342. package/dist/components/pro/Sprite/shared/scene.js +21 -0
  343. package/dist/components/pro/Sprite/shared/scene.js.map +1 -0
  344. package/dist/components/pro/Sprite/shared/sculptor.d.ts +14 -0
  345. package/dist/components/pro/Sprite/shared/sculptor.js +78 -0
  346. package/dist/components/pro/Sprite/shared/sculptor.js.map +1 -0
  347. package/dist/components/pro/Sprite/shared/speechBubble.d.ts +15 -0
  348. package/dist/components/pro/Sprite/shared/speechBubble.js +129 -0
  349. package/dist/components/pro/Sprite/shared/speechBubble.js.map +1 -0
  350. package/dist/components/pro/Sprite/types.d.ts +40 -0
  351. package/dist/contexts/AppContext.js.map +1 -1
  352. package/dist/contexts/authentication.js.map +1 -1
  353. package/dist/data-table.js +3 -3
  354. package/dist/data-table.js.map +1 -1
  355. package/dist/dishui.css +1 -1
  356. package/dist/hooks/useClickOutside.js.map +1 -1
  357. package/dist/hooks/useContainerElement.js.map +1 -1
  358. package/dist/hooks/useControllableState.js.map +1 -1
  359. package/dist/hooks/useCopyToClipboard.js.map +1 -1
  360. package/dist/hooks/useDebounce.js.map +1 -1
  361. package/dist/hooks/useDraggable.js.map +1 -1
  362. package/dist/hooks/useTableColumns.js.map +1 -1
  363. package/dist/hooks/useTableData.js.map +1 -1
  364. package/dist/index-nostyled.d.ts +2 -0
  365. package/dist/index.d.ts +2 -0
  366. package/dist/index.js +116 -115
  367. package/dist/layouts/MainLayout.js.map +1 -1
  368. package/dist/layouts/Navbar.js.map +1 -1
  369. package/dist/layouts/Sidebar.js.map +1 -1
  370. package/dist/layouts/headbar/Headbar.js.map +1 -1
  371. package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
  372. package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
  373. package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
  374. package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
  375. package/dist/sprite.js +2 -0
  376. package/dist/styles/themeStyles.js.map +1 -1
  377. package/dist/utils/cn.js.map +1 -1
  378. package/dist/utils/flexLayout.js.map +1 -1
  379. package/dist/utils/i18n.js.map +1 -1
  380. package/dist/utils/menu.js.map +1 -1
  381. package/dist/utils/rehype-code-meta.js.map +1 -1
  382. package/dist/utils/remark-code-meta.js.map +1 -1
  383. package/dist/utils/routerBuilder.js.map +1 -1
  384. package/dist/utils/safeStorage.js.map +1 -1
  385. package/dist/utils/selection.js +29 -20
  386. package/dist/utils/selection.js.map +1 -1
  387. package/dist/utils/themes.js.map +1 -1
  388. package/package.json +15 -11
@@ -1 +1 @@
1
- {"version":3,"file":"DropZone.js","names":[],"sources":["../../../src/components/FileUploader/DropZone.tsx"],"sourcesContent":["import React, { useRef, useState, useCallback } from 'react';\nimport { DropZoneProps } from './types';\nimport Button from '../Button';\n\nconst defaultLabels = {\n dropzoneTitle: 'Drop files here',\n dropzoneHint: 'or click to browse',\n browseButton: 'Browse Files',\n fileTooLarge: 'File too large',\n fileTypeNotAllowed: 'File type not allowed',\n maxFilesReached: 'Maximum number of files reached',\n};\n\nconst UploadIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-10 w-10 opacity-40\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12\" />\n </svg>\n);\n\n/** Validate a single file against accept list and max size */\nfunction validateFile(\n file: File,\n accept?: string[],\n maxFileSize?: number,\n): string | null {\n // Check file type\n if (accept && accept.length > 0) {\n const allowed = accept.some(pattern => {\n if (pattern.startsWith('.')) {\n // Extension match\n return file.name.toLowerCase().endsWith(pattern.toLowerCase());\n }\n if (pattern.endsWith('/*')) {\n // MIME prefix match (e.g. image/*)\n const prefix = pattern.replace('/*', '/');\n return file.type.startsWith(prefix);\n }\n // Exact MIME match\n return file.type === pattern;\n });\n if (!allowed) return 'fileTypeNotAllowed';\n }\n\n // Check file size\n if (maxFileSize && file.size > maxFileSize) {\n return 'fileTooLarge';\n }\n\n return null;\n}\n\nexport const DropZone: React.FC<DropZoneProps> = ({\n accept,\n maxFileSize,\n maxFiles,\n multiple = true,\n currentFileCount = 0,\n labels: userLabels,\n className = '',\n disabled = false,\n onFilesAdded,\n onValidationError,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n const inputRef = useRef<HTMLInputElement>(null);\n const [isDragOver, setIsDragOver] = useState(false);\n\n const processFiles = useCallback((rawFiles: File[]) => {\n const valid: File[] = [];\n for (const file of rawFiles) {\n // Check max files limit\n if (maxFiles && (currentFileCount + valid.length) >= maxFiles) {\n onValidationError?.(file, labels.maxFilesReached!);\n break;\n }\n const error = validateFile(file, accept, maxFileSize);\n if (error) {\n onValidationError?.(file, labels[error as keyof typeof labels] || error);\n } else {\n valid.push(file);\n }\n }\n if (valid.length > 0) {\n onFilesAdded(multiple ? valid : [valid[0]]);\n }\n }, [accept, maxFileSize, maxFiles, multiple, currentFileCount, labels, onFilesAdded, onValidationError]);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (!disabled) setIsDragOver(true);\n }, [disabled]);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n }, []);\n\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n if (disabled) return;\n const files = Array.from(e.dataTransfer.files);\n processFiles(files);\n }, [disabled, processFiles]);\n\n const handleClick = useCallback(() => {\n if (!disabled) inputRef.current?.click();\n }, [disabled]);\n\n const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const files = Array.from(e.target.files || []);\n processFiles(files);\n // Reset input so same file can be re-selected\n if (inputRef.current) inputRef.current.value = '';\n }, [processFiles]);\n\n const acceptStr = accept?.join(',');\n\n return (\n <div\n className={`\n relative flex flex-col items-center justify-center\n min-h-[200px] p-6 sm:p-8\n border-2 border-dashed rounded-xl\n transition-colors duration-200 cursor-pointer\n ${isDragOver\n ? 'border-primary bg-primary/5'\n : 'border-base-300 hover:border-primary/50 bg-base-100'\n }\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${className}\n `}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onClick={handleClick}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') handleClick(); }}\n >\n <input\n ref={inputRef}\n type=\"file\"\n className=\"hidden\"\n accept={acceptStr}\n multiple={multiple}\n onChange={handleInputChange}\n disabled={disabled}\n />\n\n <UploadIcon />\n\n <p className=\"mt-3 text-base font-semibold text-base-content\">\n {labels.dropzoneTitle}\n </p>\n <p className=\"mt-1 text-sm opacity-60\">\n {labels.dropzoneHint}\n </p>\n\n <Button\n variant=\"primary\"\n size=\"sm\"\n outline\n className=\"mt-4\"\n disabled={disabled}\n onClick={() => { /* click propagation handled by parent div */ }}\n >\n {labels.browseButton}\n </Button>\n\n {accept && accept.length > 0 && (\n <p className=\"mt-3 text-xs opacity-50\">\n {accept.join(', ')}\n </p>\n )}\n {maxFileSize && (\n <p className=\"text-xs opacity-50\">\n Max: {formatFileSize(maxFileSize)}\n </p>\n )}\n </div>\n );\n};\n\n/** Format bytes to human-readable string */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DropZone.js","names":["Button","ButtonWithCompounds","defaultLabels","UploadIcon","validateFile","accept","pattern","file","prefix","maxFileSize","DropZone","userLabels","labels","inputRef","useRef","isDragOver","setIsDragOver","useState","processFiles","useCallback","valid","rawFiles","maxFiles","currentFileCount","error","onValidationError","onFilesAdded","multiple","handleDragOver","disabled","handleDragLeave","handleDrop","files","handleClick","handleInputChange","acceptStr","className","formatFileSize","bytes","k","sizes","i"],"sources":["../../../src/components/FileUploader/DropZone.tsx"],"sourcesContent":["import React, { useRef, useState, useCallback } from 'react';\nimport { DropZoneProps } from './types';\nimport Button from '../Button';\n\nconst defaultLabels = {\n dropzoneTitle: 'Drop files here',\n dropzoneHint: 'or click to browse',\n browseButton: 'Browse Files',\n fileTooLarge: 'File too large',\n fileTypeNotAllowed: 'File type not allowed',\n maxFilesReached: 'Maximum number of files reached',\n};\n\nconst UploadIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-10 w-10 opacity-40\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12\" />\n </svg>\n);\n\n/** Validate a single file against accept list and max size */\nfunction validateFile(\n file: File,\n accept?: string[],\n maxFileSize?: number,\n): string | null {\n // Check file type\n if (accept && accept.length > 0) {\n const allowed = accept.some(pattern => {\n if (pattern.startsWith('.')) {\n // Extension match\n return file.name.toLowerCase().endsWith(pattern.toLowerCase());\n }\n if (pattern.endsWith('/*')) {\n // MIME prefix match (e.g. image/*)\n const prefix = pattern.replace('/*', '/');\n return file.type.startsWith(prefix);\n }\n // Exact MIME match\n return file.type === pattern;\n });\n if (!allowed) return 'fileTypeNotAllowed';\n }\n\n // Check file size\n if (maxFileSize && file.size > maxFileSize) {\n return 'fileTooLarge';\n }\n\n return null;\n}\n\nexport const DropZone: React.FC<DropZoneProps> = ({\n accept,\n maxFileSize,\n maxFiles,\n multiple = true,\n currentFileCount = 0,\n labels: userLabels,\n className = '',\n disabled = false,\n onFilesAdded,\n onValidationError,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n const inputRef = useRef<HTMLInputElement>(null);\n const [isDragOver, setIsDragOver] = useState(false);\n\n const processFiles = useCallback((rawFiles: File[]) => {\n const valid: File[] = [];\n for (const file of rawFiles) {\n // Check max files limit\n if (maxFiles && (currentFileCount + valid.length) >= maxFiles) {\n onValidationError?.(file, labels.maxFilesReached!);\n break;\n }\n const error = validateFile(file, accept, maxFileSize);\n if (error) {\n onValidationError?.(file, labels[error as keyof typeof labels] || error);\n } else {\n valid.push(file);\n }\n }\n if (valid.length > 0) {\n onFilesAdded(multiple ? valid : [valid[0]]);\n }\n }, [accept, maxFileSize, maxFiles, multiple, currentFileCount, labels, onFilesAdded, onValidationError]);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (!disabled) setIsDragOver(true);\n }, [disabled]);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n }, []);\n\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n if (disabled) return;\n const files = Array.from(e.dataTransfer.files);\n processFiles(files);\n }, [disabled, processFiles]);\n\n const handleClick = useCallback(() => {\n if (!disabled) inputRef.current?.click();\n }, [disabled]);\n\n const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const files = Array.from(e.target.files || []);\n processFiles(files);\n // Reset input so same file can be re-selected\n if (inputRef.current) inputRef.current.value = '';\n }, [processFiles]);\n\n const acceptStr = accept?.join(',');\n\n return (\n <div\n className={`\n relative flex flex-col items-center justify-center\n min-h-[200px] p-6 sm:p-8\n border-2 border-dashed rounded-xl\n transition-colors duration-200 cursor-pointer\n ${isDragOver\n ? 'border-primary bg-primary/5'\n : 'border-base-300 hover:border-primary/50 bg-base-100'\n }\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${className}\n `}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onClick={handleClick}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') handleClick(); }}\n >\n <input\n ref={inputRef}\n type=\"file\"\n className=\"hidden\"\n accept={acceptStr}\n multiple={multiple}\n onChange={handleInputChange}\n disabled={disabled}\n />\n\n <UploadIcon />\n\n <p className=\"mt-3 text-base font-semibold text-base-content\">\n {labels.dropzoneTitle}\n </p>\n <p className=\"mt-1 text-sm opacity-60\">\n {labels.dropzoneHint}\n </p>\n\n <Button\n variant=\"primary\"\n size=\"sm\"\n outline\n className=\"mt-4\"\n disabled={disabled}\n onClick={() => { /* click propagation handled by parent div */ }}\n >\n {labels.browseButton}\n </Button>\n\n {accept && accept.length > 0 && (\n <p className=\"mt-3 text-xs opacity-50\">\n {accept.join(', ')}\n </p>\n )}\n {maxFileSize && (\n <p className=\"text-xs opacity-50\">\n Max: {formatFileSize(maxFileSize)}\n </p>\n )}\n </div>\n );\n};\n\n/** Format bytes to human-readable string */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"FileItem.js","names":[],"sources":["../../../src/components/FileUploader/FileItem.tsx"],"sourcesContent":["import React from 'react';\nimport { FileItemProps, UploadStatus } from './types';\nimport Badge from '../Badge';\nimport Button from '../Button';\nimport { formatFileSize } from './DropZone';\n\nconst defaultLabels = {\n removeFile: 'Remove',\n retryFile: 'Retry',\n uploading: 'Uploading',\n uploaded: 'Uploaded',\n failed: 'Failed',\n pending: 'Pending',\n};\n\n// --- Icons ---\n\nconst FileIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5 opacity-60 flex-shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n);\n\nconst RemoveIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n);\n\nconst RetryIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\" />\n </svg>\n);\n\nconst CheckIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n);\n\n// --- Status Badge ---\n\nfunction statusBadge(status: UploadStatus, labels: typeof defaultLabels) {\n switch (status) {\n case 'pending':\n return <Badge variant=\"ghost\" size=\"xs\">{labels.pending}</Badge>;\n case 'uploading':\n return <Badge variant=\"info\" size=\"xs\">{labels.uploading}</Badge>;\n case 'success':\n return <Badge variant=\"success\" size=\"xs\"><CheckIcon /> {labels.uploaded}</Badge>;\n case 'error':\n return <Badge variant=\"error\" size=\"xs\">{labels.failed}</Badge>;\n }\n}\n\n// --- Component ---\n\nexport const FileItem: React.FC<FileItemProps> = ({\n item,\n labels: userLabels,\n onRemove,\n onRetry,\n onCancel,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n\n return (\n <div className=\"flex items-center gap-3 px-3 py-2 rounded-lg bg-base-200/50 hover:bg-base-200 transition-colors min-h-[52px]\">\n {/* File icon */}\n <FileIcon />\n\n {/* File info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium truncate\">{item.file.name}</span>\n {statusBadge(item.status, labels)}\n </div>\n <div className=\"flex items-center gap-2 mt-0.5\">\n <span className=\"text-xs opacity-50\">{formatFileSize(item.file.size)}</span>\n {item.error && (\n <span className=\"text-xs text-error truncate\">{item.error}</span>\n )}\n </div>\n\n {/* Progress bar */}\n {item.status === 'uploading' && (\n <div className=\"mt-1\">\n <progress\n className=\"progress progress-primary w-full h-1.5\"\n value={item.progress}\n max={100}\n />\n </div>\n )}\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n {item.status === 'error' && (\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n onClick={() => onRetry(item.id)}\n className=\"text-info\"\n >\n <RetryIcon />\n </Button>\n )}\n {item.status === 'uploading' && (\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n onClick={() => onCancel(item.id)}\n className=\"text-warning\"\n >\n <RemoveIcon />\n </Button>\n )}\n {(item.status === 'pending' || item.status === 'success' || item.status === 'error') && (\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n onClick={() => onRemove(item.id)}\n className=\"text-error\"\n >\n <RemoveIcon />\n </Button>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"FileItem.js","names":["Button","ButtonWithCompounds","Badge","defaultLabels","FileIcon","RemoveIcon","RetryIcon","CheckIcon","statusBadge","status","labels","FileItem","userLabels","item","formatFileSize","onRetry","onCancel","onRemove"],"sources":["../../../src/components/FileUploader/FileItem.tsx"],"sourcesContent":["import React from 'react';\nimport { FileItemProps, UploadStatus } from './types';\nimport Badge from '../Badge';\nimport Button from '../Button';\nimport { formatFileSize } from './DropZone';\n\nconst defaultLabels = {\n removeFile: 'Remove',\n retryFile: 'Retry',\n uploading: 'Uploading',\n uploaded: 'Uploaded',\n failed: 'Failed',\n pending: 'Pending',\n};\n\n// --- Icons ---\n\nconst FileIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5 opacity-60 flex-shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n);\n\nconst RemoveIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n);\n\nconst RetryIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\" />\n </svg>\n);\n\nconst CheckIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n);\n\n// --- Status Badge ---\n\nfunction statusBadge(status: UploadStatus, labels: typeof defaultLabels) {\n switch (status) {\n case 'pending':\n return <Badge variant=\"ghost\" size=\"xs\">{labels.pending}</Badge>;\n case 'uploading':\n return <Badge variant=\"info\" size=\"xs\">{labels.uploading}</Badge>;\n case 'success':\n return <Badge variant=\"success\" size=\"xs\"><CheckIcon /> {labels.uploaded}</Badge>;\n case 'error':\n return <Badge variant=\"error\" size=\"xs\">{labels.failed}</Badge>;\n }\n}\n\n// --- Component ---\n\nexport const FileItem: React.FC<FileItemProps> = ({\n item,\n labels: userLabels,\n onRemove,\n onRetry,\n onCancel,\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n\n return (\n <div className=\"flex items-center gap-3 px-3 py-2 rounded-lg bg-base-200/50 hover:bg-base-200 transition-colors min-h-[52px]\">\n {/* File icon */}\n <FileIcon />\n\n {/* File info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium truncate\">{item.file.name}</span>\n {statusBadge(item.status, labels)}\n </div>\n <div className=\"flex items-center gap-2 mt-0.5\">\n <span className=\"text-xs opacity-50\">{formatFileSize(item.file.size)}</span>\n {item.error && (\n <span className=\"text-xs text-error truncate\">{item.error}</span>\n )}\n </div>\n\n {/* Progress bar */}\n {item.status === 'uploading' && (\n <div className=\"mt-1\">\n <progress\n className=\"progress progress-primary w-full h-1.5\"\n value={item.progress}\n max={100}\n />\n </div>\n )}\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n {item.status === 'error' && (\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n onClick={() => onRetry(item.id)}\n className=\"text-info\"\n >\n <RetryIcon />\n </Button>\n )}\n {item.status === 'uploading' && (\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n onClick={() => onCancel(item.id)}\n className=\"text-warning\"\n >\n <RemoveIcon />\n </Button>\n )}\n {(item.status === 'pending' || item.status === 'success' || item.status === 'error') && (\n <Button\n variant=\"ghost\"\n size=\"xs\"\n circle\n onClick={() => onRemove(item.id)}\n className=\"text-error\"\n >\n <RemoveIcon />\n </Button>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"FileUploader.js","names":[],"sources":["../../../src/components/FileUploader/FileUploader.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef } from 'react';\nimport { FileUploaderProps, FileItemState, UploadResult } from './types';\nimport { DropZone } from './DropZone';\nimport { UploadQueue } from './UploadQueue';\n\nlet fileIdCounter = 0;\nfunction nextFileId(): string {\n return `file-${Date.now()}-${++fileIdCounter}`;\n}\n\nexport const FileUploader: React.FC<FileUploaderProps> = ({\n adapter,\n accept,\n maxFileSize,\n maxFiles,\n multiple = true,\n autoUpload = false,\n className = '',\n labels,\n onUploadComplete,\n onError,\n onFilesChange,\n}) => {\n const [items, setItems] = useState<FileItemState[]>([]);\n const itemsRef = useRef<FileItemState[]>([]);\n\n // Keep ref in sync for use in async callbacks\n const updateItems = useCallback((updater: (prev: FileItemState[]) => FileItemState[]) => {\n setItems(prev => {\n const next = updater(prev);\n itemsRef.current = next;\n onFilesChange?.(next);\n return next;\n });\n }, [onFilesChange]);\n\n // Upload a single file item\n const uploadFile = useCallback(async (item: FileItemState) => {\n const abortController = new AbortController();\n\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id\n ? { ...i, status: 'uploading' as const, progress: 0, error: undefined, abortController }\n : i\n )\n );\n\n try {\n const result = await adapter.upload(\n item.file,\n (percent) => {\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id ? { ...i, progress: Math.min(percent, 100) } : i\n )\n );\n },\n abortController.signal,\n );\n\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id\n ? { ...i, status: 'success' as const, progress: 100, result, abortController: undefined }\n : i\n )\n );\n\n return result;\n } catch (err: any) {\n if (err?.name === 'AbortError') {\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id\n ? { ...i, status: 'pending' as const, progress: 0, abortController: undefined }\n : i\n )\n );\n return null;\n }\n\n const errorMsg = err?.message || 'Upload failed';\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id\n ? { ...i, status: 'error' as const, error: errorMsg, abortController: undefined }\n : i\n )\n );\n onError?.(item.file, err instanceof Error ? err : new Error(errorMsg));\n return null;\n }\n }, [adapter, updateItems, onError]);\n\n // Add files from drop zone\n const handleFilesAdded = useCallback((files: File[]) => {\n const newItems: FileItemState[] = files.map(file => ({\n id: nextFileId(),\n file,\n status: 'pending' as const,\n progress: 0,\n }));\n\n updateItems(prev => [...prev, ...newItems]);\n\n if (autoUpload) {\n // Start uploading each new file\n newItems.forEach(item => {\n uploadFile(item).then(result => {\n if (result) {\n // Check if all items are done after this upload\n const current = itemsRef.current;\n const allDone = current.every(i => i.status === 'success' || i.status === 'error');\n if (allDone) {\n const results = current\n .filter(i => i.status === 'success' && i.result)\n .map(i => i.result!);\n if (results.length > 0) {\n onUploadComplete?.(results);\n }\n }\n }\n });\n });\n }\n }, [autoUpload, uploadFile, updateItems, onUploadComplete]);\n\n // Upload all pending\n const handleUploadAll = useCallback(() => {\n const pending = itemsRef.current.filter(i => i.status === 'pending');\n const uploads = pending.map(item => uploadFile(item));\n\n Promise.allSettled(uploads).then(() => {\n const current = itemsRef.current;\n const results = current\n .filter(i => i.status === 'success' && i.result)\n .map(i => i.result!);\n if (results.length > 0) {\n onUploadComplete?.(results);\n }\n });\n }, [uploadFile, onUploadComplete]);\n\n // Cancel all uploading\n const handleCancelAll = useCallback(() => {\n items.forEach(item => {\n if (item.status === 'uploading' && item.abortController) {\n item.abortController.abort();\n }\n });\n }, [items]);\n\n // Clear completed\n const handleClearCompleted = useCallback(() => {\n updateItems(prev => prev.filter(i => i.status !== 'success'));\n }, [updateItems]);\n\n // Remove single file\n const handleRemove = useCallback((id: string) => {\n updateItems(prev => prev.filter(i => i.id !== id));\n }, [updateItems]);\n\n // Retry single file\n const handleRetry = useCallback((id: string) => {\n const item = itemsRef.current.find(i => i.id === id);\n if (item) uploadFile(item);\n }, [uploadFile]);\n\n // Cancel single upload\n const handleCancel = useCallback((id: string) => {\n const item = itemsRef.current.find(i => i.id === id);\n if (item?.abortController) {\n item.abortController.abort();\n }\n }, []);\n\n const handleValidationError = useCallback((file: File, error: string) => {\n onError?.(file, new Error(error));\n }, [onError]);\n\n return (\n <div className={`w-full ${className}`}>\n <DropZone\n accept={accept}\n maxFileSize={maxFileSize}\n maxFiles={maxFiles}\n multiple={multiple}\n currentFileCount={items.length}\n labels={labels}\n onFilesAdded={handleFilesAdded}\n onValidationError={handleValidationError}\n />\n <UploadQueue\n items={items}\n labels={labels}\n onRemove={handleRemove}\n onRetry={handleRetry}\n onCancel={handleCancel}\n onUploadAll={handleUploadAll}\n onCancelAll={handleCancelAll}\n onClearCompleted={handleClearCompleted}\n />\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"FileUploader.js","names":["fileIdCounter","nextFileId","FileUploader","items","setItems","useState","itemsRef","useRef","updateItems","useCallback","next","updater","prev","onFilesChange","uploadFile","abortController","i","item","result","adapter","percent","err","errorMsg","onError","handleFilesAdded","newItems","files","autoUpload","current","results","onUploadComplete","handleUploadAll","uploads","handleCancelAll","handleClearCompleted","handleRemove","id","handleRetry","handleCancel","handleValidationError","file","error","className","DropZone","UploadQueue"],"sources":["../../../src/components/FileUploader/FileUploader.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef } from 'react';\nimport { FileUploaderProps, FileItemState, UploadResult } from './types';\nimport { DropZone } from './DropZone';\nimport { UploadQueue } from './UploadQueue';\n\nlet fileIdCounter = 0;\nfunction nextFileId(): string {\n return `file-${Date.now()}-${++fileIdCounter}`;\n}\n\nexport const FileUploader: React.FC<FileUploaderProps> = ({\n adapter,\n accept,\n maxFileSize,\n maxFiles,\n multiple = true,\n autoUpload = false,\n className = '',\n labels,\n onUploadComplete,\n onError,\n onFilesChange,\n}) => {\n const [items, setItems] = useState<FileItemState[]>([]);\n const itemsRef = useRef<FileItemState[]>([]);\n\n // Keep ref in sync for use in async callbacks\n const updateItems = useCallback((updater: (prev: FileItemState[]) => FileItemState[]) => {\n setItems(prev => {\n const next = updater(prev);\n itemsRef.current = next;\n onFilesChange?.(next);\n return next;\n });\n }, [onFilesChange]);\n\n // Upload a single file item\n const uploadFile = useCallback(async (item: FileItemState) => {\n const abortController = new AbortController();\n\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id\n ? { ...i, status: 'uploading' as const, progress: 0, error: undefined, abortController }\n : i\n )\n );\n\n try {\n const result = await adapter.upload(\n item.file,\n (percent) => {\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id ? { ...i, progress: Math.min(percent, 100) } : i\n )\n );\n },\n abortController.signal,\n );\n\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id\n ? { ...i, status: 'success' as const, progress: 100, result, abortController: undefined }\n : i\n )\n );\n\n return result;\n } catch (err: any) {\n if (err?.name === 'AbortError') {\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id\n ? { ...i, status: 'pending' as const, progress: 0, abortController: undefined }\n : i\n )\n );\n return null;\n }\n\n const errorMsg = err?.message || 'Upload failed';\n updateItems(prev =>\n prev.map(i =>\n i.id === item.id\n ? { ...i, status: 'error' as const, error: errorMsg, abortController: undefined }\n : i\n )\n );\n onError?.(item.file, err instanceof Error ? err : new Error(errorMsg));\n return null;\n }\n }, [adapter, updateItems, onError]);\n\n // Add files from drop zone\n const handleFilesAdded = useCallback((files: File[]) => {\n const newItems: FileItemState[] = files.map(file => ({\n id: nextFileId(),\n file,\n status: 'pending' as const,\n progress: 0,\n }));\n\n updateItems(prev => [...prev, ...newItems]);\n\n if (autoUpload) {\n // Start uploading each new file\n newItems.forEach(item => {\n uploadFile(item).then(result => {\n if (result) {\n // Check if all items are done after this upload\n const current = itemsRef.current;\n const allDone = current.every(i => i.status === 'success' || i.status === 'error');\n if (allDone) {\n const results = current\n .filter(i => i.status === 'success' && i.result)\n .map(i => i.result!);\n if (results.length > 0) {\n onUploadComplete?.(results);\n }\n }\n }\n });\n });\n }\n }, [autoUpload, uploadFile, updateItems, onUploadComplete]);\n\n // Upload all pending\n const handleUploadAll = useCallback(() => {\n const pending = itemsRef.current.filter(i => i.status === 'pending');\n const uploads = pending.map(item => uploadFile(item));\n\n Promise.allSettled(uploads).then(() => {\n const current = itemsRef.current;\n const results = current\n .filter(i => i.status === 'success' && i.result)\n .map(i => i.result!);\n if (results.length > 0) {\n onUploadComplete?.(results);\n }\n });\n }, [uploadFile, onUploadComplete]);\n\n // Cancel all uploading\n const handleCancelAll = useCallback(() => {\n items.forEach(item => {\n if (item.status === 'uploading' && item.abortController) {\n item.abortController.abort();\n }\n });\n }, [items]);\n\n // Clear completed\n const handleClearCompleted = useCallback(() => {\n updateItems(prev => prev.filter(i => i.status !== 'success'));\n }, [updateItems]);\n\n // Remove single file\n const handleRemove = useCallback((id: string) => {\n updateItems(prev => prev.filter(i => i.id !== id));\n }, [updateItems]);\n\n // Retry single file\n const handleRetry = useCallback((id: string) => {\n const item = itemsRef.current.find(i => i.id === id);\n if (item) uploadFile(item);\n }, [uploadFile]);\n\n // Cancel single upload\n const handleCancel = useCallback((id: string) => {\n const item = itemsRef.current.find(i => i.id === id);\n if (item?.abortController) {\n item.abortController.abort();\n }\n }, []);\n\n const handleValidationError = useCallback((file: File, error: string) => {\n onError?.(file, new Error(error));\n }, [onError]);\n\n return (\n <div className={`w-full ${className}`}>\n <DropZone\n accept={accept}\n maxFileSize={maxFileSize}\n maxFiles={maxFiles}\n multiple={multiple}\n currentFileCount={items.length}\n labels={labels}\n onFilesAdded={handleFilesAdded}\n onValidationError={handleValidationError}\n />\n <UploadQueue\n items={items}\n labels={labels}\n onRemove={handleRemove}\n onRetry={handleRetry}\n onCancel={handleCancel}\n onUploadAll={handleUploadAll}\n onCancelAll={handleCancelAll}\n onClearCompleted={handleClearCompleted}\n />\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"UploadQueue.js","names":[],"sources":["../../../src/components/FileUploader/UploadQueue.tsx"],"sourcesContent":["import React from 'react';\nimport { UploadQueueProps } from './types';\nimport { FileItem } from './FileItem';\nimport Button from '../Button';\n\nconst defaultLabels = {\n uploadAll: 'Upload All',\n cancelAll: 'Cancel All',\n clearCompleted: 'Clear Completed',\n fileCount: 'files',\n};\n\nexport const UploadQueue: React.FC<UploadQueueProps> = ({\n items,\n labels: userLabels,\n onRemove,\n onRetry,\n onCancel,\n onUploadAll,\n onCancelAll,\n onClearCompleted,\n className = '',\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n\n const hasPending = items.some(i => i.status === 'pending');\n const hasUploading = items.some(i => i.status === 'uploading');\n const hasCompleted = items.some(i => i.status === 'success');\n\n if (items.length === 0) return null;\n\n return (\n <div className={`mt-4 ${className}`}>\n {/* Batch actions bar */}\n <div className=\"flex items-center justify-between mb-2 px-1\">\n <span className=\"text-sm opacity-60\">\n {items.length} {labels.fileCount}\n </span>\n <div className=\"flex gap-1\">\n {hasPending && (\n <Button variant=\"primary\" size=\"xs\" onClick={onUploadAll}>\n {labels.uploadAll}\n </Button>\n )}\n {hasUploading && (\n <Button variant=\"warning\" size=\"xs\" outline onClick={onCancelAll}>\n {labels.cancelAll}\n </Button>\n )}\n {hasCompleted && (\n <Button variant=\"ghost\" size=\"xs\" onClick={onClearCompleted}>\n {labels.clearCompleted}\n </Button>\n )}\n </div>\n </div>\n\n {/* File list */}\n <div className=\"flex flex-col gap-1.5 max-h-[360px] overflow-y-auto pr-1\">\n {items.map(item => (\n <FileItem\n key={item.id}\n item={item}\n labels={labels}\n onRemove={onRemove}\n onRetry={onRetry}\n onCancel={onCancel}\n />\n ))}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;AAKA,IAAM,IAAgB;CAClB,WAAW;CACX,WAAW;CACX,gBAAgB;CAChB,WAAW;AACf,GAEa,KAA2C,EACpD,UACA,QAAQ,GACR,aACA,YACA,aACA,gBACA,gBACA,qBACA,eAAY,SACV;CACF,IAAM,IAAS;EAAE,GAAG;EAAe,GAAG;CAAW,GAE3C,IAAa,EAAM,MAAK,MAAK,EAAE,WAAW,SAAS,GACnD,IAAe,EAAM,MAAK,MAAK,EAAE,WAAW,WAAW,GACvD,IAAe,EAAM,MAAK,MAAK,EAAE,WAAW,SAAS;CAI3D,OAFI,EAAM,WAAW,IAAU,OAG3B,kBAAC,OAAD;EAAK,WAAW,QAAQ;EAAxB,UAAA,CAEI,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACI,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA;KACK,EAAM;KAAO;KAAE,EAAO;IACrB;GACN,CAAA,GAAA,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACK,KACG,kBAAC,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,SAAS;MACxC,UAAA,EAAO;KACJ,CAAA;KAEX,KACG,kBAAC,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,SAAA;MAAQ,SAAS;MAChD,UAAA,EAAO;KACJ,CAAA;KAEX,KACG,kBAAC,GAAD;MAAQ,SAAQ;MAAQ,MAAK;MAAK,SAAS;MACtC,UAAA,EAAO;KACJ,CAAA;IAEX;GACJ,CAAA,CAAA;EAGL,CAAA,GAAA,kBAAC,OAAD;GAAK,WAAU;GACV,UAAA,EAAM,KAAI,MACP,kBAAC,GAAD;IAEU;IACE;IACE;IACD;IACC;GACb,GANQ,EAAK,EAMb,CACJ;EACA,CAAA,CACJ;;AAEb"}
1
+ {"version":3,"file":"UploadQueue.js","names":["Button","ButtonWithCompounds","defaultLabels","UploadQueue","userLabels","labels","hasPending","items","i","hasUploading","hasCompleted","className","onUploadAll","onCancelAll","onClearCompleted","FileItem","item"],"sources":["../../../src/components/FileUploader/UploadQueue.tsx"],"sourcesContent":["import React from 'react';\nimport { UploadQueueProps } from './types';\nimport { FileItem } from './FileItem';\nimport Button from '../Button';\n\nconst defaultLabels = {\n uploadAll: 'Upload All',\n cancelAll: 'Cancel All',\n clearCompleted: 'Clear Completed',\n fileCount: 'files',\n};\n\nexport const UploadQueue: React.FC<UploadQueueProps> = ({\n items,\n labels: userLabels,\n onRemove,\n onRetry,\n onCancel,\n onUploadAll,\n onCancelAll,\n onClearCompleted,\n className = '',\n}) => {\n const labels = { ...defaultLabels, ...userLabels };\n\n const hasPending = items.some(i => i.status === 'pending');\n const hasUploading = items.some(i => i.status === 'uploading');\n const hasCompleted = items.some(i => i.status === 'success');\n\n if (items.length === 0) return null;\n\n return (\n <div className={`mt-4 ${className}`}>\n {/* Batch actions bar */}\n <div className=\"flex items-center justify-between mb-2 px-1\">\n <span className=\"text-sm opacity-60\">\n {items.length} {labels.fileCount}\n </span>\n <div className=\"flex gap-1\">\n {hasPending && (\n <Button variant=\"primary\" size=\"xs\" onClick={onUploadAll}>\n {labels.uploadAll}\n </Button>\n )}\n {hasUploading && (\n <Button variant=\"warning\" size=\"xs\" outline onClick={onCancelAll}>\n {labels.cancelAll}\n </Button>\n )}\n {hasCompleted && (\n <Button variant=\"ghost\" size=\"xs\" onClick={onClearCompleted}>\n {labels.clearCompleted}\n </Button>\n )}\n </div>\n </div>\n\n {/* File list */}\n <div className=\"flex flex-col gap-1.5 max-h-[360px] overflow-y-auto pr-1\">\n {items.map(item => (\n <FileItem\n key={item.id}\n item={item}\n labels={labels}\n onRemove={onRemove}\n onRetry={onRetry}\n onCancel={onCancel}\n />\n ))}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;AAKA,IAAME,IAAgB;CAClB,WAAW;CACX,WAAW;CACX,gBAAgB;CAChB,WAAW;AACf,GAEaC,KAA2C,EACpD,UACA,QAAQC,GACR,aACA,YACA,aACA,gBACA,gBACA,qBACA,eAAY,SACV;CACF,IAAMC,IAAS;EAAE,GAAGH;EAAe,GAAGE;CAAW,GAE3CE,IAAaC,EAAM,MAAK,MAAKC,EAAE,WAAW,SAAS,GACnDC,IAAeF,EAAM,MAAK,MAAKC,EAAE,WAAW,WAAW,GACvDE,IAAeH,EAAM,MAAK,MAAKC,EAAE,WAAW,SAAS;CAI3D,OAFID,EAAM,WAAW,IAAU,OAG3B,kBAAC,OAAD;EAAK,WAAW,QAAQI;EAAxB,UAAA,CAEI,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACI,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA;KACKJ,EAAM;KAAO;KAAEF,EAAO;IACrB;GACN,CAAA,GAAA,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACKC,KACG,kBAACN,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,SAASY;MACxC,UAAAP,EAAO;KACJ,CAAA;KAEXI,KACG,kBAACT,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,SAAA;MAAQ,SAASa;MAChD,UAAAR,EAAO;KACJ,CAAA;KAEXK,KACG,kBAACV,GAAD;MAAQ,SAAQ;MAAQ,MAAK;MAAK,SAASc;MACtC,UAAAT,EAAO;KACJ,CAAA;IAEX;GACJ,CAAA,CAAA;EAGL,CAAA,GAAA,kBAAC,OAAD;GAAK,WAAU;GACV,UAAAE,EAAM,KAAI,MACP,kBAACQ,GAAD;IAEU;IACE;IACE;IACD;IACC;GACb,GANQC,EAAK,EAMb,CACJ;EACA,CAAA,CACJ;;AAEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/GroupButton/index.tsx"],"sourcesContent":["import React, { useId } from 'react';\nimport Button from '../Button';\nimport { cn } from '../../utils/cn';\nimport './GroupButton.css';\n\nexport type GroupButtonOption = {\n value: string;\n label: React.ReactNode;\n disabled?: boolean;\n disabledReason?: string;\n};\n\nexport type GroupButtonProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'defaultValue'> & {\n options: GroupButtonOption[];\n value: string;\n onValueChange: (value: string) => void;\n variant?: 'segmented' | 'pills';\n 'aria-label': string;\n};\n\nconst GroupButton = ({\n options, value, onValueChange, variant = 'segmented', className, ...rest\n}: GroupButtonProps) => {\n const id = useId();\n return (\n <div {...rest} role=\"group\" className={cn('dishui-group-button', `dishui-group-button--${variant}`, className)}>\n {options.map((option, index) => {\n const reasonId = `${id}-reason-${index}`;\n const reason = option.disabled ? option.disabledReason : undefined;\n return (\n <div className=\"dishui-group-button__option\" key={option.value}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"dishui-group-button__button\"\n aria-pressed={value === option.value}\n disabled={option.disabled}\n aria-describedby={reason ? reasonId : undefined}\n title={reason}\n onClick={() => {\n if (!option.disabled && option.value !== value) onValueChange(option.value);\n }}\n >\n {option.label}\n </Button>\n {reason && <span id={reasonId} className=\"dishui-group-button__reason\">{reason}</span>}\n </div>\n );\n })}\n </div>\n );\n};\n\nexport default GroupButton;\n"],"mappings":";;;;;;AAoBA,IAAM,KAAe,EACnB,YAAS,UAAO,kBAAe,aAAU,aAAa,cAAW,GAAG,QAC9C;CACtB,IAAM,IAAK,EAAM;CACjB,OACE,kBAAC,OAAD;EAAK,GAAI;EAAM,MAAK;EAAQ,WAAW,EAAG,uBAAuB,wBAAwB,KAAW,CAAS;EAC1G,UAAA,EAAQ,KAAK,GAAQ,MAAU;GAC9B,IAAM,IAAW,GAAG,EAAG,UAAU,KAC3B,IAAS,EAAO,WAAW,EAAO,iBAAiB,KAAA;GACzD,OACE,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,GAAD;KACE,MAAK;KACL,SAAQ;KACR,WAAU;KACV,gBAAc,MAAU,EAAO;KAC/B,UAAU,EAAO;KACjB,oBAAkB,IAAS,IAAW,KAAA;KACtC,OAAO;KACP,eAAe;MACb,AAAI,CAAC,EAAO,YAAY,EAAO,UAAU,KAAO,EAAc,EAAO,KAAK;KAC5E;KAEC,UAAA,EAAO;IACF,CAAA,GACP,KAAU,kBAAC,QAAD;KAAM,IAAI;KAAU,WAAU;KAA+B,UAAA;IAAa,CAAA,CAClF;GAhB6C,GAAA,EAAO,KAgBpD;EAET,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"index.js","names":["Button","ButtonWithCompounds","GroupButton","rest","id","useId","cn","variant","className","options","reasonId","index","reason","option","value","onValueChange"],"sources":["../../../src/components/GroupButton/index.tsx"],"sourcesContent":["import React, { useId } from 'react';\nimport Button from '../Button';\nimport { cn } from '../../utils/cn';\nimport './GroupButton.css';\n\nexport type GroupButtonOption = {\n value: string;\n label: React.ReactNode;\n disabled?: boolean;\n disabledReason?: string;\n};\n\nexport type GroupButtonProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'defaultValue'> & {\n options: GroupButtonOption[];\n value: string;\n onValueChange: (value: string) => void;\n variant?: 'segmented' | 'pills';\n 'aria-label': string;\n};\n\nconst GroupButton = ({\n options, value, onValueChange, variant = 'segmented', className, ...rest\n}: GroupButtonProps) => {\n const id = useId();\n return (\n <div {...rest} role=\"group\" className={cn('dishui-group-button', `dishui-group-button--${variant}`, className)}>\n {options.map((option, index) => {\n const reasonId = `${id}-reason-${index}`;\n const reason = option.disabled ? option.disabledReason : undefined;\n return (\n <div className=\"dishui-group-button__option\" key={option.value}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"dishui-group-button__button\"\n aria-pressed={value === option.value}\n disabled={option.disabled}\n aria-describedby={reason ? reasonId : undefined}\n title={reason}\n onClick={() => {\n if (!option.disabled && option.value !== value) onValueChange(option.value);\n }}\n >\n {option.label}\n </Button>\n {reason && <span id={reasonId} className=\"dishui-group-button__reason\">{reason}</span>}\n </div>\n );\n })}\n </div>\n );\n};\n\nexport default GroupButton;\n"],"mappings":";;;;;;AAoBA,IAAME,KAAe,EACnB,YAAS,UAAO,kBAAe,aAAU,aAAa,cAAW,GAAGC,QAC9C;CACtB,IAAMC,IAAKC,EAAM;CACjB,OACE,kBAAC,OAAD;EAAK,GAAIF;EAAM,MAAK;EAAQ,WAAWG,EAAG,uBAAuB,wBAAwBC,KAAWC,CAAS;EAC1G,UAAAC,EAAQ,KAAK,GAAQ,MAAU;GAC9B,IAAMC,IAAW,GAAGN,EAAG,UAAUO,KAC3BC,IAASC,EAAO,WAAWA,EAAO,iBAAiB,KAAA;GACzD,OACE,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAACb,GAAD;KACE,MAAK;KACL,SAAQ;KACR,WAAU;KACV,gBAAcc,MAAUD,EAAO;KAC/B,UAAUA,EAAO;KACjB,oBAAkBD,IAASF,IAAW,KAAA;KACtC,OAAOE;KACP,eAAe;MACb,AAAI,CAACC,EAAO,YAAYA,EAAO,UAAUC,KAAOC,EAAcF,EAAO,KAAK;KAC5E;KAEC,UAAAA,EAAO;IACF,CAAA,GACPD,KAAU,kBAAC,QAAD;KAAM,IAAIF;KAAU,WAAU;KAA+B,UAAAE;IAAa,CAAA,CAClF;GAhB6C,GAAAC,EAAO,KAgBpD;EAET,CAAC;CACE,CAAA;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/GroupedTable/index.tsx"],"sourcesContent":["import React, { useId, useLayoutEffect, useRef, useState } from 'react';\nimport Table from '../Table';\nimport Button from '../Button';\nimport Skeleton from '../Skeleton';\nimport { cn } from '../../utils/cn';\nimport './GroupedTable.css';\n\nexport type GroupedTableColumn<T> = {\n key: string;\n header: React.ReactNode;\n render: (row: T) => React.ReactNode;\n numeric?: boolean;\n rowHeader?: boolean;\n};\n\nexport type GroupedTableGroup<T> = {\n key: string;\n label: React.ReactNode;\n rows: readonly T[];\n /** Summary cells keyed by column key; the first column is the group label. */\n summary?: Record<string, React.ReactNode>;\n};\n\nexport type GroupedTableProps<T> = {\n columns: readonly GroupedTableColumn<T>[];\n groups: readonly GroupedTableGroup<T>[];\n rowKey: (row: T) => React.Key;\n caption: React.ReactNode;\n 'aria-label': string;\n collapsedKeys?: readonly string[];\n defaultCollapsedKeys?: readonly string[];\n onToggleGroup?: (key: string) => void;\n footer?: { label: React.ReactNode; summary: Record<string, React.ReactNode> };\n density?: 'compact' | 'comfortable';\n stickyHeader?: boolean;\n maxHeight?: React.CSSProperties['maxHeight'];\n minWidth?: React.CSSProperties['minWidth'];\n loading?: boolean;\n loadingLabel?: string;\n loadingRows?: number;\n className?: string;\n};\n\nfunction AnimatedBody({ expanded, id, label, children }: {\n expanded: boolean; id: string; label?: string; children: React.ReactNode;\n}) {\n const ref = useRef<HTMLTableSectionElement>(null);\n const previous = useRef(expanded);\n const animations = useRef<Animation[]>([]);\n const [hidden, setHidden] = useState(!expanded);\n\n useLayoutEffect(() => {\n const body = ref.current!;\n if (previous.current === expanded) return;\n previous.current = expanded;\n if (!expanded && body.contains(document.activeElement)) {\n const toggle = body.previousElementSibling?.querySelector<HTMLButtonElement>('[aria-expanded]');\n (toggle ?? body.closest<HTMLElement>('.dishui-grouped-table__scroll'))?.focus({ preventScroll: true });\n }\n const cells = Array.from(body.querySelectorAll<HTMLElement>(':scope > tr > :is(td, th) > .dishui-grouped-table__cell'));\n // Capture the current frame before cancelling, so rapid reversals never jump.\n const starts = cells.map(cell => ({ height: cell.getBoundingClientRect().height, opacity: body.hidden ? '0' : getComputedStyle(cell).opacity }));\n animations.current.forEach(animation => animation.cancel());\n body.hidden = false;\n setHidden(false);\n const media = window.matchMedia('(prefers-reduced-motion: reduce)');\n const finish = () => {\n animations.current.forEach(animation => animation.cancel());\n animations.current = [];\n body.hidden = !expanded;\n setHidden(!expanded);\n };\n if (media.matches || !body.animate) {\n finish();\n return;\n }\n // Measure all natural heights before applying any animation styles.\n const heights = cells.map(cell => expanded ? cell.getBoundingClientRect().height : 0);\n animations.current = cells.map((cell, index) => cell.animate([\n { height: `${starts[index].height}px`, opacity: starts[index].opacity },\n { height: `${heights[index]}px`, opacity: expanded ? 1 : 0 },\n ], { duration: 180, easing: 'ease-in-out', fill: 'both' }));\n let active = true;\n Promise.all(animations.current.map(animation => animation.finished)).then(() => {\n if (active) finish();\n }).catch(() => { /* Cancellation is expected when the direction changes. */ });\n const reduce = () => { if (media.matches) finish(); };\n media.addEventListener('change', reduce);\n return () => { active = false; media.removeEventListener('change', reduce); };\n }, [expanded]);\n\n useLayoutEffect(() => () => animations.current.forEach(animation => animation.cancel()), []);\n return <tbody ref={ref} id={id} className=\"dishui-grouped-table__body\" hidden={hidden}\n inert={!expanded} aria-hidden={!expanded || undefined} aria-label={label}>{children}</tbody>;\n}\n\n/** Scrollable, accessible grouped records. Formatting and aggregation stay with the caller. */\nexport default function GroupedTable<T>({\n columns, groups, rowKey, caption, 'aria-label': label,\n collapsedKeys, defaultCollapsedKeys, onToggleGroup, footer, density = 'compact', stickyHeader = true,\n maxHeight = 560, minWidth = 800, loading = false, loadingLabel = 'Loading records…',\n loadingRows = 6, className,\n}: GroupedTableProps<T>) {\n const id = useId();\n const [internalCollapsed, setInternalCollapsed] = useState<readonly string[]>(() => defaultCollapsedKeys ?? []);\n const collapsed = collapsedKeys ?? internalCollapsed;\n const toggleGroup = (key: string) => {\n if (collapsedKeys === undefined) {\n setInternalCollapsed(current => current.includes(key) ? current.filter(value => value !== key) : [...current, key]);\n }\n onToggleGroup?.(key);\n };\n const summaryCells = (summary?: Record<string, React.ReactNode>) => columns.slice(1).map(column => (\n <td key={column.key} data-numeric={column.numeric || undefined}>{summary?.[column.key]}</td>\n ));\n return (\n <div className={cn('dishui-grouped-table', className)} style={{ '--grouped-table-min-width': typeof minWidth === 'number' ? `${minWidth}px` : minWidth } as React.CSSProperties}>\n {loading && <p role=\"status\" className=\"dishui-grouped-table__loading\">{loadingLabel}</p>}\n <div className=\"dishui-grouped-table__scroll\" role=\"region\" aria-label={label} aria-busy={loading} tabIndex={0} style={{ maxHeight }}>\n <Table className={cn('dishui-grouped-table__table', `dishui-grouped-table--${density}`, stickyHeader && 'dishui-grouped-table--sticky')}>\n <caption>{caption}</caption>\n <colgroup>{columns.map(column => <col key={column.key} />)}</colgroup>\n <thead><tr>{columns.map(column => <th key={column.key} scope=\"col\" data-numeric={column.numeric || undefined}>{column.header}</th>)}</tr></thead>\n {loading ? <tbody>{Array.from({ length: loadingRows }, (_, index) => <tr key={index}>{columns.map(column => <td key={column.key}><Skeleton /></td>)}</tr>)}</tbody>\n : groups.filter(group => group.rows.length > 0).map((group, index) => {\n const expanded = !collapsed.includes(group.key);\n const bodyId = `${id}-group-${index}`;\n return <React.Fragment key={group.key}>\n <tbody><tr className=\"dishui-grouped-table__summary\">\n <th scope=\"row\">\n {collapsedKeys === undefined || onToggleGroup ? <Button type=\"button\" variant=\"ghost\" size=\"xs\" aria-expanded={expanded} aria-controls={bodyId} onClick={() => toggleGroup(group.key)}>\n {expanded ? '−' : '+'} {group.label} ({group.rows.length})\n </Button> : <>{group.label} ({group.rows.length})</>}\n </th>\n {summaryCells(group.summary)}\n </tr></tbody>\n <AnimatedBody id={bodyId} expanded={expanded} label={typeof group.label === 'string' ? group.label : undefined}>\n {group.rows.map(row => <tr key={rowKey(row)}>{columns.map(column => {\n const Cell = column.rowHeader ? 'th' : 'td';\n return <Cell key={column.key} scope={column.rowHeader ? 'row' : undefined} data-numeric={column.numeric || undefined}><div className=\"dishui-grouped-table__cell\"><div className=\"dishui-grouped-table__content\">{column.render(row)}</div></div></Cell>;\n })}</tr>)}\n </AnimatedBody>\n </React.Fragment>;\n })}\n {!loading && footer && <tfoot><tr><th scope=\"row\">{footer.label}</th>{summaryCells(footer.summary)}</tr></tfoot>}\n </Table>\n </div>\n\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Table","Button","_Fragment","ButtonWithCompounds","TableWithCompounds","Skeleton","React","AnimatedBody","ref","useRef","previous","expanded","animations","hidden","setHidden","useState","useLayoutEffect","body","cells","starts","cell","animation","media","finish","heights","index","active","reduce","label","GroupedTable","id","useId","internalCollapsed","setInternalCollapsed","defaultCollapsedKeys","collapsed","collapsedKeys","toggleGroup","current","key","value","onToggleGroup","summaryCells","columns","column","summary","cn","className","minWidth","loading","loadingLabel","density","stickyHeader","caption","loadingRows","groups","group","bodyId","Fragment","Cell","row","rowKey","footer"],"sources":["../../../src/components/GroupedTable/index.tsx"],"sourcesContent":["import React, { useId, useLayoutEffect, useRef, useState } from 'react';\nimport Table from '../Table';\nimport Button from '../Button';\nimport Skeleton from '../Skeleton';\nimport { cn } from '../../utils/cn';\nimport './GroupedTable.css';\n\nexport type GroupedTableColumn<T> = {\n key: string;\n header: React.ReactNode;\n render: (row: T) => React.ReactNode;\n numeric?: boolean;\n rowHeader?: boolean;\n};\n\nexport type GroupedTableGroup<T> = {\n key: string;\n label: React.ReactNode;\n rows: readonly T[];\n /** Summary cells keyed by column key; the first column is the group label. */\n summary?: Record<string, React.ReactNode>;\n};\n\nexport type GroupedTableProps<T> = {\n columns: readonly GroupedTableColumn<T>[];\n groups: readonly GroupedTableGroup<T>[];\n rowKey: (row: T) => React.Key;\n caption: React.ReactNode;\n 'aria-label': string;\n collapsedKeys?: readonly string[];\n defaultCollapsedKeys?: readonly string[];\n onToggleGroup?: (key: string) => void;\n footer?: { label: React.ReactNode; summary: Record<string, React.ReactNode> };\n density?: 'compact' | 'comfortable';\n stickyHeader?: boolean;\n maxHeight?: React.CSSProperties['maxHeight'];\n minWidth?: React.CSSProperties['minWidth'];\n loading?: boolean;\n loadingLabel?: string;\n loadingRows?: number;\n className?: string;\n};\n\nfunction AnimatedBody({ expanded, id, label, children }: {\n expanded: boolean; id: string; label?: string; children: React.ReactNode;\n}) {\n const ref = useRef<HTMLTableSectionElement>(null);\n const previous = useRef(expanded);\n const animations = useRef<Animation[]>([]);\n const [hidden, setHidden] = useState(!expanded);\n\n useLayoutEffect(() => {\n const body = ref.current!;\n if (previous.current === expanded) return;\n previous.current = expanded;\n if (!expanded && body.contains(document.activeElement)) {\n const toggle = body.previousElementSibling?.querySelector<HTMLButtonElement>('[aria-expanded]');\n (toggle ?? body.closest<HTMLElement>('.dishui-grouped-table__scroll'))?.focus({ preventScroll: true });\n }\n const cells = Array.from(body.querySelectorAll<HTMLElement>(':scope > tr > :is(td, th) > .dishui-grouped-table__cell'));\n // Capture the current frame before cancelling, so rapid reversals never jump.\n const starts = cells.map(cell => ({ height: cell.getBoundingClientRect().height, opacity: body.hidden ? '0' : getComputedStyle(cell).opacity }));\n animations.current.forEach(animation => animation.cancel());\n body.hidden = false;\n setHidden(false);\n const media = window.matchMedia('(prefers-reduced-motion: reduce)');\n const finish = () => {\n animations.current.forEach(animation => animation.cancel());\n animations.current = [];\n body.hidden = !expanded;\n setHidden(!expanded);\n };\n if (media.matches || !body.animate) {\n finish();\n return;\n }\n // Measure all natural heights before applying any animation styles.\n const heights = cells.map(cell => expanded ? cell.getBoundingClientRect().height : 0);\n animations.current = cells.map((cell, index) => cell.animate([\n { height: `${starts[index].height}px`, opacity: starts[index].opacity },\n { height: `${heights[index]}px`, opacity: expanded ? 1 : 0 },\n ], { duration: 180, easing: 'ease-in-out', fill: 'both' }));\n let active = true;\n Promise.all(animations.current.map(animation => animation.finished)).then(() => {\n if (active) finish();\n }).catch(() => { /* Cancellation is expected when the direction changes. */ });\n const reduce = () => { if (media.matches) finish(); };\n media.addEventListener('change', reduce);\n return () => { active = false; media.removeEventListener('change', reduce); };\n }, [expanded]);\n\n useLayoutEffect(() => () => animations.current.forEach(animation => animation.cancel()), []);\n return <tbody ref={ref} id={id} className=\"dishui-grouped-table__body\" hidden={hidden}\n inert={!expanded} aria-hidden={!expanded || undefined} aria-label={label}>{children}</tbody>;\n}\n\n/** Scrollable, accessible grouped records. Formatting and aggregation stay with the caller. */\nexport default function GroupedTable<T>({\n columns, groups, rowKey, caption, 'aria-label': label,\n collapsedKeys, defaultCollapsedKeys, onToggleGroup, footer, density = 'compact', stickyHeader = true,\n maxHeight = 560, minWidth = 800, loading = false, loadingLabel = 'Loading records…',\n loadingRows = 6, className,\n}: GroupedTableProps<T>) {\n const id = useId();\n const [internalCollapsed, setInternalCollapsed] = useState<readonly string[]>(() => defaultCollapsedKeys ?? []);\n const collapsed = collapsedKeys ?? internalCollapsed;\n const toggleGroup = (key: string) => {\n if (collapsedKeys === undefined) {\n setInternalCollapsed(current => current.includes(key) ? current.filter(value => value !== key) : [...current, key]);\n }\n onToggleGroup?.(key);\n };\n const summaryCells = (summary?: Record<string, React.ReactNode>) => columns.slice(1).map(column => (\n <td key={column.key} data-numeric={column.numeric || undefined}>{summary?.[column.key]}</td>\n ));\n return (\n <div className={cn('dishui-grouped-table', className)} style={{ '--grouped-table-min-width': typeof minWidth === 'number' ? `${minWidth}px` : minWidth } as React.CSSProperties}>\n {loading && <p role=\"status\" className=\"dishui-grouped-table__loading\">{loadingLabel}</p>}\n <div className=\"dishui-grouped-table__scroll\" role=\"region\" aria-label={label} aria-busy={loading} tabIndex={0} style={{ maxHeight }}>\n <Table className={cn('dishui-grouped-table__table', `dishui-grouped-table--${density}`, stickyHeader && 'dishui-grouped-table--sticky')}>\n <caption>{caption}</caption>\n <colgroup>{columns.map(column => <col key={column.key} />)}</colgroup>\n <thead><tr>{columns.map(column => <th key={column.key} scope=\"col\" data-numeric={column.numeric || undefined}>{column.header}</th>)}</tr></thead>\n {loading ? <tbody>{Array.from({ length: loadingRows }, (_, index) => <tr key={index}>{columns.map(column => <td key={column.key}><Skeleton /></td>)}</tr>)}</tbody>\n : groups.filter(group => group.rows.length > 0).map((group, index) => {\n const expanded = !collapsed.includes(group.key);\n const bodyId = `${id}-group-${index}`;\n return <React.Fragment key={group.key}>\n <tbody><tr className=\"dishui-grouped-table__summary\">\n <th scope=\"row\">\n {collapsedKeys === undefined || onToggleGroup ? <Button type=\"button\" variant=\"ghost\" size=\"xs\" aria-expanded={expanded} aria-controls={bodyId} onClick={() => toggleGroup(group.key)}>\n {expanded ? '−' : '+'} {group.label} ({group.rows.length})\n </Button> : <>{group.label} ({group.rows.length})</>}\n </th>\n {summaryCells(group.summary)}\n </tr></tbody>\n <AnimatedBody id={bodyId} expanded={expanded} label={typeof group.label === 'string' ? group.label : undefined}>\n {group.rows.map(row => <tr key={rowKey(row)}>{columns.map(column => {\n const Cell = column.rowHeader ? 'th' : 'td';\n return <Cell key={column.key} scope={column.rowHeader ? 'row' : undefined} data-numeric={column.numeric || undefined}><div className=\"dishui-grouped-table__cell\"><div className=\"dishui-grouped-table__content\">{column.render(row)}</div></div></Cell>;\n })}</tr>)}\n </AnimatedBody>\n </React.Fragment>;\n })}\n {!loading && footer && <tfoot><tr><th scope=\"row\">{footer.label}</th>{summaryCells(footer.summary)}</tr></tfoot>}\n </Table>\n </div>\n\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Icon/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type IconProps = {\n /** Icon content — typically an inline `<svg>` (e.g. from icon libraries). */\n children?: React.ReactNode;\n /** Square size; number is treated as px. */\n size?: number | string;\n /** Icon color (inherits `currentColor` when omitted). */\n color?: string;\n /** Fill color applied to the child `<svg>`; defaults to `transparent` (outline look). Pass `currentColor` / any CSS color for a filled icon — takes precedence over the svg's own fill attribute. */\n filledColor?: string;\n /** Continuous rotation animation. */\n spin?: boolean;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Inline styles on the wrapper. */\n style?: React.CSSProperties;\n /** Click handler. */\n onClick?: (e: React.MouseEvent<HTMLSpanElement>) => void;\n};\n\n/**\n * Icon —— A2UI 展示组件:图标容器。\n * 不绑定具体图标库:把任意内联 `<svg>`(lucide / heroicons / 自定义)作为\n * children 传入,由本组件统一控制尺寸、颜色、填充与旋转动画。\n */\nconst Icon: React.FC<IconProps> = ({\n children,\n size = 18,\n color,\n filledColor = 'transparent',\n spin = false,\n className = '',\n style,\n onClick,\n}) => {\n const px = typeof size === 'number' ? `${size}px` : size;\n\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n 'inline-flex shrink-0 items-center justify-center leading-none',\n spin && 'animate-spin',\n className,\n )}\n style={{ width: px, height: px, color, '--icon-fill': filledColor, ...style } as React.CSSProperties}\n onClick={onClick}\n >\n {/* 让未带尺寸的 svg 自动铺满容器;fill 统一交给 filledColor 控制 */}\n <span className=\"inline-flex [&>svg]:h-full [&>svg]:w-full [&>svg]:fill-(--icon-fill)\">{children}</span>\n </span>\n );\n};\n\nexport default Icon;\n"],"mappings":";;;;AA2BA,IAAM,KAA6B,EACjC,aACA,UAAO,IACP,UACA,iBAAc,eACd,UAAO,IACP,eAAY,IACZ,UACA,iBACI;CACJ,IAAM,IAAK,OAAO,KAAS,WAAW,GAAG,EAAK,MAAM;CAEpD,OACE,kBAAC,QAAD;EACE,eAAY;EACZ,WAAW,EACT,iEACA,KAAQ,gBACR,CACF;EACA,OAAO;GAAE,OAAO;GAAI,QAAQ;GAAI;GAAO,eAAe;GAAa,GAAG;EAAM;EACnE;EAGT,UAAA,kBAAC,QAAD;GAAM,WAAU;GAAwE;EAAe,CAAA;CACnG,CAAA;AAEV"}
1
+ {"version":3,"file":"index.js","names":["Icon","px","size","cn","spin","className","filledColor","style"],"sources":["../../../src/components/Icon/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type IconProps = {\n /** Icon content — typically an inline `<svg>` (e.g. from icon libraries). */\n children?: React.ReactNode;\n /** Square size; number is treated as px. */\n size?: number | string;\n /** Icon color (inherits `currentColor` when omitted). */\n color?: string;\n /** Fill color applied to the child `<svg>`; defaults to `transparent` (outline look). Pass `currentColor` / any CSS color for a filled icon — takes precedence over the svg's own fill attribute. */\n filledColor?: string;\n /** Continuous rotation animation. */\n spin?: boolean;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Inline styles on the wrapper. */\n style?: React.CSSProperties;\n /** Click handler. */\n onClick?: (e: React.MouseEvent<HTMLSpanElement>) => void;\n};\n\n/**\n * Icon —— A2UI 展示组件:图标容器。\n * 不绑定具体图标库:把任意内联 `<svg>`(lucide / heroicons / 自定义)作为\n * children 传入,由本组件统一控制尺寸、颜色、填充与旋转动画。\n */\nconst Icon: React.FC<IconProps> = ({\n children,\n size = 18,\n color,\n filledColor = 'transparent',\n spin = false,\n className = '',\n style,\n onClick,\n}) => {\n const px = typeof size === 'number' ? `${size}px` : size;\n\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n 'inline-flex shrink-0 items-center justify-center leading-none',\n spin && 'animate-spin',\n className,\n )}\n style={{ width: px, height: px, color, '--icon-fill': filledColor, ...style } as React.CSSProperties}\n onClick={onClick}\n >\n {/* 让未带尺寸的 svg 自动铺满容器;fill 统一交给 filledColor 控制 */}\n <span className=\"inline-flex [&>svg]:h-full [&>svg]:w-full [&>svg]:fill-(--icon-fill)\">{children}</span>\n </span>\n );\n};\n\nexport default Icon;\n"],"mappings":";;;;AA2BA,IAAMA,KAA6B,EACjC,aACA,UAAO,IACP,UACA,iBAAc,eACd,UAAO,IACP,eAAY,IACZ,UACA,iBACI;CACJ,IAAMC,IAAK,OAAOC,KAAS,WAAW,GAAGA,EAAK,MAAMA;CAEpD,OACE,kBAAC,QAAD;EACE,eAAY;EACZ,WAAWC,EACT,iEACAC,KAAQ,gBACRC,CACF;EACA,OAAO;GAAE,OAAOJ;GAAI,QAAQA;GAAI;GAAO,eAAeK;GAAa,GAAGC;EAAM;EACnE;EAGT,UAAA,kBAAC,QAAD;GAAM,WAAU;GAAwE;EAAe,CAAA;CACnG,CAAA;AAEV"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Image/index.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type ImageFit = 'cover' | 'contain' | 'fill' | 'scale-down' | 'none';\nexport type ImageRadius = 'none' | 'sm' | 'md' | 'lg' | 'full';\n\nexport type ImageProps = {\n /** Image source URL. */\n src: string;\n /** Alternative text (accessibility). */\n alt?: string;\n /** Object-fit mode. */\n fit?: ImageFit;\n /** Width; number is treated as px. */\n width?: number | string;\n /** Height; number is treated as px. */\n height?: number | string;\n /** Corner radius preset. */\n radius?: ImageRadius;\n /** Shown when the image fails to load (node or replacement URL). */\n fallback?: React.ReactNode;\n /** Native lazy loading. */\n lazy?: boolean;\n /** Extra class names on the img element. */\n className?: string;\n /** Inline styles on the img element. */\n style?: React.CSSProperties;\n /** Click handler. */\n onClick?: (e: React.MouseEvent<HTMLImageElement>) => void;\n};\n\nconst FIT_CLASS: Record<ImageFit, string> = {\n cover: 'object-cover',\n contain: 'object-contain',\n fill: 'object-fill',\n 'scale-down': 'object-scale-down',\n none: 'object-none',\n};\n\nconst RADIUS_CLASS: Record<ImageRadius, string> = {\n none: '',\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n full: 'rounded-full',\n};\n\nconst size = (v: number | string | undefined): string | undefined =>\n typeof v === 'number' ? `${v}px` : v;\n\n/**\n * Image —— A2UI 展示组件:图片。\n * 支持自适应填充模式、圆角、懒加载与加载失败时的 fallback。\n */\nconst Image: React.FC<ImageProps> = ({\n src,\n alt = '',\n fit = 'cover',\n width,\n height,\n radius = 'md',\n fallback,\n lazy = true,\n className = '',\n style,\n onClick,\n}) => {\n const [failed, setFailed] = useState(false);\n\n const classes = cn('max-w-full', FIT_CLASS[fit], RADIUS_CLASS[radius], className);\n\n if (failed) {\n if (fallback !== undefined) {\n return <>{fallback}</>;\n }\n return (\n <span\n className={cn(\n 'inline-flex items-center justify-center bg-base-200 text-base-content/40 text-xs select-none',\n RADIUS_CLASS[radius],\n className,\n )}\n style={{ width: size(width) ?? '100%', height: size(height) ?? '96px', ...style }}\n >\n Image\n </span>\n );\n }\n\n return (\n <img\n src={src}\n alt={alt}\n loading={lazy ? 'lazy' : 'eager'}\n onError={() => setFailed(true)}\n className={classes}\n style={{ width: size(width), height: size(height), ...style }}\n onClick={onClick}\n />\n );\n};\n\nexport default Image;\n"],"mappings":";;;;AA+BA,IAAM,IAAsC;CAC1C,OAAO;CACP,SAAS;CACT,MAAM;CACN,cAAc;CACd,MAAM;AACR,GAEM,IAA4C;CAChD,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;AACR,GAEM,KAAQ,MACZ,OAAO,KAAM,WAAW,GAAG,EAAE,MAAM,GAM/B,KAA+B,EACnC,QACA,SAAM,IACN,SAAM,SACN,UACA,WACA,YAAS,MACT,aACA,UAAO,IACP,eAAY,IACZ,UACA,iBACI;CACJ,IAAM,CAAC,GAAQ,KAAa,EAAS,EAAK,GAEpC,IAAU,EAAG,cAAc,EAAU,IAAM,EAAa,IAAS,CAAS;CAoBhF,OAlBI,IACE,MAAa,KAAA,IAIf,kBAAC,QAAD;EACE,WAAW,EACT,gGACA,EAAa,IACb,CACF;EACA,OAAO;GAAE,OAAO,EAAK,CAAK,KAAK;GAAQ,QAAQ,EAAK,CAAM,KAAK;GAAQ,GAAG;EAAM;EACjF,UAAA;CAEK,CAAA,IAZC,kBAAA,GAAA,EAAA,UAAG,EAAW,CAAA,IAiBvB,kBAAC,OAAD;EACO;EACA;EACL,SAAS,IAAO,SAAS;EACzB,eAAe,EAAU,EAAI;EAC7B,WAAW;EACX,OAAO;GAAE,OAAO,EAAK,CAAK;GAAG,QAAQ,EAAK,CAAM;GAAG,GAAG;EAAM;EACnD;CACV,CAAA;AAEL"}
1
+ {"version":3,"file":"index.js","names":["_Fragment","FIT_CLASS","RADIUS_CLASS","size","v","Image","failed","setFailed","useState","classes","cn","fit","radius","className","fallback","width","height","style","Fragment","lazy"],"sources":["../../../src/components/Image/index.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type ImageFit = 'cover' | 'contain' | 'fill' | 'scale-down' | 'none';\nexport type ImageRadius = 'none' | 'sm' | 'md' | 'lg' | 'full';\n\nexport type ImageProps = {\n /** Image source URL. */\n src: string;\n /** Alternative text (accessibility). */\n alt?: string;\n /** Object-fit mode. */\n fit?: ImageFit;\n /** Width; number is treated as px. */\n width?: number | string;\n /** Height; number is treated as px. */\n height?: number | string;\n /** Corner radius preset. */\n radius?: ImageRadius;\n /** Shown when the image fails to load (node or replacement URL). */\n fallback?: React.ReactNode;\n /** Native lazy loading. */\n lazy?: boolean;\n /** Extra class names on the img element. */\n className?: string;\n /** Inline styles on the img element. */\n style?: React.CSSProperties;\n /** Click handler. */\n onClick?: (e: React.MouseEvent<HTMLImageElement>) => void;\n};\n\nconst FIT_CLASS: Record<ImageFit, string> = {\n cover: 'object-cover',\n contain: 'object-contain',\n fill: 'object-fill',\n 'scale-down': 'object-scale-down',\n none: 'object-none',\n};\n\nconst RADIUS_CLASS: Record<ImageRadius, string> = {\n none: '',\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n full: 'rounded-full',\n};\n\nconst size = (v: number | string | undefined): string | undefined =>\n typeof v === 'number' ? `${v}px` : v;\n\n/**\n * Image —— A2UI 展示组件:图片。\n * 支持自适应填充模式、圆角、懒加载与加载失败时的 fallback。\n */\nconst Image: React.FC<ImageProps> = ({\n src,\n alt = '',\n fit = 'cover',\n width,\n height,\n radius = 'md',\n fallback,\n lazy = true,\n className = '',\n style,\n onClick,\n}) => {\n const [failed, setFailed] = useState(false);\n\n const classes = cn('max-w-full', FIT_CLASS[fit], RADIUS_CLASS[radius], className);\n\n if (failed) {\n if (fallback !== undefined) {\n return <>{fallback}</>;\n }\n return (\n <span\n className={cn(\n 'inline-flex items-center justify-center bg-base-200 text-base-content/40 text-xs select-none',\n RADIUS_CLASS[radius],\n className,\n )}\n style={{ width: size(width) ?? '100%', height: size(height) ?? '96px', ...style }}\n >\n Image\n </span>\n );\n }\n\n return (\n <img\n src={src}\n alt={alt}\n loading={lazy ? 'lazy' : 'eager'}\n onError={() => setFailed(true)}\n className={classes}\n style={{ width: size(width), height: size(height), ...style }}\n onClick={onClick}\n />\n );\n};\n\nexport default Image;\n"],"mappings":";;;;AA+BA,IAAMC,IAAsC;CAC1C,OAAO;CACP,SAAS;CACT,MAAM;CACN,cAAc;CACd,MAAM;AACR,GAEMC,IAA4C;CAChD,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;AACR,GAEMC,KAAQ,MACZ,OAAOC,KAAM,WAAW,GAAGA,EAAE,MAAMA,GAM/BC,KAA+B,EACnC,QACA,SAAM,IACN,SAAM,SACN,UACA,WACA,YAAS,MACT,aACA,UAAO,IACP,eAAY,IACZ,UACA,iBACI;CACJ,IAAM,CAACC,GAAQC,KAAaC,EAAS,EAAK,GAEpCC,IAAUC,EAAG,cAAcT,EAAUU,IAAMT,EAAaU,IAASC,CAAS;CAoBhF,OAlBIP,IACEQ,MAAa,KAAA,IAIf,kBAAC,QAAD;EACE,WAAWJ,EACT,gGACAR,EAAaU,IACbC,CACF;EACA,OAAO;GAAE,OAAOV,EAAKY,CAAK,KAAK;GAAQ,QAAQZ,EAAKa,CAAM,KAAK;GAAQ,GAAGC;EAAM;EACjF,UAAA;CAEK,CAAA,IAZC,kBAAAjB,GAAA,EAAA,UAAGc,EAAW,CAAA,IAiBvB,kBAAC,OAAD;EACO;EACA;EACL,SAASK,IAAO,SAAS;EACzB,eAAeZ,EAAU,EAAI;EAC7B,WAAWE;EACX,OAAO;GAAE,OAAON,EAAKY,CAAK;GAAG,QAAQZ,EAAKa,CAAM;GAAG,GAAGC;EAAM;EACnD;CACV,CAAA;AAEL"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Input/index.tsx"],"sourcesContent":["import React, { useState, useRef, useId } from 'react';\nimport './Input.css';\n\nexport type InputProps = Pick<React.InputHTMLAttributes<HTMLInputElement>, 'id' | 'name' | 'readOnly' | 'aria-label' | 'aria-labelledby' | 'aria-describedby' | 'aria-invalid'> & {\n placeholder?: string;\n value?: string;\n onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;\n type?: string;\n variant?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'ghost';\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n disabled?: boolean;\n required?: boolean;\n label?: string;\n labelPosition?: 'inline' | 'top';\n leftSection?: React.ReactNode;\n rightSection?: React.ReactNode;\n pattern?: string;\n className?: string;\n validator?: boolean;\n validatorHint?: string;\n validationRules?: {\n pattern: RegExp;\n message: string;\n }[];\n};\n\nconst Input = ({\n placeholder,\n value,\n onChange,\n type = 'text',\n variant,\n size = 'sm',\n disabled = false,\n required = false,\n label,\n labelPosition = 'inline',\n leftSection,\n rightSection,\n pattern,\n className = '',\n validator = false,\n validatorHint,\n validationRules = [],\n id,\n readOnly,\n ...inputAttributes\n}: InputProps) => {\n const generatedId = useId();\n const fieldId = id || generatedId;\n\n // 密码显示/隐藏状态\n const [showPassword, setShowPassword] = useState(false);\n // 表单验证状态\n const [isValid, setIsValid] = useState<boolean | null>(null);\n // 显示验证提示\n const [showValidationHint, setShowValidationHint] = useState(false);\n // 验证失败的规则消息\n const [failedRules, setFailedRules] = useState<string[]>([]);\n \n // 输入框引用,用于焦点和验证\n const inputRef = useRef<HTMLInputElement>(null);\n \n // 确定实际使用的输入类型\n const actualType = type === 'password' && showPassword ? 'text' : type;\n \n // 处理输入变化和验证\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n \n // 验证输入\n if (validator && inputRef.current) {\n validateInput(newValue);\n }\n \n // 调用原始的onChange处理函数\n if (onChange) {\n onChange(e);\n }\n };\n \n // 验证输入值\n const validateInput = (inputValue: string) => {\n if (!inputRef.current) return;\n \n // 使用HTML5自带的验证\n const isNativeValid = inputRef.current.checkValidity();\n \n // 检查自定义验证规则\n const failedMessages: string[] = [];\n \n if (validationRules.length > 0) {\n validationRules.forEach(rule => {\n // Global/sticky RegExp.test mutates lastIndex; validation must not depend on prior keystrokes.\n const rulePattern = rule.pattern.global || rule.pattern.sticky\n ? new RegExp(rule.pattern.source, rule.pattern.flags)\n : rule.pattern;\n if (!rulePattern.test(inputValue)) {\n failedMessages.push(rule.message);\n }\n });\n }\n \n setFailedRules(failedMessages);\n setIsValid(isNativeValid && failedMessages.length === 0);\n };\n \n // 切换密码显示/隐藏\n const togglePasswordVisibility = () => {\n setShowPassword(!showPassword);\n };\n \n // 鼠标悬停事件处理\n const handleMouseEnter = () => {\n if (validator && !isValid) {\n setShowValidationHint(true);\n }\n };\n \n const handleMouseLeave = () => {\n setShowValidationHint(false);\n };\n \n // 验证状态相关的类名\n let validationStateClass = '';\n if (validator && isValid !== null) {\n validationStateClass = isValid ? 'input-success' : 'input-error';\n }\n \n const fieldAttributes = {\n ...inputAttributes,\n id: fieldId,\n readOnly,\n 'aria-invalid': inputAttributes['aria-invalid'] ?? (validator && isValid === false ? true : undefined),\n };\n const baseClass = 'input dishui-input';\n const variantClass = variant && !validationStateClass ? `input-${variant}` : '';\n const sizeClass = size ? `input-${size}` : '';\n const validatorClass = validator ? 'validator' : '';\n \n\n // 密码可见性切换按钮\n const passwordToggle = type === 'password' && (\n <button\n type=\"button\"\n disabled={disabled}\n aria-label={showPassword ? 'Hide password' : 'Show password'}\n aria-pressed={showPassword}\n className=\"cursor-pointer opacity-70 hover:opacity-100\"\n onClick={togglePasswordVisibility}\n >\n {showPassword ? (\n // 眼睛关闭图标\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\" />\n <path d=\"M14.12 14.12a3 3 0 1 1-4.24-4.24\" />\n <path d=\"M1 1l22 22\" />\n <path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\" />\n </svg>\n ) : (\n // 眼睛打开图标\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n )}\n </button>\n );\n \n // 构建验证提示悬浮框\n const validationTooltip = (\n <div className=\"validation-tooltip\">\n {failedRules.length > 0 ? (\n <ul className=\"text-xs list-disc pl-4 py-1\">\n {failedRules.map((rule, index) => (\n <li key={index}>{rule}</li>\n ))}\n </ul>\n ) : validatorHint ? (\n <p className=\"text-xs py-1\">{validatorHint}</p>\n ) : null}\n </div>\n );\n\n // 如果有label,则使用label作为容器\n if (label || leftSection || rightSection || type === 'password') {\n // labelPosition === 'top': label above the input field\n if (label && labelPosition === 'top') {\n return (\n <div className={`relative w-full ${className}`} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>\n <label htmlFor={fieldId} className=\"text-sm font-medium mb-1 block\">{label}</label>\n <label className={`${baseClass} ${variantClass} ${sizeClass} ${validatorClass} ${validationStateClass} w-full flex items-center gap-2`}>\n {leftSection && <span>{leftSection}</span>}\n <input\n {...fieldAttributes}\n ref={inputRef}\n type={actualType}\n placeholder={placeholder}\n value={value}\n onChange={handleInputChange}\n disabled={disabled}\n required={required}\n className=\"grow\"\n pattern={pattern}\n />\n {type === 'password' ? (\n <button type=\"button\" disabled={disabled} aria-label={showPassword ? 'Hide password' : 'Show password'} aria-pressed={showPassword} className=\"cursor-pointer opacity-70 hover:opacity-100\" onClick={togglePasswordVisibility}>\n {showPassword ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\" />\n <path d=\"M14.12 14.12a3 3 0 1 1-4.24-4.24\" />\n <path d=\"M1 1l22 22\" />\n <path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\" />\n </svg>\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n )}\n </button>\n ) : rightSection ? (\n <span>{rightSection}</span>\n ) : null}\n </label>\n {validator && validatorHint && !showValidationHint && (\n <p className=\"validator-hint text-xs mt-1 opacity-70\">{validatorHint}</p>\n )}\n {showValidationHint && validator && !isValid && (\n <div className=\"absolute z-10 mt-1 bg-base-200 border border-error rounded shadow-lg text-error px-3 py-1\">\n {validationTooltip}\n </div>\n )}\n </div>\n );\n }\n\n // Default: inline label\n return (\n <div className={`relative w-full ${className}`} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>\n <label className={`${baseClass} ${variantClass} ${sizeClass} ${validatorClass} ${validationStateClass} w-full flex items-center gap-2`}>\n {leftSection && <span>{leftSection}</span>}\n {label && <span>{label}</span>}\n <input\n {...fieldAttributes}\n ref={inputRef}\n type={actualType}\n placeholder={placeholder}\n value={value}\n onChange={handleInputChange}\n disabled={disabled}\n required={required}\n className=\"grow\"\n pattern={pattern}\n />\n {/* 加入密码切换按钮或其他右侧元素 */}\n {type === 'password' ? (\n <span>{passwordToggle}</span>\n ) : rightSection ? (\n <span>{rightSection}</span>\n ) : null}\n </label>\n {validator && validatorHint && !showValidationHint && (\n <p className=\"validator-hint text-xs mt-1 opacity-70\">{validatorHint}</p>\n )}\n {showValidationHint && validator && !isValid && (\n <div className=\"absolute z-10 mt-1 bg-base-200 border border-error rounded shadow-lg text-error px-3 py-1\">\n {validationTooltip}\n </div>\n )}\n </div>\n );\n }\n\n // 如果没有label,则直接返回input\n return (\n <div className={`relative w-full ${className}`} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>\n <input\n {...fieldAttributes}\n ref={inputRef}\n type={actualType}\n placeholder={placeholder}\n value={value}\n onChange={handleInputChange}\n disabled={disabled}\n required={required}\n className={`${baseClass} ${variantClass} ${sizeClass} ${validatorClass} ${validationStateClass} w-full`}\n pattern={pattern}\n />\n {validator && validatorHint && !showValidationHint && (\n <p className=\"validator-hint text-xs mt-1 opacity-70\">{validatorHint}</p>\n )}\n {showValidationHint && validator && !isValid && (\n <div className=\"absolute z-10 mt-1 bg-base-200 border border-error rounded shadow-lg text-error px-3 py-1\">\n {validationTooltip}\n </div>\n )}\n </div>\n );\n};\n\nexport default Input; "],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Input","inputAttributes","generatedId","useId","fieldId","id","showPassword","setShowPassword","useState","isValid","setIsValid","showValidationHint","setShowValidationHint","failedRules","setFailedRules","inputRef","useRef","actualType","type","handleInputChange","newValue","validator","validateInput","onChange","isNativeValid","failedMessages","validationRules","rule","inputValue","togglePasswordVisibility","handleMouseEnter","handleMouseLeave","validationStateClass","fieldAttributes","baseClass","variantClass","variant","sizeClass","size","validatorClass","passwordToggle","validationTooltip","index","validatorHint","label","leftSection","rightSection","labelPosition","className"],"sources":["../../../src/components/Input/index.tsx"],"sourcesContent":["import React, { useState, useRef, useId } from 'react';\nimport './Input.css';\n\nexport type InputProps = Pick<React.InputHTMLAttributes<HTMLInputElement>, 'id' | 'name' | 'readOnly' | 'aria-label' | 'aria-labelledby' | 'aria-describedby' | 'aria-invalid'> & {\n placeholder?: string;\n value?: string;\n onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;\n type?: string;\n variant?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'ghost';\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n disabled?: boolean;\n required?: boolean;\n label?: string;\n labelPosition?: 'inline' | 'top';\n leftSection?: React.ReactNode;\n rightSection?: React.ReactNode;\n pattern?: string;\n className?: string;\n validator?: boolean;\n validatorHint?: string;\n validationRules?: {\n pattern: RegExp;\n message: string;\n }[];\n};\n\nconst Input = ({\n placeholder,\n value,\n onChange,\n type = 'text',\n variant,\n size = 'sm',\n disabled = false,\n required = false,\n label,\n labelPosition = 'inline',\n leftSection,\n rightSection,\n pattern,\n className = '',\n validator = false,\n validatorHint,\n validationRules = [],\n id,\n readOnly,\n ...inputAttributes\n}: InputProps) => {\n const generatedId = useId();\n const fieldId = id || generatedId;\n\n // 密码显示/隐藏状态\n const [showPassword, setShowPassword] = useState(false);\n // 表单验证状态\n const [isValid, setIsValid] = useState<boolean | null>(null);\n // 显示验证提示\n const [showValidationHint, setShowValidationHint] = useState(false);\n // 验证失败的规则消息\n const [failedRules, setFailedRules] = useState<string[]>([]);\n \n // 输入框引用,用于焦点和验证\n const inputRef = useRef<HTMLInputElement>(null);\n \n // 确定实际使用的输入类型\n const actualType = type === 'password' && showPassword ? 'text' : type;\n \n // 处理输入变化和验证\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n \n // 验证输入\n if (validator && inputRef.current) {\n validateInput(newValue);\n }\n \n // 调用原始的onChange处理函数\n if (onChange) {\n onChange(e);\n }\n };\n \n // 验证输入值\n const validateInput = (inputValue: string) => {\n if (!inputRef.current) return;\n \n // 使用HTML5自带的验证\n const isNativeValid = inputRef.current.checkValidity();\n \n // 检查自定义验证规则\n const failedMessages: string[] = [];\n \n if (validationRules.length > 0) {\n validationRules.forEach(rule => {\n // Global/sticky RegExp.test mutates lastIndex; validation must not depend on prior keystrokes.\n const rulePattern = rule.pattern.global || rule.pattern.sticky\n ? new RegExp(rule.pattern.source, rule.pattern.flags)\n : rule.pattern;\n if (!rulePattern.test(inputValue)) {\n failedMessages.push(rule.message);\n }\n });\n }\n \n setFailedRules(failedMessages);\n setIsValid(isNativeValid && failedMessages.length === 0);\n };\n \n // 切换密码显示/隐藏\n const togglePasswordVisibility = () => {\n setShowPassword(!showPassword);\n };\n \n // 鼠标悬停事件处理\n const handleMouseEnter = () => {\n if (validator && !isValid) {\n setShowValidationHint(true);\n }\n };\n \n const handleMouseLeave = () => {\n setShowValidationHint(false);\n };\n \n // 验证状态相关的类名\n let validationStateClass = '';\n if (validator && isValid !== null) {\n validationStateClass = isValid ? 'input-success' : 'input-error';\n }\n \n const fieldAttributes = {\n ...inputAttributes,\n id: fieldId,\n readOnly,\n 'aria-invalid': inputAttributes['aria-invalid'] ?? (validator && isValid === false ? true : undefined),\n };\n const baseClass = 'input dishui-input';\n const variantClass = variant && !validationStateClass ? `input-${variant}` : '';\n const sizeClass = size ? `input-${size}` : '';\n const validatorClass = validator ? 'validator' : '';\n \n\n // 密码可见性切换按钮\n const passwordToggle = type === 'password' && (\n <button\n type=\"button\"\n disabled={disabled}\n aria-label={showPassword ? 'Hide password' : 'Show password'}\n aria-pressed={showPassword}\n className=\"cursor-pointer opacity-70 hover:opacity-100\"\n onClick={togglePasswordVisibility}\n >\n {showPassword ? (\n // 眼睛关闭图标\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\" />\n <path d=\"M14.12 14.12a3 3 0 1 1-4.24-4.24\" />\n <path d=\"M1 1l22 22\" />\n <path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\" />\n </svg>\n ) : (\n // 眼睛打开图标\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n )}\n </button>\n );\n \n // 构建验证提示悬浮框\n const validationTooltip = (\n <div className=\"validation-tooltip\">\n {failedRules.length > 0 ? (\n <ul className=\"text-xs list-disc pl-4 py-1\">\n {failedRules.map((rule, index) => (\n <li key={index}>{rule}</li>\n ))}\n </ul>\n ) : validatorHint ? (\n <p className=\"text-xs py-1\">{validatorHint}</p>\n ) : null}\n </div>\n );\n\n // 如果有label,则使用label作为容器\n if (label || leftSection || rightSection || type === 'password') {\n // labelPosition === 'top': label above the input field\n if (label && labelPosition === 'top') {\n return (\n <div className={`relative w-full ${className}`} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>\n <label htmlFor={fieldId} className=\"text-sm font-medium mb-1 block\">{label}</label>\n <label className={`${baseClass} ${variantClass} ${sizeClass} ${validatorClass} ${validationStateClass} w-full flex items-center gap-2`}>\n {leftSection && <span>{leftSection}</span>}\n <input\n {...fieldAttributes}\n ref={inputRef}\n type={actualType}\n placeholder={placeholder}\n value={value}\n onChange={handleInputChange}\n disabled={disabled}\n required={required}\n className=\"grow\"\n pattern={pattern}\n />\n {type === 'password' ? (\n <button type=\"button\" disabled={disabled} aria-label={showPassword ? 'Hide password' : 'Show password'} aria-pressed={showPassword} className=\"cursor-pointer opacity-70 hover:opacity-100\" onClick={togglePasswordVisibility}>\n {showPassword ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\" />\n <path d=\"M14.12 14.12a3 3 0 1 1-4.24-4.24\" />\n <path d=\"M1 1l22 22\" />\n <path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\" />\n </svg>\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n )}\n </button>\n ) : rightSection ? (\n <span>{rightSection}</span>\n ) : null}\n </label>\n {validator && validatorHint && !showValidationHint && (\n <p className=\"validator-hint text-xs mt-1 opacity-70\">{validatorHint}</p>\n )}\n {showValidationHint && validator && !isValid && (\n <div className=\"absolute z-10 mt-1 bg-base-200 border border-error rounded shadow-lg text-error px-3 py-1\">\n {validationTooltip}\n </div>\n )}\n </div>\n );\n }\n\n // Default: inline label\n return (\n <div className={`relative w-full ${className}`} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>\n <label className={`${baseClass} ${variantClass} ${sizeClass} ${validatorClass} ${validationStateClass} w-full flex items-center gap-2`}>\n {leftSection && <span>{leftSection}</span>}\n {label && <span>{label}</span>}\n <input\n {...fieldAttributes}\n ref={inputRef}\n type={actualType}\n placeholder={placeholder}\n value={value}\n onChange={handleInputChange}\n disabled={disabled}\n required={required}\n className=\"grow\"\n pattern={pattern}\n />\n {/* 加入密码切换按钮或其他右侧元素 */}\n {type === 'password' ? (\n <span>{passwordToggle}</span>\n ) : rightSection ? (\n <span>{rightSection}</span>\n ) : null}\n </label>\n {validator && validatorHint && !showValidationHint && (\n <p className=\"validator-hint text-xs mt-1 opacity-70\">{validatorHint}</p>\n )}\n {showValidationHint && validator && !isValid && (\n <div className=\"absolute z-10 mt-1 bg-base-200 border border-error rounded shadow-lg text-error px-3 py-1\">\n {validationTooltip}\n </div>\n )}\n </div>\n );\n }\n\n // 如果没有label,则直接返回input\n return (\n <div className={`relative w-full ${className}`} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>\n <input\n {...fieldAttributes}\n ref={inputRef}\n type={actualType}\n placeholder={placeholder}\n value={value}\n onChange={handleInputChange}\n disabled={disabled}\n required={required}\n className={`${baseClass} ${variantClass} ${sizeClass} ${validatorClass} ${validationStateClass} w-full`}\n pattern={pattern}\n />\n {validator && validatorHint && !showValidationHint && (\n <p className=\"validator-hint text-xs mt-1 opacity-70\">{validatorHint}</p>\n )}\n {showValidationHint && validator && !isValid && (\n <div className=\"absolute z-10 mt-1 bg-base-200 border border-error rounded shadow-lg text-error px-3 py-1\">\n {validationTooltip}\n </div>\n )}\n </div>\n );\n};\n\nexport default Input; "],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Label/index.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, DragEvent } from 'react';\nimport { cn } from '../../utils/cn';\n\n// 扩展LabelState类型为字符串,允许用户定义任意状态\nexport type LabelState = string;\n\nexport type LabelStyleConfig = {\n [key: string]: {\n className?: string;\n style?: React.CSSProperties;\n }\n};\n\nexport type LabelProps = {\n children: React.ReactNode;\n variant?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error';\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n outline?: boolean;\n dash?: boolean;\n soft?: boolean;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n ellipsis?: boolean;\n maxWidth?: string;\n stateTimeout?: number;\n styleConfig?: LabelStyleConfig;\n // 新增属性:用户自定义状态\n state?: LabelState;\n // 新增属性:状态变化回调\n onStateChange?: (newState: LabelState) => void;\n onClick?: (e: React.MouseEvent) => void;\n onDoubleClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n onDragStart?: (e: DragEvent<HTMLSpanElement>) => void;\n onDragEnd?: (e: DragEvent<HTMLSpanElement>) => void;\n draggable?: boolean;\n className?: string;\n style?: React.CSSProperties;\n};\n\nconst Label = ({\n children,\n variant = 'neutral',\n size = 'sm',\n outline = false,\n dash = false,\n soft = false,\n bold = false,\n italic = false,\n underline = false,\n ellipsis = false,\n maxWidth,\n stateTimeout,\n styleConfig = {},\n // 使用用户传入的状态,默认为'default'\n state: userState,\n onStateChange,\n onClick,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n onDragStart,\n onDragEnd,\n draggable = false,\n className = '',\n style = {},\n}: LabelProps) => {\n // 当用户传入state时使用用户的状态,否则内部管理状态\n const [internalState, setInternalState] = useState<LabelState>('default');\n const state = userState !== undefined ? userState : internalState;\n \n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n \n // 更新状态的函数,同时执行回调\n const updateState = (newState: LabelState) => {\n if (userState === undefined) {\n setInternalState(newState);\n }\n onStateChange?.(newState);\n resetStateTimeout(newState);\n };\n \n // 重置状态计时器\n const resetStateTimeout = (currentState: LabelState = state) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n \n if (stateTimeout && currentState !== 'default' && userState === undefined) {\n timeoutRef.current = setTimeout(() => {\n setInternalState('default');\n onStateChange?.('default');\n }, stateTimeout);\n }\n };\n \n // 当状态变化或stateTimeout变化时重置计时器\n useEffect(() => {\n resetStateTimeout();\n \n // 清除计时器\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, [state, stateTimeout, userState]);\n \n // 尺寸类映射\n const sizeClassMap = {\n 'xs': 'text-xs',\n 'sm': 'text-sm',\n 'md': 'text-base',\n 'lg': 'text-lg',\n 'xl': 'text-xl',\n };\n const sizeClass = sizeClassMap[size] || sizeClassMap.md;\n \n // 样式类(依托 daisyUI badge 的 outline/dash/soft 外观,保证与主题联动)\n const decorated = outline || dash || soft;\n // 基础类:普通文本 label;带装饰时用 badge 充当“标签”容器\n //(装饰态不叠加 text-${variant}/dark:text-white,避免与 badge 自身前景色冲突)\n const baseClass = decorated ? 'badge' : cn('label min-w-0 dark:text-white', !ellipsis && 'whitespace-normal wrap-anywhere');\n const variantClass = !decorated && variant ? `text-${variant}` : '';\n const outlineClass = outline ? 'badge-outline' : '';\n const dashClass = dash ? 'badge-dash' : '';\n const softClass = soft ? 'badge-soft' : '';\n // 为带装饰的标签补上色调变体(badge-${variant}),让边框/底色跟随 variant\n const badgeVariantClass = decorated && variant && variant !== 'neutral' ? `badge-${variant}` : '';\n const boldClass = bold ? 'font-bold' : '';\n const italicClass = italic ? 'italic' : '';\n const underlineClass = underline ? 'underline' : '';\n const ellipsisClass = ellipsis ? 'truncate' : '';\n \n // 组合所有类名\n const labelClasses = cn(\n baseClass,\n variantClass,\n sizeClass,\n outlineClass,\n dashClass,\n softClass,\n badgeVariantClass,\n boldClass,\n italicClass,\n underlineClass,\n ellipsisClass,\n className\n );\n \n // 处理事件\n const handleClick = (e: React.MouseEvent) => {\n updateState('clicked');\n onClick?.(e);\n };\n \n const handleDoubleClick = (e: React.MouseEvent) => {\n updateState('doubleClicked');\n onDoubleClick?.(e);\n };\n \n const handleMouseEnter = (e: React.MouseEvent) => {\n updateState('hover');\n onMouseEnter?.(e);\n };\n \n const handleMouseLeave = (e: React.MouseEvent) => {\n updateState('default');\n onMouseLeave?.(e);\n };\n \n const handleDragStart = (e: DragEvent<HTMLSpanElement>) => {\n updateState('dragging');\n onDragStart?.(e);\n };\n \n const handleDragEnd = (e: DragEvent<HTMLSpanElement>) => {\n updateState('default');\n onDragEnd?.(e);\n };\n \n // 获取当前状态的自定义样式和类\n const stateStyle = styleConfig[state]?.style || {};\n const stateClassName = styleConfig[state]?.className || '';\n \n // 合并样式\n const combinedStyle = {\n ...style,\n ...stateStyle,\n ...(maxWidth ? { maxWidth } : {}),\n ...(ellipsis ? { display: 'inline-block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } : {})\n };\n \n // 最终类名\n const finalClassName = cn(labelClasses, stateClassName);\n \n return (\n <span\n className={finalClassName}\n style={combinedStyle}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n draggable={draggable}\n >\n {children}\n </span>\n );\n};\n\nexport default Label; "],"mappings":";;;;AA0CA,IAAM,KAAS,EACb,aACA,aAAU,WACV,UAAO,MACP,aAAU,IACV,UAAO,IACP,UAAO,IACP,UAAO,IACP,YAAS,IACT,eAAY,IACZ,cAAW,IACX,aACA,iBACA,iBAAc,CAAC,GAEf,OAAO,GACP,kBACA,YACA,kBACA,iBACA,iBACA,gBACA,cACA,eAAY,IACZ,eAAY,IACZ,WAAQ,CAAC,QACO;CAEhB,IAAM,CAAC,GAAe,KAAoB,EAAqB,SAAS,GAClE,IAAQ,MAAc,KAAA,IAAwB,IAAZ,GAElC,IAAa,EAA6C,IAAI,GAG9D,KAAe,MAAyB;EAK5C,AAJI,MAAc,KAAA,KAChB,EAAiB,CAAQ,GAE3B,IAAgB,CAAQ,GACxB,EAAkB,CAAQ;CAC5B,GAGM,KAAqB,IAA2B,MAAU;EAM9D,AALA,AAEE,EAAW,aADX,aAAa,EAAW,OAAO,GACV,OAGnB,KAAgB,MAAiB,aAAa,MAAc,KAAA,MAC9D,EAAW,UAAU,iBAAiB;GAEpC,AADA,EAAiB,SAAS,GAC1B,IAAgB,SAAS;EAC3B,GAAG,CAAY;CAEnB;CAGA,SACE,EAAkB,SAGL;EACX,AAAI,EAAW,WACb,aAAa,EAAW,OAAO;CAEnC,IACC;EAAC;EAAO;EAAc;CAAS,CAAC;CAGnC,IAAM,IAAe;EACnB,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;CACR,GACM,KAAY,EAAa,MAAS,EAAa,IAG/C,IAAY,KAAW,KAAQ,GAG/B,IAAY,IAAY,UAAU,EAAG,iCAAiC,CAAC,KAAY,iCAAiC,GACpH,IAAe,CAAC,KAAa,IAAU,QAAQ,MAAY,IAC3D,IAAe,IAAU,kBAAkB,IAC3C,IAAY,IAAO,eAAe,IAClC,IAAY,IAAO,eAAe,IAElC,IAAoB,KAAa,KAAW,MAAY,YAAY,SAAS,MAAY,IAOzF,IAAe,EACnB,GACA,GACA,IACA,GACA,GACA,GACA,GAbgB,IAAO,cAAc,IACnB,IAAS,WAAW,IACjB,IAAY,cAAc,IAC3B,IAAW,aAAa,IAe5C,CACF,GAGM,KAAe,MAAwB;EAE3C,AADA,EAAY,SAAS,GACrB,IAAU,CAAC;CACb,GAEM,KAAqB,MAAwB;EAEjD,AADA,EAAY,eAAe,GAC3B,IAAgB,CAAC;CACnB,GAEM,KAAoB,MAAwB;EAEhD,AADA,EAAY,OAAO,GACnB,IAAe,CAAC;CAClB,GAEM,KAAoB,MAAwB;EAEhD,AADA,EAAY,SAAS,GACrB,IAAe,CAAC;CAClB,GAEM,KAAmB,MAAkC;EAEzD,AADA,EAAY,UAAU,GACtB,IAAc,CAAC;CACjB,GAEM,KAAiB,MAAkC;EAEvD,AADA,EAAY,SAAS,GACrB,IAAY,CAAC;CACf,GAGM,IAAa,EAAY,EAAM,EAAE,SAAS,CAAC,GAC3C,IAAiB,EAAY,EAAM,EAAE,aAAa,IAGlD,IAAgB;EACpB,GAAG;EACH,GAAG;EACH,GAAI,IAAW,EAAE,YAAS,IAAI,CAAC;EAC/B,GAAI,IAAW;GAAE,SAAS;GAAgB,UAAU;GAAU,cAAc;GAAY,YAAY;EAAS,IAAI,CAAC;CACpH,GAGM,IAAiB,EAAG,GAAc,CAAc;CAEtD,OACE,kBAAC,QAAD;EACE,WAAW;EACX,OAAO;EACP,SAAS;EACT,eAAe;EACf,cAAc;EACd,cAAc;EACd,aAAa;EACb,WAAW;EACA;EAEV;CACG,CAAA;AAEV"}
1
+ {"version":3,"file":"index.js","names":["Label","userState","internalState","setInternalState","useState","state","timeoutRef","useRef","updateState","newState","onStateChange","resetStateTimeout","stateTimeout","currentState","sizeClassMap","\"xs\"","\"sm\"","\"md\"","\"lg\"","\"xl\"","sizeClass","size","decorated","outline","dash","soft","baseClass","cn","ellipsis","variantClass","variant","outlineClass","dashClass","softClass","badgeVariantClass","labelClasses","bold","italic","underline","className","handleClick","onClick","handleDoubleClick","onDoubleClick","handleMouseEnter","onMouseEnter","handleMouseLeave","onMouseLeave","handleDragStart","onDragStart","handleDragEnd","onDragEnd","stateStyle","styleConfig","stateClassName","combinedStyle","style","maxWidth","finalClassName"],"sources":["../../../src/components/Label/index.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, DragEvent } from 'react';\nimport { cn } from '../../utils/cn';\n\n// 扩展LabelState类型为字符串,允许用户定义任意状态\nexport type LabelState = string;\n\nexport type LabelStyleConfig = {\n [key: string]: {\n className?: string;\n style?: React.CSSProperties;\n }\n};\n\nexport type LabelProps = {\n children: React.ReactNode;\n variant?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error';\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n outline?: boolean;\n dash?: boolean;\n soft?: boolean;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n ellipsis?: boolean;\n maxWidth?: string;\n stateTimeout?: number;\n styleConfig?: LabelStyleConfig;\n // 新增属性:用户自定义状态\n state?: LabelState;\n // 新增属性:状态变化回调\n onStateChange?: (newState: LabelState) => void;\n onClick?: (e: React.MouseEvent) => void;\n onDoubleClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n onDragStart?: (e: DragEvent<HTMLSpanElement>) => void;\n onDragEnd?: (e: DragEvent<HTMLSpanElement>) => void;\n draggable?: boolean;\n className?: string;\n style?: React.CSSProperties;\n};\n\nconst Label = ({\n children,\n variant = 'neutral',\n size = 'sm',\n outline = false,\n dash = false,\n soft = false,\n bold = false,\n italic = false,\n underline = false,\n ellipsis = false,\n maxWidth,\n stateTimeout,\n styleConfig = {},\n // 使用用户传入的状态,默认为'default'\n state: userState,\n onStateChange,\n onClick,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n onDragStart,\n onDragEnd,\n draggable = false,\n className = '',\n style = {},\n}: LabelProps) => {\n // 当用户传入state时使用用户的状态,否则内部管理状态\n const [internalState, setInternalState] = useState<LabelState>('default');\n const state = userState !== undefined ? userState : internalState;\n \n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n \n // 更新状态的函数,同时执行回调\n const updateState = (newState: LabelState) => {\n if (userState === undefined) {\n setInternalState(newState);\n }\n onStateChange?.(newState);\n resetStateTimeout(newState);\n };\n \n // 重置状态计时器\n const resetStateTimeout = (currentState: LabelState = state) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n \n if (stateTimeout && currentState !== 'default' && userState === undefined) {\n timeoutRef.current = setTimeout(() => {\n setInternalState('default');\n onStateChange?.('default');\n }, stateTimeout);\n }\n };\n \n // 当状态变化或stateTimeout变化时重置计时器\n useEffect(() => {\n resetStateTimeout();\n \n // 清除计时器\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, [state, stateTimeout, userState]);\n \n // 尺寸类映射\n const sizeClassMap = {\n 'xs': 'text-xs',\n 'sm': 'text-sm',\n 'md': 'text-base',\n 'lg': 'text-lg',\n 'xl': 'text-xl',\n };\n const sizeClass = sizeClassMap[size] || sizeClassMap.md;\n \n // 样式类(依托 daisyUI badge 的 outline/dash/soft 外观,保证与主题联动)\n const decorated = outline || dash || soft;\n // 基础类:普通文本 label;带装饰时用 badge 充当“标签”容器\n //(装饰态不叠加 text-${variant}/dark:text-white,避免与 badge 自身前景色冲突)\n const baseClass = decorated ? 'badge' : cn('label min-w-0 dark:text-white', !ellipsis && 'whitespace-normal wrap-anywhere');\n const variantClass = !decorated && variant ? `text-${variant}` : '';\n const outlineClass = outline ? 'badge-outline' : '';\n const dashClass = dash ? 'badge-dash' : '';\n const softClass = soft ? 'badge-soft' : '';\n // 为带装饰的标签补上色调变体(badge-${variant}),让边框/底色跟随 variant\n const badgeVariantClass = decorated && variant && variant !== 'neutral' ? `badge-${variant}` : '';\n const boldClass = bold ? 'font-bold' : '';\n const italicClass = italic ? 'italic' : '';\n const underlineClass = underline ? 'underline' : '';\n const ellipsisClass = ellipsis ? 'truncate' : '';\n \n // 组合所有类名\n const labelClasses = cn(\n baseClass,\n variantClass,\n sizeClass,\n outlineClass,\n dashClass,\n softClass,\n badgeVariantClass,\n boldClass,\n italicClass,\n underlineClass,\n ellipsisClass,\n className\n );\n \n // 处理事件\n const handleClick = (e: React.MouseEvent) => {\n updateState('clicked');\n onClick?.(e);\n };\n \n const handleDoubleClick = (e: React.MouseEvent) => {\n updateState('doubleClicked');\n onDoubleClick?.(e);\n };\n \n const handleMouseEnter = (e: React.MouseEvent) => {\n updateState('hover');\n onMouseEnter?.(e);\n };\n \n const handleMouseLeave = (e: React.MouseEvent) => {\n updateState('default');\n onMouseLeave?.(e);\n };\n \n const handleDragStart = (e: DragEvent<HTMLSpanElement>) => {\n updateState('dragging');\n onDragStart?.(e);\n };\n \n const handleDragEnd = (e: DragEvent<HTMLSpanElement>) => {\n updateState('default');\n onDragEnd?.(e);\n };\n \n // 获取当前状态的自定义样式和类\n const stateStyle = styleConfig[state]?.style || {};\n const stateClassName = styleConfig[state]?.className || '';\n \n // 合并样式\n const combinedStyle = {\n ...style,\n ...stateStyle,\n ...(maxWidth ? { maxWidth } : {}),\n ...(ellipsis ? { display: 'inline-block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } : {})\n };\n \n // 最终类名\n const finalClassName = cn(labelClasses, stateClassName);\n \n return (\n <span\n className={finalClassName}\n style={combinedStyle}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n draggable={draggable}\n >\n {children}\n </span>\n );\n};\n\nexport default Label; "],"mappings":";;;;AA0CA,IAAMA,KAAS,EACb,aACA,aAAU,WACV,UAAO,MACP,aAAU,IACV,UAAO,IACP,UAAO,IACP,UAAO,IACP,YAAS,IACT,eAAY,IACZ,cAAW,IACX,aACA,iBACA,iBAAc,CAAC,GAEf,OAAOC,GACP,kBACA,YACA,kBACA,iBACA,iBACA,gBACA,cACA,eAAY,IACZ,eAAY,IACZ,WAAQ,CAAC,QACO;CAEhB,IAAM,CAACC,GAAeC,KAAoBC,EAAqB,SAAS,GAClEC,IAAQJ,MAAc,KAAA,IAAwBC,IAAZD,GAElCK,IAAaC,EAA6C,IAAI,GAG9DC,KAAe,MAAyB;EAK5C,AAJIP,MAAc,KAAA,KAChBE,EAAiBM,CAAQ,GAE3BC,IAAgBD,CAAQ,GACxBE,EAAkBF,CAAQ;CAC5B,GAGME,KAAqB,IAA2BN,MAAU;EAM9D,AALA,AAEEC,EAAW,aADX,aAAaA,EAAW,OAAO,GACV,OAGnBM,KAAgBC,MAAiB,aAAaZ,MAAc,KAAA,MAC9D,EAAW,UAAU,iBAAiB;GAEpC,AADAE,EAAiB,SAAS,GAC1BO,IAAgB,SAAS;EAC3B,GAAGE,CAAY;CAEnB;CAGA,SACED,EAAkB,SAGL;EACX,AAAIL,EAAW,WACb,aAAaA,EAAW,OAAO;CAEnC,IACC;EAACD;EAAOO;EAAcX;CAAS,CAAC;CAGnC,IAAMa,IAAe;EACnBC,IAAM;EACNC,IAAM;EACNC,IAAM;EACNC,IAAM;EACNC,IAAM;CACR,GACMC,KAAYN,EAAaO,MAASP,EAAa,IAG/CQ,IAAYC,KAAWC,KAAQC,GAG/BC,IAAYJ,IAAY,UAAUK,EAAG,iCAAiC,CAACC,KAAY,iCAAiC,GACpHC,IAAe,CAACP,KAAaQ,IAAU,QAAQA,MAAY,IAC3DC,IAAeR,IAAU,kBAAkB,IAC3CS,IAAYR,IAAO,eAAe,IAClCS,IAAYR,IAAO,eAAe,IAElCS,IAAoBZ,KAAaQ,KAAWA,MAAY,YAAY,SAASA,MAAY,IAOzFK,IAAeR,EACnBD,GACAG,GACAT,IACAW,GACAC,GACAC,GACAC,GAbgBE,IAAO,cAAc,IACnBC,IAAS,WAAW,IACjBC,IAAY,cAAc,IAC3BV,IAAW,aAAa,IAe5CW,CACF,GAGMC,KAAe,MAAwB;EAE3C,AADAhC,EAAY,SAAS,GACrBiC,IAAU,CAAC;CACb,GAEMC,KAAqB,MAAwB;EAEjD,AADAlC,EAAY,eAAe,GAC3BmC,IAAgB,CAAC;CACnB,GAEMC,KAAoB,MAAwB;EAEhD,AADApC,EAAY,OAAO,GACnBqC,IAAe,CAAC;CAClB,GAEMC,KAAoB,MAAwB;EAEhD,AADAtC,EAAY,SAAS,GACrBuC,IAAe,CAAC;CAClB,GAEMC,KAAmB,MAAkC;EAEzD,AADAxC,EAAY,UAAU,GACtByC,IAAc,CAAC;CACjB,GAEMC,KAAiB,MAAkC;EAEvD,AADA1C,EAAY,SAAS,GACrB2C,IAAY,CAAC;CACf,GAGMC,IAAaC,EAAYhD,EAAM,EAAE,SAAS,CAAC,GAC3CiD,IAAiBD,EAAYhD,EAAM,EAAE,aAAa,IAGlDkD,IAAgB;EACpB,GAAGC;EACH,GAAGJ;EACH,GAAIK,IAAW,EAAE,YAAS,IAAI,CAAC;EAC/B,GAAI7B,IAAW;GAAE,SAAS;GAAgB,UAAU;GAAU,cAAc;GAAY,YAAY;EAAS,IAAI,CAAC;CACpH,GAGM8B,IAAiB/B,EAAGQ,GAAcmB,CAAc;CAEtD,OACE,kBAAC,QAAD;EACE,WAAWI;EACX,OAAOH;EACP,SAASf;EACT,eAAeE;EACf,cAAcE;EACd,cAAcE;EACd,aAAaE;EACb,WAAWE;EACA;EAEV;CACG,CAAA;AAEV"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Layout/index.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type LayoutGap = number | string;\nexport type GridColumns = number | readonly number[] | string;\nexport type GridPlacement = number | string;\nexport type LayoutMaxWidth = number | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full' | string;\nexport type LayoutAlign = React.CSSProperties['alignItems'] | 'start' | 'end';\nexport type LayoutJustify = React.CSSProperties['justifyContent'] | 'start' | 'end' | 'between' | 'around' | 'evenly';\n\nexport type LayoutContainerProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Maximum content width. Numbers are interpreted as pixels. */\n maxWidth?: LayoutMaxWidth;\n /** Horizontal container padding. Numbers are interpreted as pixels. */\n padding?: number | string;\n /** Centers the container when a max width is applied. */\n centered?: boolean;\n /** Makes the container span the available width. */\n fluid?: boolean;\n /** Uses adaptive horizontal padding that grows with the viewport. */\n responsive?: boolean;\n};\n\nexport type LayoutGridProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Column count (12 by default) or a custom ratio such as [1, 2, 1] or \"1fr 2fr 1fr\". */\n columns?: GridColumns;\n gap?: LayoutGap;\n /** Alias for gap. gap takes precedence when both are provided. */\n space?: LayoutGap;\n rowGap?: LayoutGap;\n columnGap?: LayoutGap;\n align?: LayoutAlign;\n justify?: LayoutJustify;\n autoRows?: React.CSSProperties['gridAutoRows'];\n dense?: boolean;\n};\n\nexport type LayoutGridItemProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Number of grid tracks to span, or a valid CSS grid-column value. */\n span?: GridPlacement;\n /** One-based grid column start, or a valid CSS grid-column-start value. */\n start?: GridPlacement;\n /** Number of empty tracks before the item. Ignored when start is set. */\n offset?: number;\n rowSpan?: GridPlacement;\n rowStart?: GridPlacement;\n};\n\nexport type LayoutFlexProps = React.HTMLAttributes<HTMLDivElement> & {\n direction?: React.CSSProperties['flexDirection'];\n wrap?: React.CSSProperties['flexWrap'];\n align?: LayoutAlign;\n justify?: LayoutJustify;\n gap?: LayoutGap;\n rowGap?: LayoutGap;\n columnGap?: LayoutGap;\n inline?: boolean;\n};\n\nexport type LayoutGroupProps = React.HTMLAttributes<HTMLDivElement> & {\n direction?: React.CSSProperties['flexDirection'];\n /** Boolean shorthand is supported alongside CSS wrap values. */\n wrap?: React.CSSProperties['flexWrap'] | boolean;\n align?: LayoutAlign;\n justify?: LayoutJustify;\n gap?: LayoutGap;\n fullWidth?: boolean;\n};\n\nexport type LayoutSpaceProps = React.HTMLAttributes<HTMLSpanElement> & {\n direction?: 'horizontal' | 'vertical';\n /** Width for horizontal spaces and height for vertical spaces. */\n size?: number | string;\n /** Makes the spacer consume remaining flex space. */\n flex?: number | string;\n};\n\nconst maxWidths: Record<string, string> = {\n sm: '640px',\n md: '768px',\n lg: '1024px',\n xl: '1280px',\n '2xl': '1536px',\n full: '100%',\n};\n\nconst cssSize = (value: number | string | undefined): string | undefined =>\n typeof value === 'number' ? `${value}px` : value;\n\nconst cssMaxWidth = (value: LayoutMaxWidth | undefined): string | undefined =>\n typeof value === 'string' ? maxWidths[value] ?? value : cssSize(value);\n\nconst cssAlign = (value: LayoutAlign | undefined): React.CSSProperties['alignItems'] =>\n value === 'start' || value === 'end' ? `flex-${value}` : value;\n\nconst cssJustify = (value: LayoutJustify | undefined): React.CSSProperties['justifyContent'] => {\n const aliases: Record<string, React.CSSProperties['justifyContent']> = {\n start: 'flex-start',\n end: 'flex-end',\n between: 'space-between',\n around: 'space-around',\n evenly: 'space-evenly',\n };\n return typeof value === 'string' ? aliases[value] ?? value : value;\n};\n\nconst cssGap = (value: LayoutGap | undefined): string | undefined =>\n typeof value === 'number' ? `${value}px` : value;\n\nconst positiveInteger = (value: number, name: string): number => {\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`Layout.${name} must be a positive integer.`);\n }\n return value;\n};\n\nconst positiveNumber = (value: number, name: string): number => {\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error(`Layout.${name} must be a positive number.`);\n }\n return value;\n};\n\nconst gridTemplateColumns = (columns: GridColumns): string => {\n if (typeof columns === 'number') {\n return `repeat(${positiveInteger(columns, 'Grid columns')}, minmax(0, 1fr))`;\n }\n\n if (typeof columns === 'string') {\n return columns;\n }\n\n if (columns.length === 0) {\n throw new Error('Layout.Grid columns ratio must contain at least one value.');\n }\n\n return columns\n .map((ratio) => `${positiveNumber(ratio, 'Grid ratio')}fr`)\n .join(' ');\n};\n\nconst gridSpan = (value: GridPlacement | undefined): string | number | undefined =>\n typeof value === 'number'\n ? `span ${positiveInteger(value, 'Grid.Item span')} / span ${value}`\n : value;\n\nconst gridStart = (value: GridPlacement | undefined, name: string): string | number | undefined =>\n typeof value === 'number' ? positiveInteger(value, name) : value;\n\nconst Container = forwardRef<HTMLDivElement, LayoutContainerProps>(function LayoutContainer(\n {\n maxWidth = 1280,\n padding = '1rem',\n centered = true,\n fluid = false,\n responsive = false,\n className = '',\n style,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-container', className)}\n style={{\n width: '100%',\n maxWidth: fluid ? undefined : cssMaxWidth(maxWidth),\n marginInline: centered && !fluid ? 'auto' : undefined,\n paddingInline: responsive\n ? `clamp(${cssSize(padding)}, 4vw, max(${cssSize(padding)}, 2rem))`\n : cssSize(padding),\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst GridItem = forwardRef<HTMLDivElement, LayoutGridItemProps>(function LayoutGridItem(\n { span, start, offset, rowSpan, rowStart, className = '', style, ...props },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-grid-item', className)}\n style={{\n gridColumn: gridSpan(span),\n gridColumnStart: gridStart(\n start ?? (offset !== undefined ? positiveInteger(offset + 1, 'Grid.Item offset') : undefined),\n 'Grid.Item start',\n ),\n gridRow: gridSpan(rowSpan),\n gridRowStart: gridStart(rowStart, 'Grid.Item rowStart'),\n minWidth: 0,\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst GridRoot = forwardRef<HTMLDivElement, LayoutGridProps>(function LayoutGrid(\n {\n columns = 12,\n gap,\n space,\n rowGap,\n columnGap,\n align,\n justify,\n autoRows,\n dense = false,\n className = '',\n style,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-grid', className)}\n style={{\n display: 'grid',\n gridTemplateColumns: gridTemplateColumns(columns),\n gap: cssGap(gap ?? space),\n rowGap: cssGap(rowGap),\n columnGap: cssGap(columnGap),\n alignItems: cssAlign(align),\n justifyContent: cssJustify(justify),\n gridAutoRows: autoRows,\n gridAutoFlow: dense ? 'row dense' : undefined,\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst Group = forwardRef<HTMLDivElement, LayoutGroupProps>(function LayoutGroup(\n {\n direction = 'row',\n wrap = 'nowrap',\n align = 'center',\n justify = 'start',\n gap,\n fullWidth = false,\n className = '',\n style,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-group', className)}\n style={{\n display: 'flex',\n width: fullWidth ? '100%' : undefined,\n flexDirection: direction,\n flexWrap: typeof wrap === 'boolean' ? (wrap ? 'wrap' : 'nowrap') : wrap,\n alignItems: cssAlign(align),\n justifyContent: cssJustify(justify),\n gap: cssGap(gap),\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst Space = forwardRef<HTMLSpanElement, LayoutSpaceProps>(function LayoutSpace(\n { direction = 'horizontal', size = 16, flex, className = '', style, ...props },\n ref,\n) {\n const dimension = cssSize(size);\n\n return (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn('dishui-layout-space', className)}\n style={{\n display: 'block',\n flex: flex ?? '0 0 auto',\n width: direction === 'horizontal' ? dimension : '100%',\n minWidth: direction === 'horizontal' ? dimension : undefined,\n height: direction === 'vertical' ? dimension : 1,\n minHeight: direction === 'vertical' ? dimension : undefined,\n pointerEvents: 'none',\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst Flex = forwardRef<HTMLDivElement, LayoutFlexProps>(function LayoutFlex(\n {\n direction = 'row',\n wrap = 'nowrap',\n align,\n justify,\n gap,\n rowGap,\n columnGap,\n inline = false,\n className = '',\n style,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-flex', className)}\n style={{\n display: inline ? 'inline-flex' : 'flex',\n flexDirection: direction,\n flexWrap: wrap,\n alignItems: cssAlign(align),\n justifyContent: cssJustify(justify),\n gap: cssGap(gap),\n rowGap: cssGap(rowGap),\n columnGap: cssGap(columnGap),\n ...style,\n }}\n {...props}\n />\n );\n});\n\ninterface LayoutGridCompound extends React.ForwardRefExoticComponent<\n LayoutGridProps & React.RefAttributes<HTMLDivElement>\n> {\n Item: typeof GridItem;\n}\n\nconst Grid = GridRoot as LayoutGridCompound;\nGrid.Item = GridItem;\n\nexport interface LayoutCompound {\n Container: typeof Container;\n Grid: LayoutGridCompound;\n Flex: typeof Flex;\n Group: typeof Group;\n Space: typeof Space;\n}\n\nconst Layout: LayoutCompound = {\n Container,\n Grid,\n Flex,\n Group,\n Space,\n};\n\nexport { Container, Grid, GridItem, Flex, Group, Space };\nexport default Layout;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["maxWidths","cssSize","value","cssMaxWidth","cssAlign","cssJustify","cssGap","positiveInteger","name","positiveNumber","gridTemplateColumns","columns","ratio","gridSpan","gridStart","Container","forwardRef","props","cn","className","fluid","maxWidth","centered","responsive","padding","style","GridItem","span","start","offset","rowSpan","rowStart","GridRoot","gap","space","rowGap","columnGap","align","justify","autoRows","dense","Group","fullWidth","direction","wrap","Space","dimension","size","flex","Flex","inline","Grid","Layout"],"sources":["../../../src/components/Layout/index.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type LayoutGap = number | string;\nexport type GridColumns = number | readonly number[] | string;\nexport type GridPlacement = number | string;\nexport type LayoutMaxWidth = number | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full' | string;\nexport type LayoutAlign = React.CSSProperties['alignItems'] | 'start' | 'end';\nexport type LayoutJustify = React.CSSProperties['justifyContent'] | 'start' | 'end' | 'between' | 'around' | 'evenly';\n\nexport type LayoutContainerProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Maximum content width. Numbers are interpreted as pixels. */\n maxWidth?: LayoutMaxWidth;\n /** Horizontal container padding. Numbers are interpreted as pixels. */\n padding?: number | string;\n /** Centers the container when a max width is applied. */\n centered?: boolean;\n /** Makes the container span the available width. */\n fluid?: boolean;\n /** Uses adaptive horizontal padding that grows with the viewport. */\n responsive?: boolean;\n};\n\nexport type LayoutGridProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Column count (12 by default) or a custom ratio such as [1, 2, 1] or \"1fr 2fr 1fr\". */\n columns?: GridColumns;\n gap?: LayoutGap;\n /** Alias for gap. gap takes precedence when both are provided. */\n space?: LayoutGap;\n rowGap?: LayoutGap;\n columnGap?: LayoutGap;\n align?: LayoutAlign;\n justify?: LayoutJustify;\n autoRows?: React.CSSProperties['gridAutoRows'];\n dense?: boolean;\n};\n\nexport type LayoutGridItemProps = React.HTMLAttributes<HTMLDivElement> & {\n /** Number of grid tracks to span, or a valid CSS grid-column value. */\n span?: GridPlacement;\n /** One-based grid column start, or a valid CSS grid-column-start value. */\n start?: GridPlacement;\n /** Number of empty tracks before the item. Ignored when start is set. */\n offset?: number;\n rowSpan?: GridPlacement;\n rowStart?: GridPlacement;\n};\n\nexport type LayoutFlexProps = React.HTMLAttributes<HTMLDivElement> & {\n direction?: React.CSSProperties['flexDirection'];\n wrap?: React.CSSProperties['flexWrap'];\n align?: LayoutAlign;\n justify?: LayoutJustify;\n gap?: LayoutGap;\n rowGap?: LayoutGap;\n columnGap?: LayoutGap;\n inline?: boolean;\n};\n\nexport type LayoutGroupProps = React.HTMLAttributes<HTMLDivElement> & {\n direction?: React.CSSProperties['flexDirection'];\n /** Boolean shorthand is supported alongside CSS wrap values. */\n wrap?: React.CSSProperties['flexWrap'] | boolean;\n align?: LayoutAlign;\n justify?: LayoutJustify;\n gap?: LayoutGap;\n fullWidth?: boolean;\n};\n\nexport type LayoutSpaceProps = React.HTMLAttributes<HTMLSpanElement> & {\n direction?: 'horizontal' | 'vertical';\n /** Width for horizontal spaces and height for vertical spaces. */\n size?: number | string;\n /** Makes the spacer consume remaining flex space. */\n flex?: number | string;\n};\n\nconst maxWidths: Record<string, string> = {\n sm: '640px',\n md: '768px',\n lg: '1024px',\n xl: '1280px',\n '2xl': '1536px',\n full: '100%',\n};\n\nconst cssSize = (value: number | string | undefined): string | undefined =>\n typeof value === 'number' ? `${value}px` : value;\n\nconst cssMaxWidth = (value: LayoutMaxWidth | undefined): string | undefined =>\n typeof value === 'string' ? maxWidths[value] ?? value : cssSize(value);\n\nconst cssAlign = (value: LayoutAlign | undefined): React.CSSProperties['alignItems'] =>\n value === 'start' || value === 'end' ? `flex-${value}` : value;\n\nconst cssJustify = (value: LayoutJustify | undefined): React.CSSProperties['justifyContent'] => {\n const aliases: Record<string, React.CSSProperties['justifyContent']> = {\n start: 'flex-start',\n end: 'flex-end',\n between: 'space-between',\n around: 'space-around',\n evenly: 'space-evenly',\n };\n return typeof value === 'string' ? aliases[value] ?? value : value;\n};\n\nconst cssGap = (value: LayoutGap | undefined): string | undefined =>\n typeof value === 'number' ? `${value}px` : value;\n\nconst positiveInteger = (value: number, name: string): number => {\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`Layout.${name} must be a positive integer.`);\n }\n return value;\n};\n\nconst positiveNumber = (value: number, name: string): number => {\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error(`Layout.${name} must be a positive number.`);\n }\n return value;\n};\n\nconst gridTemplateColumns = (columns: GridColumns): string => {\n if (typeof columns === 'number') {\n return `repeat(${positiveInteger(columns, 'Grid columns')}, minmax(0, 1fr))`;\n }\n\n if (typeof columns === 'string') {\n return columns;\n }\n\n if (columns.length === 0) {\n throw new Error('Layout.Grid columns ratio must contain at least one value.');\n }\n\n return columns\n .map((ratio) => `${positiveNumber(ratio, 'Grid ratio')}fr`)\n .join(' ');\n};\n\nconst gridSpan = (value: GridPlacement | undefined): string | number | undefined =>\n typeof value === 'number'\n ? `span ${positiveInteger(value, 'Grid.Item span')} / span ${value}`\n : value;\n\nconst gridStart = (value: GridPlacement | undefined, name: string): string | number | undefined =>\n typeof value === 'number' ? positiveInteger(value, name) : value;\n\nconst Container = forwardRef<HTMLDivElement, LayoutContainerProps>(function LayoutContainer(\n {\n maxWidth = 1280,\n padding = '1rem',\n centered = true,\n fluid = false,\n responsive = false,\n className = '',\n style,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-container', className)}\n style={{\n width: '100%',\n maxWidth: fluid ? undefined : cssMaxWidth(maxWidth),\n marginInline: centered && !fluid ? 'auto' : undefined,\n paddingInline: responsive\n ? `clamp(${cssSize(padding)}, 4vw, max(${cssSize(padding)}, 2rem))`\n : cssSize(padding),\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst GridItem = forwardRef<HTMLDivElement, LayoutGridItemProps>(function LayoutGridItem(\n { span, start, offset, rowSpan, rowStart, className = '', style, ...props },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-grid-item', className)}\n style={{\n gridColumn: gridSpan(span),\n gridColumnStart: gridStart(\n start ?? (offset !== undefined ? positiveInteger(offset + 1, 'Grid.Item offset') : undefined),\n 'Grid.Item start',\n ),\n gridRow: gridSpan(rowSpan),\n gridRowStart: gridStart(rowStart, 'Grid.Item rowStart'),\n minWidth: 0,\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst GridRoot = forwardRef<HTMLDivElement, LayoutGridProps>(function LayoutGrid(\n {\n columns = 12,\n gap,\n space,\n rowGap,\n columnGap,\n align,\n justify,\n autoRows,\n dense = false,\n className = '',\n style,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-grid', className)}\n style={{\n display: 'grid',\n gridTemplateColumns: gridTemplateColumns(columns),\n gap: cssGap(gap ?? space),\n rowGap: cssGap(rowGap),\n columnGap: cssGap(columnGap),\n alignItems: cssAlign(align),\n justifyContent: cssJustify(justify),\n gridAutoRows: autoRows,\n gridAutoFlow: dense ? 'row dense' : undefined,\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst Group = forwardRef<HTMLDivElement, LayoutGroupProps>(function LayoutGroup(\n {\n direction = 'row',\n wrap = 'nowrap',\n align = 'center',\n justify = 'start',\n gap,\n fullWidth = false,\n className = '',\n style,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-group', className)}\n style={{\n display: 'flex',\n width: fullWidth ? '100%' : undefined,\n flexDirection: direction,\n flexWrap: typeof wrap === 'boolean' ? (wrap ? 'wrap' : 'nowrap') : wrap,\n alignItems: cssAlign(align),\n justifyContent: cssJustify(justify),\n gap: cssGap(gap),\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst Space = forwardRef<HTMLSpanElement, LayoutSpaceProps>(function LayoutSpace(\n { direction = 'horizontal', size = 16, flex, className = '', style, ...props },\n ref,\n) {\n const dimension = cssSize(size);\n\n return (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn('dishui-layout-space', className)}\n style={{\n display: 'block',\n flex: flex ?? '0 0 auto',\n width: direction === 'horizontal' ? dimension : '100%',\n minWidth: direction === 'horizontal' ? dimension : undefined,\n height: direction === 'vertical' ? dimension : 1,\n minHeight: direction === 'vertical' ? dimension : undefined,\n pointerEvents: 'none',\n ...style,\n }}\n {...props}\n />\n );\n});\n\nconst Flex = forwardRef<HTMLDivElement, LayoutFlexProps>(function LayoutFlex(\n {\n direction = 'row',\n wrap = 'nowrap',\n align,\n justify,\n gap,\n rowGap,\n columnGap,\n inline = false,\n className = '',\n style,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn('dishui-layout-flex', className)}\n style={{\n display: inline ? 'inline-flex' : 'flex',\n flexDirection: direction,\n flexWrap: wrap,\n alignItems: cssAlign(align),\n justifyContent: cssJustify(justify),\n gap: cssGap(gap),\n rowGap: cssGap(rowGap),\n columnGap: cssGap(columnGap),\n ...style,\n }}\n {...props}\n />\n );\n});\n\ninterface LayoutGridCompound extends React.ForwardRefExoticComponent<\n LayoutGridProps & React.RefAttributes<HTMLDivElement>\n> {\n Item: typeof GridItem;\n}\n\nconst Grid = GridRoot as LayoutGridCompound;\nGrid.Item = GridItem;\n\nexport interface LayoutCompound {\n Container: typeof Container;\n Grid: LayoutGridCompound;\n Flex: typeof Flex;\n Group: typeof Group;\n Space: typeof Space;\n}\n\nconst Layout: LayoutCompound = {\n Container,\n Grid,\n Flex,\n Group,\n Space,\n};\n\nexport { Container, Grid, GridItem, Flex, Group, Space };\nexport default Layout;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardSuite.js","names":[],"sources":["../../../src/components/LayoutSuite/DashboardSuite.tsx"],"sourcesContent":["import React from 'react';\nimport Page, { type PageProps, type PageBodyProps, type PageMainProps, type PageAsideProps } from '../Page';\nimport Card, { type CardMetricProps } from '../Card';\nimport NavigationList, { type NavigationListProps } from '../NavigationList';\nimport { Grid, Group, type LayoutGridProps } from '../Layout';\nimport { cn } from '../../utils/cn';\n\nexport type DashboardSuiteProps = PageProps & {\n header?: React.ReactNode;\n overview?: React.ReactNode;\n /** Persistent partial/stale/error feedback; data semantics remain with the caller. */\n notice?: React.ReactNode;\n metrics?: {\n 'aria-label': string;\n items: readonly (CardMetricProps & { key: React.Key })[];\n loading?: boolean;\n grid?: Omit<LayoutGridProps, 'children'>;\n };\n /** Cross-dashboard filters, above navigation and main content. */\n filters?: React.ReactNode;\n navigation?: NavigationListProps;\n /** Explicit children (including null) override the built-in NavigationList. */\n left?: PageAsideProps;\n body?: Omit<PageBodyProps, 'children'>;\n main?: PageMainProps;\n toolbar?: React.ReactNode;\n contentHeader?: React.ReactNode;\n footer?: React.ReactNode;\n};\n\n/** Controlled dashboard composition; no fetching, filtering or table dependency. */\nexport const DashboardSuite = ({\n header, overview, notice, metrics, filters, navigation, left, body, main,\n toolbar, contentHeader, footer, children, fullHeight = false, className, ...page\n}: DashboardSuiteProps) => (\n <Page {...page} fullHeight={fullHeight} className={cn('gap-4', className)}>\n {header}\n {overview}\n {notice}\n {metrics && metrics.items.length > 0 && (\n <section aria-label={metrics['aria-label']} aria-busy={metrics.loading}>\n <Grid columns=\"repeat(auto-fit, minmax(min(100%, 220px), 1fr))\" gap={12} {...metrics.grid}>\n {metrics.items.map(({ key, ...metric }) => (\n <Card.Metric key={key} {...metric} loading={metrics.loading ?? metric.loading} />\n ))}\n </Grid>\n </section>\n )}\n {filters}\n <Page.Body scroll={fullHeight} {...body}>\n {(left || navigation) && (\n <Page.Left width={240} bordered={false} scroll={false} {...left}>\n {left?.children !== undefined ? left.children : navigation && <NavigationList {...navigation} />}\n </Page.Left>\n )}\n <Page.Main scroll={fullHeight} {...main}>\n <Group direction=\"column\" align=\"stretch\" gap={16}>\n {toolbar}\n {contentHeader}\n {children !== undefined ? children : main?.children}\n </Group>\n </Page.Main>\n </Page.Body>\n {footer}\n </Page>\n);\n\n// lite exposes only the lightweight suite, without loading the Sidebar/router graph.\nexport const LayoutSuite = { DashboardSuite };\nexport default DashboardSuite;\n"],"mappings":";;;;;;;;AA+BA,IAAa,KAAkB,EAC3B,WAAQ,aAAU,WAAQ,YAAS,YAAS,eAAY,SAAM,SAAM,SACpE,YAAS,kBAAe,WAAQ,aAAU,gBAAa,IAAO,cAAW,GAAG,QAE5E,kBAAC,GAAD;CAAM,GAAI;CAAkB;CAAY,WAAW,EAAG,SAAS,CAAS;CAAxE,UAAA;EACK;EACA;EACA;EACA,KAAW,EAAQ,MAAM,SAAS,KAC/B,kBAAC,WAAD;GAAS,cAAY,EAAQ;GAAe,aAAW,EAAQ;GAC3D,UAAA,kBAAC,GAAD;IAAM,SAAQ;IAAkD,KAAK;IAAI,GAAI,EAAQ;IAChF,UAAA,EAAQ,MAAM,KAAK,EAAE,QAAK,GAAG,QAC1B,kBAAC,EAAK,QAAN;KAAuB,GAAI;KAAQ,SAAS,EAAQ,WAAW,EAAO;IAAU,GAA9D,CAA8D,CACnF;GACC,CAAA;EACD,CAAA;EAEZ;EACD,kBAAC,EAAK,MAAN;GAAW,QAAQ;GAAY,GAAI;GAAnC,UAAA,EACM,KAAQ,MACN,kBAAC,EAAK,MAAN;IAAW,OAAO;IAAK,UAAU;IAAO,QAAQ;IAAO,GAAI;IACtD,UAAA,GAAM,aAAa,KAAA,IAA4B,KAAc,kBAAC,GAAD,EAAgB,GAAI,EAAa,CAAA,IAA/D,EAAK;GAC9B,CAAA,GAEf,kBAAC,EAAK,MAAN;IAAW,QAAQ;IAAY,GAAI;IAC/B,UAAA,kBAAC,GAAD;KAAO,WAAU;KAAS,OAAM;KAAU,KAAK;KAA/C,UAAA;MACK;MACA;MACA,MAAa,KAAA,IAAuB,GAAM,WAAjB;KACvB;;GACA,CAAA,CACJ;;EACV;CACC;IAIG,IAAc,EAAE,kBAAe"}
1
+ {"version":3,"file":"DashboardSuite.js","names":["Page","Card","NavigationList","CardWithCompounds","PageWithCompounds","DashboardSuite","page","cn","className","header","overview","notice","metrics","Grid","metric","key","filters","fullHeight","body","left","navigation","main","Group","toolbar","contentHeader","children","footer","LayoutSuite"],"sources":["../../../src/components/LayoutSuite/DashboardSuite.tsx"],"sourcesContent":["import React from 'react';\nimport Page, { type PageProps, type PageBodyProps, type PageMainProps, type PageAsideProps } from '../Page';\nimport Card, { type CardMetricProps } from '../Card';\nimport NavigationList, { type NavigationListProps } from '../NavigationList';\nimport { Grid, Group, type LayoutGridProps } from '../Layout';\nimport { cn } from '../../utils/cn';\n\nexport type DashboardSuiteProps = PageProps & {\n header?: React.ReactNode;\n overview?: React.ReactNode;\n /** Persistent partial/stale/error feedback; data semantics remain with the caller. */\n notice?: React.ReactNode;\n metrics?: {\n 'aria-label': string;\n items: readonly (CardMetricProps & { key: React.Key })[];\n loading?: boolean;\n grid?: Omit<LayoutGridProps, 'children'>;\n };\n /** Cross-dashboard filters, above navigation and main content. */\n filters?: React.ReactNode;\n navigation?: NavigationListProps;\n /** Explicit children (including null) override the built-in NavigationList. */\n left?: PageAsideProps;\n body?: Omit<PageBodyProps, 'children'>;\n main?: PageMainProps;\n toolbar?: React.ReactNode;\n contentHeader?: React.ReactNode;\n footer?: React.ReactNode;\n};\n\n/** Controlled dashboard composition; no fetching, filtering or table dependency. */\nexport const DashboardSuite = ({\n header, overview, notice, metrics, filters, navigation, left, body, main,\n toolbar, contentHeader, footer, children, fullHeight = false, className, ...page\n}: DashboardSuiteProps) => (\n <Page {...page} fullHeight={fullHeight} className={cn('gap-4', className)}>\n {header}\n {overview}\n {notice}\n {metrics && metrics.items.length > 0 && (\n <section aria-label={metrics['aria-label']} aria-busy={metrics.loading}>\n <Grid columns=\"repeat(auto-fit, minmax(min(100%, 220px), 1fr))\" gap={12} {...metrics.grid}>\n {metrics.items.map(({ key, ...metric }) => (\n <Card.Metric key={key} {...metric} loading={metrics.loading ?? metric.loading} />\n ))}\n </Grid>\n </section>\n )}\n {filters}\n <Page.Body scroll={fullHeight} {...body}>\n {(left || navigation) && (\n <Page.Left width={240} bordered={false} scroll={false} {...left}>\n {left?.children !== undefined ? left.children : navigation && <NavigationList {...navigation} />}\n </Page.Left>\n )}\n <Page.Main scroll={fullHeight} {...main}>\n <Group direction=\"column\" align=\"stretch\" gap={16}>\n {toolbar}\n {contentHeader}\n {children !== undefined ? children : main?.children}\n </Group>\n </Page.Main>\n </Page.Body>\n {footer}\n </Page>\n);\n\n// lite exposes only the lightweight suite, without loading the Sidebar/router graph.\nexport const LayoutSuite = { DashboardSuite };\nexport default DashboardSuite;\n"],"mappings":";;;;;;;;AA+BA,IAAaK,KAAkB,EAC3B,WAAQ,aAAU,WAAQ,YAAS,YAAS,eAAY,SAAM,SAAM,SACpE,YAAS,kBAAe,WAAQ,aAAU,gBAAa,IAAO,cAAW,GAAGC,QAE5E,kBAACN,GAAD;CAAM,GAAIM;CAAkB;CAAY,WAAWC,EAAG,SAASC,CAAS;CAAxE,UAAA;EACKC;EACAC;EACAC;EACAC,KAAWA,EAAQ,MAAM,SAAS,KAC/B,kBAAC,WAAD;GAAS,cAAYA,EAAQ;GAAe,aAAWA,EAAQ;GAC3D,UAAA,kBAACC,GAAD;IAAM,SAAQ;IAAkD,KAAK;IAAI,GAAID,EAAQ;IAChF,UAAAA,EAAQ,MAAM,KAAK,EAAE,QAAK,GAAGE,QAC1B,kBAACb,EAAK,QAAN;KAAuB,GAAIa;KAAQ,SAASF,EAAQ,WAAWE,EAAO;IAAU,GAA9DC,CAA8D,CACnF;GACC,CAAA;EACD,CAAA;EAEZC;EACD,kBAAChB,EAAK,MAAN;GAAW,QAAQiB;GAAY,GAAIC;GAAnC,UAAA,EACMC,KAAQC,MACN,kBAACpB,EAAK,MAAN;IAAW,OAAO;IAAK,UAAU;IAAO,QAAQ;IAAO,GAAImB;IACtD,UAAAA,GAAM,aAAa,KAAA,IAA4BC,KAAc,kBAAClB,GAAD,EAAgB,GAAIkB,EAAa,CAAA,IAA/DD,EAAK;GAC9B,CAAA,GAEf,kBAACnB,EAAK,MAAN;IAAW,QAAQiB;IAAY,GAAII;IAC/B,UAAA,kBAACC,GAAD;KAAO,WAAU;KAAS,OAAM;KAAU,KAAK;KAA/C,UAAA;MACKC;MACAC;MACAC,MAAa,KAAA,IAAuBJ,GAAM,WAAjBI;KACvB;;GACA,CAAA,CACJ;;EACVC;CACC;IAIGC,IAAc,EAAE,kBAAe"}