@dreamtree-org/twreact-ui 2.0.4 → 2.0.6

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 (60) hide show
  1. package/README.md +12 -4
  2. package/ai-skills/dreamtree-ui.md +4 -3
  3. package/dist/ai-schema.json +135 -0
  4. package/dist/charts/index.d.ts +2 -1
  5. package/dist/charts/index.js +298 -13
  6. package/dist/components/charts/ChartFrame.d.ts +1 -0
  7. package/dist/components/charts/ChartFrame.d.ts.map +1 -1
  8. package/dist/components/charts/ScatterChart.d.ts +4 -0
  9. package/dist/components/charts/ScatterChart.d.ts.map +1 -0
  10. package/dist/components/charts/ScatterTooltip.d.ts +14 -0
  11. package/dist/components/charts/ScatterTooltip.d.ts.map +1 -0
  12. package/dist/components/charts/scatterData.d.ts +17 -0
  13. package/dist/components/charts/scatterData.d.ts.map +1 -0
  14. package/dist/components/core/Popover.d.ts.map +1 -1
  15. package/dist/components/feedback/Tour.d.ts.map +1 -1
  16. package/dist/components/navigation/Sidebar.d.ts.map +1 -1
  17. package/dist/components/utility/Sortable.d.ts.map +1 -1
  18. package/dist/components/utility/SortableGroup.d.ts +15 -0
  19. package/dist/components/utility/SortableGroup.d.ts.map +1 -0
  20. package/dist/esm/charts/index.js +1 -0
  21. package/dist/esm/components/charts/ChartFrame.js +6 -6
  22. package/dist/esm/components/charts/ScatterChart.js +204 -0
  23. package/dist/esm/components/charts/ScatterTooltip.js +61 -0
  24. package/dist/esm/components/charts/scatterData.js +43 -0
  25. package/dist/esm/components/core/Accordion.js +2 -2
  26. package/dist/esm/components/core/DatePicker.js +3 -3
  27. package/dist/esm/components/core/DateRangePicker.js +3 -3
  28. package/dist/esm/components/core/Form.js +3 -3
  29. package/dist/esm/components/core/LocationPicker.js +1 -1
  30. package/dist/esm/components/core/Popover.js +1 -1
  31. package/dist/esm/components/core/Select.js +16 -16
  32. package/dist/esm/components/core/Table/Table.js +1 -1
  33. package/dist/esm/components/core/internal/Calendar.js +2 -2
  34. package/dist/esm/components/feedback/Drawer.js +5 -5
  35. package/dist/esm/components/feedback/Tour.js +1 -1
  36. package/dist/esm/components/rich-text/RichTextEditor.js +2 -2
  37. package/dist/esm/components/rich-text/RichTextToolbar.js +1 -1
  38. package/dist/esm/components/utility/Pagination.js +1 -1
  39. package/dist/esm/components/utility/Sortable.js +70 -48
  40. package/dist/esm/components/utility/SortableGroup.js +48 -0
  41. package/dist/esm/hooks/useSortable.js +96 -30
  42. package/dist/esm/hooks/useSortableGroup.js +268 -0
  43. package/dist/esm/index.js +1 -0
  44. package/dist/hooks/useSortable.d.ts +12 -3
  45. package/dist/hooks/useSortable.d.ts.map +1 -1
  46. package/dist/hooks/useSortableGroup.d.ts +43 -0
  47. package/dist/hooks/useSortableGroup.d.ts.map +1 -0
  48. package/dist/index.css +1 -1
  49. package/dist/index.d.ts +2 -1
  50. package/dist/index.esm.css +1 -1
  51. package/dist/index.esm.js +904 -513
  52. package/dist/index.js +904 -512
  53. package/dist/rich-text/index.js +3 -3
  54. package/dist/types/charts.d.ts +28 -0
  55. package/dist/types/charts.d.ts.map +1 -1
  56. package/dist/types/index.d.ts +33 -0
  57. package/dist/types/index.d.ts.map +1 -1
  58. package/doc/README.md +2 -0
  59. package/mcp/catalog.snapshot.json +248 -28
  60. package/package.json +1 -1
@@ -505,7 +505,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
505
505
  className: "flex flex-wrap gap-1",
