@runlume/admin-ui 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/README.en.md +7 -5
  2. package/README.md +5 -4
  3. package/dist-package/_virtual/_rolldown/runtime.cjs +1 -0
  4. package/dist-package/admin-ui.cjs +1 -0
  5. package/dist-package/admin-ui.d.ts +41 -1
  6. package/dist-package/admin-ui.d.ts.map +1 -1
  7. package/dist-package/admin-ui.js +79 -0
  8. package/dist-package/components/calendar.cjs +1 -0
  9. package/dist-package/components/calendar.d.ts +13 -0
  10. package/dist-package/components/calendar.d.ts.map +1 -0
  11. package/dist-package/components/calendar.js +91 -0
  12. package/dist-package/components/cascader.cjs +1 -0
  13. package/dist-package/components/cascader.d.ts +19 -0
  14. package/dist-package/components/cascader.d.ts.map +1 -0
  15. package/dist-package/components/cascader.js +85 -0
  16. package/dist-package/components/charts.cjs +1 -0
  17. package/dist-package/components/charts.d.ts +80 -0
  18. package/dist-package/components/charts.d.ts.map +1 -0
  19. package/dist-package/components/charts.js +374 -0
  20. package/dist-package/components/code-block.cjs +1 -0
  21. package/dist-package/components/code-block.d.ts +7 -0
  22. package/dist-package/components/code-block.d.ts.map +1 -0
  23. package/dist-package/components/code-block.js +47 -0
  24. package/dist-package/components/column-chart.cjs +1 -0
  25. package/dist-package/components/column-chart.d.ts +18 -0
  26. package/dist-package/components/column-chart.d.ts.map +1 -0
  27. package/dist-package/components/column-chart.js +89 -0
  28. package/dist-package/components/combobox.cjs +1 -0
  29. package/dist-package/components/combobox.d.ts +24 -0
  30. package/dist-package/components/combobox.d.ts.map +1 -0
  31. package/dist-package/components/combobox.js +111 -0
  32. package/dist-package/components/confirm-dialog.cjs +1 -0
  33. package/dist-package/components/confirm-dialog.d.ts +17 -0
  34. package/dist-package/components/confirm-dialog.d.ts.map +1 -0
  35. package/dist-package/components/confirm-dialog.js +44 -0
  36. package/dist-package/components/count-to.cjs +1 -0
  37. package/dist-package/components/count-to.d.ts +13 -0
  38. package/dist-package/components/count-to.d.ts.map +1 -0
  39. package/dist-package/components/count-to.js +36 -0
  40. package/dist-package/components/cursor-pagination.cjs +1 -0
  41. package/dist-package/components/cursor-pagination.d.ts +11 -0
  42. package/dist-package/components/cursor-pagination.d.ts.map +1 -0
  43. package/dist-package/components/cursor-pagination.js +39 -0
  44. package/dist-package/components/data-table.cjs +1 -0
  45. package/dist-package/components/data-table.d.ts +69 -0
  46. package/dist-package/components/data-table.d.ts.map +1 -0
  47. package/dist-package/components/data-table.js +377 -0
  48. package/dist-package/components/descriptions.cjs +1 -0
  49. package/dist-package/components/descriptions.d.ts +16 -0
  50. package/dist-package/components/descriptions.d.ts.map +1 -0
  51. package/dist-package/components/descriptions.js +28 -0
  52. package/dist-package/components/editable-table.cjs +1 -0
  53. package/dist-package/components/editable-table.d.ts +27 -0
  54. package/dist-package/components/editable-table.d.ts.map +1 -0
  55. package/dist-package/components/editable-table.js +212 -0
  56. package/dist-package/components/filter-presets.cjs +1 -0
  57. package/dist-package/components/filter-presets.d.ts +11 -0
  58. package/dist-package/components/filter-presets.d.ts.map +1 -0
  59. package/dist-package/components/filter-presets.js +17 -0
  60. package/dist-package/components/fixed-bar.cjs +1 -0
  61. package/dist-package/components/fixed-bar.d.ts +11 -0
  62. package/dist-package/components/fixed-bar.d.ts.map +1 -0
  63. package/dist-package/components/fixed-bar.js +18 -0
  64. package/dist-package/components/image-preview.cjs +1 -0
  65. package/dist-package/components/image-preview.d.ts +14 -0
  66. package/dist-package/components/image-preview.d.ts.map +1 -0
  67. package/dist-package/components/image-preview.js +166 -0
  68. package/dist-package/components/layout-container.cjs +1 -0
  69. package/dist-package/components/layout-container.d.ts +17 -0
  70. package/dist-package/components/layout-container.d.ts.map +1 -0
  71. package/dist-package/components/layout-container.js +85 -0
  72. package/dist-package/components/mention.cjs +1 -0
  73. package/dist-package/components/mention.d.ts +20 -0
  74. package/dist-package/components/mention.d.ts.map +1 -0
  75. package/dist-package/components/mention.js +126 -0
  76. package/dist-package/components/multi-select.cjs +1 -0
  77. package/dist-package/components/multi-select.d.ts +17 -0
  78. package/dist-package/components/multi-select.d.ts.map +1 -0
  79. package/dist-package/components/multi-select.js +126 -0
  80. package/dist-package/components/multi-step-loader.cjs +1 -0
  81. package/dist-package/components/multi-step-loader.d.ts +18 -0
  82. package/dist-package/components/multi-step-loader.d.ts.map +1 -0
  83. package/dist-package/components/multi-step-loader.js +38 -0
  84. package/dist-package/components/page-button.cjs +1 -0
  85. package/dist-package/components/page-button.d.ts +6 -0
  86. package/dist-package/components/page-button.d.ts.map +1 -0
  87. package/dist-package/components/page-button.js +24 -0
  88. package/dist-package/components/page-pager.cjs +1 -0
  89. package/dist-package/components/page-pager.d.ts +11 -0
  90. package/dist-package/components/page-pager.d.ts.map +1 -0
  91. package/dist-package/components/page-pager.js +51 -0
  92. package/dist-package/components/page.cjs +1 -0
  93. package/dist-package/components/page.d.ts +34 -0
  94. package/dist-package/components/page.d.ts.map +1 -0
  95. package/dist-package/components/page.js +208 -0
  96. package/dist-package/components/pagination-bar.cjs +1 -0
  97. package/dist-package/components/pagination-bar.d.ts +8 -0
  98. package/dist-package/components/pagination-bar.d.ts.map +1 -0
  99. package/dist-package/components/pagination-bar.js +23 -0
  100. package/dist-package/components/password-strength.cjs +1 -0
  101. package/dist-package/components/password-strength.d.ts +11 -0
  102. package/dist-package/components/password-strength.d.ts.map +1 -0
  103. package/dist-package/components/password-strength.js +70 -0
  104. package/dist-package/components/rate.cjs +1 -0
  105. package/dist-package/components/rate.d.ts +13 -0
  106. package/dist-package/components/rate.d.ts.map +1 -0
  107. package/dist-package/components/rate.js +56 -0
  108. package/dist-package/components/resizable-panel.cjs +1 -0
  109. package/dist-package/components/resizable-panel.d.ts +15 -0
  110. package/dist-package/components/resizable-panel.d.ts.map +1 -0
  111. package/dist-package/components/resizable-panel.js +56 -0
  112. package/dist-package/components/search-filters.cjs +1 -0
  113. package/dist-package/components/search-filters.d.ts +31 -0
  114. package/dist-package/components/search-filters.d.ts.map +1 -0
  115. package/dist-package/components/search-filters.js +110 -0
  116. package/dist-package/components/sortable-list.cjs +1 -0
  117. package/dist-package/components/sortable-list.d.ts +14 -0
  118. package/dist-package/components/sortable-list.d.ts.map +1 -0
  119. package/dist-package/components/sortable-list.js +48 -0
  120. package/dist-package/components/sparkline.cjs +1 -0
  121. package/dist-package/components/sparkline.d.ts +11 -0
  122. package/dist-package/components/sparkline.d.ts.map +1 -0
  123. package/dist-package/components/sparkline.js +50 -0
  124. package/dist-package/components/status-badge.cjs +1 -0
  125. package/dist-package/components/status-badge.d.ts +4 -0
  126. package/dist-package/components/status-badge.d.ts.map +1 -0
  127. package/dist-package/components/status-badge.js +28 -0
  128. package/dist-package/components/steps.cjs +1 -0
  129. package/dist-package/components/steps.d.ts +15 -0
  130. package/dist-package/components/steps.d.ts.map +1 -0
  131. package/dist-package/components/steps.js +41 -0
  132. package/dist-package/components/storage-box.cjs +1 -0
  133. package/dist-package/components/storage-box.d.ts +19 -0
  134. package/dist-package/components/storage-box.d.ts.map +1 -0
  135. package/dist-package/components/storage-box.js +153 -0
  136. package/dist-package/components/table-cell-overflow.cjs +1 -0
  137. package/dist-package/components/table-cell-overflow.d.ts +5 -0
  138. package/dist-package/components/table-cell-overflow.d.ts.map +1 -0
  139. package/dist-package/components/table-cell-overflow.js +31 -0
  140. package/dist-package/components/table-toolbar.cjs +1 -0
  141. package/dist-package/components/table-toolbar.d.ts +5 -0
  142. package/dist-package/components/table-toolbar.d.ts.map +1 -0
  143. package/dist-package/components/table-toolbar.js +11 -0
  144. package/dist-package/components/timeline.cjs +1 -0
  145. package/dist-package/components/timeline.d.ts +14 -0
  146. package/dist-package/components/timeline.d.ts.map +1 -0
  147. package/dist-package/components/timeline.js +40 -0
  148. package/dist-package/components/transfer.cjs +1 -0
  149. package/dist-package/components/transfer.d.ts +18 -0
  150. package/dist-package/components/transfer.d.ts.map +1 -0
  151. package/dist-package/components/transfer.js +98 -0
  152. package/dist-package/components/tree-table.cjs +1 -0
  153. package/dist-package/components/tree-table.d.ts +23 -0
  154. package/dist-package/components/tree-table.d.ts.map +1 -0
  155. package/dist-package/components/tree-table.js +53 -0
  156. package/dist-package/components/tree.cjs +1 -0
  157. package/dist-package/components/tree.d.ts +36 -0
  158. package/dist-package/components/tree.d.ts.map +1 -0
  159. package/dist-package/components/tree.js +204 -0
  160. package/dist-package/components/trend.cjs +1 -0
  161. package/dist-package/components/trend.d.ts +19 -0
  162. package/dist-package/components/trend.d.ts.map +1 -0
  163. package/dist-package/components/trend.js +18 -0
  164. package/dist-package/components/ui/alert-dialog.cjs +1 -0
  165. package/dist-package/components/ui/alert-dialog.js +57 -0
  166. package/dist-package/components/ui/alert.cjs +1 -0
  167. package/dist-package/components/ui/alert.js +63 -0
  168. package/dist-package/components/ui/avatar.cjs +1 -0
  169. package/dist-package/components/ui/avatar.js +27 -0
  170. package/dist-package/components/ui/badge.cjs +1 -0
  171. package/dist-package/components/ui/badge.js +40 -0
  172. package/dist-package/components/ui/breadcrumb.cjs +1 -0
  173. package/dist-package/components/ui/breadcrumb.js +70 -0
  174. package/dist-package/components/ui/button.cjs +1 -0
  175. package/dist-package/components/ui/button.js +58 -0
  176. package/dist-package/components/ui/card.cjs +1 -0
  177. package/dist-package/components/ui/card.js +55 -0
  178. package/dist-package/components/ui/checkbox.cjs +1 -0
  179. package/dist-package/components/ui/checkbox.js +19 -0
  180. package/dist-package/components/ui/collapsible.cjs +1 -0
  181. package/dist-package/components/ui/collapsible.js +32 -0
  182. package/dist-package/components/ui/context-menu.cjs +1 -0
  183. package/dist-package/components/ui/context-menu.js +46 -0
  184. package/dist-package/components/ui/date-input.cjs +1 -0
  185. package/dist-package/components/ui/date-input.js +183 -0
  186. package/dist-package/components/ui/date-range-input.cjs +1 -0
  187. package/dist-package/components/ui/date-range-input.js +209 -0
  188. package/dist-package/components/ui/date-time-input.cjs +1 -0
  189. package/dist-package/components/ui/date-time-input.js +23 -0
  190. package/dist-package/components/ui/dialog.cjs +1 -0
  191. package/dist-package/components/ui/dialog.js +189 -0
  192. package/dist-package/components/ui/dropdown-menu.cjs +1 -0
  193. package/dist-package/components/ui/dropdown-menu.js +124 -0
  194. package/dist-package/components/ui/file-upload.cjs +1 -0
  195. package/dist-package/components/ui/file-upload.js +160 -0
  196. package/dist-package/components/ui/hover-card.cjs +1 -0
  197. package/dist-package/components/ui/hover-card.js +28 -0
  198. package/dist-package/components/ui/input-otp.cjs +1 -0
  199. package/dist-package/components/ui/input-otp.js +33 -0
  200. package/dist-package/components/ui/input.cjs +1 -0
  201. package/dist-package/components/ui/input.js +65 -0
  202. package/dist-package/components/ui/kbd.cjs +1 -0
  203. package/dist-package/components/ui/kbd.js +20 -0
  204. package/dist-package/components/ui/label.cjs +1 -0
  205. package/dist-package/components/ui/label.js +14 -0
  206. package/dist-package/components/ui/native-select.cjs +1 -0
  207. package/dist-package/components/ui/native-select.js +125 -0
  208. package/dist-package/components/ui/number-field.cjs +1 -0
  209. package/dist-package/components/ui/number-field.js +50 -0
  210. package/dist-package/components/ui/progress.cjs +1 -0
  211. package/dist-package/components/ui/progress.js +28 -0
  212. package/dist-package/components/ui/radio-group.cjs +1 -0
  213. package/dist-package/components/ui/radio-group.js +27 -0
  214. package/dist-package/components/ui/scroll-area.cjs +1 -0
  215. package/dist-package/components/ui/scroll-area.js +25 -0
  216. package/dist-package/components/ui/select.cjs +1 -0
  217. package/dist-package/components/ui/select.js +23 -0
  218. package/dist-package/components/ui/separator.cjs +1 -0
  219. package/dist-package/components/ui/separator.js +17 -0
  220. package/dist-package/components/ui/sheet.cjs +1 -0
  221. package/dist-package/components/ui/sheet.js +86 -0
  222. package/dist-package/components/ui/sidebar.cjs +1 -0
  223. package/dist-package/components/ui/sidebar.js +350 -0
  224. package/dist-package/components/ui/skeleton.cjs +1 -0
  225. package/dist-package/components/ui/skeleton.js +12 -0
  226. package/dist-package/components/ui/slider.cjs +1 -0
  227. package/dist-package/components/ui/slider.js +36 -0
  228. package/dist-package/components/ui/switch.cjs +1 -0
  229. package/dist-package/components/ui/switch.js +14 -0
  230. package/dist-package/components/ui/table.cjs +1 -0
  231. package/dist-package/components/ui/table.js +66 -0
  232. package/dist-package/components/ui/tabs.cjs +1 -0
  233. package/dist-package/components/ui/tabs.js +47 -0
  234. package/dist-package/components/ui/tag-variants.cjs +1 -0
  235. package/dist-package/components/ui/tag-variants.js +15 -0
  236. package/dist-package/components/ui/tag.cjs +1 -0
  237. package/dist-package/components/ui/tag.js +31 -0
  238. package/dist-package/components/ui/textarea.cjs +1 -0
  239. package/dist-package/components/ui/textarea.js +13 -0
  240. package/dist-package/components/ui/time-input.cjs +1 -0
  241. package/dist-package/components/ui/time-input.js +89 -0
  242. package/dist-package/components/ui/tooltip.cjs +1 -0
  243. package/dist-package/components/ui/tooltip.js +35 -0
  244. package/dist-package/hooks/use-mobile.cjs +1 -0
  245. package/dist-package/hooks/use-mobile.js +11 -0
  246. package/dist-package/lib/dialog-focus.cjs +1 -0
  247. package/dist-package/lib/dialog-focus.js +10 -0
  248. package/dist-package/lib/metrics.cjs +1 -0
  249. package/dist-package/lib/metrics.d.ts +18 -0
  250. package/dist-package/lib/metrics.d.ts.map +1 -0
  251. package/dist-package/lib/metrics.js +22 -0
  252. package/dist-package/lib/pager.cjs +1 -0
  253. package/dist-package/lib/pager.d.ts +8 -0
  254. package/dist-package/lib/pager.d.ts.map +1 -0
  255. package/dist-package/lib/pager.js +18 -0
  256. package/dist-package/lib/password.cjs +1 -0
  257. package/dist-package/lib/password.d.ts +14 -0
  258. package/dist-package/lib/password.d.ts.map +1 -0
  259. package/dist-package/lib/password.js +34 -0
  260. package/dist-package/lib/presets.cjs +1 -0
  261. package/dist-package/lib/presets.d.ts +25 -0
  262. package/dist-package/lib/presets.d.ts.map +1 -0
  263. package/dist-package/lib/presets.js +48 -0
  264. package/dist-package/lib/range.cjs +1 -0
  265. package/dist-package/lib/range.js +57 -0
  266. package/dist-package/lib/storage-key.cjs +1 -0
  267. package/dist-package/lib/storage-key.d.ts +2 -0
  268. package/dist-package/lib/storage-key.d.ts.map +1 -0
  269. package/dist-package/lib/storage-key.js +6 -0
  270. package/dist-package/lib/table-prefs.cjs +1 -0
  271. package/dist-package/lib/table-prefs.d.ts +17 -0
  272. package/dist-package/lib/table-prefs.d.ts.map +1 -0
  273. package/dist-package/lib/table-prefs.js +64 -0
  274. package/dist-package/lib/tree.cjs +1 -0
  275. package/dist-package/lib/tree.d.ts +37 -0
  276. package/dist-package/lib/tree.d.ts.map +1 -0
  277. package/dist-package/lib/tree.js +57 -0
  278. package/dist-package/lib/use-ui-translation.cjs +1 -0
  279. package/dist-package/lib/use-ui-translation.d.ts +15 -0
  280. package/dist-package/lib/use-ui-translation.d.ts.map +1 -0
  281. package/dist-package/lib/use-ui-translation.js +65 -0
  282. package/dist-package/lib/utils.cjs +1 -0
  283. package/dist-package/lib/utils.js +8 -0
  284. package/dist-package/styles.css +1 -1
  285. package/package.json +25 -15
  286. package/dist-package/index.js +0 -12212
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from 'react';
2
+ export type TimelineItem = {
3
+ key: string;
4
+ title: ReactNode;
5
+ description?: ReactNode;
6
+ time?: ReactNode;
7
+ tone?: 'default' | 'success' | 'warning' | 'danger';
8
+ };
9
+ /** 时间线:用于操作记录与审批轨迹,按时间倒序展示。 */
10
+ export declare function Timeline({ items, className }: {
11
+ items: TimelineItem[];
12
+ className?: string;
13
+ }): import("react").JSX.Element;
14
+ //# sourceMappingURL=timeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../../src/components/timeline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;CACpD,CAAA;AASD,+BAA+B;AAC/B,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;IAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAwB3F"}
@@ -0,0 +1,40 @@
1
+ import { cn as e } from "../lib/utils.js";
2
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
+ //#region src/components/timeline.tsx
4
+ var r = {
5
+ default: "bg-primary",
6
+ success: "bg-success",
7
+ warning: "bg-warning",
8
+ danger: "bg-danger"
9
+ };
10
+ function i({ items: i, className: a }) {
11
+ return /* @__PURE__ */ t("ol", {
12
+ "data-slot": "timeline",
13
+ className: e("relative space-y-5", a),
14
+ children: i.map((a, o) => /* @__PURE__ */ n("li", {
15
+ className: "relative flex gap-3 pb-1 pl-1",
16
+ children: [/* @__PURE__ */ n("span", {
17
+ "aria-hidden": "true",
18
+ className: "relative flex w-3 shrink-0 justify-center",
19
+ children: [o < i.length - 1 && /* @__PURE__ */ t("span", { className: "absolute top-3 h-[calc(100%+8px)] w-px bg-border" }), /* @__PURE__ */ t("span", { className: e("mt-1.5 size-2 rounded-full", r[a.tone ?? "default"]) })]
20
+ }), /* @__PURE__ */ n("div", {
21
+ className: "min-w-0 flex-1",
22
+ children: [/* @__PURE__ */ n("div", {
23
+ className: "flex flex-wrap items-baseline justify-between gap-2",
24
+ children: [/* @__PURE__ */ t("p", {
25
+ className: "text-sm font-medium",
26
+ children: a.title
27
+ }), a.time && /* @__PURE__ */ t("span", {
28
+ className: "text-xs text-muted-foreground",
29
+ children: a.time
30
+ })]
31
+ }), a.description && /* @__PURE__ */ t("p", {
32
+ className: "mt-1 text-xs leading-5 text-muted-foreground",
33
+ children: a.description
34
+ })]
35
+ })]
36
+ }, a.key))
37
+ });
38
+ }
39
+ //#endregion
40
+ export { i as Timeline };
@@ -0,0 +1 @@
1
+ const e=require("../lib/utils.cjs"),t=require("./ui/button.cjs"),n=require("./ui/checkbox.cjs"),r=require("./ui/input.cjs");let i=require("react"),a=require("lucide-react"),o=require("react/jsx-runtime");function s({items:s,value:c,onValueChange:l,sourceTitle:u=`可选项`,targetTitle:d=`已选项`,searchPlaceholder:f=`搜索`,emptyText:p=`暂无数据`,className:m}){let[h,g]=(0,i.useState)(``),[_,v]=(0,i.useState)([]),[y,b]=(0,i.useState)([]),x=new Set(c),S=(0,i.useMemo)(()=>s.filter(e=>e.label.toLowerCase().includes(h.trim().toLowerCase())),[s,h]).filter(e=>!x.has(e.value)),C=s.filter(e=>x.has(e.value));function w(e,t,n){n(e.includes(t)?e.filter(e=>e!==t):[...e,t])}function T(){l([...c,..._.filter(e=>!x.has(e))]),v([])}function E(){l(c.filter(e=>!y.includes(e))),b([])}let D=(t,r,i,a)=>(0,o.jsxs)(`section`,{className:`min-w-0 flex-1 overflow-hidden rounded-lg border bg-card`,children:[(0,o.jsxs)(`header`,{className:`flex items-center justify-between border-b px-3 py-2 text-sm font-medium`,children:[(0,o.jsx)(`span`,{children:t}),(0,o.jsx)(`span`,{className:`text-xs font-normal text-muted-foreground`,children:r.length})]}),(0,o.jsx)(`div`,{className:`max-h-64 min-h-52 overflow-auto p-2`,role:`listbox`,"aria-label":t,children:r.length===0?(0,o.jsx)(`p`,{className:`grid min-h-36 place-items-center text-sm text-muted-foreground`,children:p}):r.map(t=>(0,o.jsxs)(`label`,{className:e.cn(`flex min-h-11 items-start gap-2 rounded-md px-2 py-2 text-sm hover:bg-muted`,t.disabled&&`cursor-not-allowed opacity-50`),children:[(0,o.jsx)(n.Checkbox,{disabled:t.disabled,checked:i.includes(t.value),onCheckedChange:()=>w(i,t.value,a),"aria-label":t.label}),(0,o.jsxs)(`span`,{className:`min-w-0`,children:[(0,o.jsx)(`span`,{className:`block truncate`,children:t.label}),t.description&&(0,o.jsx)(`span`,{className:`block truncate text-xs text-muted-foreground`,children:t.description})]})]},t.value))})]});return(0,o.jsxs)(`div`,{className:e.cn(`space-y-3`,m),children:[(0,o.jsx)(r.Input,{value:h,onChange:e=>g(e.target.value),placeholder:f,"aria-label":f,start:(0,o.jsx)(a.Search,{"aria-hidden":`true`,className:`size-4`}),clearable:!0,onClear:()=>g(``)}),(0,o.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[D(u,S,_,v),(0,o.jsxs)(`div`,{className:`flex shrink-0 flex-col gap-2`,children:[(0,o.jsx)(t.Button,{type:`button`,size:`icon`,variant:`outline`,disabled:_.length===0,onClick:T,"aria-label":`移动到${d}`,children:(0,o.jsx)(a.ArrowRight,{"aria-hidden":`true`})}),(0,o.jsx)(t.Button,{type:`button`,size:`icon`,variant:`outline`,disabled:y.length===0,onClick:E,"aria-label":`移动到${u}`,children:(0,o.jsx)(a.ArrowLeft,{"aria-hidden":`true`})})]}),D(d,C,y,b)]})]})}exports.Transfer=s;
@@ -0,0 +1,18 @@
1
+ export type TransferItem = {
2
+ value: string;
3
+ label: string;
4
+ description?: string;
5
+ disabled?: boolean;
6
+ };
7
+ export type TransferProps = {
8
+ items: TransferItem[];
9
+ value: string[];
10
+ onValueChange: (value: string[]) => void;
11
+ sourceTitle?: string;
12
+ targetTitle?: string;
13
+ searchPlaceholder?: string;
14
+ emptyText?: string;
15
+ className?: string;
16
+ };
17
+ export declare function Transfer({ items, value, onValueChange, sourceTitle, targetTitle, searchPlaceholder, emptyText, className, }: TransferProps): import("react").JSX.Element;
18
+ //# sourceMappingURL=transfer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../../src/components/transfer.tsx"],"names":[],"mappings":"AAOA,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,KAAK,EACL,aAAa,EACb,WAAmB,EACnB,WAAmB,EACnB,iBAAwB,EACxB,SAAkB,EAClB,SAAS,GACV,EAAE,aAAa,+BA+Gf"}
@@ -0,0 +1,98 @@
1
+ import { cn as e } from "../lib/utils.js";
2
+ import { Button as t } from "./ui/button.js";
3
+ import { Checkbox as n } from "./ui/checkbox.js";
4
+ import { Input as r } from "./ui/input.js";
5
+ import { useMemo as i, useState as a } from "react";
6
+ import { ArrowLeft as o, ArrowRight as s, Search as c } from "lucide-react";
7
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
8
+ //#region src/components/transfer.tsx
9
+ function d({ items: d, value: f, onValueChange: p, sourceTitle: m = "可选项", targetTitle: h = "已选项", searchPlaceholder: g = "搜索", emptyText: _ = "暂无数据", className: v }) {
10
+ let [y, b] = a(""), [x, S] = a([]), [C, w] = a([]), T = new Set(f), E = i(() => d.filter((e) => e.label.toLowerCase().includes(y.trim().toLowerCase())), [d, y]).filter((e) => !T.has(e.value)), D = d.filter((e) => T.has(e.value));
11
+ function O(e, t, n) {
12
+ n(e.includes(t) ? e.filter((e) => e !== t) : [...e, t]);
13
+ }
14
+ function k() {
15
+ p([...f, ...x.filter((e) => !T.has(e))]), S([]);
16
+ }
17
+ function A() {
18
+ p(f.filter((e) => !C.includes(e))), w([]);
19
+ }
20
+ let j = (t, r, i, a) => /* @__PURE__ */ u("section", {
21
+ className: "min-w-0 flex-1 overflow-hidden rounded-lg border bg-card",
22
+ children: [/* @__PURE__ */ u("header", {
23
+ className: "flex items-center justify-between border-b px-3 py-2 text-sm font-medium",
24
+ children: [/* @__PURE__ */ l("span", { children: t }), /* @__PURE__ */ l("span", {
25
+ className: "text-xs font-normal text-muted-foreground",
26
+ children: r.length
27
+ })]
28
+ }), /* @__PURE__ */ l("div", {
29
+ className: "max-h-64 min-h-52 overflow-auto p-2",
30
+ role: "listbox",
31
+ "aria-label": t,
32
+ children: r.length === 0 ? /* @__PURE__ */ l("p", {
33
+ className: "grid min-h-36 place-items-center text-sm text-muted-foreground",
34
+ children: _
35
+ }) : r.map((t) => /* @__PURE__ */ u("label", {
36
+ className: e("flex min-h-11 items-start gap-2 rounded-md px-2 py-2 text-sm hover:bg-muted", t.disabled && "cursor-not-allowed opacity-50"),
37
+ children: [/* @__PURE__ */ l(n, {
38
+ disabled: t.disabled,
39
+ checked: i.includes(t.value),
40
+ onCheckedChange: () => O(i, t.value, a),
41
+ "aria-label": t.label
42
+ }), /* @__PURE__ */ u("span", {
43
+ className: "min-w-0",
44
+ children: [/* @__PURE__ */ l("span", {
45
+ className: "block truncate",
46
+ children: t.label
47
+ }), t.description && /* @__PURE__ */ l("span", {
48
+ className: "block truncate text-xs text-muted-foreground",
49
+ children: t.description
50
+ })]
51
+ })]
52
+ }, t.value))
53
+ })]
54
+ });
55
+ return /* @__PURE__ */ u("div", {
56
+ className: e("space-y-3", v),
57
+ children: [/* @__PURE__ */ l(r, {
58
+ value: y,
59
+ onChange: (e) => b(e.target.value),
60
+ placeholder: g,
61
+ "aria-label": g,
62
+ start: /* @__PURE__ */ l(c, {
63
+ "aria-hidden": "true",
64
+ className: "size-4"
65
+ }),
66
+ clearable: !0,
67
+ onClear: () => b("")
68
+ }), /* @__PURE__ */ u("div", {
69
+ className: "flex min-w-0 items-center gap-2",
70
+ children: [
71
+ j(m, E, x, S),
72
+ /* @__PURE__ */ u("div", {
73
+ className: "flex shrink-0 flex-col gap-2",
74
+ children: [/* @__PURE__ */ l(t, {
75
+ type: "button",
76
+ size: "icon",
77
+ variant: "outline",
78
+ disabled: x.length === 0,
79
+ onClick: k,
80
+ "aria-label": `移动到${h}`,
81
+ children: /* @__PURE__ */ l(s, { "aria-hidden": "true" })
82
+ }), /* @__PURE__ */ l(t, {
83
+ type: "button",
84
+ size: "icon",
85
+ variant: "outline",
86
+ disabled: C.length === 0,
87
+ onClick: A,
88
+ "aria-label": `移动到${m}`,
89
+ children: /* @__PURE__ */ l(o, { "aria-hidden": "true" })
90
+ })]
91
+ }),
92
+ j(h, D, C, w)
93
+ ]
94
+ })]
95
+ });
96
+ }
97
+ //#endregion
98
+ export { d as Transfer };
@@ -0,0 +1 @@
1
+ const e=require("../lib/utils.cjs"),t=require("./ui/button.cjs"),n=require("../lib/use-ui-translation.cjs"),r=require("./data-table.cjs"),i=require("../lib/tree.cjs");let a=require("react"),o=require("lucide-react"),s=require("react/jsx-runtime");function c({nodes:c,columns:l,caption:u,rowLabel:d,defaultExpanded:f=[]}){let{t:p}=n.useUiTranslation(),[m,h]=(0,a.useState)(()=>new Set(f)),g=i.flattenTree(c,m);function _(e){h(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})}let v=l.map((n,r)=>({id:n.id,header:n.header,size:n.width,cell:({row:i})=>r>0?n.cell(i.original):(0,s.jsxs)(`div`,{className:`flex items-center gap-1`,style:{paddingInlineStart:i.original.depth*20},children:[i.original.hasChildren?(0,s.jsx)(t.Button,{type:`button`,variant:`ghost`,size:`icon`,className:`size-7 shrink-0`,"aria-label":p(i.original.expanded?`tree.collapse`:`tree.expand`,{name:d(i.original.node)}),"aria-expanded":i.original.expanded,onClick:()=>_(i.original.node.id),children:(0,s.jsx)(o.ChevronRight,{"aria-hidden":`true`,className:e.cn(`size-4 transition-transform`,i.original.expanded&&`rotate-90`)})}):(0,s.jsx)(`span`,{"aria-hidden":`true`,className:`size-7 shrink-0`}),(0,s.jsx)(`span`,{className:`min-w-0 flex-1`,children:n.cell(i.original)})]})}));return(0,s.jsx)(r.DataTable,{data:g,columns:v,caption:u})}exports.TreeTable=c;
@@ -0,0 +1,23 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type FlatTreeRow, type TreeNode } from '../lib/tree';
3
+ export type TreeTableColumn<T> = {
4
+ id: string;
5
+ header: string;
6
+ /** 固定列宽;省略时由标准表格按可用宽度分配。 */
7
+ width?: number;
8
+ /** 第一列的返回值会自动获得层级缩进与展开按钮。 */
9
+ cell: (row: FlatTreeRow<T>) => ReactNode;
10
+ };
11
+ /**
12
+ * 表格树:层级数据复用标准表格,表格样式、列宽拖拽、溢出提示与空态都来自 `DataTable`。
13
+ * 只把父子关系拍平成行,并在第一列补上缩进与展开按钮。
14
+ */
15
+ export declare function TreeTable<T>({ nodes, columns, caption, rowLabel, defaultExpanded, }: {
16
+ nodes: TreeNode<T>[];
17
+ columns: TreeTableColumn<T>[];
18
+ caption: string;
19
+ /** 展开/收起按钮的提示文本,通常返回行的名称。 */
20
+ rowLabel: (node: TreeNode<T>) => string;
21
+ defaultExpanded?: string[];
22
+ }): import("react").JSX.Element;
23
+ //# sourceMappingURL=tree-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-table.d.ts","sourceRoot":"","sources":["../../src/components/tree-table.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAMhD,OAAO,EAAe,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAA;AAGzE,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6BAA6B;IAC7B,IAAI,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,SAAS,CAAA;CACzC,CAAA;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAC3B,KAAK,EACL,OAAO,EACP,OAAO,EACP,QAAQ,EACR,eAAoB,GACrB,EAAE;IACD,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;IACpB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAA;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,6BAA6B;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,MAAM,CAAA;IACvC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B,+BAoDA"}
@@ -0,0 +1,53 @@
1
+ import { cn as e } from "../lib/utils.js";
2
+ import { Button as t } from "./ui/button.js";
3
+ import { useUiTranslation as n } from "../lib/use-ui-translation.js";
4
+ import { DataTable as r } from "./data-table.js";
5
+ import { flattenTree as i } from "../lib/tree.js";
6
+ import { useState as a } from "react";
7
+ import { ChevronRight as o } from "lucide-react";
8
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
9
+ //#region src/components/tree-table.tsx
10
+ function l({ nodes: l, columns: u, caption: d, rowLabel: f, defaultExpanded: p = [] }) {
11
+ let { t: m } = n(), [h, g] = a(() => new Set(p)), _ = i(l, h);
12
+ function v(e) {
13
+ g((t) => {
14
+ let n = new Set(t);
15
+ return n.has(e) ? n.delete(e) : n.add(e), n;
16
+ });
17
+ }
18
+ let y = u.map((n, r) => ({
19
+ id: n.id,
20
+ header: n.header,
21
+ size: n.width,
22
+ cell: ({ row: i }) => r > 0 ? n.cell(i.original) : /* @__PURE__ */ c("div", {
23
+ className: "flex items-center gap-1",
24
+ style: { paddingInlineStart: i.original.depth * 20 },
25
+ children: [i.original.hasChildren ? /* @__PURE__ */ s(t, {
26
+ type: "button",
27
+ variant: "ghost",
28
+ size: "icon",
29
+ className: "size-7 shrink-0",
30
+ "aria-label": m(i.original.expanded ? "tree.collapse" : "tree.expand", { name: f(i.original.node) }),
31
+ "aria-expanded": i.original.expanded,
32
+ onClick: () => v(i.original.node.id),
33
+ children: /* @__PURE__ */ s(o, {
34
+ "aria-hidden": "true",
35
+ className: e("size-4 transition-transform", i.original.expanded && "rotate-90")
36
+ })
37
+ }) : /* @__PURE__ */ s("span", {
38
+ "aria-hidden": "true",
39
+ className: "size-7 shrink-0"
40
+ }), /* @__PURE__ */ s("span", {
41
+ className: "min-w-0 flex-1",
42
+ children: n.cell(i.original)
43
+ })]
44
+ })
45
+ }));
46
+ return /* @__PURE__ */ s(r, {
47
+ data: _,
48
+ columns: y,
49
+ caption: d
50
+ });
51
+ }
52
+ //#endregion
53
+ export { l as TreeTable };
@@ -0,0 +1 @@
1
+ const e=require("../lib/utils.cjs"),t=require("./ui/button.cjs"),n=require("../lib/use-ui-translation.cjs"),r=require("./ui/checkbox.cjs"),i=require("./ui/input.cjs"),a=require("./ui/skeleton.cjs"),o=require("../lib/tree.cjs");let s=require("react"),c=require("lucide-react"),l=require("react/jsx-runtime");function u({nodes:u,label:d,defaultExpanded:f=[],defaultSelected:p,guides:m=!0,filterable:h=!1,showExpandControls:g=!1,checkable:_=!1,defaultChecked:v=[],onCheckedChange:y,filterPlaceholder:b,onMove:x,loadChildren:S,virtual:C,className:w}){let{t:T}=n.useUiTranslation(),[E,D]=(0,s.useState)(()=>new Set(f)),[O,k]=(0,s.useState)(p),[ee,A]=(0,s.useState)(p??u[0]?.id),[j,M]=(0,s.useState)(``),[N,P]=(0,s.useState)(),[F,I]=(0,s.useState)(),L=(0,s.useRef)(0),R=(0,s.useRef)(null),[z,B]=(0,s.useState)({start:0,end:40}),[V,H]=(0,s.useState)(()=>new Set),[U,W]=(0,s.useState)(()=>new Set(v)),G=(0,s.useRef)(new Map),K=(0,s.useMemo)(()=>{let e=j.trim().toLowerCase();if(!e)return{nodes:u,matched:new Set,autoExpand:new Set};let t=new Set,n=new Set,r=new Map(u.map(e=>[e.id,e]));for(let i of u){if(!i.data.label.toLowerCase().includes(e))continue;t.add(i.id);let a=i.parentId;for(;a&&r.has(a);)n.add(a),a=r.get(a)?.parentId}return{nodes:u.filter(e=>t.has(e.id)||n.has(e.id)),matched:t,autoExpand:n}},[u,j]),q=o.flattenTree(K.nodes,j?new Set([...E,...K.autoExpand]):E),J=q.map(e=>e.node.id),Y=u.map(e=>e.id),X=K.nodes.map(e=>e.id);function Z(e){let t=!U.has(e),n=o.toggleChecked(u,U,e,t);W(n),y?.([...n])}function Q(e){e&&(A(e),G.current.get(e)?.focus())}function $(e){!e.expanded&&e.hasChildren===!1&&S&&(H(t=>new Set(t).add(e.node.id)),S(e.node.id),window.setTimeout(()=>H(t=>{let n=new Set(t);return n.delete(e.node.id),n}),600)),D(t=>{let n=new Set(t);return n.has(e.node.id)?n.delete(e.node.id):n.add(e.node.id),n})}function te(e,t){let n=J.indexOf(t.node.id),r=q.find(e=>e.node.id===t.node.parentId);e.key===`ArrowDown`?(e.preventDefault(),Q(J[Math.min(n+1,J.length-1)])):e.key===`ArrowUp`?(e.preventDefault(),Q(J[Math.max(n-1,0)])):e.key===`Home`?(e.preventDefault(),Q(J[0])):e.key===`End`?(e.preventDefault(),Q(J.at(-1))):e.key===`ArrowRight`?(e.preventDefault(),t.hasChildren&&!t.expanded?$(t):t.hasChildren&&Q(J[n+1])):e.key===`ArrowLeft`?(e.preventDefault(),t.expanded?$(t):Q(r?.node.id)):(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),t.node.data.disabled||k(t.node.id))}let ne=(h||g)&&(0,l.jsxs)(`div`,{className:`mb-2 flex flex-wrap items-center gap-2`,children:[h&&(0,l.jsxs)(`div`,{className:`relative min-w-40 flex-1`,children:[(0,l.jsx)(c.Search,{"aria-hidden":`true`,className:`pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground`}),(0,l.jsx)(i.Input,{"aria-label":T(`filterNodes`),value:j,placeholder:b??T(`filterNodes`),className:`h-8 pl-8`,onChange:e=>M(e.target.value)})]}),g&&(0,l.jsxs)(`div`,{className:`flex items-center gap-1`,children:[_&&(0,l.jsxs)(`label`,{className:`flex items-center gap-2 whitespace-nowrap text-xs text-muted-foreground`,children:[(0,l.jsx)(r.Checkbox,{"aria-label":T(`tree.selectAll`),checked:X.length>0&&X.every(e=>U.has(e)),indeterminate:X.some(e=>U.has(e))&&!X.every(e=>U.has(e)),onCheckedChange:e=>{let t=new Set(U);for(let n of X)e?t.add(n):t.delete(n);W(t),y?.([...t])}}),T(`tree.selected`,{count:U.size})]}),(0,l.jsxs)(t.Button,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>D(new Set(Y)),children:[(0,l.jsx)(c.ListTree,{"aria-hidden":`true`}),T(`expandAll`)]}),(0,l.jsx)(t.Button,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>D(new Set),children:T(`collapseAll`)})]})]});return u.length?(0,l.jsxs)(`div`,{className:e.cn(`rounded-xl border bg-card p-2 text-sm`,w),children:[ne,(0,l.jsxs)(`div`,{ref:R,role:`tree`,"aria-label":d,className:C?`max-h-96 overflow-y-auto`:void 0,onScroll:e=>{if(!C)return;let t=Math.floor(e.currentTarget.scrollTop/36);B({start:Math.max(0,t-8),end:t+40})},children:[q.length===0&&(0,l.jsx)(`p`,{className:`px-2 py-6 text-center text-sm text-muted-foreground`,children:T(`filterEmpty`)}),(C&&q.length>200?q.slice(z.start,z.end):q).map(n=>{let i=n.node.data;return(0,l.jsxs)(`div`,{role:`treeitem`,"aria-level":n.depth+1,"aria-expanded":n.hasChildren?n.expanded:void 0,"aria-selected":O===n.node.id,"aria-checked":_?U.has(n.node.id)?!0:o.checkState(u,U,n.node.id)===`indeterminate`&&`mixed`:void 0,"aria-disabled":i.disabled||void 0,"data-depth":n.depth,tabIndex:ee===n.node.id?0:-1,ref:e=>{e?G.current.set(n.node.id,e):G.current.delete(n.node.id)},className:e.cn(`relative flex min-h-9 cursor-pointer items-center gap-2 rounded-md pr-2 outline-none`,`hover:bg-accent/60 focus-visible:ring-2 focus-visible:ring-ring/40`,O===n.node.id&&`bg-primary/8 text-primary`,i.disabled&&`pointer-events-none opacity-50`,F===n.node.id&&`ring-2 ring-primary/50`),style:{paddingInlineStart:n.depth*20},draggable:!!x,onDragStart:()=>P(n.node.id),onDragOver:e=>{x&&N&&N!==n.node.id&&(o.subtreeIds(u,N).includes(n.node.id)||(e.preventDefault(),I(n.node.id)))},onDragLeave:()=>I(e=>e===n.node.id?void 0:e),onDrop:e=>{x&&N&&N!==n.node.id&&(e.preventDefault(),o.subtreeIds(u,N).includes(n.node.id)||x(N,n.node.id),P(void 0),I(void 0))},onTouchStart:()=>{x&&(L.current=window.setTimeout(()=>P(n.node.id),400))},onTouchEnd:()=>window.clearTimeout(L.current),onTouchMove:()=>window.clearTimeout(L.current),onClick:()=>{A(n.node.id),k(n.node.id)},onKeyDown:e=>te(e,n),children:[m&&n.depth>0&&Array.from({length:n.depth},(e,t)=>(0,l.jsx)(`span`,{"aria-hidden":`true`,className:`pointer-events-none absolute inset-y-0 border-l border-dashed border-border`,style:{insetInlineStart:t*20+14}},t)),_&&(0,l.jsx)(r.Checkbox,{className:`mr-0.5`,"aria-label":T(`tree.select`,{name:i.label}),checked:U.has(n.node.id),indeterminate:o.checkState(u,U,n.node.id)===`indeterminate`,onCheckedChange:()=>Z(n.node.id)}),n.hasChildren?(0,l.jsx)(t.Button,{type:`button`,variant:`ghost`,size:`icon`,className:`size-7 shrink-0`,tabIndex:-1,"aria-label":T(n.expanded?`tree.collapse`:`tree.expand`,{name:i.label}),onClick:e=>{e.stopPropagation(),$(n)},children:(0,l.jsx)(c.ChevronRight,{"aria-hidden":`true`,className:e.cn(`size-4 transition-transform`,n.expanded&&`rotate-90`)})}):(0,l.jsx)(`span`,{"aria-hidden":`true`,className:`size-7 shrink-0`}),(0,l.jsxs)(`span`,{className:e.cn(`min-w-0 flex-1 truncate`,K.matched.size>0&&K.matched.has(n.node.id)&&`text-primary`),children:[V.has(n.node.id)&&(0,l.jsx)(a.Skeleton,{className:`size-3.5 shrink-0 rounded-full`}),i.label]}),i.description&&(0,l.jsx)(`span`,{className:`shrink-0 text-xs text-muted-foreground`,children:i.description})]},n.node.id)})]})]}):(0,l.jsx)(`p`,{className:e.cn(`rounded-xl border bg-card p-4 text-sm text-muted-foreground`,w),children:T(`tree.empty`)})}exports.Tree=u;
@@ -0,0 +1,36 @@
1
+ import { type TreeNode } from '../lib/tree';
2
+ export type TreeItem = {
3
+ label: string;
4
+ description?: string;
5
+ disabled?: boolean;
6
+ };
7
+ /**
8
+ * 列表树:层级缩进 + 可选虚线层级线,行本身即选中项,不在行首放其他控件。
9
+ * ↑/↓ 在可见节点间移动,→ 展开或进入子节点,← 收起或回到父节点,Enter/空格 选中。
10
+ */
11
+ export declare function Tree({ nodes, label, defaultExpanded, defaultSelected, guides, filterable, showExpandControls, checkable, defaultChecked, onCheckedChange, filterPlaceholder, onMove, loadChildren, virtual, className, }: {
12
+ nodes: TreeNode<TreeItem>[];
13
+ /** 树的访问名称,同时用于展开/收起按钮的提示。 */
14
+ label: string;
15
+ defaultExpanded?: string[];
16
+ defaultSelected?: string;
17
+ /** 是否显示层级虚线;层级缩进始终保留。 */
18
+ guides?: boolean;
19
+ /** 显示节点搜索框;命中节点会自动展开其祖先。 */
20
+ filterable?: boolean;
21
+ /** 显示展开全部 / 收起全部按钮。 */
22
+ showExpandControls?: boolean;
23
+ /** 开启后每行带勾选框:父节点级联子节点,子节点全选后父节点自动勾选。 */
24
+ checkable?: boolean;
25
+ defaultChecked?: string[];
26
+ onCheckedChange?: (ids: string[]) => void;
27
+ filterPlaceholder?: string;
28
+ /** 拖拽排序:把 source 拖到 target 之后(target 为空表示成为根节点)。 */
29
+ onMove?: (sourceId: string, targetId: string | undefined) => void;
30
+ /** 懒加载:节点首次展开时回调,业务把子节点补进 nodes。 */
31
+ loadChildren?: (id: string) => void;
32
+ /** 节点超过 200 时启用窗口化渲染,只渲染可视区域。 */
33
+ virtual?: boolean;
34
+ className?: string;
35
+ }): import("react").JSX.Element;
36
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/components/tree.tsx"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,QAAQ,EACd,MAAM,YAAY,CAAA;AAOnB,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,EACnB,KAAK,EACL,KAAK,EACL,eAAoB,EACpB,eAAe,EACf,MAAa,EACb,UAAkB,EAClB,kBAA0B,EAC1B,SAAiB,EACjB,cAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,MAAM,EACN,YAAY,EACZ,OAAO,EACP,SAAS,GACV,EAAE;IACD,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAA;IAC3B,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,yBAAyB;IACzB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,uBAAuB;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,oDAAoD;IACpD,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAA;IACjE,oCAAoC;IACpC,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,iCAAiC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,+BA0TA"}
@@ -0,0 +1,204 @@
1
+ import { cn as e } from "../lib/utils.js";
2
+ import { Button as t } from "./ui/button.js";
3
+ import { useUiTranslation as n } from "../lib/use-ui-translation.js";
4
+ import { Checkbox as r } from "./ui/checkbox.js";
5
+ import { Input as i } from "./ui/input.js";
6
+ import { Skeleton as a } from "./ui/skeleton.js";
7
+ import { checkState as o, flattenTree as ee, subtreeIds as s, toggleChecked as c } from "../lib/tree.js";
8
+ import { useMemo as te, useRef as l, useState as u } from "react";
9
+ import { ChevronRight as d, ListTree as f, Search as p } from "lucide-react";
10
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
11
+ //#region src/components/tree.tsx
12
+ function g({ nodes: g, label: ne, defaultExpanded: _ = [], defaultSelected: v, guides: y = !0, filterable: b = !1, showExpandControls: x = !1, checkable: S = !1, defaultChecked: re = [], onCheckedChange: C, filterPlaceholder: ie, onMove: w, loadChildren: T, virtual: E, className: D }) {
13
+ let { t: O } = n(), [k, A] = u(() => new Set(_)), [j, M] = u(v), [N, P] = u(v ?? g[0]?.id), [F, ae] = u(""), [I, L] = u(), [oe, R] = u(), z = l(0), B = l(null), [V, H] = u({
14
+ start: 0,
15
+ end: 40
16
+ }), [U, W] = u(() => /* @__PURE__ */ new Set()), [G, K] = u(() => new Set(re)), q = l(/* @__PURE__ */ new Map()), J = te(() => {
17
+ let e = F.trim().toLowerCase();
18
+ if (!e) return {
19
+ nodes: g,
20
+ matched: /* @__PURE__ */ new Set(),
21
+ autoExpand: /* @__PURE__ */ new Set()
22
+ };
23
+ let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = new Map(g.map((e) => [e.id, e]));
24
+ for (let i of g) {
25
+ if (!i.data.label.toLowerCase().includes(e)) continue;
26
+ t.add(i.id);
27
+ let a = i.parentId;
28
+ for (; a && r.has(a);) n.add(a), a = r.get(a)?.parentId;
29
+ }
30
+ return {
31
+ nodes: g.filter((e) => t.has(e.id) || n.has(e.id)),
32
+ matched: t,
33
+ autoExpand: n
34
+ };
35
+ }, [g, F]), Y = ee(J.nodes, F ? /* @__PURE__ */ new Set([...k, ...J.autoExpand]) : k), X = Y.map((e) => e.node.id), se = g.map((e) => e.id), Z = J.nodes.map((e) => e.id);
36
+ function ce(e) {
37
+ let t = !G.has(e), n = c(g, G, e, t);
38
+ K(n), C?.([...n]);
39
+ }
40
+ function Q(e) {
41
+ e && (P(e), q.current.get(e)?.focus());
42
+ }
43
+ function $(e) {
44
+ !e.expanded && e.hasChildren === !1 && T && (W((t) => new Set(t).add(e.node.id)), T(e.node.id), window.setTimeout(() => W((t) => {
45
+ let n = new Set(t);
46
+ return n.delete(e.node.id), n;
47
+ }), 600)), A((t) => {
48
+ let n = new Set(t);
49
+ return n.has(e.node.id) ? n.delete(e.node.id) : n.add(e.node.id), n;
50
+ });
51
+ }
52
+ function le(e, t) {
53
+ let n = X.indexOf(t.node.id), r = Y.find((e) => e.node.id === t.node.parentId);
54
+ e.key === "ArrowDown" ? (e.preventDefault(), Q(X[Math.min(n + 1, X.length - 1)])) : e.key === "ArrowUp" ? (e.preventDefault(), Q(X[Math.max(n - 1, 0)])) : e.key === "Home" ? (e.preventDefault(), Q(X[0])) : e.key === "End" ? (e.preventDefault(), Q(X.at(-1))) : e.key === "ArrowRight" ? (e.preventDefault(), t.hasChildren && !t.expanded ? $(t) : t.hasChildren && Q(X[n + 1])) : e.key === "ArrowLeft" ? (e.preventDefault(), t.expanded ? $(t) : Q(r?.node.id)) : (e.key === "Enter" || e.key === " ") && (e.preventDefault(), t.node.data.disabled || M(t.node.id));
55
+ }
56
+ let ue = (b || x) && /* @__PURE__ */ h("div", {
57
+ className: "mb-2 flex flex-wrap items-center gap-2",
58
+ children: [b && /* @__PURE__ */ h("div", {
59
+ className: "relative min-w-40 flex-1",
60
+ children: [/* @__PURE__ */ m(p, {
61
+ "aria-hidden": "true",
62
+ className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground"
63
+ }), /* @__PURE__ */ m(i, {
64
+ "aria-label": O("filterNodes"),
65
+ value: F,
66
+ placeholder: ie ?? O("filterNodes"),
67
+ className: "h-8 pl-8",
68
+ onChange: (e) => ae(e.target.value)
69
+ })]
70
+ }), x && /* @__PURE__ */ h("div", {
71
+ className: "flex items-center gap-1",
72
+ children: [
73
+ S && /* @__PURE__ */ h("label", {
74
+ className: "flex items-center gap-2 whitespace-nowrap text-xs text-muted-foreground",
75
+ children: [/* @__PURE__ */ m(r, {
76
+ "aria-label": O("tree.selectAll"),
77
+ checked: Z.length > 0 && Z.every((e) => G.has(e)),
78
+ indeterminate: Z.some((e) => G.has(e)) && !Z.every((e) => G.has(e)),
79
+ onCheckedChange: (e) => {
80
+ let t = new Set(G);
81
+ for (let n of Z) e ? t.add(n) : t.delete(n);
82
+ K(t), C?.([...t]);
83
+ }
84
+ }), O("tree.selected", { count: G.size })]
85
+ }),
86
+ /* @__PURE__ */ h(t, {
87
+ type: "button",
88
+ variant: "outline",
89
+ size: "sm",
90
+ onClick: () => A(new Set(se)),
91
+ children: [/* @__PURE__ */ m(f, { "aria-hidden": "true" }), O("expandAll")]
92
+ }),
93
+ /* @__PURE__ */ m(t, {
94
+ type: "button",
95
+ variant: "outline",
96
+ size: "sm",
97
+ onClick: () => A(/* @__PURE__ */ new Set()),
98
+ children: O("collapseAll")
99
+ })
100
+ ]
101
+ })]
102
+ });
103
+ return g.length ? /* @__PURE__ */ h("div", {
104
+ className: e("rounded-xl border bg-card p-2 text-sm", D),
105
+ children: [ue, /* @__PURE__ */ h("div", {
106
+ ref: B,
107
+ role: "tree",
108
+ "aria-label": ne,
109
+ className: E ? "max-h-96 overflow-y-auto" : void 0,
110
+ onScroll: (e) => {
111
+ if (!E) return;
112
+ let t = Math.floor(e.currentTarget.scrollTop / 36);
113
+ H({
114
+ start: Math.max(0, t - 8),
115
+ end: t + 40
116
+ });
117
+ },
118
+ children: [Y.length === 0 && /* @__PURE__ */ m("p", {
119
+ className: "px-2 py-6 text-center text-sm text-muted-foreground",
120
+ children: O("filterEmpty")
121
+ }), (E && Y.length > 200 ? Y.slice(V.start, V.end) : Y).map((n) => {
122
+ let i = n.node.data;
123
+ return /* @__PURE__ */ h("div", {
124
+ role: "treeitem",
125
+ "aria-level": n.depth + 1,
126
+ "aria-expanded": n.hasChildren ? n.expanded : void 0,
127
+ "aria-selected": j === n.node.id,
128
+ "aria-checked": S ? G.has(n.node.id) ? !0 : o(g, G, n.node.id) === "indeterminate" && "mixed" : void 0,
129
+ "aria-disabled": i.disabled || void 0,
130
+ "data-depth": n.depth,
131
+ tabIndex: N === n.node.id ? 0 : -1,
132
+ ref: (e) => {
133
+ e ? q.current.set(n.node.id, e) : q.current.delete(n.node.id);
134
+ },
135
+ className: e("relative flex min-h-9 cursor-pointer items-center gap-2 rounded-md pr-2 outline-none", "hover:bg-accent/60 focus-visible:ring-2 focus-visible:ring-ring/40", j === n.node.id && "bg-primary/8 text-primary", i.disabled && "pointer-events-none opacity-50", oe === n.node.id && "ring-2 ring-primary/50"),
136
+ style: { paddingInlineStart: n.depth * 20 },
137
+ draggable: !!w,
138
+ onDragStart: () => L(n.node.id),
139
+ onDragOver: (e) => {
140
+ w && I && I !== n.node.id && (s(g, I).includes(n.node.id) || (e.preventDefault(), R(n.node.id)));
141
+ },
142
+ onDragLeave: () => R((e) => e === n.node.id ? void 0 : e),
143
+ onDrop: (e) => {
144
+ w && I && I !== n.node.id && (e.preventDefault(), s(g, I).includes(n.node.id) || w(I, n.node.id), L(void 0), R(void 0));
145
+ },
146
+ onTouchStart: () => {
147
+ w && (z.current = window.setTimeout(() => L(n.node.id), 400));
148
+ },
149
+ onTouchEnd: () => window.clearTimeout(z.current),
150
+ onTouchMove: () => window.clearTimeout(z.current),
151
+ onClick: () => {
152
+ P(n.node.id), M(n.node.id);
153
+ },
154
+ onKeyDown: (e) => le(e, n),
155
+ children: [
156
+ y && n.depth > 0 && Array.from({ length: n.depth }, (e, t) => /* @__PURE__ */ m("span", {
157
+ "aria-hidden": "true",
158
+ className: "pointer-events-none absolute inset-y-0 border-l border-dashed border-border",
159
+ style: { insetInlineStart: t * 20 + 14 }
160
+ }, t)),
161
+ S && /* @__PURE__ */ m(r, {
162
+ className: "mr-0.5",
163
+ "aria-label": O("tree.select", { name: i.label }),
164
+ checked: G.has(n.node.id),
165
+ indeterminate: o(g, G, n.node.id) === "indeterminate",
166
+ onCheckedChange: () => ce(n.node.id)
167
+ }),
168
+ n.hasChildren ? /* @__PURE__ */ m(t, {
169
+ type: "button",
170
+ variant: "ghost",
171
+ size: "icon",
172
+ className: "size-7 shrink-0",
173
+ tabIndex: -1,
174
+ "aria-label": O(n.expanded ? "tree.collapse" : "tree.expand", { name: i.label }),
175
+ onClick: (e) => {
176
+ e.stopPropagation(), $(n);
177
+ },
178
+ children: /* @__PURE__ */ m(d, {
179
+ "aria-hidden": "true",
180
+ className: e("size-4 transition-transform", n.expanded && "rotate-90")
181
+ })
182
+ }) : /* @__PURE__ */ m("span", {
183
+ "aria-hidden": "true",
184
+ className: "size-7 shrink-0"
185
+ }),
186
+ /* @__PURE__ */ h("span", {
187
+ className: e("min-w-0 flex-1 truncate", J.matched.size > 0 && J.matched.has(n.node.id) && "text-primary"),
188
+ children: [U.has(n.node.id) && /* @__PURE__ */ m(a, { className: "size-3.5 shrink-0 rounded-full" }), i.label]
189
+ }),
190
+ i.description && /* @__PURE__ */ m("span", {
191
+ className: "shrink-0 text-xs text-muted-foreground",
192
+ children: i.description
193
+ })
194
+ ]
195
+ }, n.node.id);
196
+ })]
197
+ })]
198
+ }) : /* @__PURE__ */ m("p", {
199
+ className: e("rounded-xl border bg-card p-4 text-sm text-muted-foreground", D),
200
+ children: O("tree.empty")
201
+ });
202
+ }
203
+ //#endregion
204
+ export { g as Tree };
@@ -0,0 +1 @@
1
+ const e=require("../lib/utils.cjs");let t=require("lucide-react"),n=require("react/jsx-runtime");function r({value:r,direction:i,reverse:a=!1,variant:o=`soft`,suffix:s=`%`,className:c}){let l=i===`flat`?void 0:i===`up`!==a,u=i===`flat`?t.Minus:i===`up`?t.ArrowUpRight:t.ArrowDownRight,d=r===void 0?``:`${r>0?`+`:``}${r.toFixed(1)}${s}`;return(0,n.jsxs)(`span`,{"data-slot":`trend`,"data-direction":i,className:e.cn(`inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 text-xs font-medium tabular-nums`,l===void 0&&`bg-muted text-muted-foreground`,l===!0&&`bg-success-soft text-success`,l===!1&&`bg-danger-soft text-danger`,o===`outline`&&`border-current/30 bg-transparent`,c),children:[(0,n.jsx)(u,{"aria-hidden":`true`,className:`size-3`}),i===`flat`?`0.0`+s:d]})}exports.Trend=r;
@@ -0,0 +1,19 @@
1
+ declare const tones: {
2
+ readonly default: "";
3
+ readonly soft: "";
4
+ readonly outline: "border";
5
+ };
6
+ /**
7
+ * 指标涨跌徽标。`reverse` 表示"数值上升是坏事"(如待处理数)。
8
+ */
9
+ export declare function Trend({ value, direction, reverse, variant, suffix, className, }: {
10
+ /** 百分比数值,undefined 时显示持平。 */
11
+ value?: number;
12
+ direction: 'up' | 'down' | 'flat';
13
+ reverse?: boolean;
14
+ variant?: keyof typeof tones;
15
+ suffix?: string;
16
+ className?: string;
17
+ }): import("react").JSX.Element;
18
+ export {};
19
+ //# sourceMappingURL=trend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trend.d.ts","sourceRoot":"","sources":["../../src/components/trend.tsx"],"names":[],"mappings":"AAGA,QAAA,MAAM,KAAK;;;;CAID,CAAA;AAEV;;GAEG;AACH,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,SAAS,EACT,OAAe,EACf,OAAgB,EAChB,MAAY,EACZ,SAAS,GACV,EAAE;IACD,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,OAAO,KAAK,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,+BAqBA"}
@@ -0,0 +1,18 @@
1
+ import { cn as e } from "../lib/utils.js";
2
+ import { ArrowDownRight as t, ArrowUpRight as n, Minus as r } from "lucide-react";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ //#region src/components/trend.tsx
5
+ function o({ value: o, direction: s, reverse: c = !1, variant: l = "soft", suffix: u = "%", className: d }) {
6
+ let f = s === "flat" ? void 0 : s === "up" !== c, p = s === "flat" ? r : s === "up" ? n : t, m = o === void 0 ? "" : `${o > 0 ? "+" : ""}${o.toFixed(1)}${u}`;
7
+ return /* @__PURE__ */ a("span", {
8
+ "data-slot": "trend",
9
+ "data-direction": s,
10
+ className: e("inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 text-xs font-medium tabular-nums", f === void 0 && "bg-muted text-muted-foreground", f === !0 && "bg-success-soft text-success", f === !1 && "bg-danger-soft text-danger", l === "outline" && "border-current/30 bg-transparent", d),
11
+ children: [/* @__PURE__ */ i(p, {
12
+ "aria-hidden": "true",
13
+ className: "size-3"
14
+ }), s === "flat" ? "0.0" + u : m]
15
+ });
16
+ }
17
+ //#endregion
18
+ export { o as Trend };
@@ -0,0 +1 @@
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/utils.cjs"),n=require("./button.cjs");let r=require("react");r=e.__toESM(r,1);let i=require("radix-ui"),a=require("react/jsx-runtime");var o=i.AlertDialog.Root,s=i.AlertDialog.Trigger,c=i.AlertDialog.Portal;function l({className:e,...n}){return(0,a.jsx)(i.AlertDialog.Overlay,{className:t.cn(`fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0`,e),...n})}function u({className:e,...n}){return(0,a.jsxs)(c,{children:[(0,a.jsx)(l,{}),(0,a.jsx)(i.AlertDialog.Content,{className:t.cn(`fixed left-1/2 top-1/2 z-50 grid w-[calc(100%-2rem)] max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl border bg-background p-6 shadow-lg`,e),...n})]})}function d({className:e,...n}){return(0,a.jsx)(`div`,{className:t.cn(`flex flex-col gap-2 text-center sm:text-left`,e),...n})}function f({className:e,...n}){return(0,a.jsx)(`div`,{className:t.cn(`flex flex-col-reverse gap-2 sm:flex-row sm:justify-end`,e),...n})}function p({className:e,...n}){return(0,a.jsx)(i.AlertDialog.Title,{className:t.cn(`text-lg font-semibold`,e),...n})}function m({className:e,...n}){return(0,a.jsx)(i.AlertDialog.Description,{className:t.cn(`text-sm leading-6 text-muted-foreground`,e),...n})}function h({className:e,...r}){return(0,a.jsx)(i.AlertDialog.Action,{className:t.cn(n.buttonVariants({variant:`destructive`}),e),...r})}function g({className:e,...r}){return(0,a.jsx)(i.AlertDialog.Cancel,{className:t.cn(n.buttonVariants({variant:`outline`}),e),...r})}exports.AlertDialog=o,exports.AlertDialogAction=h,exports.AlertDialogCancel=g,exports.AlertDialogContent=u,exports.AlertDialogDescription=m,exports.AlertDialogFooter=f,exports.AlertDialogHeader=d,exports.AlertDialogTitle=p,exports.AlertDialogTrigger=s;