@dreamtree-org/twreact-ui 1.3.11 → 2.0.1
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 +40 -6
- package/ai-skills/dreamtree-ui.md +47 -9
- package/codemods/v2.cjs +198 -0
- package/dist/ai-schema.json +609 -33
- package/dist/components/blocks/AppShell.d.ts.map +1 -1
- package/dist/components/blocks/BottomActionBar.d.ts +6 -0
- package/dist/components/blocks/BottomActionBar.d.ts.map +1 -0
- package/dist/components/blocks/ConfirmDialog.d.ts.map +1 -1
- package/dist/components/blocks/PageHeader.d.ts.map +1 -1
- package/dist/components/core/Checkbox.d.ts.map +1 -1
- package/dist/components/core/DatePicker.d.ts.map +1 -1
- package/dist/components/core/DateRangePicker.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/Popover.d.ts.map +1 -1
- package/dist/components/core/ProgressBar.d.ts.map +1 -1
- package/dist/components/core/Rate.d.ts.map +1 -1
- package/dist/components/core/SearchField.d.ts +9 -0
- package/dist/components/core/SearchField.d.ts.map +1 -0
- package/dist/components/core/SegmentedControl.d.ts +8 -0
- package/dist/components/core/SegmentedControl.d.ts.map +1 -0
- package/dist/components/core/Select.d.ts.map +1 -1
- package/dist/components/core/SwipeableListItem.d.ts +4 -0
- package/dist/components/core/SwipeableListItem.d.ts.map +1 -0
- package/dist/components/core/SwipeableListItemGesture.d.ts +58 -0
- package/dist/components/core/SwipeableListItemGesture.d.ts.map +1 -0
- package/dist/components/core/Switch.d.ts.map +1 -1
- package/dist/components/core/Table/ActionMenu.d.ts +10 -3
- package/dist/components/core/Table/ActionMenu.d.ts.map +1 -1
- package/dist/components/core/Table/MobileCard.d.ts +10 -1
- package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
- package/dist/components/core/Table/MobileFilters.d.ts +8 -2
- package/dist/components/core/Table/MobileFilters.d.ts.map +1 -1
- package/dist/components/core/Table/Table.d.ts.map +1 -1
- package/dist/components/core/Table/TableRow.d.ts +2 -1
- package/dist/components/core/Table/TableRow.d.ts.map +1 -1
- package/dist/components/core/Tabs.d.ts +3 -3
- package/dist/components/core/Tabs.d.ts.map +1 -1
- package/dist/components/core/ThreeDotPopover.d.ts +10 -22
- package/dist/components/core/ThreeDotPopover.d.ts.map +1 -1
- package/dist/components/core/Tooltip.d.ts +2 -1
- package/dist/components/core/Tooltip.d.ts.map +1 -1
- package/dist/components/core/internal/Calendar.d.ts +77 -0
- package/dist/components/core/internal/Calendar.d.ts.map +1 -0
- package/dist/components/core/menu/ActionMenuSurface.d.ts +42 -0
- package/dist/components/core/menu/ActionMenuSurface.d.ts.map +1 -0
- package/dist/components/core/menu/ActionSheetMenu.d.ts +17 -0
- package/dist/components/core/menu/ActionSheetMenu.d.ts.map +1 -0
- package/dist/components/core/menu/MenuPopover.d.ts +21 -0
- package/dist/components/core/menu/MenuPopover.d.ts.map +1 -0
- package/dist/components/core/menu/menuItems.d.ts +21 -0
- package/dist/components/core/menu/menuItems.d.ts.map +1 -0
- package/dist/components/core/menu/menuKeyboard.d.ts +16 -0
- package/dist/components/core/menu/menuKeyboard.d.ts.map +1 -0
- package/dist/components/feedback/ActionSheet.d.ts +4 -0
- package/dist/components/feedback/ActionSheet.d.ts.map +1 -0
- package/dist/components/feedback/Alert.d.ts.map +1 -1
- package/dist/components/feedback/Dialog.d.ts.map +1 -1
- package/dist/components/feedback/Drawer.d.ts.map +1 -1
- package/dist/components/feedback/Sheet.d.ts +4 -0
- package/dist/components/feedback/Sheet.d.ts.map +1 -0
- package/dist/components/feedback/Toast.d.ts +4 -3
- package/dist/components/feedback/Toast.d.ts.map +1 -1
- package/dist/components/feedback/ToastItem.d.ts +47 -0
- package/dist/components/feedback/ToastItem.d.ts.map +1 -0
- package/dist/components/feedback/ToastStack.d.ts +20 -0
- package/dist/components/feedback/ToastStack.d.ts.map +1 -0
- package/dist/components/feedback/ToastSwipe.d.ts +22 -0
- package/dist/components/feedback/ToastSwipe.d.ts.map +1 -0
- package/dist/components/feedback/Tour.d.ts.map +1 -1
- package/dist/components/feedback/sheetCore.d.ts +30 -0
- package/dist/components/feedback/sheetCore.d.ts.map +1 -0
- package/dist/components/navigation/Navbar.d.ts.map +1 -1
- package/dist/components/navigation/Sidebar.d.ts +6 -0
- package/dist/components/navigation/Sidebar.d.ts.map +1 -1
- package/dist/components/rich-text/RichTextEditor.d.ts.map +1 -1
- package/dist/components/rich-text/RichTextToolbar.d.ts +6 -2
- package/dist/components/rich-text/RichTextToolbar.d.ts.map +1 -1
- package/dist/components/utility/PullToRefresh.d.ts +5 -0
- package/dist/components/utility/PullToRefresh.d.ts.map +1 -0
- package/dist/esm/components/blocks/AppShell.js +97 -90
- package/dist/esm/components/blocks/BottomActionBar.js +132 -0
- package/dist/esm/components/blocks/ConfirmDialog.js +40 -4
- package/dist/esm/components/blocks/PageHeader.js +16 -3
- package/dist/esm/components/core/Checkbox.js +13 -24
- package/dist/esm/components/core/DatePicker.js +117 -304
- package/dist/esm/components/core/DateRangePicker.js +260 -308
- package/dist/esm/components/core/Form.js +11 -2
- package/dist/esm/components/core/Input.js +13 -18
- package/dist/esm/components/core/Popover.js +59 -48
- package/dist/esm/components/core/ProgressBar.js +36 -64
- package/dist/esm/components/core/Rate.js +5 -10
- package/dist/esm/components/core/SearchField.js +311 -0
- package/dist/esm/components/core/SegmentedControl.js +189 -0
- package/dist/esm/components/core/Select.js +185 -190
- package/dist/esm/components/core/SwipeableListItem.js +286 -0
- package/dist/esm/components/core/SwipeableListItemGesture.js +219 -0
- package/dist/esm/components/core/Switch.js +11 -13
- package/dist/esm/components/core/Table/ActionMenu.js +45 -231
- package/dist/esm/components/core/Table/ColumnMenu.js +1 -1
- package/dist/esm/components/core/Table/MobileCard.js +66 -16
- package/dist/esm/components/core/Table/MobileFilters.js +181 -10
- package/dist/esm/components/core/Table/Table.js +149 -102
- package/dist/esm/components/core/Table/TableRow.js +10 -2
- package/dist/esm/components/core/Tabs.js +7 -7
- package/dist/esm/components/core/ThreeDotPopover.js +93 -99
- package/dist/esm/components/core/Tooltip.js +138 -145
- package/dist/esm/components/core/internal/Calendar.js +381 -0
- package/dist/esm/components/core/menu/ActionMenuSurface.js +110 -0
- package/dist/esm/components/core/menu/ActionSheetMenu.js +140 -0
- package/dist/esm/components/core/menu/MenuPopover.js +177 -0
- package/dist/esm/components/core/menu/menuItems.js +61 -0
- package/dist/esm/components/core/menu/menuKeyboard.js +54 -0
- package/dist/esm/components/feedback/ActionSheet.js +55 -0
- package/dist/esm/components/feedback/Alert.js +63 -53
- package/dist/esm/components/feedback/Dialog.js +141 -53
- package/dist/esm/components/feedback/Drawer.js +130 -132
- package/dist/esm/components/feedback/Sheet.js +125 -0
- package/dist/esm/components/feedback/Toast.js +21 -291
- package/dist/esm/components/feedback/ToastItem.js +348 -0
- package/dist/esm/components/feedback/ToastStack.js +130 -0
- package/dist/esm/components/feedback/ToastSwipe.js +52 -0
- package/dist/esm/components/feedback/Tour.js +107 -30
- package/dist/esm/components/feedback/sheetCore.js +494 -0
- package/dist/esm/components/navigation/Dropdown.js +1 -1
- package/dist/esm/components/navigation/Navbar.js +172 -37
- package/dist/esm/components/navigation/Sidebar.js +263 -111
- package/dist/esm/components/rich-text/RichTextEditor.js +9 -3
- package/dist/esm/components/rich-text/RichTextToolbar.js +29 -9
- package/dist/esm/components/utility/Portal.js +31 -0
- package/dist/esm/components/utility/PullToRefresh.js +229 -0
- package/dist/esm/hooks/useFloatingPosition.js +82 -0
- package/dist/esm/hooks/useHaptics.js +65 -0
- package/dist/esm/hooks/usePresence.js +58 -0
- package/dist/esm/hooks/usePresentation.js +21 -0
- package/dist/esm/hooks/useSheetDrag.js +220 -0
- package/dist/esm/index.js +13 -2
- package/dist/esm/utils/position.js +10 -63
- package/dist/hooks/useFloatingPosition.d.ts +8 -4
- package/dist/hooks/useFloatingPosition.d.ts.map +1 -1
- package/dist/hooks/useHaptics.d.ts +19 -0
- package/dist/hooks/useHaptics.d.ts.map +1 -0
- package/dist/hooks/useSheetDrag.d.ts +31 -0
- package/dist/hooks/useSheetDrag.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +8851 -3198
- package/dist/index.js +8856 -3195
- package/dist/rich-text/index.js +41 -11
- package/dist/types/blocks.d.ts +32 -2
- package/dist/types/blocks.d.ts.map +1 -1
- package/dist/types/index.d.ts +353 -19
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/rich-text.d.ts +5 -0
- package/dist/types/rich-text.d.ts.map +1 -1
- package/dist/utils/position.d.ts +0 -15
- package/dist/utils/position.d.ts.map +1 -1
- package/doc/README.md +15 -0
- package/mcp/catalog.snapshot.json +1398 -464
- package/package.json +7 -2
- package/dist/esm/hooks/useSwipeToClose.js +0 -66
- package/dist/hooks/useSwipeToClose.d.ts +0 -24
- package/dist/hooks/useSwipeToClose.d.ts.map +0 -1
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, typeof as _typeof, toConsumableArray as _toConsumableArray, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import React, { useMemo, useRef, useState, useCallback } from 'react';
|
|
5
|
+
import { MoreHorizontal } from 'lucide-react';
|
|
6
|
+
import { cn } from '../../utils/cn.js';
|
|
7
|
+
import { setRefs } from '../../utils/position.js';
|
|
8
|
+
import { useControllableState } from '../../hooks/useControllableState.js';
|
|
9
|
+
import { useClickOutside } from '../../hooks/useClickOutside.js';
|
|
10
|
+
import ActionMenuSurface from './menu/ActionMenuSurface.js';
|
|
11
|
+
import { renderIcon } from './menu/menuItems.js';
|
|
12
|
+
import { useSwipeGesture, restingOffset } from './SwipeableListItemGesture.js';
|
|
13
|
+
|
|
14
|
+
var _excluded = ["as", "children", "leadingActions", "trailingActions", "fullSwipe", "fullSwipeThreshold", "actionWidth", "open", "defaultOpen", "onOpenChange", "disabled", "moreActions", "moreActionsLabel", "menuPresentation", "contentClassName", "className", "onKeyDown"];
|
|
15
|
+
// The iOS Mail / Gmail row: swipe horizontally to reveal actions, swipe all
|
|
16
|
+
// the way to commit the first one. Every action is also reachable without a
|
|
17
|
+
// gesture through the "More actions" button (a menu, or an action sheet on
|
|
18
|
+
// phones).
|
|
19
|
+
var TONE_CLASSES = {
|
|
20
|
+
"default": "bg-secondary-600 text-secondary-50",
|
|
21
|
+
primary: "bg-primary-600 text-primary-50",
|
|
22
|
+
secondary: "bg-secondary-600 text-secondary-50",
|
|
23
|
+
success: "bg-success-600 text-success-50",
|
|
24
|
+
warning: "bg-warning-600 text-warning-50",
|
|
25
|
+
info: "bg-info-600 text-info-50",
|
|
26
|
+
error: "bg-error-600 text-error-50",
|
|
27
|
+
destructive: "bg-error-600 text-error-50"
|
|
28
|
+
};
|
|
29
|
+
var MOTION = "duration-base ease-standard motion-reduce:transition-none";
|
|
30
|
+
var toneClass = function toneClass(tone) {
|
|
31
|
+
return TONE_CLASSES[tone] || TONE_CLASSES["default"];
|
|
32
|
+
};
|
|
33
|
+
var isMenuDestructive = function isMenuDestructive(tone) {
|
|
34
|
+
return tone === "destructive" || tone === "error";
|
|
35
|
+
};
|
|
36
|
+
function ActionPanel(_ref) {
|
|
37
|
+
var side = _ref.side,
|
|
38
|
+
actions = _ref.actions,
|
|
39
|
+
width = _ref.width,
|
|
40
|
+
open = _ref.open,
|
|
41
|
+
armed = _ref.armed,
|
|
42
|
+
dragging = _ref.dragging,
|
|
43
|
+
onSelect = _ref.onSelect;
|
|
44
|
+
// The first action sits at the outer edge, so trailing actions render reversed.
|
|
45
|
+
var ordered = side === "trailing" ? _toConsumableArray(actions).reverse() : actions;
|
|
46
|
+
var first = actions[0];
|
|
47
|
+
return jsx("div", {
|
|
48
|
+
"data-swipe-actions": side,
|
|
49
|
+
"aria-hidden": open ? undefined : true,
|
|
50
|
+
className: cn("absolute inset-y-0 flex overflow-hidden", side === "leading" ? "left-0" : "right-0 flex-row", !dragging && cn("transition-[width]", MOTION)),
|
|
51
|
+
style: {
|
|
52
|
+
width: width
|
|
53
|
+
},
|
|
54
|
+
children: ordered.map(function (action, idx) {
|
|
55
|
+
var _action$key;
|
|
56
|
+
var grow = armed && action === first;
|
|
57
|
+
var collapsed = armed && action !== first;
|
|
58
|
+
return jsxs("button", {
|
|
59
|
+
type: "button",
|
|
60
|
+
tabIndex: open ? 0 : -1,
|
|
61
|
+
disabled: action.disabled || undefined,
|
|
62
|
+
"data-tone": action.tone || "default",
|
|
63
|
+
className: cn("flex min-w-0 flex-col items-center justify-center gap-1 overflow-hidden px-2 text-xs font-medium outline-none", "focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-50", "disabled:cursor-not-allowed disabled:opacity-60", toneClass(action.tone), grow ? "flex-[1_0_auto]" : collapsed ? "w-0 flex-none px-0" : "flex-1", !dragging && cn("transition-[flex-grow,width]", MOTION)),
|
|
64
|
+
onClick: function onClick(e) {
|
|
65
|
+
e.stopPropagation();
|
|
66
|
+
onSelect(action, "button");
|
|
67
|
+
},
|
|
68
|
+
children: [action.icon != null && jsx("span", {
|
|
69
|
+
className: "inline-flex shrink-0",
|
|
70
|
+
"aria-hidden": "true",
|
|
71
|
+
children: renderIcon(action.icon, "h-5 w-5")
|
|
72
|
+
}), jsx("span", {
|
|
73
|
+
className: "max-w-full truncate",
|
|
74
|
+
children: action.label
|
|
75
|
+
})]
|
|
76
|
+
}, (_action$key = action.key) !== null && _action$key !== void 0 ? _action$key : "".concat(side, "-").concat(idx));
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
var SwipeableListItem = /*#__PURE__*/React.forwardRef(function SwipeableListItem(_ref2, _ref4) {
|
|
81
|
+
var _ref2$as = _ref2.as,
|
|
82
|
+
Component = _ref2$as === void 0 ? "div" : _ref2$as,
|
|
83
|
+
children = _ref2.children,
|
|
84
|
+
_ref2$leadingActions = _ref2.leadingActions,
|
|
85
|
+
leadingActions = _ref2$leadingActions === void 0 ? [] : _ref2$leadingActions,
|
|
86
|
+
_ref2$trailingActions = _ref2.trailingActions,
|
|
87
|
+
trailingActions = _ref2$trailingActions === void 0 ? [] : _ref2$trailingActions,
|
|
88
|
+
_ref2$fullSwipe = _ref2.fullSwipe,
|
|
89
|
+
fullSwipe = _ref2$fullSwipe === void 0 ? true : _ref2$fullSwipe,
|
|
90
|
+
_ref2$fullSwipeThresh = _ref2.fullSwipeThreshold,
|
|
91
|
+
fullSwipeThreshold = _ref2$fullSwipeThresh === void 0 ? 0.6 : _ref2$fullSwipeThresh,
|
|
92
|
+
_ref2$actionWidth = _ref2.actionWidth,
|
|
93
|
+
actionWidth = _ref2$actionWidth === void 0 ? 80 : _ref2$actionWidth,
|
|
94
|
+
open = _ref2.open,
|
|
95
|
+
_ref2$defaultOpen = _ref2.defaultOpen,
|
|
96
|
+
defaultOpen = _ref2$defaultOpen === void 0 ? null : _ref2$defaultOpen,
|
|
97
|
+
onOpenChange = _ref2.onOpenChange,
|
|
98
|
+
_ref2$disabled = _ref2.disabled,
|
|
99
|
+
disabled = _ref2$disabled === void 0 ? false : _ref2$disabled,
|
|
100
|
+
_ref2$moreActions = _ref2.moreActions,
|
|
101
|
+
moreActions = _ref2$moreActions === void 0 ? "focus" : _ref2$moreActions,
|
|
102
|
+
_ref2$moreActionsLabe = _ref2.moreActionsLabel,
|
|
103
|
+
moreActionsLabel = _ref2$moreActionsLabe === void 0 ? "More actions" : _ref2$moreActionsLabe,
|
|
104
|
+
_ref2$menuPresentatio = _ref2.menuPresentation,
|
|
105
|
+
menuPresentation = _ref2$menuPresentatio === void 0 ? "auto" : _ref2$menuPresentatio,
|
|
106
|
+
contentClassName = _ref2.contentClassName,
|
|
107
|
+
className = _ref2.className,
|
|
108
|
+
onKeyDown = _ref2.onKeyDown,
|
|
109
|
+
rest = _objectWithoutProperties(_ref2, _excluded);
|
|
110
|
+
var leading = useMemo(function () {
|
|
111
|
+
return Array.isArray(leadingActions) ? leadingActions : [];
|
|
112
|
+
}, [leadingActions]);
|
|
113
|
+
var trailing = useMemo(function () {
|
|
114
|
+
return Array.isArray(trailingActions) ? trailingActions : [];
|
|
115
|
+
}, [trailingActions]);
|
|
116
|
+
var widths = useMemo(function () {
|
|
117
|
+
return {
|
|
118
|
+
leading: leading.length * actionWidth,
|
|
119
|
+
trailing: trailing.length * actionWidth
|
|
120
|
+
};
|
|
121
|
+
}, [leading.length, trailing.length, actionWidth]);
|
|
122
|
+
var _useControllableState = useControllableState({
|
|
123
|
+
value: open,
|
|
124
|
+
defaultValue: defaultOpen,
|
|
125
|
+
onChange: onOpenChange
|
|
126
|
+
}),
|
|
127
|
+
_useControllableState2 = _slicedToArray(_useControllableState, 2),
|
|
128
|
+
rawOpenSide = _useControllableState2[0],
|
|
129
|
+
setOpenSide = _useControllableState2[1];
|
|
130
|
+
// A side without actions can't be open.
|
|
131
|
+
var openSide = rawOpenSide && widths[rawOpenSide] > 0 ? rawOpenSide : null;
|
|
132
|
+
var rootRef = useRef(null);
|
|
133
|
+
var _useState = useState(null),
|
|
134
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
135
|
+
moreButtonEl = _useState2[0],
|
|
136
|
+
setMoreButtonEl = _useState2[1];
|
|
137
|
+
var _useState3 = useState(false),
|
|
138
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
139
|
+
menuOpen = _useState4[0],
|
|
140
|
+
setMenuOpen = _useState4[1];
|
|
141
|
+
var close = useCallback(function () {
|
|
142
|
+
if (openSide != null) setOpenSide(null);
|
|
143
|
+
}, [openSide, setOpenSide]);
|
|
144
|
+
var runAction = useCallback(function (action, source) {
|
|
145
|
+
var _action$onSelect;
|
|
146
|
+
if (!action || action.disabled) return;
|
|
147
|
+
(_action$onSelect = action.onSelect) === null || _action$onSelect === void 0 || _action$onSelect.call(action, {
|
|
148
|
+
action: action,
|
|
149
|
+
source: source
|
|
150
|
+
});
|
|
151
|
+
setOpenSide(null);
|
|
152
|
+
}, [setOpenSide]);
|
|
153
|
+
var allowFull = _typeof(fullSwipe) === "object" && fullSwipe !== null ? {
|
|
154
|
+
leading: fullSwipe.leading !== false,
|
|
155
|
+
trailing: fullSwipe.trailing !== false
|
|
156
|
+
} : {
|
|
157
|
+
leading: Boolean(fullSwipe),
|
|
158
|
+
trailing: Boolean(fullSwipe)
|
|
159
|
+
};
|
|
160
|
+
var onSettle = function onSettle(_ref3) {
|
|
161
|
+
var side = _ref3.side,
|
|
162
|
+
commit = _ref3.commit;
|
|
163
|
+
if (commit) {
|
|
164
|
+
runAction((side === "leading" ? leading : trailing)[0], "full-swipe");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (side !== openSide) setOpenSide(side);
|
|
168
|
+
};
|
|
169
|
+
var enabled = !disabled && (widths.leading > 0 || widths.trailing > 0);
|
|
170
|
+
var _useSwipeGesture = useSwipeGesture({
|
|
171
|
+
enabled: enabled,
|
|
172
|
+
widths: widths,
|
|
173
|
+
openSide: openSide,
|
|
174
|
+
fullSwipe: allowFull,
|
|
175
|
+
fullSwipeThreshold: fullSwipeThreshold,
|
|
176
|
+
onSettle: onSettle
|
|
177
|
+
}),
|
|
178
|
+
offset = _useSwipeGesture.offset,
|
|
179
|
+
dragging = _useSwipeGesture.dragging,
|
|
180
|
+
armed = _useSwipeGesture.armed,
|
|
181
|
+
handlers = _useSwipeGesture.handlers,
|
|
182
|
+
consumeClick = _useSwipeGesture.consumeClick;
|
|
183
|
+
useClickOutside([rootRef], close, {
|
|
184
|
+
enabled: openSide != null
|
|
185
|
+
});
|
|
186
|
+
var x = offset !== null && offset !== void 0 ? offset : restingOffset(openSide, widths);
|
|
187
|
+
var menuItems = useMemo(function () {
|
|
188
|
+
return [].concat(_toConsumableArray(leading), _toConsumableArray(trailing)).map(function (action, idx) {
|
|
189
|
+
var _action$key2;
|
|
190
|
+
return {
|
|
191
|
+
key: (_action$key2 = action.key) !== null && _action$key2 !== void 0 ? _action$key2 : "action-".concat(idx),
|
|
192
|
+
label: action.label,
|
|
193
|
+
icon: action.icon != null ? renderIcon(action.icon, "h-4 w-4") : null,
|
|
194
|
+
disabled: Boolean(action.disabled),
|
|
195
|
+
tone: isMenuDestructive(action.tone) ? "destructive" : "default",
|
|
196
|
+
onSelect: function onSelect() {
|
|
197
|
+
return runAction(action, "menu");
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
}, [leading, trailing, runAction]);
|
|
202
|
+
var hasActions = menuItems.length > 0;
|
|
203
|
+
var showMore = hasActions && moreActions !== false && !disabled;
|
|
204
|
+
var handleKeyDown = function handleKeyDown(e) {
|
|
205
|
+
onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
|
|
206
|
+
if (e.defaultPrevented) return;
|
|
207
|
+
if (e.key === "Escape" && openSide != null) {
|
|
208
|
+
e.stopPropagation();
|
|
209
|
+
setOpenSide(null);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
return jsxs(Component, _objectSpread2(_objectSpread2({
|
|
213
|
+
ref: function ref(node) {
|
|
214
|
+
return setRefs(node, rootRef, _ref4);
|
|
215
|
+
},
|
|
216
|
+
"data-swipe-open": openSide !== null && openSide !== void 0 ? openSide : undefined,
|
|
217
|
+
"data-swiping": dragging || undefined,
|
|
218
|
+
className: cn("group/swipe relative isolate overflow-hidden", className),
|
|
219
|
+
onKeyDown: handleKeyDown
|
|
220
|
+
}, rest), {}, {
|
|
221
|
+
children: [widths.leading > 0 && jsx(ActionPanel, {
|
|
222
|
+
side: "leading",
|
|
223
|
+
actions: leading,
|
|
224
|
+
width: Math.max(0, x),
|
|
225
|
+
open: openSide === "leading",
|
|
226
|
+
armed: armed === "leading",
|
|
227
|
+
dragging: dragging,
|
|
228
|
+
onSelect: runAction
|
|
229
|
+
}), widths.trailing > 0 && jsx(ActionPanel, {
|
|
230
|
+
side: "trailing",
|
|
231
|
+
actions: trailing,
|
|
232
|
+
width: Math.max(0, -x),
|
|
233
|
+
open: openSide === "trailing",
|
|
234
|
+
armed: armed === "trailing",
|
|
235
|
+
dragging: dragging,
|
|
236
|
+
onSelect: runAction
|
|
237
|
+
}), jsx("div", _objectSpread2(_objectSpread2({
|
|
238
|
+
"data-swipe-content": "",
|
|
239
|
+
className: cn("relative bg-surface touch-pan-y", dragging ? "select-none" : cn("transition-transform", MOTION), contentClassName),
|
|
240
|
+
style: x ? {
|
|
241
|
+
transform: "translate3d(".concat(x, "px, 0, 0)")
|
|
242
|
+
} : undefined
|
|
243
|
+
}, handlers), {}, {
|
|
244
|
+
onClickCapture: function onClickCapture(e) {
|
|
245
|
+
// The click that ends a swipe, or a tap on an open row, only closes.
|
|
246
|
+
var endedSwipe = consumeClick();
|
|
247
|
+
if (!endedSwipe && openSide == null) return;
|
|
248
|
+
e.stopPropagation();
|
|
249
|
+
e.preventDefault();
|
|
250
|
+
if (!endedSwipe) close();
|
|
251
|
+
},
|
|
252
|
+
children: children
|
|
253
|
+
})), showMore && jsx("button", {
|
|
254
|
+
ref: setMoreButtonEl,
|
|
255
|
+
type: "button",
|
|
256
|
+
"aria-label": moreActionsLabel,
|
|
257
|
+
"aria-haspopup": "menu",
|
|
258
|
+
"aria-expanded": menuOpen,
|
|
259
|
+
"data-swipe-more": "",
|
|
260
|
+
className: cn("absolute right-2 top-1/2 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full", "border border-line bg-surface text-foreground shadow-sm outline-none", "focus-visible:ring-2 focus-visible:ring-primary-500 transition-opacity duration-fast motion-reduce:transition-none", moreActions === "focus" && !menuOpen && "pointer-events-none opacity-0 focus-visible:pointer-events-auto focus-visible:opacity-100 [@media(hover:hover)]:group-hover/swipe:pointer-events-auto [@media(hover:hover)]:group-hover/swipe:opacity-100", openSide != null && "hidden"),
|
|
261
|
+
onClick: function onClick(e) {
|
|
262
|
+
e.stopPropagation();
|
|
263
|
+
setMenuOpen(function (v) {
|
|
264
|
+
return !v;
|
|
265
|
+
});
|
|
266
|
+
},
|
|
267
|
+
children: jsx(MoreHorizontal, {
|
|
268
|
+
className: "h-5 w-5",
|
|
269
|
+
"aria-hidden": "true"
|
|
270
|
+
})
|
|
271
|
+
}), showMore && jsx(ActionMenuSurface, {
|
|
272
|
+
open: menuOpen,
|
|
273
|
+
onClose: function onClose() {
|
|
274
|
+
return setMenuOpen(false);
|
|
275
|
+
},
|
|
276
|
+
anchorEl: moreButtonEl,
|
|
277
|
+
items: menuItems,
|
|
278
|
+
presentation: menuPresentation,
|
|
279
|
+
placement: "bottom-end",
|
|
280
|
+
label: moreActionsLabel
|
|
281
|
+
})]
|
|
282
|
+
}));
|
|
283
|
+
});
|
|
284
|
+
SwipeableListItem.displayName = "SwipeableListItem";
|
|
285
|
+
|
|
286
|
+
export { SwipeableListItem as default };
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { slicedToArray as _slicedToArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { useState, useRef, useCallback } from 'react';
|
|
4
|
+
import { useLatestRef } from '../../hooks/useLatestRef.js';
|
|
5
|
+
import { rubberBand, FLICK_VELOCITY } from '../../hooks/useSheetDrag.js';
|
|
6
|
+
|
|
7
|
+
// Internal (not exported). The horizontal swipe gesture behind
|
|
8
|
+
// SwipeableListItem. Offsets are in px; positive moves the content right
|
|
9
|
+
// (revealing the leading actions), negative moves it left (trailing).
|
|
10
|
+
//
|
|
11
|
+
// The gesture only starts once horizontal movement dominates, so a vertical
|
|
12
|
+
// pan scrolls the page as usual (pair with `touch-action: pan-y`). Past the
|
|
13
|
+
// revealed actions the content rubber-bands, unless a full swipe is possible,
|
|
14
|
+
// in which case it follows the finger up to the row width.
|
|
15
|
+
var SLOP = 6; // px before a press becomes a swipe (or a scroll)
|
|
16
|
+
var VELOCITY_WINDOW = 100; // ms of recent samples used for release velocity
|
|
17
|
+
var FULL_SWIPE_MARGIN = 24; // px a full swipe must travel past the revealed actions
|
|
18
|
+
var FALLBACK_WIDTH = 320; // px, when the row has no layout (jsdom, hidden)
|
|
19
|
+
var now = function now() {
|
|
20
|
+
return Date.now();
|
|
21
|
+
};
|
|
22
|
+
var sideOf = function sideOf(offset) {
|
|
23
|
+
return offset > 0 ? "leading" : offset < 0 ? "trailing" : null;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Where the content rests for an open side.
|
|
27
|
+
* @param {'leading'|'trailing'|null} side
|
|
28
|
+
* @param {{ leading: number, trailing: number }} widths - revealed widths in px.
|
|
29
|
+
*/
|
|
30
|
+
function restingOffset(side, widths) {
|
|
31
|
+
if (side === "leading") return widths.leading;
|
|
32
|
+
if (side === "trailing") return -widths.trailing;
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
/** Distance (px) past which releasing commits the side's first action. */
|
|
36
|
+
function fullSwipeDistance(reveal, width, threshold) {
|
|
37
|
+
return Math.max(reveal + FULL_SWIPE_MARGIN, width * threshold);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Maps a raw finger offset to the displayed offset for one side.
|
|
41
|
+
* @param {number} raw - px, signed.
|
|
42
|
+
* @param {{ reveal: number, fullSwipe: boolean, width: number }} opts
|
|
43
|
+
*/
|
|
44
|
+
function constrainOffset(raw, _ref) {
|
|
45
|
+
var reveal = _ref.reveal,
|
|
46
|
+
fullSwipe = _ref.fullSwipe,
|
|
47
|
+
width = _ref.width;
|
|
48
|
+
var sign = Math.sign(raw);
|
|
49
|
+
var distance = Math.abs(raw);
|
|
50
|
+
var limit = reveal > 0 && fullSwipe ? width : reveal;
|
|
51
|
+
if (distance <= limit) return raw;
|
|
52
|
+
return sign * (limit + rubberBand(distance - limit, width));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* @param {{
|
|
56
|
+
* enabled: boolean,
|
|
57
|
+
* widths: { leading: number, trailing: number },
|
|
58
|
+
* openSide: 'leading'|'trailing'|null,
|
|
59
|
+
* fullSwipe: { leading: boolean, trailing: boolean },
|
|
60
|
+
* fullSwipeThreshold: number,
|
|
61
|
+
* onSettle: (r: { side: 'leading'|'trailing'|null, commit: boolean }) => void,
|
|
62
|
+
* }} options
|
|
63
|
+
* @returns {{ offset: number|null, dragging: boolean, armed: 'leading'|'trailing'|null,
|
|
64
|
+
* handlers: object, consumeClick: () => boolean }}
|
|
65
|
+
*/
|
|
66
|
+
function useSwipeGesture(_ref2) {
|
|
67
|
+
var enabled = _ref2.enabled,
|
|
68
|
+
widths = _ref2.widths,
|
|
69
|
+
openSide = _ref2.openSide,
|
|
70
|
+
fullSwipe = _ref2.fullSwipe,
|
|
71
|
+
fullSwipeThreshold = _ref2.fullSwipeThreshold,
|
|
72
|
+
onSettle = _ref2.onSettle;
|
|
73
|
+
// `{ offset, width }` while a swipe is in progress, else null.
|
|
74
|
+
var _useState = useState(null),
|
|
75
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
76
|
+
drag = _useState2[0],
|
|
77
|
+
setDrag = _useState2[1];
|
|
78
|
+
var gesture = useRef(null);
|
|
79
|
+
var swallowClick = useRef(false);
|
|
80
|
+
var latest = useLatestRef({
|
|
81
|
+
widths: widths,
|
|
82
|
+
openSide: openSide,
|
|
83
|
+
fullSwipe: fullSwipe,
|
|
84
|
+
fullSwipeThreshold: fullSwipeThreshold,
|
|
85
|
+
onSettle: onSettle
|
|
86
|
+
});
|
|
87
|
+
var reset = useCallback(function () {
|
|
88
|
+
gesture.current = null;
|
|
89
|
+
setDrag(null);
|
|
90
|
+
}, []);
|
|
91
|
+
var onPointerDown = useCallback(function (e) {
|
|
92
|
+
var _el$getBoundingClient;
|
|
93
|
+
if (!enabled || e.button !== undefined && e.button !== 0) return;
|
|
94
|
+
var el = e.currentTarget;
|
|
95
|
+
var width = ((_el$getBoundingClient = el.getBoundingClientRect) === null || _el$getBoundingClient === void 0 ? void 0 : _el$getBoundingClient.call(el).width) || el.offsetWidth || FALLBACK_WIDTH;
|
|
96
|
+
var start = restingOffset(latest.current.openSide, latest.current.widths);
|
|
97
|
+
gesture.current = {
|
|
98
|
+
x: e.clientX,
|
|
99
|
+
y: e.clientY,
|
|
100
|
+
start: start,
|
|
101
|
+
width: width,
|
|
102
|
+
el: el,
|
|
103
|
+
pointerId: e.pointerId,
|
|
104
|
+
active: false,
|
|
105
|
+
current: start,
|
|
106
|
+
samples: [{
|
|
107
|
+
o: start,
|
|
108
|
+
t: now()
|
|
109
|
+
}]
|
|
110
|
+
};
|
|
111
|
+
swallowClick.current = false;
|
|
112
|
+
}, [enabled, latest]);
|
|
113
|
+
var onPointerMove = useCallback(function (e) {
|
|
114
|
+
var g = gesture.current;
|
|
115
|
+
if (!g) return;
|
|
116
|
+
var dx = e.clientX - g.x;
|
|
117
|
+
var dy = e.clientY - g.y;
|
|
118
|
+
if (!g.active) {
|
|
119
|
+
if (Math.max(Math.abs(dx), Math.abs(dy)) < SLOP) return;
|
|
120
|
+
if (Math.abs(dy) >= Math.abs(dx)) {
|
|
121
|
+
gesture.current = null; // a vertical pan: let the page scroll
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
g.active = true;
|
|
125
|
+
swallowClick.current = true;
|
|
126
|
+
try {
|
|
127
|
+
var _g$el, _g$el$setPointerCaptu;
|
|
128
|
+
(_g$el = g.el) === null || _g$el === void 0 || (_g$el$setPointerCaptu = _g$el.setPointerCapture) === null || _g$el$setPointerCaptu === void 0 || _g$el$setPointerCaptu.call(_g$el, g.pointerId);
|
|
129
|
+
} catch (_unused) {
|
|
130
|
+
// The pointer may already be gone (synthetic events, fast lifts).
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
var raw = g.start + dx;
|
|
134
|
+
var side = sideOf(raw);
|
|
135
|
+
var _latest$current = latest.current,
|
|
136
|
+
w = _latest$current.widths,
|
|
137
|
+
fs = _latest$current.fullSwipe;
|
|
138
|
+
var next = side ? constrainOffset(raw, {
|
|
139
|
+
reveal: w[side],
|
|
140
|
+
fullSwipe: fs[side],
|
|
141
|
+
width: g.width
|
|
142
|
+
}) : 0;
|
|
143
|
+
g.current = next;
|
|
144
|
+
var t = now();
|
|
145
|
+
g.samples.push({
|
|
146
|
+
o: next,
|
|
147
|
+
t: t
|
|
148
|
+
});
|
|
149
|
+
while (g.samples.length > 2 && t - g.samples[0].t > VELOCITY_WINDOW) g.samples.shift();
|
|
150
|
+
setDrag({
|
|
151
|
+
offset: next,
|
|
152
|
+
width: g.width
|
|
153
|
+
});
|
|
154
|
+
}, [latest]);
|
|
155
|
+
var onPointerUp = useCallback(function () {
|
|
156
|
+
var g = gesture.current;
|
|
157
|
+
if (!g) return;
|
|
158
|
+
gesture.current = null;
|
|
159
|
+
if (!g.active) return;
|
|
160
|
+
var _latest$current2 = latest.current,
|
|
161
|
+
w = _latest$current2.widths,
|
|
162
|
+
fs = _latest$current2.fullSwipe,
|
|
163
|
+
t = _latest$current2.fullSwipeThreshold,
|
|
164
|
+
settle = _latest$current2.onSettle;
|
|
165
|
+
var value = g.current;
|
|
166
|
+
var side = sideOf(value);
|
|
167
|
+
var first = g.samples[0];
|
|
168
|
+
var velocity = (value - first.o) / Math.max(1, now() - first.t);
|
|
169
|
+
setDrag(null);
|
|
170
|
+
if (!side || w[side] === 0) {
|
|
171
|
+
settle({
|
|
172
|
+
side: null,
|
|
173
|
+
commit: false
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (fs[side] && Math.abs(value) >= fullSwipeDistance(w[side], g.width, t)) {
|
|
178
|
+
settle({
|
|
179
|
+
side: side,
|
|
180
|
+
commit: true
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
// A flick decides by direction; otherwise past half the actions opens.
|
|
185
|
+
var towardOpen = side === "leading" ? velocity > 0 : velocity < 0;
|
|
186
|
+
var flick = Math.abs(velocity) >= FLICK_VELOCITY;
|
|
187
|
+
var open = flick ? towardOpen : Math.abs(value) >= w[side] / 2;
|
|
188
|
+
settle({
|
|
189
|
+
side: open ? side : null,
|
|
190
|
+
commit: false
|
|
191
|
+
});
|
|
192
|
+
}, [latest]);
|
|
193
|
+
var onPointerCancel = useCallback(function () {
|
|
194
|
+
swallowClick.current = false;
|
|
195
|
+
reset();
|
|
196
|
+
}, [reset]);
|
|
197
|
+
// The click that ends a swipe must not activate the row.
|
|
198
|
+
var consumeClick = useCallback(function () {
|
|
199
|
+
if (!swallowClick.current) return false;
|
|
200
|
+
swallowClick.current = false;
|
|
201
|
+
return true;
|
|
202
|
+
}, []);
|
|
203
|
+
var dragSide = drag ? sideOf(drag.offset) : null;
|
|
204
|
+
var armed = dragSide && fullSwipe[dragSide] && widths[dragSide] > 0 && Math.abs(drag.offset) >= fullSwipeDistance(widths[dragSide], drag.width, fullSwipeThreshold) ? dragSide : null;
|
|
205
|
+
return {
|
|
206
|
+
offset: drag ? drag.offset : null,
|
|
207
|
+
dragging: drag != null,
|
|
208
|
+
armed: armed,
|
|
209
|
+
consumeClick: consumeClick,
|
|
210
|
+
handlers: enabled ? {
|
|
211
|
+
onPointerDown: onPointerDown,
|
|
212
|
+
onPointerMove: onPointerMove,
|
|
213
|
+
onPointerUp: onPointerUp,
|
|
214
|
+
onPointerCancel: onPointerCancel
|
|
215
|
+
} : {}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export { FALLBACK_WIDTH, constrainOffset, fullSwipeDistance, restingOffset, useSwipeGesture };
|
|
@@ -3,8 +3,9 @@ import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _
|
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
import { forwardRef, useState, useId, useEffect, useRef } from 'react';
|
|
5
5
|
import { cn } from '../../utils/cn.js';
|
|
6
|
+
import { useHaptics } from '../../hooks/useHaptics.js';
|
|
6
7
|
|
|
7
|
-
var _excluded = ["id", "name", "checked", "defaultChecked", "onChange", "disabled", "size", "color", "trackClass", "thumbClass", "className", "topLabel", "bottomLabel", "rightLabel", "leftLabel", "ariaLabel", "onPointerDown", "onPointerMove", "onPointerUp", "onPointerCancel"];
|
|
8
|
+
var _excluded = ["id", "name", "checked", "defaultChecked", "onChange", "disabled", "size", "color", "trackClass", "thumbClass", "className", "topLabel", "bottomLabel", "rightLabel", "leftLabel", "ariaLabel", "onPointerDown", "onPointerMove", "onPointerUp", "onPointerCancel", "haptics"];
|
|
8
9
|
/**
|
|
9
10
|
* Switch.jsx
|
|
10
11
|
* - Plain JSX (no TypeScript)
|
|
@@ -40,6 +41,8 @@ var SIZE_MAP = {
|
|
|
40
41
|
};
|
|
41
42
|
// Horizontal travel (px) before a press becomes a drag.
|
|
42
43
|
var DRAG_THRESHOLD = 4;
|
|
44
|
+
// Token presets only: the raw-palette presets (blue / indigo / purple) were
|
|
45
|
+
// removed in 2.0.0 (DTUI-65).
|
|
43
46
|
var COLOR_PRESETS = {
|
|
44
47
|
primary: {
|
|
45
48
|
bg: "bg-primary-600",
|
|
@@ -72,18 +75,6 @@ var COLOR_PRESETS = {
|
|
|
72
75
|
warning: {
|
|
73
76
|
bg: "bg-warning-600",
|
|
74
77
|
ring: "focus-visible:ring-warning-300"
|
|
75
|
-
},
|
|
76
|
-
blue: {
|
|
77
|
-
bg: "bg-blue-600",
|
|
78
|
-
ring: "focus-visible:ring-blue-300"
|
|
79
|
-
},
|
|
80
|
-
indigo: {
|
|
81
|
-
bg: "bg-indigo-600",
|
|
82
|
-
ring: "focus-visible:ring-indigo-300"
|
|
83
|
-
},
|
|
84
|
-
purple: {
|
|
85
|
-
bg: "bg-purple-600",
|
|
86
|
-
ring: "focus-visible:ring-purple-300"
|
|
87
78
|
}
|
|
88
79
|
};
|
|
89
80
|
var Switch = /*#__PURE__*/forwardRef(function Switch(props, ref) {
|
|
@@ -112,6 +103,8 @@ var Switch = /*#__PURE__*/forwardRef(function Switch(props, ref) {
|
|
|
112
103
|
onPointerMove = props.onPointerMove,
|
|
113
104
|
onPointerUp = props.onPointerUp,
|
|
114
105
|
onPointerCancel = props.onPointerCancel,
|
|
106
|
+
_props$haptics = props.haptics,
|
|
107
|
+
haptics = _props$haptics === void 0 ? false : _props$haptics,
|
|
115
108
|
rest = _objectWithoutProperties(props, _excluded);
|
|
116
109
|
var isControlled = typeof checked === "boolean";
|
|
117
110
|
var _useState = useState(defaultChecked),
|
|
@@ -132,9 +125,14 @@ var Switch = /*#__PURE__*/forwardRef(function Switch(props, ref) {
|
|
|
132
125
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
133
126
|
dragPreview = _useState4[0],
|
|
134
127
|
setDragPreview = _useState4[1];
|
|
128
|
+
var _useHaptics = useHaptics({
|
|
129
|
+
enabled: haptics
|
|
130
|
+
}),
|
|
131
|
+
haptic = _useHaptics.trigger;
|
|
135
132
|
var setOn = function setOn(next) {
|
|
136
133
|
if (disabled || next === isOn) return;
|
|
137
134
|
if (!isControlled) setInternalChecked(next);
|
|
135
|
+
haptic("selection");
|
|
138
136
|
onChange && onChange(next);
|
|
139
137
|
};
|
|
140
138
|
var toggle = function toggle() {
|