@dreamtree-org/twreact-ui 2.0.4 → 2.0.5

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 (43) hide show
  1. package/README.md +11 -3
  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 +297 -12
  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/navigation/Sidebar.d.ts.map +1 -1
  15. package/dist/components/utility/Sortable.d.ts.map +1 -1
  16. package/dist/components/utility/SortableGroup.d.ts +15 -0
  17. package/dist/components/utility/SortableGroup.d.ts.map +1 -0
  18. package/dist/esm/charts/index.js +1 -0
  19. package/dist/esm/components/charts/ChartFrame.js +5 -5
  20. package/dist/esm/components/charts/ScatterChart.js +204 -0
  21. package/dist/esm/components/charts/ScatterTooltip.js +61 -0
  22. package/dist/esm/components/charts/scatterData.js +43 -0
  23. package/dist/esm/components/utility/Sortable.js +70 -48
  24. package/dist/esm/components/utility/SortableGroup.js +48 -0
  25. package/dist/esm/hooks/useSortable.js +96 -30
  26. package/dist/esm/hooks/useSortableGroup.js +268 -0
  27. package/dist/esm/index.js +1 -0
  28. package/dist/hooks/useSortable.d.ts +12 -3
  29. package/dist/hooks/useSortable.d.ts.map +1 -1
  30. package/dist/hooks/useSortableGroup.d.ts +43 -0
  31. package/dist/hooks/useSortableGroup.d.ts.map +1 -0
  32. package/dist/index.css +1 -1
  33. package/dist/index.d.ts +2 -1
  34. package/dist/index.esm.css +1 -1
  35. package/dist/index.esm.js +865 -474
  36. package/dist/index.js +865 -473
  37. package/dist/types/charts.d.ts +28 -0
  38. package/dist/types/charts.d.ts.map +1 -1
  39. package/dist/types/index.d.ts +33 -0
  40. package/dist/types/index.d.ts.map +1 -1
  41. package/doc/README.md +2 -0
  42. package/mcp/catalog.snapshot.json +224 -4
  43. package/package.json +1 -1
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tooltip for one ScatterChart point: the entity (`index`) or series name as the
3
+ * heading, then the series (when both are set) and the formatted x and y values.
4
+ */
5
+ export default function ScatterTooltipContent({ active, payload, index, category, colorFor, x, y }: {
6
+ active: any;
7
+ payload: any;
8
+ index: any;
9
+ category: any;
10
+ colorFor?: {} | undefined;
11
+ x: any;
12
+ y: any;
13
+ }): import("react/jsx-runtime").JSX.Element | null;
14
+ //# sourceMappingURL=ScatterTooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScatterTooltip.d.ts","sourceRoot":"","sources":["../../../src/components/charts/ScatterTooltip.jsx"],"names":[],"mappings":"AAIA;;;GAGG;AACH;;;;;;;;mDA4BC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Axis domain. recharts draws a zero-width scale for a single distinct value, so
3
+ * pad around it; otherwise let recharts pick nice bounds.
4
+ */
5
+ export function scatterDomain(values: any): string[] | number[];
6
+ /** Rows with a numeric x and y, split into series by the `category` key (first-seen order). */
7
+ export function groupScatter(data: any, { x, y, category }: {
8
+ x: any;
9
+ y: any;
10
+ category: any;
11
+ }): {
12
+ rows: any[];
13
+ names: any[];
14
+ groups: Map<any, any>;
15
+ };
16
+ export function textOf(v: any): string;
17
+ //# sourceMappingURL=scatterData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scatterData.d.ts","sourceRoot":"","sources":["../../../src/components/charts/scatterData.js"],"names":[],"mappings":"AAKA;;;GAGG;AACH,gEAOC;AAED,+FAA+F;AAC/F;;;;;;;;EASC;AAzBM,uCAAkD"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/Sidebar.jsx"],"names":[],"mappings":"AAqBA,oCAAqC,oBAAoB,CAAC;;AAoJ1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,iFAglBG;kBA1wBI,OAAO"}
1
+ {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/Sidebar.jsx"],"names":[],"mappings":"AAoBA,oCAAqC,oBAAoB,CAAC;;AAoJ1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,iFAglBG;kBAzwBI,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sortable.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Sortable.jsx"],"names":[],"mappings":";AAqBA,kFAsHG;kBA3I0G,OAAO"}
1
+ {"version":3,"file":"Sortable.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Sortable.jsx"],"names":[],"mappings":";AASA,kFAmIG;kBA5I0G,OAAO"}
@@ -0,0 +1,15 @@
1
+ /** Where an item from another list would land; styled by whether `canDrop` allows it. */
2
+ export function SortablePlaceholder({ as: Tag, allowed }: {
3
+ as: any;
4
+ allowed: any;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ export default SortableGroup;
7
+ /**
8
+ * Connects several `<Sortable id="…">` lists so items can move between them
9
+ * (pointer drag, or the cross-axis arrow keys while an item is picked up).
10
+ * `canDrop(item, target, from)` is asked before a target is shown as droppable;
11
+ * a refused target is marked as such and dropping there does nothing.
12
+ */
13
+ declare const SortableGroup: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
14
+ import React from "react";
15
+ //# sourceMappingURL=SortableGroup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SortableGroup.d.ts","sourceRoot":"","sources":["../../../src/components/utility/SortableGroup.jsx"],"names":[],"mappings":"AAuBA,yFAAyF;AACzF;;;4CAaC;;AAjCD;;;;;GAKG;AACH,uFASG;kBAnB+B,OAAO"}
@@ -3,3 +3,4 @@ export { default as BarChart } from '../components/charts/BarChart.js';
3
3
  export { default as AreaChart } from '../components/charts/AreaChart.js';
4
4
  export { default as DonutChart } from '../components/charts/DonutChart.js';
5
5
  export { default as Sparkline } from '../components/charts/Sparkline.js';
6
+ export { default as ScatterChart } from '../components/charts/ScatterChart.js';
@@ -90,11 +90,11 @@ function ChartDataTable(_ref3) {
90
90
  children: caption
91
91
  }), jsx("thead", {
92
92
  children: jsx("tr", {
93
- children: columns.map(function (c) {
93
+ children: columns.map(function (c, i) {
94
94
  return jsx("th", {
95
95
  scope: "col",
96
96
  children: c.label
97
- }, c.key);
97
+ }, "".concat(c.key, "-").concat(i));
98
98
  })
99
99
  })
100
100
  }), jsx("tbody", {
@@ -104,9 +104,9 @@ function ChartDataTable(_ref3) {
104
104
  return i === 0 ? jsx("th", {
105
105
  scope: "row",
106
106
  children: c.format(row[c.key])
107
- }, c.key) : jsx("td", {
107
+ }, "".concat(c.key, "-").concat(i)) : jsx("td", {
108
108
  children: c.format(row[c.key])
109
- }, c.key);
109
+ }, "".concat(c.key, "-").concat(i));
110
110
  })
