@dreamtree-org/twreact-ui 1.3.9 → 1.3.11
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.
- package/README.md +32 -0
- package/ai-skills/dreamtree-ui.md +12 -7
- package/dist/ai-schema.json +156 -29
- package/dist/charts/index.js +195 -66
- package/dist/components/blocks/AppShell.d.ts.map +1 -1
- package/dist/components/charts/CartesianChart.d.ts.map +1 -1
- package/dist/components/charts/ChartFrame.d.ts.map +1 -1
- package/dist/components/charts/useChartLayout.d.ts +25 -0
- package/dist/components/charts/useChartLayout.d.ts.map +1 -0
- package/dist/components/core/Accordion.d.ts.map +1 -1
- package/dist/components/core/Button.d.ts.map +1 -1
- package/dist/components/core/Checkbox.d.ts.map +1 -1
- package/dist/components/core/ColorPicker.d.ts.map +1 -1
- package/dist/components/core/DatePicker.d.ts.map +1 -1
- package/dist/components/core/Form.d.ts.map +1 -1
- package/dist/components/core/Input.d.ts.map +1 -1
- package/dist/components/core/Loader.d.ts.map +1 -1
- package/dist/components/core/LocationPicker.d.ts.map +1 -1
- package/dist/components/core/PriceRangePicker.d.ts +0 -29
- package/dist/components/core/PriceRangePicker.d.ts.map +1 -1
- package/dist/components/core/ProgressBar.d.ts.map +1 -1
- package/dist/components/core/Radio.d.ts.map +1 -1
- package/dist/components/core/Rate.d.ts.map +1 -1
- package/dist/components/core/RoundedTag.d.ts.map +1 -1
- package/dist/components/core/Skeleton.d.ts.map +1 -1
- package/dist/components/core/Slider.d.ts.map +1 -1
- package/dist/components/core/SpeechToText.d.ts.map +1 -1
- package/dist/components/core/Switch.d.ts.map +1 -1
- package/dist/components/core/Table/ColumnMenu.d.ts.map +1 -1
- package/dist/components/core/Table/Pagination.d.ts.map +1 -1
- package/dist/components/core/Table/TableRow.d.ts.map +1 -1
- package/dist/components/core/Table/helpers.d.ts +2 -0
- package/dist/components/core/Table/helpers.d.ts.map +1 -1
- package/dist/components/core/Tabs.d.ts +2 -5
- package/dist/components/core/Tabs.d.ts.map +1 -1
- package/dist/components/core/TextToSpeech.d.ts +2 -7
- package/dist/components/core/TextToSpeech.d.ts.map +1 -1
- package/dist/components/core/Textarea.d.ts.map +1 -1
- package/dist/components/core/Tooltip.d.ts.map +1 -1
- package/dist/components/feedback/Alert.d.ts.map +1 -1
- package/dist/components/feedback/Dialog.d.ts.map +1 -1
- package/dist/components/feedback/Toast.d.ts.map +1 -1
- package/dist/components/navigation/Breadcrumbs.d.ts.map +1 -1
- package/dist/components/navigation/FootNav.d.ts.map +1 -1
- package/dist/components/navigation/Sidebar.d.ts.map +1 -1
- package/dist/components/utility/Avatar.d.ts +8 -0
- package/dist/components/utility/Avatar.d.ts.map +1 -1
- package/dist/components/utility/AvatarGroup.d.ts +4 -0
- package/dist/components/utility/AvatarGroup.d.ts.map +1 -0
- package/dist/components/utility/Badge.d.ts.map +1 -1
- package/dist/components/utility/Card.d.ts.map +1 -1
- package/dist/components/utility/Carousel.d.ts.map +1 -1
- package/dist/components/utility/FileUpload.d.ts.map +1 -1
- package/dist/components/utility/Pagination.d.ts.map +1 -1
- package/dist/components/utility/Sortable.d.ts.map +1 -1
- package/dist/components/utility/Stepper.d.ts.map +1 -1
- package/dist/esm/components/blocks/AppShell.js +24 -18
- package/dist/esm/components/blocks/EmptyState.js +1 -1
- package/dist/esm/components/blocks/ErrorState.js +1 -1
- package/dist/esm/components/blocks/LoadingState.js +4 -4
- package/dist/esm/components/blocks/StatCard.js +6 -6
- package/dist/esm/components/blocks/StatusPill.js +5 -8
- package/dist/esm/components/charts/CartesianChart.js +85 -62
- package/dist/esm/components/charts/ChartFrame.js +12 -5
- package/dist/esm/components/charts/useChartLayout.js +105 -0
- package/dist/esm/components/core/Accordion.js +40 -9
- package/dist/esm/components/core/Button.js +49 -25
- package/dist/esm/components/core/Checkbox.js +71 -45
- package/dist/esm/components/core/ColorPicker.js +49 -48
- package/dist/esm/components/core/DatePicker.js +97 -58
- package/dist/esm/components/core/Form.js +35 -8
- package/dist/esm/components/core/Input.js +89 -20
- package/dist/esm/components/core/Loader.js +30 -44
- package/dist/esm/components/core/LocationPicker.js +82 -16
- package/dist/esm/components/core/PriceRangePicker.js +205 -218
- package/dist/esm/components/core/ProgressBar.js +8 -12
- package/dist/esm/components/core/Radio.js +43 -15
- package/dist/esm/components/core/Rate.js +109 -50
- package/dist/esm/components/core/RoundedTag.js +27 -10
- package/dist/esm/components/core/Skeleton.js +13 -14
- package/dist/esm/components/core/Slider.js +24 -6
- package/dist/esm/components/core/SpeechToText.js +68 -16
- package/dist/esm/components/core/Switch.js +88 -16
- package/dist/esm/components/core/Table/ColumnMenu.js +2 -4
- package/dist/esm/components/core/Table/Pagination.js +15 -18
- package/dist/esm/components/core/Table/TableRow.js +2 -2
- package/dist/esm/components/core/Table/helpers.js +33 -1
- package/dist/esm/components/core/Tabs.js +185 -37
- package/dist/esm/components/core/TextToSpeech.js +121 -28
- package/dist/esm/components/core/Textarea.js +10 -2
- package/dist/esm/components/core/Tooltip.js +100 -28
- package/dist/esm/components/feedback/Alert.js +21 -11
- package/dist/esm/components/feedback/Dialog.js +44 -100
- package/dist/esm/components/feedback/Toast.js +24 -5
- package/dist/esm/components/navigation/Breadcrumbs.js +97 -35
- package/dist/esm/components/navigation/FootNav.js +102 -13
- package/dist/esm/components/navigation/Sidebar.js +13 -61
- package/dist/esm/components/utility/Avatar.js +37 -22
- package/dist/esm/components/utility/AvatarGroup.js +56 -0
- package/dist/esm/components/utility/Badge.js +43 -23
- package/dist/esm/components/utility/Card.js +32 -8
- package/dist/esm/components/utility/Carousel.js +165 -38
- package/dist/esm/components/utility/FileUpload.js +106 -31
- package/dist/esm/components/utility/Pagination.js +33 -15
- package/dist/esm/components/utility/Sortable.js +6 -2
- package/dist/esm/components/utility/Stepper.js +110 -47
- package/dist/esm/hooks/useFocusTrap.js +10 -2
- package/dist/esm/hooks/useSliderValues.js +8 -2
- package/dist/esm/hooks/useSortable.js +107 -5
- package/dist/esm/index.js +1 -0
- package/dist/esm/utils/touchTarget.js +4 -1
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useSliderValues.d.ts +6 -2
- package/dist/hooks/useSliderValues.d.ts.map +1 -1
- package/dist/hooks/useSortable.d.ts +11 -1
- package/dist/hooks/useSortable.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +3734 -2174
- package/dist/index.js +3732 -2171
- package/dist/types/charts.d.ts +3 -1
- package/dist/types/charts.d.ts.map +1 -1
- package/dist/types/index.d.ts +64 -9
- package/dist/types/index.d.ts.map +1 -1
- package/doc/README.md +1 -0
- package/mcp/catalog.snapshot.json +350 -121
- package/package.json +1 -1
|
@@ -4,8 +4,21 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
4
4
|
import { forwardRef, useRef, useState, useEffect, useCallback, useImperativeHandle } from 'react';
|
|
5
5
|
import { MicOff, Mic } from 'lucide-react';
|
|
6
6
|
import { cn } from '../../utils/cn.js';
|
|
7
|
+
import { PRESS_FEEDBACK } from '../../utils/touchTarget.js';
|
|
7
8
|
|
|
8
9
|
var _excluded = ["lang", "continuous", "interimResults", "onSpeechComplete", "onSpeaking", "onError", "onStart", "onStop", "renderButton", "autoStart", "disabled", "resetOnStart", "className"];
|
|
10
|
+
// Level bars (DTUI-42). There is no audio-level API without getUserMedia, so the
|
|
11
|
+
// bars show *whether* speech is being heard (speechstart / results), not volume.
|
|
12
|
+
var LEVEL_BARS = [{
|
|
13
|
+
height: "h-2",
|
|
14
|
+
delay: "[animation-delay:0ms]"
|
|
15
|
+
}, {
|
|
16
|
+
height: "h-3.5",
|
|
17
|
+
delay: "[animation-delay:150ms]"
|
|
18
|
+
}, {
|
|
19
|
+
height: "h-2.5",
|
|
20
|
+
delay: "[animation-delay:300ms]"
|
|
21
|
+
}];
|
|
9
22
|
var isProbablyMobile = function isProbablyMobile() {
|
|
10
23
|
if (typeof navigator === "undefined") return false;
|
|
11
24
|
return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
|
|
@@ -48,14 +61,19 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
48
61
|
_useState2 = _slicedToArray(_useState, 2),
|
|
49
62
|
_isListening = _useState2[0],
|
|
50
63
|
setIsListening = _useState2[1];
|
|
51
|
-
|
|
64
|
+
// True while the engine reports speech (speechstart → speechend, or results).
|
|
65
|
+
var _useState3 = useState(false),
|
|
52
66
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
var _useState5 = useState(
|
|
67
|
+
isHearing = _useState4[0],
|
|
68
|
+
setIsHearing = _useState4[1];
|
|
69
|
+
var _useState5 = useState(true),
|
|
56
70
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
57
|
-
|
|
58
|
-
|
|
71
|
+
_isSupported = _useState6[0],
|
|
72
|
+
setIsSupported = _useState6[1];
|
|
73
|
+
var _useState7 = useState(null),
|
|
74
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
75
|
+
error = _useState8[0],
|
|
76
|
+
setError = _useState8[1];
|
|
59
77
|
useEffect(function () {
|
|
60
78
|
var hasSpeechRecognition = typeof window !== "undefined" && ("SpeechRecognition" in window || "webkitSpeechRecognition" in window);
|
|
61
79
|
setIsSupported(hasSpeechRecognition);
|
|
@@ -76,6 +94,14 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
76
94
|
recognition.continuous = isProbablyMobile() ? false : continuous;
|
|
77
95
|
recognition.interimResults = interimResults;
|
|
78
96
|
recognition.lang = lang;
|
|
97
|
+
recognition.onspeechstart = function () {
|
|
98
|
+
if (!isMountedRef.current) return;
|
|
99
|
+
setIsHearing(true);
|
|
100
|
+
};
|
|
101
|
+
recognition.onspeechend = function () {
|
|
102
|
+
if (!isMountedRef.current) return;
|
|
103
|
+
setIsHearing(false);
|
|
104
|
+
};
|
|
79
105
|
recognition.onstart = function () {
|
|
80
106
|
if (!isMountedRef.current) return;
|
|
81
107
|
setIsListening(true);
|
|
@@ -97,6 +123,7 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
97
123
|
interim += text;
|
|
98
124
|
}
|
|
99
125
|
}
|
|
126
|
+
if (interim || finalChunk) setIsHearing(true);
|
|
100
127
|
if (interim) onSpeaking(interim.trim());
|
|
101
128
|
if (finalChunk) onSpeechComplete(finalChunk.trim());
|
|
102
129
|
};
|
|
@@ -107,11 +134,13 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
107
134
|
var err = new Error((event === null || event === void 0 ? void 0 : event.error) || "Speech recognition error");
|
|
108
135
|
setError(err);
|
|
109
136
|
setIsListening(false);
|
|
137
|
+
setIsHearing(false);
|
|
110
138
|
onError(err);
|
|
111
139
|
};
|
|
112
140
|
recognition.onend = function () {
|
|
113
141
|
if (!isMountedRef.current) return;
|
|
114
142
|
setIsListening(false);
|
|
143
|
+
setIsHearing(false);
|
|
115
144
|
onStop();
|
|
116
145
|
};
|
|
117
146
|
recognitionRef.current = recognition;
|
|
@@ -192,6 +221,7 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
192
221
|
// eslint-disable-next-line react-hooks/refs
|
|
193
222
|
return renderButton({
|
|
194
223
|
isListening: _isListening,
|
|
224
|
+
isHearing: isHearing,
|
|
195
225
|
isSupported: _isSupported,
|
|
196
226
|
error: error,
|
|
197
227
|
start: startListening,
|
|
@@ -207,18 +237,40 @@ var SpeechToText = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
207
237
|
"aria-label": _isListening ? "Stop listening" : "Start listening",
|
|
208
238
|
onClick: toggleListening,
|
|
209
239
|
disabled: isDisabled,
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
240
|
+
"data-listening": _isListening || undefined,
|
|
241
|
+
"data-hearing": _isListening && isHearing || undefined,
|
|
242
|
+
className: cn("inline-flex items-center gap-2 rounded-md px-4 h-10 text-sm font-medium", "[@media(pointer:coarse)]:min-h-11", "border border-gray-300 bg-transparent transition-colors duration-fast motion-reduce:transition-none", "hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-gray-800", "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500 dark:focus-visible:ring-offset-gray-900", "disabled:opacity-50 disabled:pointer-events-none", PRESS_FEEDBACK,
|
|
243
|
+
// PRESS_FEEDBACK sets transition-transform; keep the colour transition too.
|
|
244
|
+
"transition-[color,background-color,border-color,transform]", {
|
|
245
|
+
"text-error-600 border-error-600 dark:text-error-400 dark:border-error-400": _isListening,
|
|
246
|
+
"text-gray-900 dark:text-gray-100": !_isListening
|
|
213
247
|
}, className)
|
|
214
248
|
}, rest), {}, {
|
|
215
|
-
children: [
|
|
216
|
-
className: "h-4 w-4",
|
|
217
|
-
"aria-hidden": "true"
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
"
|
|
221
|
-
|
|
249
|
+
children: [jsxs("span", {
|
|
250
|
+
className: "relative inline-flex h-4 w-4 items-center justify-center",
|
|
251
|
+
"aria-hidden": "true",
|
|
252
|
+
children: [_isListening &&
|
|
253
|
+
// Listening pulse; a static ring replaces it under reduced motion.
|
|
254
|
+
jsx("span", {
|
|
255
|
+
"data-testid": "stt-pulse",
|
|
256
|
+
className: "absolute -inset-1.5 rounded-full bg-error-500/30 animate-ping motion-reduce:animate-none motion-reduce:bg-transparent motion-reduce:ring-2 motion-reduce:ring-error-500/60"
|
|
257
|
+
}), _isListening ? jsx(MicOff, {
|
|
258
|
+
className: "relative h-4 w-4",
|
|
259
|
+
"aria-hidden": "true"
|
|
260
|
+
}) : jsx(Mic, {
|
|
261
|
+
className: "relative h-4 w-4",
|
|
262
|
+
"aria-hidden": "true"
|
|
263
|
+
})]
|
|
264
|
+
}), _isListening ? "Stop" : "Start", _isListening && jsx("span", {
|
|
265
|
+
className: "inline-flex h-3.5 items-end gap-0.5",
|
|
266
|
+
"aria-hidden": "true",
|
|
267
|
+
"data-testid": "stt-level",
|
|
268
|
+
children: LEVEL_BARS.map(function (bar, i) {
|
|
269
|
+
return jsx("span", {
|
|
270
|
+
className: cn("w-0.5 rounded-full transition-colors duration-base motion-reduce:transition-none", isHearing ? cn("bg-current animate-pulse motion-reduce:animate-none", bar.height, bar.delay) : "h-1 bg-current opacity-40")
|
|
271
|
+
}, i);
|
|
272
|
+
})
|
|
273
|
+
})]
|
|
222
274
|
}));
|
|
223
275
|
});
|
|
224
276
|
SpeechToText.displayName = "SpeechToText";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
-
import { forwardRef, useState, useId, useEffect } from 'react';
|
|
4
|
+
import { forwardRef, useState, useId, useEffect, useRef } from 'react';
|
|
5
5
|
import { cn } from '../../utils/cn.js';
|
|
6
6
|
|
|
7
|
-
var _excluded = ["id", "name", "checked", "defaultChecked", "onChange", "disabled", "size", "color", "trackClass", "thumbClass", "className", "topLabel", "bottomLabel", "rightLabel", "leftLabel", "ariaLabel"];
|
|
7
|
+
var _excluded = ["id", "name", "checked", "defaultChecked", "onChange", "disabled", "size", "color", "trackClass", "thumbClass", "className", "topLabel", "bottomLabel", "rightLabel", "leftLabel", "ariaLabel", "onPointerDown", "onPointerMove", "onPointerUp", "onPointerCancel"];
|
|
8
8
|
/**
|
|
9
9
|
* Switch.jsx
|
|
10
10
|
* - Plain JSX (no TypeScript)
|
|
@@ -17,23 +17,29 @@ var _excluded = ["id", "name", "checked", "defaultChecked", "onChange", "disable
|
|
|
17
17
|
* New props:
|
|
18
18
|
* - topLabel, bottomLabel, rightLabel, leftLabel (renders label in those positions)
|
|
19
19
|
*/
|
|
20
|
+
// `md` takes the iOS 51×31 size on coarse pointers (27px knob, 2px inset).
|
|
20
21
|
var SIZE_MAP = {
|
|
21
22
|
sm: {
|
|
22
23
|
track: "w-9 h-5",
|
|
23
24
|
knob: "w-4 h-4",
|
|
24
|
-
|
|
25
|
+
knobOn: "translate-x-4",
|
|
26
|
+
knobOff: "translate-x-1"
|
|
25
27
|
},
|
|
26
28
|
md: {
|
|
27
|
-
track: "w-11 h-6",
|
|
28
|
-
knob: "w-5 h-5",
|
|
29
|
-
|
|
29
|
+
track: "w-11 h-6 [@media(pointer:coarse)]:h-[31px] [@media(pointer:coarse)]:w-[51px]",
|
|
30
|
+
knob: "w-5 h-5 [@media(pointer:coarse)]:h-[27px] [@media(pointer:coarse)]:w-[27px]",
|
|
31
|
+
knobOn: "translate-x-5 [@media(pointer:coarse)]:translate-x-[22px]",
|
|
32
|
+
knobOff: "translate-x-1 [@media(pointer:coarse)]:translate-x-0.5"
|
|
30
33
|
},
|
|
31
34
|
lg: {
|
|
32
35
|
track: "w-14 h-8",
|
|
33
36
|
knob: "w-6 h-6",
|
|
34
|
-
|
|
37
|
+
knobOn: "translate-x-6",
|
|
38
|
+
knobOff: "translate-x-1"
|
|
35
39
|
}
|
|
36
40
|
};
|
|
41
|
+
// Horizontal travel (px) before a press becomes a drag.
|
|
42
|
+
var DRAG_THRESHOLD = 4;
|
|
37
43
|
var COLOR_PRESETS = {
|
|
38
44
|
primary: {
|
|
39
45
|
bg: "bg-primary-600",
|
|
@@ -102,6 +108,10 @@ var Switch = /*#__PURE__*/forwardRef(function Switch(props, ref) {
|
|
|
102
108
|
rightLabel = props.rightLabel,
|
|
103
109
|
leftLabel = props.leftLabel,
|
|
104
110
|
ariaLabel = props.ariaLabel,
|
|
111
|
+
onPointerDown = props.onPointerDown,
|
|
112
|
+
onPointerMove = props.onPointerMove,
|
|
113
|
+
onPointerUp = props.onPointerUp,
|
|
114
|
+
onPointerCancel = props.onPointerCancel,
|
|
105
115
|
rest = _objectWithoutProperties(props, _excluded);
|
|
106
116
|
var isControlled = typeof checked === "boolean";
|
|
107
117
|
var _useState = useState(defaultChecked),
|
|
@@ -115,31 +125,89 @@ var Switch = /*#__PURE__*/forwardRef(function Switch(props, ref) {
|
|
|
115
125
|
if (!isControlled) setInternalChecked(defaultChecked);
|
|
116
126
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
117
127
|
}, [defaultChecked]);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
// Drag-to-toggle: slide the knob (iOS style). A tap still toggles via click.
|
|
129
|
+
var drag = useRef(null);
|
|
130
|
+
var suppressClick = useRef(false);
|
|
131
|
+
var _useState3 = useState(null),
|
|
132
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
133
|
+
dragPreview = _useState4[0],
|
|
134
|
+
setDragPreview = _useState4[1];
|
|
135
|
+
var setOn = function setOn(next) {
|
|
136
|
+
if (disabled || next === isOn) return;
|
|
121
137
|
if (!isControlled) setInternalChecked(next);
|
|
122
138
|
onChange && onChange(next);
|
|
123
139
|
};
|
|
140
|
+
var toggle = function toggle() {
|
|
141
|
+
if (disabled) return;
|
|
142
|
+
if (suppressClick.current) {
|
|
143
|
+
// The click that follows a drag's pointerup; the drag already decided.
|
|
144
|
+
suppressClick.current = false;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
setOn(!isOn);
|
|
148
|
+
};
|
|
149
|
+
var dragTarget = function dragTarget(dx, start) {
|
|
150
|
+
return dx > DRAG_THRESHOLD ? true : dx < -DRAG_THRESHOLD ? false : start;
|
|
151
|
+
};
|
|
152
|
+
var handlePointerDown = function handlePointerDown(e) {
|
|
153
|
+
var _e$currentTarget$setP, _e$currentTarget;
|
|
154
|
+
onPointerDown && onPointerDown(e);
|
|
155
|
+
if (disabled || e.button > 0) return;
|
|
156
|
+
suppressClick.current = false;
|
|
157
|
+
drag.current = {
|
|
158
|
+
x: e.clientX,
|
|
159
|
+
start: isOn,
|
|
160
|
+
moved: false
|
|
161
|
+
};
|
|
162
|
+
(_e$currentTarget$setP = (_e$currentTarget = e.currentTarget).setPointerCapture) === null || _e$currentTarget$setP === void 0 || _e$currentTarget$setP.call(_e$currentTarget, e.pointerId);
|
|
163
|
+
};
|
|
164
|
+
var handlePointerMove = function handlePointerMove(e) {
|
|
165
|
+
onPointerMove && onPointerMove(e);
|
|
166
|
+
if (!drag.current) return;
|
|
167
|
+
var dx = e.clientX - drag.current.x;
|
|
168
|
+
if (Math.abs(dx) > DRAG_THRESHOLD) drag.current.moved = true;
|
|
169
|
+
if (drag.current.moved) setDragPreview(dragTarget(dx, drag.current.start));
|
|
170
|
+
};
|
|
171
|
+
var endDrag = function endDrag(e, commit) {
|
|
172
|
+
var d = drag.current;
|
|
173
|
+
drag.current = null;
|
|
174
|
+
setDragPreview(null);
|
|
175
|
+
if (!d || !d.moved) return;
|
|
176
|
+
suppressClick.current = true;
|
|
177
|
+
if (commit) setOn(dragTarget(e.clientX - d.x, d.start));
|
|
178
|
+
};
|
|
179
|
+
var handlePointerUp = function handlePointerUp(e) {
|
|
180
|
+
onPointerUp && onPointerUp(e);
|
|
181
|
+
endDrag(e, true);
|
|
182
|
+
};
|
|
183
|
+
var handlePointerCancel = function handlePointerCancel(e) {
|
|
184
|
+
onPointerCancel && onPointerCancel(e);
|
|
185
|
+
endDrag(e, false);
|
|
186
|
+
};
|
|
124
187
|
var handleKeyDown = function handleKeyDown(e) {
|
|
125
188
|
if (disabled) return;
|
|
126
189
|
if (e.key === " " || e.key === "Spacebar" || e.key === "Enter") {
|
|
127
190
|
e.preventDefault();
|
|
128
|
-
|
|
191
|
+
setOn(!isOn);
|
|
129
192
|
}
|
|
130
193
|
};
|
|
131
194
|
var sizeStuff = SIZE_MAP[size] || SIZE_MAP.md;
|
|
132
195
|
var isPreset = COLOR_PRESETS[color];
|
|
133
196
|
// Classes for the track (we use inline style for arbitrary trackClass when ON)
|
|
134
|
-
|
|
197
|
+
// While dragging, the knob and track follow the drag's preview state.
|
|
198
|
+
var shownOn = dragPreview !== null && dragPreview !== void 0 ? dragPreview : isOn;
|
|
199
|
+
var trackClasses = cn("relative inline-flex shrink-0 items-center rounded-full touch-pan-y select-none", "transition-colors duration-base ease-standard motion-reduce:transition-none", sizeStuff.track,
|
|
200
|
+
// Off track: a visible grey on white (light) and on dark surfaces.
|
|
201
|
+
shownOn ? trackClass ? "" : isPreset ? isPreset.bg : "" : "bg-gray-300 dark:bg-gray-600", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer", trackClass // Accepting trackClass as a class name
|
|
135
202
|
);
|
|
136
203
|
// Knob classes (thumb)
|
|
137
|
-
|
|
204
|
+
// The knob stays white in both themes (it sits on a coloured or grey track).
|
|
205
|
+
var knobBase = cn("pointer-events-none inline-block rounded-full bg-white shadow-sm transform ring-0", "transition-transform duration-base ease-spring-out motion-reduce:transition-none", sizeStuff.knob, thumbClass // Accepting thumbClass as a class name
|
|
138
206
|
);
|
|
139
|
-
var knobTransform =
|
|
207
|
+
var knobTransform = shownOn ? sizeStuff.knobOn : sizeStuff.knobOff;
|
|
140
208
|
var ringClass = isPreset ? isPreset.ring : "focus-visible:ring-primary-300";
|
|
141
|
-
var focusClasses = disabled ? "" : "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 ".concat(ringClass);
|
|
142
|
-
var trackStyle =
|
|
209
|
+
var focusClasses = disabled ? "" : "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-900 ".concat(ringClass);
|
|
210
|
+
var trackStyle = shownOn && !trackClass && !isPreset ? {
|
|
143
211
|
backgroundColor: color
|
|
144
212
|
} : undefined; // Fallback to default trackClass if trackClass is not a class
|
|
145
213
|
var accessibleLabel = ariaLabel || rightLabel || leftLabel || topLabel || bottomLabel || "Toggle";
|
|
@@ -171,6 +239,10 @@ var Switch = /*#__PURE__*/forwardRef(function Switch(props, ref) {
|
|
|
171
239
|
className: cn(trackClasses, focusClasses),
|
|
172
240
|
onClick: toggle,
|
|
173
241
|
onKeyDown: handleKeyDown,
|
|
242
|
+
onPointerDown: handlePointerDown,
|
|
243
|
+
onPointerMove: handlePointerMove,
|
|
244
|
+
onPointerUp: handlePointerUp,
|
|
245
|
+
onPointerCancel: handlePointerCancel,
|
|
174
246
|
style: trackStyle
|
|
175
247
|
}, rest), {}, {
|
|
176
248
|
children: [jsx("span", {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { defineProperty as _defineProperty } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
3
|
import 'react';
|
|
5
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
|
+
import { getHoverClass } from './helpers.js';
|
|
6
6
|
|
|
7
7
|
var DEFAULT_ROW_HOVER = "bg-background";
|
|
8
8
|
/**
|
|
@@ -32,9 +32,7 @@ function ColumnMenu(_ref) {
|
|
|
32
32
|
className: "max-h-56 overflow-auto",
|
|
33
33
|
children: columns.map(function (col) {
|
|
34
34
|
return jsxs("label", {
|
|
35
|
-
className: cn(
|
|
36
|
-
"flex cursor-pointer items-center gap-2 px-2 py-1.5 rounded": true
|
|
37
|
-
}, "hover:" + rowHover, true)),
|
|
35
|
+
className: cn("flex cursor-pointer items-center gap-2 px-2 py-1.5 rounded", getHoverClass(rowHover)),
|
|
38
36
|
children: [jsx("input", {
|
|
39
37
|
type: "checkbox",
|
|
40
38
|
checked: col.isVisible !== false,
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { defineProperty as _defineProperty } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
3
|
import 'react';
|
|
5
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
|
+
import { TOUCH_TARGET } from '../../../utils/touchTarget.js';
|
|
6
|
+
import { getHoverClass } from './helpers.js';
|
|
6
7
|
import { ChevronsLeft, ChevronLeft, ChevronRight, ChevronsRight } from 'lucide-react';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Pagination controls component for the table
|
|
10
11
|
* Supports both header (icon-only) and footer (with page numbers) variants
|
|
11
12
|
*/
|
|
12
|
-
var
|
|
13
|
+
var NAV_BUTTON_BASE = "inline-flex items-center justify-center rounded-lg md:rounded-md border border-gray-300 disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500";
|
|
13
14
|
// Header pagination (compact, icon-based)
|
|
14
15
|
function PaginationHeader(_ref) {
|
|
15
|
-
var _theme$rowHover;
|
|
16
16
|
var currentPage = _ref.currentPage,
|
|
17
17
|
totalPages = _ref.totalPages,
|
|
18
18
|
onPageChange = _ref.onPageChange,
|
|
19
19
|
theme = _ref.theme;
|
|
20
|
-
var
|
|
20
|
+
var hoverClass = getHoverClass(theme === null || theme === void 0 ? void 0 : theme.rowHover);
|
|
21
21
|
return jsxs("div", {
|
|
22
22
|
className: "flex items-center gap-1",
|
|
23
23
|
children: [totalPages >= 4 && jsx("button", {
|
|
24
|
-
className: cn("
|
|
24
|
+
className: cn(NAV_BUTTON_BASE, "p-2", TOUCH_TARGET, hoverClass),
|
|
25
25
|
disabled: currentPage === 1,
|
|
26
26
|
onClick: function onClick() {
|
|
27
27
|
return onPageChange(1);
|
|
@@ -31,7 +31,7 @@ function PaginationHeader(_ref) {
|
|
|
31
31
|
className: "size-4 md:size-5 text-primary-800"
|
|
32
32
|
})
|
|
33
33
|
}), jsx("button", {
|
|
34
|
-
className: cn("
|
|
34
|
+
className: cn(NAV_BUTTON_BASE, "p-2", TOUCH_TARGET, hoverClass),
|
|
35
35
|
disabled: currentPage === 1,
|
|
36
36
|
onClick: function onClick() {
|
|
37
37
|
return onPageChange(Math.max(1, currentPage - 1));
|
|
@@ -41,7 +41,7 @@ function PaginationHeader(_ref) {
|
|
|
41
41
|
className: "size-4 md:size-5 text-primary-800"
|
|
42
42
|
})
|
|
43
43
|
}), jsx("button", {
|
|
44
|
-
className: cn("
|
|
44
|
+
className: cn(NAV_BUTTON_BASE, "p-2", TOUCH_TARGET, hoverClass),
|
|
45
45
|
disabled: currentPage === totalPages,
|
|
46
46
|
onClick: function onClick() {
|
|
47
47
|
return onPageChange(Math.min(totalPages, currentPage + 1));
|
|
@@ -51,7 +51,7 @@ function PaginationHeader(_ref) {
|
|
|
51
51
|
className: "size-4 md:size-5 text-primary-800"
|
|
52
52
|
})
|
|
53
53
|
}), totalPages >= 4 && jsx("button", {
|
|
54
|
-
className: cn("
|
|
54
|
+
className: cn(NAV_BUTTON_BASE, "p-2", TOUCH_TARGET, hoverClass),
|
|
55
55
|
disabled: currentPage === totalPages,
|
|
56
56
|
onClick: function onClick() {
|
|
57
57
|
return onPageChange(totalPages);
|
|
@@ -65,13 +65,12 @@ function PaginationHeader(_ref) {
|
|
|
65
65
|
}
|
|
66
66
|
// Footer pagination (with page numbers)
|
|
67
67
|
function PaginationFooter(_ref2) {
|
|
68
|
-
var _theme$rowHover2;
|
|
69
68
|
var currentPage = _ref2.currentPage,
|
|
70
69
|
totalPages = _ref2.totalPages,
|
|
71
70
|
onPageChange = _ref2.onPageChange,
|
|
72
71
|
isMobileView = _ref2.isMobileView,
|
|
73
72
|
theme = _ref2.theme;
|
|
74
|
-
var
|
|
73
|
+
var hoverClass = getHoverClass(theme === null || theme === void 0 ? void 0 : theme.rowHover);
|
|
75
74
|
var visiblePageCount = isMobileView ? 5 : 3;
|
|
76
75
|
return jsx("div", {
|
|
77
76
|
className: "p-4 border-t",
|
|
@@ -83,7 +82,7 @@ function PaginationFooter(_ref2) {
|
|
|
83
82
|
}), jsxs("div", {
|
|
84
83
|
className: "flex items-center gap-1 sm:gap-2",
|
|
85
84
|
children: [totalPages >= 4 && jsx("button", {
|
|
86
|
-
className: cn(
|
|
85
|
+
className: cn(NAV_BUTTON_BASE, isMobileView ? "p-2" : "px-4 py-2 text-sm", TOUCH_TARGET, hoverClass),
|
|
87
86
|
disabled: currentPage === 1,
|
|
88
87
|
onClick: function onClick() {
|
|
89
88
|
return onPageChange(1);
|
|
@@ -93,7 +92,7 @@ function PaginationFooter(_ref2) {
|
|
|
93
92
|
className: "size-4 text-primary-800"
|
|
94
93
|
}) : "First"
|
|
95
94
|
}), jsx("button", {
|
|
96
|
-
className: cn(
|
|
95
|
+
className: cn(NAV_BUTTON_BASE, isMobileView ? "p-2" : "px-4 py-2 text-sm", TOUCH_TARGET, hoverClass),
|
|
97
96
|
disabled: currentPage === 1,
|
|
98
97
|
onClick: function onClick() {
|
|
99
98
|
return onPageChange(Math.max(1, currentPage - 1));
|
|
@@ -118,10 +117,8 @@ function PaginationFooter(_ref2) {
|
|
|
118
117
|
pageNum = currentPage - 2 + i;
|
|
119
118
|
}
|
|
120
119
|
return jsx("button", {
|
|
121
|
-
className: cn("h-8 w-8 rounded-lg md:rounded-md text-sm",
|
|
122
|
-
|
|
123
|
-
"border border-gray-300": pageNum !== currentPage
|
|
124
|
-
}, "hover:" + rowHover, pageNum !== currentPage)),
|
|
120
|
+
className: cn("inline-flex items-center justify-center h-8 w-8 rounded-lg md:rounded-md text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500", TOUCH_TARGET, pageNum === currentPage ? "bg-primary-600 text-white" : ["border border-gray-300", hoverClass]),
|
|
121
|
+
"aria-current": pageNum === currentPage ? "page" : undefined,
|
|
125
122
|
onClick: function onClick() {
|
|
126
123
|
return onPageChange(pageNum);
|
|
127
124
|
},
|
|
@@ -129,7 +126,7 @@ function PaginationFooter(_ref2) {
|
|
|
129
126
|
}, pageNum);
|
|
130
127
|
})
|
|
131
128
|
}), jsx("button", {
|
|
132
|
-
className: cn(
|
|
129
|
+
className: cn(NAV_BUTTON_BASE, isMobileView ? "p-2" : "px-4 py-2 text-sm", TOUCH_TARGET, hoverClass),
|
|
133
130
|
disabled: currentPage === totalPages,
|
|
134
131
|
onClick: function onClick() {
|
|
135
132
|
return onPageChange(Math.min(totalPages, currentPage + 1));
|
|
@@ -139,7 +136,7 @@ function PaginationFooter(_ref2) {
|
|
|
139
136
|
className: "size-4 text-primary-800"
|
|
140
137
|
}) : "Next"
|
|
141
138
|
}), totalPages >= 4 && jsx("button", {
|
|
142
|
-
className: cn(
|
|
139
|
+
className: cn(NAV_BUTTON_BASE, isMobileView ? "p-2" : "px-4 py-2 text-sm", TOUCH_TARGET, hoverClass),
|
|
143
140
|
disabled: currentPage === totalPages,
|
|
144
141
|
onClick: function onClick() {
|
|
145
142
|
return onPageChange(totalPages);
|
|
@@ -5,7 +5,7 @@ import React from 'react';
|
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { Trash2, MoreVertical } from 'lucide-react';
|
|
7
7
|
import ActionMenu from './ActionMenu.js';
|
|
8
|
-
import { getRowKey, resolveActions, rowHasDetails, getActionLabelText, getStripeProps } from './helpers.js';
|
|
8
|
+
import { getRowKey, resolveActions, rowHasDetails, getActionLabelText, getHoverClass, getStripeProps } from './helpers.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Desktop table row component
|
|
@@ -96,7 +96,7 @@ function TableRow(_ref) {
|
|
|
96
96
|
return jsxs(React.Fragment, {
|
|
97
97
|
children: [jsxs("tr", {
|
|
98
98
|
style: stripeProps.style,
|
|
99
|
-
className: cn(stripeProps.className, theme !== null && theme !== void 0 && theme.rowHover ?
|
|
99
|
+
className: cn(stripeProps.className, theme !== null && theme !== void 0 && theme.rowHover ? getHoverClass(theme.rowHover) : [], {
|
|
100
100
|
"cursor-pointer": !!onRowClick,
|
|
101
101
|
"bg-primary-50": isSelected,
|
|
102
102
|
"bg-primary-50/20": isRowActive && !isSelected,
|
|
@@ -135,5 +135,37 @@ var resolveActions = function resolveActions(actions, row, index) {
|
|
|
135
135
|
menuActions: menuActions
|
|
136
136
|
};
|
|
137
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* Tailwind only generates classes it can see as complete literals in source, so a
|
|
140
|
+
* runtime-built `"hover:" + token` is purged from the compiled CSS. Bare `rowHover`
|
|
141
|
+
* tokens (the shipped defaults, past and present) map to static literals here.
|
|
142
|
+
*/
|
|
143
|
+
var HOVER_BG_CLASSES = {
|
|
144
|
+
"bg-background": "hover:bg-background",
|
|
145
|
+
"bg-surface": "hover:bg-surface",
|
|
146
|
+
"bg-gray-50": "hover:bg-gray-50",
|
|
147
|
+
"bg-gray-100": "hover:bg-gray-100",
|
|
148
|
+
"bg-primary-50": "hover:bg-primary-50",
|
|
149
|
+
"bg-primary-100": "hover:bg-primary-100"
|
|
150
|
+
};
|
|
151
|
+
var DEFAULT_HOVER_CLASS = HOVER_BG_CLASSES["bg-background"];
|
|
152
|
+
/**
|
|
153
|
+
* Resolve `theme.rowHover` to a full hover class string.
|
|
154
|
+
* - A value that already contains a `hover:` variant is used as-is (preferred: pass
|
|
155
|
+
* the full literal, e.g. `"hover:bg-gray-100"`, so your Tailwind build sees it).
|
|
156
|
+
* - A bare token from the static map resolves to its literal.
|
|
157
|
+
* - Any other bare token falls back to a `hover:` prefix for backward compatibility;
|
|
158
|
+
* it only works if the consumer's own Tailwind build generates that class.
|
|
159
|
+
*/
|
|
160
|
+
var getHoverClass = function getHoverClass(rowHover) {
|
|
161
|
+
if (!rowHover || typeof rowHover !== "string") return DEFAULT_HOVER_CLASS;
|
|
162
|
+
var value = rowHover.trim();
|
|
163
|
+
if (!value) return DEFAULT_HOVER_CLASS;
|
|
164
|
+
if (/(^|\s)hover:/.test(value)) return value;
|
|
165
|
+
if (HOVER_BG_CLASSES[value]) return HOVER_BG_CLASSES[value];
|
|
166
|
+
return value.split(/\s+/).map(function (cls) {
|
|
167
|
+
return "hover:".concat(cls);
|
|
168
|
+
}).join(" ");
|
|
169
|
+
};
|
|
138
170
|
|
|
139
|
-
export { getActionLabelText, getRowKey, getStripeProps, mergeDefaultActions, resolveActions, rowHasDetails };
|
|
171
|
+
export { DEFAULT_HOVER_CLASS, getActionLabelText, getHoverClass, getRowKey, getStripeProps, mergeDefaultActions, resolveActions, rowHasDetails };
|