506
506
  children: selectedOptions.map(function (opt) {
507
507
  return jsxs("div", {
508
- className: "flex items-center gap-1 rounded-full bg-gray-100 px-2 py-0.5 text-xs",
508
+ className: "flex items-center gap-1 rounded-full bg-line/60 px-2 py-0.5 text-xs",
509
509
  children: [jsx("span", {
510
510
  className: "truncate max-w-[8rem]",
511
511
  children: opt.label
@@ -534,7 +534,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
534
534
  className: "flex flex-wrap gap-1",
535
535
  children: selectedOptions.slice(0, maxTagCount).map(function (opt) {
536
536
  return jsx("div", {
537
- className: "flex items-center gap-1 rounded-full bg-gray-100 px-2 py-0.5 text-xs",
537
+ className: "flex items-center gap-1 rounded-full bg-line/60 px-2 py-0.5 text-xs",
538
538
  children: jsx("span", {
539
539
  className: "truncate max-w-[6rem]",
540
540
  children: opt.label
@@ -572,7 +572,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
572
572
  "aria-expanded": !collapsed,
573
573
  "aria-controls": collapsed ? undefined : groupOptionsId,
574
574
  "aria-label": "".concat(collapsed ? "Expand" : "Collapse", " ").concat(groupName),
575
- className: "text-xs border border-slate-200 p-0.5 rounded-md cursor-pointer hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-primary-500",
575
+ className: "text-xs border border-line p-0.5 rounded-md cursor-pointer hover:bg-line/50 focus:outline-none focus:ring-2 focus:ring-primary-500",
576
576
  onClick: function onClick() {
577
577
  return setCollapsedGroups(function (prev) {
578
578
  return _objectSpread2(_objectSpread2({}, prev), {}, _defineProperty({}, group.label, !prev[group.label]));
@@ -599,16 +599,16 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
599
599
  onClick: function onClick() {
600
600
  return handleSelect(option);
601
601
  },
602
- className: cn("flex items-center hover:bg-gray-100 cursor-pointer", rowClass, {
602
+ className: cn("flex items-center hover:bg-line/50 cursor-pointer", rowClass, {
603
603
  "opacity-50 cursor-not-allowed": option.disabled,
604
- "bg-primary-50 text-primary-600": focusedIndex === index
604
+ "bg-primary-50 text-primary-600 dark:bg-primary-900/40 dark:text-primary-300": focusedIndex === index
605
605
  }),
606
606
  children: [multiSelect && jsx("div", {
607
607
  className: "mr-2",
608
608
  children: selectedValues.includes(option.value) ? jsx(Check, {
609
609
  className: "h-4 w-4 text-primary-600"
610
610
  }) : jsx("div", {
611
- className: "h-4 w-4 rounded border border-gray-300"
611
+ className: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600"
612
612
  })
613
613
  }), onMenuItemRender ? onMenuItemRender(option) : highlight(option.label, searchTerm), !multiSelect && selectedValues === option.value && jsx(Check, {
614
614
  className: "ml-auto h-4 w-4 text-primary-600"
@@ -637,17 +637,17 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
637
637
  onClick: function onClick() {
638
638
  return handleSelect(option);
639
639
  },
640
- className: cn("flex items-center hover:bg-gray-100 cursor-pointer", ROW_CLASSES[isSheet ? "sheet" : "popover"], {
640
+ className: cn("flex items-center hover:bg-line/50 cursor-pointer", ROW_CLASSES[isSheet ? "sheet" : "popover"], {
641
641
  "opacity-50 cursor-not-allowed": option.disabled,
642
- "bg-primary-50 text-primary-600": focusedIndex === index,
643
- "bg-primary-100": multiSelect && selectedValues.includes(option.value)
642
+ "bg-primary-50 text-primary-600 dark:bg-primary-900/40 dark:text-primary-300": focusedIndex === index,
643
+ "bg-primary-100 dark:bg-primary-900/60": multiSelect && selectedValues.includes(option.value)
644
644
  }),
645
645
  children: [multiSelect && jsx("div", {
646
646
  className: "mr-2",
647
647
  children: selectedValues.includes(option.value) ? jsx(Check, {
648
648
  className: "h-4 w-4 text-primary-600"
649
649
  }) : jsx("div", {
650
- className: "h-4 w-4 rounded border border-gray-300"
650
+ className: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600"
651
651
  })
652
652
  }), onMenuItemRender ? onMenuItemRender(option) : highlight(option.label, searchTerm), !multiSelect && selectedValues === option.value && jsx(Check, {
653
653
  className: "ml-auto h-4 w-4 text-primary-600"
@@ -659,7 +659,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
659
659
  children: jsxs("button", {
660
660
  type: "button",
661
661
  onClick: handleCreate,
662
- className: "flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-gray-100 focus:outline-none focus:bg-gray-100",
662
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-line/50 focus:outline-none focus:bg-line/50",
663
663
  children: [jsx(Plus, {
664
664
  className: "h-4 w-4",
665
665
  "aria-hidden": "true"
@@ -687,7 +687,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
687
687
  className: "h-4 w-4 text-primary-600",
688
688
  "aria-hidden": "true"
689
689
  }) : jsx("div", {
690
- className: "h-4 w-4 rounded border border-gray-300"
690
+ className: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600"
691
691
  })
692
692
  });
693
693
  }()
@@ -752,7 +752,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
752
752
  "aria-labelledby": label ? "".concat(labelId, " ").concat(valueId) : valueId,
753
753
  "aria-describedby": describedBy,
754
754
  "aria-invalid": error ? true : undefined,
755
- className: cn("flex w-full items-center justify-between rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:cursor-not-allowed disabled:opacity-50", SIZE_CLASSES[size] || SIZE_CLASSES.md, {
755
+ className: cn("flex w-full items-center justify-between rounded-md border border-line bg-surface text-foreground focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:cursor-not-allowed disabled:opacity-50", SIZE_CLASSES[size] || SIZE_CLASSES.md, {
756
756
  "border-error-500 focus:ring-error-500": error,
757
757
  // Empty: the placeholder reads muted, like Input's
758
758
  // ::placeholder (#159). `className` still merges last.
@@ -788,7 +788,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
788
788
  type: "button",
789
789
  onClick: handleClear,
790
790
  "aria-label": "Clear selection",
791
- className: cn("absolute right-8 top-1/2 -translate-y-1/2 inline-flex items-center justify-center rounded p-1 text-primary-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-primary-500", TOUCH_TARGET),
791
+ className: cn("absolute right-8 top-1/2 -translate-y-1/2 inline-flex items-center justify-center rounded p-1 text-primary-500 hover:bg-line/50 focus:outline-none focus:ring-2 focus:ring-primary-500", TOUCH_TARGET),
792
792
  children: jsx(X, {
793
793
  className: "h-4 w-4",
794
794
  "aria-hidden": "true"
@@ -811,7 +811,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
811
811
  value: selectedValues !== null && selectedValues !== void 0 ? selectedValues : ""
812
812
  })), isOpen && !isSheet && typeof document !== "undefined" && /*#__PURE__*/createPortal(jsxs("div", {
813
813
  ref: popoverRef,
814
- className: "fixed z-popover overflow-auto rounded-md border border-gray-300 bg-white shadow-lg",
814
+ className: "fixed z-popover overflow-auto rounded-md border border-line bg-surface text-foreground shadow-lg",
815
815
  role: "dialog",
816
816
  "data-placement": floatingPlacement.split("-")[0],
817
817
  // Portaled to document.body with position:fixed so the menu
@@ -823,7 +823,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
823
823
  opacity: 0
824
824
  }),
825
825
  children: [searchable && jsx("div", {
826
- className: "border-b border-gray-200 p-2",
826
+ className: "border-b border-line p-2",
827
827
  children: renderSearch()
828
828
  }), renderListbox()]
829
829
  }), document.body)]
@@ -1225,7 +1225,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1225
1225
  type: "button",
1226
1226
  "aria-label": "Reload",
1227
1227
  title: "Reload",
1228
- className: "px-4 py-2 bg-primary-100 flex items-center gap-2 rounded-lg md:rounded text-primary-700 hover:bg-primary-200 transition-colors",
1228
+ className: "px-4 py-2 bg-primary-100 flex items-center gap-2 rounded-lg md:rounded text-primary-700 hover:bg-primary-200 transition-colors dark:bg-primary-900/40 dark:text-primary-300 dark:hover:bg-primary-900/60",
1229
1229
  onClick: onReload,
1230
1230
  children: [jsx(RefreshCcw, {
1231
1231
  className: "size-4",
@@ -305,8 +305,8 @@ function Calendar(_ref3) {
305
305
  className: cn("mx-auto rounded-md text-sm transition-colors motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-1", sheet ? "h-11 w-full min-w-0 text-base" : "h-9 w-full max-w-9", {
306
306
  "text-primary-400": !currentMonth,
307
307
  "bg-primary-600 text-primary-50": state.edge,
308
- "bg-primary-200": state.inRange && !state.edge,
309
- "bg-primary-100 text-primary-600": todayDate && !state.edge && !state.inRange,
308
+ "bg-primary-200 dark:bg-primary-900/60": state.inRange && !state.edge,
309
+ "bg-primary-100 text-primary-600 dark:bg-primary-900/40 dark:text-primary-300": todayDate && !state.edge && !state.inRange,
310
310
  "hover:bg-background": currentMonth && !state.edge && !state.inRange && !disabled,
311
311
  "cursor-not-allowed opacity-50": disabled
312
312
  }),
@@ -70,7 +70,7 @@ var DrawerTitleBar = function DrawerTitleBar(_ref2) {
70
70
  dragProps = _useGrabZone.dragProps,
71
71
  grabClass = _useGrabZone.grabClass;
72
72
  return jsx("div", _objectSpread2(_objectSpread2({}, dragProps), {}, {
73
- className: cn("flex shrink-0 items-start justify-between gap-4 border-b border-gray-200 px-6 py-4 dark:border-gray-700", grabClass, className),
73
+ className: cn("flex shrink-0 items-start justify-between gap-4 border-b border-line px-6 py-4", grabClass, className),
74
74
  children: children
75
75
  }));
76
76
  };
@@ -145,7 +145,7 @@ var Drawer = /*#__PURE__*/React.forwardRef(function (_ref3, ref) {
145
145
  idPrefix: "drawer",
146
146
  testIdPrefix: "drawer",
147
147
  handleBarClassName: "bg-gray-300 dark:bg-gray-600",
148
- panelClassName: cn("border-gray-200 bg-white text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100", PLACEMENT_CLASSES[side], sizes[size] || sizes.md),
148
+ panelClassName: cn("border-line bg-surface text-foreground", PLACEMENT_CLASSES[side], sizes[size] || sizes.md),
149
149
  renderHeader: renderHeader
150
150
  }, props), {}, {
151
151
  children: composed ? children : jsxs(Fragment, {
@@ -153,7 +153,7 @@ var Drawer = /*#__PURE__*/React.forwardRef(function (_ref3, ref) {
153
153
  className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-4",
154
154
  children: children
155
155
  }), footer && jsx("div", {
156
- className: "flex shrink-0 items-center justify-end gap-3 border-t border-gray-200 px-6 py-4 dark:border-gray-700",
156
+ className: "flex shrink-0 items-center justify-end gap-3 border-t border-line px-6 py-4",
157
157
  children: footer
158
158
  })]
159
159
  })
@@ -169,7 +169,7 @@ var DrawerHeader = /*#__PURE__*/React.forwardRef(function (_ref5, ref) {
169
169
  return jsx("div", _objectSpread2(_objectSpread2(_objectSpread2({
170
170
  ref: ref
171
171
  }, props), dragProps), {}, {
172
- className: cn("border-b border-gray-200 px-6 py-4 dark:border-gray-700", grabClass, className)
172
+ className: cn("border-b border-line px-6 py-4", grabClass, className)
173
173
  }));
174
174
  });
175
175
  var DrawerBody = /*#__PURE__*/React.forwardRef(function (_ref6, ref) {
@@ -185,7 +185,7 @@ var DrawerFooter = /*#__PURE__*/React.forwardRef(function (_ref7, ref) {
185
185
  props = _objectWithoutProperties(_ref7, _excluded4);
186
186
  return jsx("div", _objectSpread2({
187
187
  ref: ref,
188
- className: cn("flex items-center justify-end gap-3 border-t border-gray-200 px-6 py-4 dark:border-gray-700", className)
188
+ className: cn("flex items-center justify-end gap-3 border-t border-line px-6 py-4", className)
189
189
  }, props));
190
190
  });
191
191
  DrawerHeader.displayName = "Drawer.Header";
@@ -221,7 +221,7 @@ var Tour = /*#__PURE__*/forwardRef(function (_ref, _ref2) {
221
221
  onKeyDown: handleKeyDown,
222
222
  "data-placement": placementAttr,
223
223
  "data-presentation": docked ? "sheet" : "popover",
224
- className: cn("fixed overflow-y-auto overscroll-contain rounded-lg border border-gray-200 bg-white text-gray-900 shadow-xl focus:outline-none", "dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100", "transition-opacity duration-200 motion-reduce:transition-none", docked ? "inset-x-4 bottom-4 max-h-[60dvh] pb-safe touch-pan-y" : "w-[min(22rem,calc(100vw-2rem))] max-h-[calc(100dvh-2rem)]", !docked && !rect && "left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2", ready ? "opacity-100" : "pointer-events-none opacity-0", className),
224
+ className: cn("fixed overflow-y-auto overscroll-contain rounded-lg border border-line bg-surface text-foreground shadow-xl focus:outline-none", "transition-opacity duration-200 motion-reduce:transition-none", docked ? "inset-x-4 bottom-4 max-h-[60dvh] pb-safe touch-pan-y" : "w-[min(22rem,calc(100vw-2rem))] max-h-[calc(100dvh-2rem)]", !docked && !rect && "left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2", ready ? "opacity-100" : "pointer-events-none opacity-0", className),
225
225
  style: anchored ? _objectSpread2(_objectSpread2({}, floatingStyles), style) : style
226
226
  }, swipeHandlers), rest), {}, {
227
227
  children: [jsxs("div", {
@@ -12,7 +12,7 @@ import { selectToolbarState, DEFAULT_TOOLBAR, RichTextToolbar } from './RichText
12
12
  var _excluded = ["id", "className", "editorClassName", "label", "error", "helperText", "required", "disabled", "readOnly", "placeholder", "value", "defaultValue", "onChange", "outputFormat", "onFocus", "onBlur", "toolbar", "toolbarLabel", "stickyToolbar", "minHeight", "maxHeight", "autoFocus", "extensions", "aria-label", "aria-describedby"];
13
13
  // Tailwind's preflight strips list bullets, heading sizes, etc. These arbitrary
14
14
  // variants restore readable defaults inside the editable area only.
15
- var CONTENT_CLASSES = cn("px-3 py-2 text-sm text-gray-900 focus:outline-none dark:text-gray-100", "[&_p]:my-1 [&_h1]:my-2 [&_h1]:text-2xl [&_h1]:font-bold [&_h2]:my-2 [&_h2]:text-xl [&_h2]:font-semibold [&_h3]:my-1.5 [&_h3]:text-lg [&_h3]:font-semibold", "[&_ul]:list-disc [&_ul]:pl-6 [&_ol]:list-decimal [&_ol]:pl-6 [&_li]:my-0.5", "[&_blockquote]:my-2 [&_blockquote]:border-l-4 [&_blockquote]:border-gray-300 [&_blockquote]:pl-3 [&_blockquote]:text-gray-600 dark:[&_blockquote]:border-gray-600 dark:[&_blockquote]:text-gray-300", "[&_code]:rounded [&_code]:bg-gray-100 [&_code]:px-1 [&_code]:font-mono [&_code]:text-[0.85em] dark:[&_code]:bg-gray-800", "[&_pre]:my-2 [&_pre]:rounded-md [&_pre]:bg-gray-100 [&_pre]:p-3 dark:[&_pre]:bg-gray-800 [&_pre_code]:bg-transparent [&_pre_code]:p-0", "[&_a]:text-primary-600 [&_a]:underline dark:[&_a]:text-primary-400 [&_hr]:my-3 [&_hr]:border-gray-200 dark:[&_hr]:border-gray-700");
15
+ var CONTENT_CLASSES = cn("px-3 py-2 text-sm text-foreground focus:outline-none", "[&_p]:my-1 [&_h1]:my-2 [&_h1]:text-2xl [&_h1]:font-bold [&_h2]:my-2 [&_h2]:text-xl [&_h2]:font-semibold [&_h3]:my-1.5 [&_h3]:text-lg [&_h3]:font-semibold", "[&_ul]:list-disc [&_ul]:pl-6 [&_ol]:list-decimal [&_ol]:pl-6 [&_li]:my-0.5", "[&_blockquote]:my-2 [&_blockquote]:border-l-4 [&_blockquote]:border-gray-300 [&_blockquote]:pl-3 [&_blockquote]:text-gray-600 dark:[&_blockquote]:border-gray-600 dark:[&_blockquote]:text-gray-300", "[&_code]:rounded [&_code]:bg-gray-100 [&_code]:px-1 [&_code]:font-mono [&_code]:text-[0.85em] dark:[&_code]:bg-gray-800", "[&_pre]:my-2 [&_pre]:rounded-md [&_pre]:bg-gray-100 [&_pre]:p-3 dark:[&_pre]:bg-gray-800 [&_pre_code]:bg-transparent [&_pre_code]:p-0", "[&_a]:text-primary-600 [&_a]:underline dark:[&_a]:text-primary-400 [&_hr]:my-3 [&_hr]:border-gray-200 dark:[&_hr]:border-gray-700");
16
16
  var toCss = function toCss(v) {
17
17
  return typeof v === "number" ? "".concat(v, "px") : v;
18
18
  };
@@ -201,7 +201,7 @@ var RichTextEditor = /*#__PURE__*/forwardRef(function (_ref, ref) {
201
201
  className: cn(
202
202
  // overflow-clip (not hidden) keeps the rounded corners without
203
203
  // creating a scroll container, so a sticky toolbar can stick to the page.
204
- stickyToolbar ? "overflow-clip" : "overflow-hidden", "rounded-md border bg-white dark:bg-gray-900", error ? "border-error-500" : "border-gray-300 dark:border-gray-600", disabled && "cursor-not-allowed opacity-50"),
204
+ stickyToolbar ? "overflow-clip" : "overflow-hidden", "rounded-md border bg-surface", error ? "border-error-500" : "border-line", disabled && "cursor-not-allowed opacity-50"),
205
205
  children: [showToolbar && jsx(RichTextToolbar, {
206
206
  editor: editor,
207
207
  state: state,
@@ -262,7 +262,7 @@ function LinkForm(_ref) {
262
262
  close();
263
263
  }
264
264
  },
265
- className: cn("h-8 min-w-0 flex-1 rounded-md border bg-white px-2 text-sm text-gray-900 placeholder-gray-400", "focus:outline-none focus:ring-2 focus:ring-primary-500 dark:bg-gray-900 dark:text-gray-100 dark:placeholder-gray-500", invalid ? "border-error-500" : "border-gray-300 dark:border-gray-600")
265
+ className: cn("h-8 min-w-0 flex-1 rounded-md border bg-surface px-2 text-sm text-foreground placeholder-gray-400", "focus:outline-none focus:ring-2 focus:ring-primary-500 dark:placeholder-gray-500", invalid ? "border-error-500" : "border-line")
266
266
  }), jsx("button", {
267
267
  type: "button",
268
268
  onClick: apply,
@@ -9,7 +9,7 @@ import { ChevronLeft, ChevronRight } from 'lucide-react';
9
9
  var _excluded = ["currentPage", "totalPages", "onPageChange", "showFirstLast", "showPrevNext", "maxVisiblePages", "className"];
10
10
  // Shared button chrome: dark-safe surface, focus-visible ring, 44px target on coarse pointers.
11
11
  var BUTTON_BASE = cn('inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-medium', 'transition-colors duration-fast motion-reduce:transition-none', 'outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-900', TOUCH_TARGET);
12
- var BUTTON_IDLE = 'border-gray-300 bg-white hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:hover:bg-gray-800';
12
+ var BUTTON_IDLE = 'border-line bg-surface text-foreground hover:bg-background dark:hover:bg-gray-800';
13
13
  var BUTTON_ACTIVE = 'border-primary-500 bg-primary-50 text-primary-600 dark:bg-primary-950 dark:text-primary-300';
14
14
  var DISABLED = 'disabled:opacity-50 disabled:cursor-not-allowed';
15
15
  var Pagination = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
@@ -3,47 +3,35 @@ import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _
3
3
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
4
4
  import { forwardRef, useId, useMemo, useState, useRef, useCallback, useLayoutEffect, useEffect } from 'react';
5
5
  import { cn } from '../../utils/cn.js';
6
- import { DEFAULT_SORTABLE_MESSAGES, useSortableKeyboard, useSortablePointer } from '../../hooks/useSortable.js';
6
+ import { setRefs } from '../../utils/position.js';
7
+ import { DEFAULT_SORTABLE_MESSAGES, useSortableKeyboard, useSortablePointer, defaultGetKey, arrayMove, defaultGetItemLabel } from '../../hooks/useSortable.js';
8
+ import { useSortableGroupMember } from '../../hooks/useSortableGroup.js';
9
+ import { SortablePlaceholder } from './SortableGroup.js';
7
10
 
8
11
  var _excluded = ["items", "onReorder", "renderItem", "getKey", "getItemLabel", "disabled", "handle", "orientation", "as", "itemClassName", "messages", "className"];
9
12
  var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
10
- var defaultGetKey = function defaultGetKey(item, index) {
11
- var _ref, _item$id;
12
- return (_ref = (_item$id = item === null || item === void 0 ? void 0 : item.id) !== null && _item$id !== void 0 ? _item$id : item === null || item === void 0 ? void 0 : item.key) !== null && _ref !== void 0 ? _ref : index;
13
- };
14
- var defaultGetItemLabel = function defaultGetItemLabel(item, index) {
15
- var _ref2, _ref3, _item$label;
16
- return typeof item === "string" || typeof item === "number" ? String(item) : (_ref2 = (_ref3 = (_item$label = item === null || item === void 0 ? void 0 : item.label) !== null && _item$label !== void 0 ? _item$label : item === null || item === void 0 ? void 0 : item.title) !== null && _ref3 !== void 0 ? _ref3 : item === null || item === void 0 ? void 0 : item.name) !== null && _ref2 !== void 0 ? _ref2 : "Item ".concat(index + 1);
17
- };
18
- function arrayMove(list, from, to) {
19
- var next = list.slice();
20
- var _next$splice = next.splice(from, 1),
21
- _next$splice2 = _slicedToArray(_next$splice, 1),
22
- moved = _next$splice2[0];
23
- next.splice(to, 0, moved);
24
- return next;
25
- }
26
- var Sortable = /*#__PURE__*/forwardRef(function (_ref4, ref) {
27
- var _ref4$items = _ref4.items,
28
- items = _ref4$items === void 0 ? [] : _ref4$items,
29
- onReorder = _ref4.onReorder,
30
- renderItem = _ref4.renderItem,
31
- _ref4$getKey = _ref4.getKey,
32
- getKey = _ref4$getKey === void 0 ? defaultGetKey : _ref4$getKey,
33
- _ref4$getItemLabel = _ref4.getItemLabel,
34
- getItemLabel = _ref4$getItemLabel === void 0 ? defaultGetItemLabel : _ref4$getItemLabel,
35
- _ref4$disabled = _ref4.disabled,
36
- disabled = _ref4$disabled === void 0 ? false : _ref4$disabled,
37
- _ref4$handle = _ref4.handle,
38
- handle = _ref4$handle === void 0 ? false : _ref4$handle,
39
- _ref4$orientation = _ref4.orientation,
40
- orientation = _ref4$orientation === void 0 ? "vertical" : _ref4$orientation,
41
- _ref4$as = _ref4.as,
42
- List = _ref4$as === void 0 ? "ul" : _ref4$as,
43
- itemClassName = _ref4.itemClassName,
44
- messages = _ref4.messages,
45
- className = _ref4.className,
46
- rest = _objectWithoutProperties(_ref4, _excluded);
13
+ var Sortable = /*#__PURE__*/forwardRef(function (_ref, ref) {
14
+ var _rest$ariaLabel;
15
+ var _ref$items = _ref.items,
16
+ items = _ref$items === void 0 ? [] : _ref$items,
17
+ onReorder = _ref.onReorder,
18
+ renderItem = _ref.renderItem,
19
+ _ref$getKey = _ref.getKey,
20
+ getKey = _ref$getKey === void 0 ? defaultGetKey : _ref$getKey,
21
+ _ref$getItemLabel = _ref.getItemLabel,
22
+ getItemLabel = _ref$getItemLabel === void 0 ? defaultGetItemLabel : _ref$getItemLabel,
23
+ _ref$disabled = _ref.disabled,
24
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
25
+ _ref$handle = _ref.handle,
26
+ handle = _ref$handle === void 0 ? false : _ref$handle,
27
+ _ref$orientation = _ref.orientation,
28
+ orientation = _ref$orientation === void 0 ? "vertical" : _ref$orientation,
29
+ _ref$as = _ref.as,
30
+ List = _ref$as === void 0 ? "ul" : _ref$as,
31
+ itemClassName = _ref.itemClassName,
32
+ messages = _ref.messages,
33
+ className = _ref.className,
34
+ rest = _objectWithoutProperties(_ref, _excluded);
47
35
  var instructionsId = "sortable-instructions-".concat(useId());
48
36
  var text = useMemo(function () {
49
37
  return _objectSpread2(_objectSpread2({}, DEFAULT_SORTABLE_MESSAGES), messages);
@@ -58,6 +46,10 @@ var Sortable = /*#__PURE__*/forwardRef(function (_ref4, ref) {
58
46
  announcement = _useState4[0],
59
47
  setAnnouncement = _useState4[1];
60
48
  var nodes = useRef(new Map());
49
+ var listRef = useRef(null);
50
+ var setListRef = useCallback(function (node) {
51
+ return setRefs(node, listRef, ref);
52
+ }, [ref]);
61
53
  var itemKeys = items.map(function (item, i) {
62
54
  return getKey(item, i);
63
55
  });
@@ -91,13 +83,32 @@ var Sortable = /*#__PURE__*/forwardRef(function (_ref4, ref) {
91
83
  var nodeFor = useCallback(function (key) {
92
84
  return nodes.current.get(key);
93
85
  }, []);
86
+ // Inside a <SortableGroup>, `id` names this list; `cross` handles moves to other lists.
87
+ var _useSortableGroupMemb = useSortableGroupMember({
88
+ listId: rest.id,
89
+ label: (_rest$ariaLabel = rest["aria-label"]) !== null && _rest$ariaLabel !== void 0 ? _rest$ariaLabel : String(rest.id),
90
+ items: items,
91
+ itemKeys: itemKeys,
92
+ keys: keys,
93
+ getKey: getKey,
94
+ nodeFor: nodeFor,
95
+ listRef: listRef,
96
+ orientation: axis,
97
+ setDraft: setDraft,
98
+ announce: announce,
99
+ labelFor: labelFor
100
+ }),
101
+ cross = _useSortableGroupMemb.cross,
102
+ incoming = _useSortableGroupMemb.incoming,
103
+ outgoing = _useSortableGroupMemb.outgoing;
94
104
  var keyboard = useSortableKeyboard({
95
105
  keys: keys,
96
106
  setDraft: setDraft,
97
107
  commit: commit,
98
108
  announce: announce,
99
109
  labelFor: labelFor,
100
- orientation: axis
110
+ orientation: axis,
111
+ cross: cross
101
112
  });
102
113
  var pointer = useSortablePointer({
103
114
  keys: keys,
@@ -105,7 +116,8 @@ var Sortable = /*#__PURE__*/forwardRef(function (_ref4, ref) {
105
116
  commit: commit,
106
117
  nodeFor: nodeFor,
107
118
  orientation: axis,
108
- disabled: disabled
119
+ disabled: disabled,
120
+ cross: cross
109
121
  });
110
122
  // Moving DOM nodes can drop focus; keep it on the item being carried.
111
123
  useIsomorphicLayoutEffect(function () {
@@ -124,24 +136,30 @@ var Sortable = /*#__PURE__*/forwardRef(function (_ref4, ref) {
124
136
  var isNativeList = List === "ul" || List === "ol";
125
137
  var ItemTag = isNativeList ? "li" : "div";
126
138
  return jsxs(Fragment, {
127
- children: [jsx(List, _objectSpread2(_objectSpread2({
128
- ref: ref,
139
+ children: [jsxs(List, _objectSpread2(_objectSpread2({
140
+ ref: setListRef,
129
141
  className: cn("flex", axis === "horizontal" ? "flex-row gap-2" : "flex-col gap-2", className),
130
142
  "data-orientation": axis,
143
+ "data-drop-target": incoming ? incoming.allowed ? "allowed" : "refused" : undefined,
131
144
  role: isNativeList ? undefined : "list"
132
145
  }, rest), {}, {
133
- children: keys.map(function (key, index) {
146
+ children: [keys.flatMap(function (key, index) {
134
147
  var _byKey$get = byKey.get(key),
135
148
  item = _byKey$get.item,
136
149
  originalIndex = _byKey$get.index;
137
150
  var isGrabbed = keyboard.grabbed === key;
138
151
  var isDragging = pointer.dragging === key;
152
+ var isLeaving = outgoing !== null && (isGrabbed || isDragging);
139
153
  var startDrag = disabled ? undefined : pointer.startFor(key);
140
154
  // Whole-item drags wait for a long-press on touch so the page still scrolls.
141
155
  var startItemDrag = disabled || handle ? undefined : pointer.startFor(key, {
142
156
  longPress: true
143
157
  });
144
- return jsx(ItemTag, {
158
+ var placeholder = (incoming === null || incoming === void 0 ? void 0 : incoming.index) === index ? [jsx(SortablePlaceholder, {
159
+ as: ItemTag,
160
+ allowed: incoming.allowed
161
+ }, "dt-sortable-placeholder")] : [];
162
+ return placeholder.concat(jsx(ItemTag, {
145
163
  ref: function ref(node) {
146
164
  if (node) nodes.current.set(key, node);else nodes.current["delete"](key);
147
165
  },
@@ -151,12 +169,13 @@ var Sortable = /*#__PURE__*/forwardRef(function (_ref4, ref) {
151
169
  role: isNativeList ? undefined : "listitem",
152
170
  "data-dragging": isDragging || undefined,
153
171
  "data-grabbed": isGrabbed || undefined,
172
+ "data-leaving": isLeaving ? outgoing.allowed ? "allowed" : "refused" : undefined,
154
173
  onKeyDown: disabled ? undefined : keyboard.keyDownFor(key),
155
174
  onBlur: function onBlur(e) {
156
175
  if (isGrabbed && e.relatedTarget && !e.currentTarget.contains(e.relatedTarget)) keyboard.cancel();
157
176
  },
158
177
  onPointerDown: startItemDrag,
159
- className: cn("rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 dark:focus:ring-offset-gray-900", !disabled && !handle && "cursor-grab select-none [-webkit-touch-callout:none]", (isGrabbed || isDragging) && "relative z-10 shadow-lg ring-2 ring-primary-500 opacity-90", itemClassName),
178
+ className: cn("rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 dark:focus:ring-offset-gray-900", !disabled && !handle && "cursor-grab select-none [-webkit-touch-callout:none]", (isGrabbed || isDragging) && "relative z-10 shadow-lg ring-2 ring-primary-500 opacity-90", isLeaving && (outgoing.allowed ? "opacity-50" : "cursor-not-allowed ring-error-500 opacity-50"), itemClassName),
160
179
  children: renderItem ? renderItem(item, {
161
180
  index: index,
162
181
  originalIndex: originalIndex,
@@ -174,12 +193,15 @@ var Sortable = /*#__PURE__*/forwardRef(function (_ref4, ref) {
174
193
  return moveBy(originalIndex, 1);
175
194
  }
176
195
  }) : labelFor(key)
177
- }, key);
178
- })
196
+ }, key));
197
+ }), incoming && incoming.index >= keys.length && jsx(SortablePlaceholder, {
198
+ as: ItemTag,
199
+ allowed: incoming.allowed
200
+ })]
179
201
  })), jsx("span", {
180
202
  id: instructionsId,
181
203
  className: "sr-only",
182
- children: text.instructions
204
+ children: cross ? "".concat(text.instructions, " ").concat(text.groupInstructions) : text.instructions
183
205
  }), jsx("span", {
184
206
  role: "status",
185
207
  "aria-live": "assertive",
@@ -0,0 +1,48 @@
1
+ 'use client';
2
+ import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import { forwardRef } from 'react';
5
+ import { cn } from '../../utils/cn.js';
6
+ import { useSortableGroupState, SortableGroupContext } from '../../hooks/useSortableGroup.js';
7
+
8
+ var _excluded = ["onMove", "canDrop", "className", "children"];
9
+ /**
10
+ * Connects several `<Sortable id="…">` lists so items can move between them
11
+ * (pointer drag, or the cross-axis arrow keys while an item is picked up).
12
+ * `canDrop(item, target, from)` is asked before a target is shown as droppable;
13
+ * a refused target is marked as such and dropping there does nothing.
14
+ */
15
+ var SortableGroup = /*#__PURE__*/forwardRef(function (_ref, ref) {
16
+ var onMove = _ref.onMove,
17
+ canDrop = _ref.canDrop,
18
+ className = _ref.className,
19
+ children = _ref.children,
20
+ rest = _objectWithoutProperties(_ref, _excluded);
21
+ var value = useSortableGroupState({
22
+ onMove: onMove,
23
+ canDrop: canDrop
24
+ });
25
+ return jsx(SortableGroupContext.Provider, {
26
+ value: value,
27
+ children: jsx("div", _objectSpread2(_objectSpread2({
28
+ ref: ref,
29
+ className: cn(className),
30
+ "data-sortable-group": ""
31
+ }, rest), {}, {
32
+ children: children
33
+ }))
34
+ });
35
+ });
36
+ SortableGroup.displayName = "SortableGroup";
37
+ /** Where an item from another list would land; styled by whether `canDrop` allows it. */
38
+ function SortablePlaceholder(_ref2) {
39
+ var Tag = _ref2.as,
40
+ allowed = _ref2.allowed;
41
+ return jsx(Tag, {
42
+ "aria-hidden": "true",
43
+ "data-sortable-placeholder": allowed ? "allowed" : "refused",
44
+ className: cn("min-h-10 rounded-md border-2 border-dashed", allowed ? "border-primary-500 bg-primary-50 dark:bg-primary-950/40" : "cursor-not-allowed border-error-500 bg-error-50 opacity-60 dark:bg-error-950/40")
45
+ });
46
+ }
47
+
48
+ export { SortablePlaceholder, SortableGroup as default };