111
111
  }, r);
112
112
  })
@@ -174,4 +174,4 @@ var ChartFrame = /*#__PURE__*/React.forwardRef(function ChartFrame(_ref4, ref) {
174
174
  }));
175
175
  });
176
176
 
177
- export { ChartFrame, ChartLegend, ChartTooltipContent };
177
+ export { ChartFrame, ChartLegend, ChartTooltipContent, swatch };
@@ -0,0 +1,204 @@
1
+ 'use client';
2
+ import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2, toConsumableArray as _toConsumableArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import React from 'react';
5
+ import { ResponsiveContainer, ScatterChart as ScatterChart$1, CartesianGrid, XAxis, YAxis, Tooltip, Scatter } from 'recharts';
6
+ import { ChartFrame } from './ChartFrame.js';
7
+ import ScatterTooltipContent from './ScatterTooltip.js';
8
+ import { useChartTheme, useChartId, defaultValueFormatter } from './chartTheme.js';
9
+ import { useElementWidth, tickGapFor, yAxisWidthFor } from './useChartLayout.js';
10
+ import { groupScatter, scatterDomain, textOf } from './scatterData.js';
11
+ import { useReducedMotion } from '../../hooks/useReducedMotion.js';
12
+
13
+ var _excluded = ["data", "x", "y", "index", "category", "colors", "valueFormatter", "xAxisFormatter", "xAxisLabel", "yAxisLabel", "height", "aspectRatio", "showLegend", "showTooltip", "showXAxis", "showYAxis", "showGrid", "yAxisWidth", "animate", "title", "description", "emptyState", "accessibleTable", "className"];
14
+ var ScatterChart = /*#__PURE__*/React.forwardRef(function ScatterChart(_ref, ref) {
15
+ var data = _ref.data,
16
+ x = _ref.x,
17
+ y = _ref.y,
18
+ index = _ref.index,
19
+ category = _ref.category,
20
+ colors = _ref.colors,
21
+ _ref$valueFormatter = _ref.valueFormatter,
22
+ valueFormatter = _ref$valueFormatter === void 0 ? defaultValueFormatter : _ref$valueFormatter,
23
+ _ref$xAxisFormatter = _ref.xAxisFormatter,
24
+ xAxisFormatter = _ref$xAxisFormatter === void 0 ? defaultValueFormatter : _ref$xAxisFormatter,
25
+ xAxisLabel = _ref.xAxisLabel,
26
+ yAxisLabel = _ref.yAxisLabel,
27
+ _ref$height = _ref.height,
28
+ height = _ref$height === void 0 ? 300 : _ref$height,
29
+ aspectRatio = _ref.aspectRatio,
30
+ _ref$showLegend = _ref.showLegend,
31
+ showLegend = _ref$showLegend === void 0 ? true : _ref$showLegend,
32
+ _ref$showTooltip = _ref.showTooltip,
33
+ showTooltip = _ref$showTooltip === void 0 ? true : _ref$showTooltip,
34
+ _ref$showXAxis = _ref.showXAxis,
35
+ showXAxis = _ref$showXAxis === void 0 ? true : _ref$showXAxis,
36
+ _ref$showYAxis = _ref.showYAxis,
37
+ showYAxis = _ref$showYAxis === void 0 ? true : _ref$showYAxis,
38
+ _ref$showGrid = _ref.showGrid,
39
+ showGrid = _ref$showGrid === void 0 ? true : _ref$showGrid,
40
+ yAxisWidth = _ref.yAxisWidth,
41
+ _ref$animate = _ref.animate,
42
+ animate = _ref$animate === void 0 ? true : _ref$animate,
43
+ title = _ref.title,
44
+ description = _ref.description,
45
+ emptyState = _ref.emptyState,
46
+ _ref$accessibleTable = _ref.accessibleTable,
47
+ accessibleTable = _ref$accessibleTable === void 0 ? true : _ref$accessibleTable,
48
+ className = _ref.className,
49
+ rest = _objectWithoutProperties(_ref, _excluded);
50
+ var _groupScatter = groupScatter(data, {
51
+ x: x,
52
+ y: y,
53
+ category: category
54
+ }),
55
+ rows = _groupScatter.rows,
56
+ names = _groupScatter.names,
57
+ groups = _groupScatter.groups;
58
+ var _useChartTheme = useChartTheme(names, colors),
59
+ chrome = _useChartTheme.chrome,
60
+ series = _useChartTheme.series;
61
+ var reducedMotion = useReducedMotion();
62
+ var chartId = useChartId();
63
+ var _useElementWidth = useElementWidth(),
64
+ _useElementWidth2 = _slicedToArray(_useElementWidth, 2),
65
+ measureRef = _useElementWidth2[0],
66
+ width = _useElementWidth2[1];
67
+ var tick = {
68
+ fill: chrome.axis,
69
+ fontSize: 12
70
+ };
71
+ var axisTitle = function axisTitle(value, angle) {
72
+ return value ? {
73
+ value: value,
74
+ angle: angle,
75
+ position: angle ? "insideLeft" : "insideBottom",
76
+ offset: angle ? 10 : -4,
77
+ fill: chrome.axis,
78
+ fontSize: 12
79
+ } : undefined;
80
+ };
81
+ var xLabel = xAxisLabel || x;
82
+ var yLabel = yAxisLabel || y;
83
+ return jsx(ChartFrame, _objectSpread2(_objectSpread2({
84
+ ref: ref,
85
+ className: className,
86
+ title: title,
87
+ description: description,
88
+ defaultTitle: "Scatter chart",
89
+ data: rows,
90
+ height: height,
91
+ aspectRatio: aspectRatio,
92
+ emptyState: emptyState,
93
+ accessibleTable: accessibleTable,
94
+ legend: showLegend && category ? names.map(function (name, i) {
95
+ return {
96
+ name: name,
97
+ color: series[i]
98
+ };
99
+ }) : null,
100
+ tableColumns: [].concat(_toConsumableArray(index ? [{
101
+ key: index,
102
+ label: index,
103
+ format: textOf
104
+ }] : []), _toConsumableArray(category && category !== index ? [{
105
+ key: category,
106
+ label: category,
107
+ format: textOf
108
+ }] : []), [{
109
+ key: x,
110
+ label: xLabel,
111
+ format: xAxisFormatter
112
+ }, {
113
+ key: y,
114
+ label: yLabel,
115
+ format: valueFormatter
116
+ }])
117
+ }, rest), {}, {
118
+ children: jsx("div", {
119
+ className: "h-full w-full",
120
+ ref: measureRef,
121
+ children: jsx(ResponsiveContainer, {
122
+ width: "100%",
123
+ height: "100%",
124
+ minWidth: 0,
125
+ children: jsxs(ScatterChart$1, {
126
+ id: chartId,
127
+ margin: {
128
+ top: 8,
129
+ right: 8,
130
+ bottom: xAxisLabel ? 16 : 0,
131
+ left: 0
132
+ },
133
+ accessibilityLayer: false,
134
+ children: [showGrid && jsx(CartesianGrid, {
135
+ stroke: chrome.grid,
136
+ strokeDasharray: "3 3"
137
+ }), jsx(XAxis, {
138
+ type: "number",
139
+ dataKey: x,
140
+ name: xLabel,
141
+ domain: scatterDomain(rows.map(function (row) {
142
+ return row[x];
143
+ })),
144
+ tick: tick,
145
+ tickLine: false,
146
+ axisLine: false,
147
+ tickFormatter: xAxisFormatter,
148
+ minTickGap: tickGapFor(width),
149
+ hide: !showXAxis,
150
+ label: axisTitle(xAxisLabel, 0)
151
+ }), jsx(YAxis, {
152
+ type: "number",
153
+ dataKey: y,
154
+ name: yLabel,
155
+ domain: scatterDomain(rows.map(function (row) {
156
+ return row[y];
157
+ })),
158
+ tick: tick,
159
+ tickLine: false,
160
+ axisLine: false,
161
+ tickFormatter: valueFormatter,
162
+ width: yAxisWidth !== null && yAxisWidth !== void 0 ? yAxisWidth : yAxisWidthFor(width),
163
+ hide: !showYAxis,
164
+ label: axisTitle(yAxisLabel, -90)
165
+ }), showTooltip && jsx(Tooltip, {
166
+ cursor: {
167
+ stroke: chrome.grid,
168
+ strokeDasharray: "3 3"
169
+ },
170
+ isAnimationActive: false,
171
+ content: jsx(ScatterTooltipContent, {
172
+ index: index,
173
+ category: category,
174
+ colorFor: Object.fromEntries(names.map(function (name, i) {
175
+ return [name, series[i]];
176
+ })),
177
+ x: {
178
+ key: x,
179
+ label: xLabel,
180
+ format: xAxisFormatter
181
+ },
182
+ y: {
183
+ key: y,
184
+ label: yLabel,
185
+ format: valueFormatter
186
+ }
187
+ })
188
+ }), names.map(function (name, i) {
189
+ return jsx(Scatter, {
190
+ id: "".concat(chartId, "-").concat(i),
191
+ name: name,
192
+ data: groups.get(name),
193
+ fill: series[i],
194
+ isAnimationActive: animate && !reducedMotion
195
+ }, name);
196
+ })]
197
+ })
198
+ })
199
+ })
200
+ }));
201
+ });
202
+ ScatterChart.displayName = "ScatterChart";
203
+
204
+ export { ScatterChart as default };
@@ -0,0 +1,61 @@
1
+ 'use client';
2
+ import { toConsumableArray as _toConsumableArray, slicedToArray as _slicedToArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import 'react';
5
+ import { swatch } from './ChartFrame.js';
6
+ import { textOf } from './scatterData.js';
7
+
8
+ /**
9
+ * Tooltip for one ScatterChart point: the entity (`index`) or series name as the
10
+ * heading, then the series (when both are set) and the formatted x and y values.
11
+ */
12
+ function ScatterTooltipContent(_ref) {
13
+ var active = _ref.active,
14
+ payload = _ref.payload,
15
+ index = _ref.index,
16
+ category = _ref.category,
17
+ _ref$colorFor = _ref.colorFor,
18
+ colorFor = _ref$colorFor === void 0 ? {} : _ref$colorFor,
19
+ x = _ref.x,
20
+ y = _ref.y;
21
+ var row = active && payload && payload.length ? payload[0].payload : null;
22
+ if (!row) return null;
23
+ var seriesName = category ? textOf(row[category]) : null;
24
+ var heading = index ? textOf(row[index]) : seriesName;
25
+ var lines = [].concat(_toConsumableArray(index && seriesName ? [[category, seriesName]] : []), [[x.label, x.format(row[x.key])], [y.label, y.format(row[y.key])]]);
26
+ return jsxs("div", {
27
+ className: "rounded-md border border-line bg-surface px-3 py-2 text-xs text-foreground shadow-md",
28
+ "data-chart-tooltip": "",
29
+ children: [heading && jsxs("p", {
30
+ className: "mb-1 flex items-center gap-2 font-medium",
31
+ children: [seriesName && jsx("span", {
32
+ className: swatch("h-2 w-2"),
33
+ style: {
34
+ "--dt-chart-color": colorFor[seriesName]
35
+ },
36
+ "aria-hidden": "true"
37
+ }), jsx("span", {
38
+ children: heading
39
+ })]
40
+ }), jsx("ul", {
41
+ className: "space-y-0.5",
42
+ children: lines.map(function (_ref2) {
43
+ var _ref3 = _slicedToArray(_ref2, 2),
44
+ name = _ref3[0],
45
+ value = _ref3[1];
46
+ return jsxs("li", {
47
+ className: "flex items-center gap-2",
48
+ children: [jsx("span", {
49
+ className: "text-muted",
50
+ children: name
51
+ }), jsx("span", {
52
+ className: "ml-auto pl-3 font-medium tabular-nums",
53
+ children: value
54
+ })]
55
+ }, name);
56
+ })
57
+ })]
58
+ });
59
+ }
60
+
61
+ export { ScatterTooltipContent as default };
@@ -0,0 +1,43 @@
1
+ import { toConsumableArray as _toConsumableArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
2
+
3
+ // Internal to the charts entry point: data shaping for ScatterChart.
4
+ var isFiniteNumber = function isFiniteNumber(v) {
5
+ return typeof v === "number" && Number.isFinite(v);
6
+ };
7
+ var textOf = function textOf(v) {
8
+ return v == null ? "" : String(v);
9
+ };
10
+ /**
11
+ * Axis domain. recharts draws a zero-width scale for a single distinct value, so
12
+ * pad around it; otherwise let recharts pick nice bounds.
13
+ */
14
+ function scatterDomain(values) {
15
+ if (!values.length) return ["auto", "auto"];
16
+ var min = Math.min.apply(Math, _toConsumableArray(values));
17
+ var max = Math.max.apply(Math, _toConsumableArray(values));
18
+ if (min !== max) return ["auto", "auto"];
19
+ var pad = Math.abs(min) / 2 || 1;
20
+ return [min - pad, max + pad];
21
+ }
22
+ /** Rows with a numeric x and y, split into series by the `category` key (first-seen order). */
23
+ function groupScatter(data, _ref) {
24
+ var x = _ref.x,
25
+ y = _ref.y,
26
+ category = _ref.category;
27
+ var rows = (Array.isArray(data) ? data : []).filter(function (row) {
28
+ return isFiniteNumber(row === null || row === void 0 ? void 0 : row[x]) && isFiniteNumber(row === null || row === void 0 ? void 0 : row[y]);
29
+ });
30
+ var groups = new Map();
31
+ rows.forEach(function (row) {
32
+ var name = category ? textOf(row[category]) : y;
33
+ if (!groups.has(name)) groups.set(name, []);
34
+ groups.get(name).push(row);
35
+ });
36
+ return {
37
+ rows: rows,
38
+ names: _toConsumableArray(groups.keys()),
39
+ groups: groups
40
+ };
41
+ }
42
+
43
+ export { groupScatter, scatterDomain, textOf };
@@ -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 };