@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,132 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
import React, { useRef, useCallback, useSyncExternalStore, useEffect } from 'react';
|
|
5
|
+
import { cn } from '../../utils/cn.js';
|
|
6
|
+
import { setRefs } from '../../utils/position.js';
|
|
7
|
+
|
|
8
|
+
var _excluded = ["children", "position", "align", "fullWidth", "stackOnMobile", "keyboardAware", "className", "style"],
|
|
9
|
+
_excluded2 = ["className"];
|
|
10
|
+
// Sticky bar at the bottom of the screen for the primary action on forms and
|
|
11
|
+
// checkout pages (DTUI-57). Pads the home indicator (pb-safe), sits on the
|
|
12
|
+
// z-sticky layer and rides above the on-screen keyboard via visualViewport.
|
|
13
|
+
/** CSS variable the bar publishes with its height, read by BottomActionBar.Spacer. */
|
|
14
|
+
var BAR_HEIGHT_VAR = '--dt-bottom-action-bar-height';
|
|
15
|
+
// Part of the layout viewport the on-screen keyboard covers (0 without visualViewport).
|
|
16
|
+
function readKeyboardOffset() {
|
|
17
|
+
if (typeof window === 'undefined') return 0;
|
|
18
|
+
var vv = window.visualViewport;
|
|
19
|
+
if (!vv) return 0;
|
|
20
|
+
var inner = window.innerHeight || 0;
|
|
21
|
+
return Math.max(0, Math.round(inner - (vv.height || inner) - (vv.offsetTop || 0)));
|
|
22
|
+
}
|
|
23
|
+
var getServerOffset = function getServerOffset() {
|
|
24
|
+
return 0;
|
|
25
|
+
};
|
|
26
|
+
/** Keyboard offset in px while `active`; 0 on the server and without visualViewport. */
|
|
27
|
+
function useKeyboardOffset(active) {
|
|
28
|
+
var subscribe = useCallback(function (onChange) {
|
|
29
|
+
var _vv$addEventListener, _vv$addEventListener2;
|
|
30
|
+
if (!active || typeof window === 'undefined') return function () {};
|
|
31
|
+
var vv = window.visualViewport;
|
|
32
|
+
vv === null || vv === void 0 || (_vv$addEventListener = vv.addEventListener) === null || _vv$addEventListener === void 0 || _vv$addEventListener.call(vv, 'resize', onChange);
|
|
33
|
+
vv === null || vv === void 0 || (_vv$addEventListener2 = vv.addEventListener) === null || _vv$addEventListener2 === void 0 || _vv$addEventListener2.call(vv, 'scroll', onChange);
|
|
34
|
+
window.addEventListener('resize', onChange);
|
|
35
|
+
return function () {
|
|
36
|
+
var _vv$removeEventListen, _vv$removeEventListen2;
|
|
37
|
+
vv === null || vv === void 0 || (_vv$removeEventListen = vv.removeEventListener) === null || _vv$removeEventListen === void 0 || _vv$removeEventListen.call(vv, 'resize', onChange);
|
|
38
|
+
vv === null || vv === void 0 || (_vv$removeEventListen2 = vv.removeEventListener) === null || _vv$removeEventListen2 === void 0 || _vv$removeEventListen2.call(vv, 'scroll', onChange);
|
|
39
|
+
window.removeEventListener('resize', onChange);
|
|
40
|
+
};
|
|
41
|
+
}, [active]);
|
|
42
|
+
var getSnapshot = function getSnapshot() {
|
|
43
|
+
return active ? readKeyboardOffset() : 0;
|
|
44
|
+
};
|
|
45
|
+
return useSyncExternalStore(subscribe, getSnapshot, getServerOffset);
|
|
46
|
+
}
|
|
47
|
+
/** Publishes the fixed bar's height as a CSS variable on <html> so the Spacer can match it. */
|
|
48
|
+
function usePublishedHeight(nodeRef, enabled) {
|
|
49
|
+
useEffect(function () {
|
|
50
|
+
var node = nodeRef.current;
|
|
51
|
+
if (!enabled || !node || typeof document === 'undefined') return undefined;
|
|
52
|
+
var root = document.documentElement;
|
|
53
|
+
var publish = function publish() {
|
|
54
|
+
var _node$getBoundingClie;
|
|
55
|
+
var h = ((_node$getBoundingClie = node.getBoundingClientRect) === null || _node$getBoundingClie === void 0 ? void 0 : _node$getBoundingClie.call(node).height) || 0;
|
|
56
|
+
if (h > 0) root.style.setProperty(BAR_HEIGHT_VAR, "".concat(Math.round(h), "px"));
|
|
57
|
+
};
|
|
58
|
+
publish();
|
|
59
|
+
var observer;
|
|
60
|
+
if (typeof window.ResizeObserver === 'function') {
|
|
61
|
+
observer = new window.ResizeObserver(publish);
|
|
62
|
+
observer.observe(node);
|
|
63
|
+
}
|
|
64
|
+
return function () {
|
|
65
|
+
var _observer;
|
|
66
|
+
(_observer = observer) === null || _observer === void 0 || _observer.disconnect();
|
|
67
|
+
root.style.removeProperty(BAR_HEIGHT_VAR);
|
|
68
|
+
};
|
|
69
|
+
}, [nodeRef, enabled]);
|
|
70
|
+
}
|
|
71
|
+
var ALIGN = {
|
|
72
|
+
start: 'justify-start',
|
|
73
|
+
center: 'justify-center',
|
|
74
|
+
end: 'justify-end',
|
|
75
|
+
between: 'justify-between'
|
|
76
|
+
};
|
|
77
|
+
var BottomActionBar = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
78
|
+
var children = _ref.children,
|
|
79
|
+
_ref$position = _ref.position,
|
|
80
|
+
position = _ref$position === void 0 ? 'fixed' : _ref$position,
|
|
81
|
+
_ref$align = _ref.align,
|
|
82
|
+
align = _ref$align === void 0 ? 'end' : _ref$align,
|
|
83
|
+
_ref$fullWidth = _ref.fullWidth,
|
|
84
|
+
fullWidth = _ref$fullWidth === void 0 ? false : _ref$fullWidth,
|
|
85
|
+
_ref$stackOnMobile = _ref.stackOnMobile,
|
|
86
|
+
stackOnMobile = _ref$stackOnMobile === void 0 ? false : _ref$stackOnMobile,
|
|
87
|
+
_ref$keyboardAware = _ref.keyboardAware,
|
|
88
|
+
keyboardAware = _ref$keyboardAware === void 0 ? true : _ref$keyboardAware,
|
|
89
|
+
className = _ref.className,
|
|
90
|
+
style = _ref.style,
|
|
91
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
92
|
+
var localRef = useRef(null);
|
|
93
|
+
var setRef = useCallback(function (node) {
|
|
94
|
+
return setRefs(node, localRef, ref);
|
|
95
|
+
}, [ref]);
|
|
96
|
+
var fixed = position !== 'sticky';
|
|
97
|
+
var offset = useKeyboardOffset(keyboardAware);
|
|
98
|
+
usePublishedHeight(localRef, fixed);
|
|
99
|
+
// Above the keyboard the home indicator is covered, so the safe-area pad goes.
|
|
100
|
+
var lifted = offset > 0;
|
|
101
|
+
var barStyle = lifted ? _objectSpread2(_objectSpread2({}, style), {}, {
|
|
102
|
+
bottom: "".concat(offset, "px")
|
|
103
|
+
}) : style;
|
|
104
|
+
return jsx("div", _objectSpread2(_objectSpread2({
|
|
105
|
+
ref: setRef,
|
|
106
|
+
"data-position": fixed ? 'fixed' : 'sticky',
|
|
107
|
+
"data-keyboard": lifted ? 'open' : undefined,
|
|
108
|
+
className: cn(fixed ? 'fixed inset-x-0 bottom-0' : 'sticky bottom-0', 'z-sticky border-t border-line bg-surface text-foreground px-safe', 'shadow-[0_-4px_12px_-4px_rgb(0_0_0/calc(0.12*var(--dt-shadow-strength,1)))]', 'transition-[bottom] duration-fast ease-standard motion-reduce:transition-none', !lifted && 'pb-safe', className),
|
|
109
|
+
style: barStyle
|
|
110
|
+
}, props), {}, {
|
|
111
|
+
children: jsx("div", {
|
|
112
|
+
className: cn('mx-auto flex w-full max-w-7xl items-center gap-3 px-4 py-3 md:px-8', ALIGN[align] || ALIGN.end, fullWidth && 'max-sm:[&>*]:flex-1', stackOnMobile && 'max-sm:flex-col-reverse max-sm:items-stretch max-sm:[&>*]:w-full'),
|
|
113
|
+
children: children
|
|
114
|
+
})
|
|
115
|
+
}));
|
|
116
|
+
});
|
|
117
|
+
BottomActionBar.displayName = 'BottomActionBar';
|
|
118
|
+
// Reserves the fixed bar's height (published by the bar, 4.5rem + safe area
|
|
119
|
+
// before it measures) so the last rows of the page aren't hidden behind it.
|
|
120
|
+
var BottomActionBarSpacer = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
121
|
+
var className = _ref2.className,
|
|
122
|
+
props = _objectWithoutProperties(_ref2, _excluded2);
|
|
123
|
+
return jsx("div", _objectSpread2({
|
|
124
|
+
ref: ref,
|
|
125
|
+
"aria-hidden": "true",
|
|
126
|
+
className: cn('h-[var(--dt-bottom-action-bar-height,calc(4.5rem+env(safe-area-inset-bottom,0px)))] shrink-0', className)
|
|
127
|
+
}, props));
|
|
128
|
+
});
|
|
129
|
+
BottomActionBarSpacer.displayName = 'BottomActionBar.Spacer';
|
|
130
|
+
BottomActionBar.Spacer = BottomActionBarSpacer;
|
|
131
|
+
|
|
132
|
+
export { BAR_HEIGHT_VAR, BottomActionBar as default };
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
3
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
-
import React from 'react';
|
|
4
|
+
import React, { useEffect } from 'react';
|
|
5
5
|
import Dialog from '../feedback/Dialog.js';
|
|
6
6
|
import Button from '../core/Button.js';
|
|
7
|
+
import { usePresentation } from '../../hooks/usePresentation.js';
|
|
8
|
+
import { useHaptics } from '../../hooks/useHaptics.js';
|
|
9
|
+
import { useLatestRef } from '../../hooks/useLatestRef.js';
|
|
7
10
|
|
|
8
|
-
var _excluded = ["isOpen", "title", "description", "confirmLabel", "cancelLabel", "destructive", "loading", "onConfirm", "onCancel", "className"];
|
|
11
|
+
var _excluded = ["isOpen", "title", "description", "confirmLabel", "cancelLabel", "destructive", "loading", "onConfirm", "onCancel", "className", "presentation", "haptics"];
|
|
9
12
|
// Extracted from firepro/components/ui/confirm-dialog.tsx. Replaces native confirm():
|
|
10
13
|
// the title asks the question, one line says what happens, the button is named with the verb.
|
|
14
|
+
//
|
|
15
|
+
// Actions keep the DOM (and Tab) order [cancel, confirm]. `flex-col-reverse`
|
|
16
|
+
// shows the confirm button on top when they stack: below `sm` in the centred
|
|
17
|
+
// modal, and always in sheet mode, where both buttons are full width.
|
|
11
18
|
var ConfirmDialog = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
12
19
|
var isOpen = _ref.isOpen,
|
|
13
20
|
title = _ref.title,
|
|
@@ -22,7 +29,33 @@ var ConfirmDialog = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
22
29
|
onConfirm = _ref.onConfirm,
|
|
23
30
|
onCancel = _ref.onCancel,
|
|
24
31
|
className = _ref.className,
|
|
32
|
+
_ref$presentation = _ref.presentation,
|
|
33
|
+
presentation = _ref$presentation === void 0 ? 'auto' : _ref$presentation,
|
|
34
|
+
_ref$haptics = _ref.haptics,
|
|
35
|
+
haptics = _ref$haptics === void 0 ? false : _ref$haptics,
|
|
25
36
|
props = _objectWithoutProperties(_ref, _excluded);
|
|
37
|
+
// Resolve once here so the footer layout and the Dialog agree on the mode.
|
|
38
|
+
var resolved = usePresentation(presentation);
|
|
39
|
+
var sheet = resolved === 'sheet';
|
|
40
|
+
// Opt-in haptics: a warning buzz when a destructive confirm opens, a success
|
|
41
|
+
// tick on confirm. Only the open transition fires the warning.
|
|
42
|
+
var _useHaptics = useHaptics({
|
|
43
|
+
enabled: haptics
|
|
44
|
+
}),
|
|
45
|
+
haptic = _useHaptics.trigger;
|
|
46
|
+
var openCue = useLatestRef(function () {
|
|
47
|
+
if (destructive) haptic('warning');
|
|
48
|
+
});
|
|
49
|
+
useEffect(function () {
|
|
50
|
+
if (isOpen) openCue.current();
|
|
51
|
+
}, [isOpen, openCue]);
|
|
52
|
+
var handleConfirm = function handleConfirm() {
|
|
53
|
+
haptic('success');
|
|
54
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
55
|
+
args[_key] = arguments[_key];
|
|
56
|
+
}
|
|
57
|
+
return onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm.apply(void 0, args);
|
|
58
|
+
};
|
|
26
59
|
return jsx(Dialog, _objectSpread2(_objectSpread2({
|
|
27
60
|
ref: ref,
|
|
28
61
|
isOpen: isOpen,
|
|
@@ -31,17 +64,20 @@ var ConfirmDialog = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
31
64
|
size: "sm",
|
|
32
65
|
dismissible: !loading,
|
|
33
66
|
className: className,
|
|
67
|
+
presentation: resolved,
|
|
34
68
|
footer: jsxs("div", {
|
|
35
|
-
className:
|
|
69
|
+
className: sheet ? 'flex flex-col-reverse gap-3' : 'flex flex-col-reverse gap-3 sm:flex-row sm:justify-end',
|
|
36
70
|
children: [jsx(Button, {
|
|
37
71
|
variant: "outline",
|
|
38
72
|
onClick: onCancel,
|
|
39
73
|
disabled: loading,
|
|
74
|
+
fullWidth: sheet,
|
|
40
75
|
children: cancelLabel
|
|
41
76
|
}), jsx(Button, {
|
|
42
77
|
variant: destructive ? 'destructive' : 'primary',
|
|
43
|
-
onClick:
|
|
78
|
+
onClick: handleConfirm,
|
|
44
79
|
loading: loading,
|
|
80
|
+
fullWidth: sheet,
|
|
45
81
|
children: confirmLabel
|
|
46
82
|
})]
|
|
47
83
|
})
|
|
@@ -4,26 +4,35 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { ArrowLeft } from 'lucide-react';
|
|
6
6
|
import { cn } from '../../utils/cn.js';
|
|
7
|
+
import { TOUCH_TARGET } from '../../utils/touchTarget.js';
|
|
8
|
+
import { usePresentation } from '../../hooks/usePresentation.js';
|
|
9
|
+
import BottomActionBar from './BottomActionBar.js';
|
|
7
10
|
|
|
8
|
-
var _excluded = ["title", "subtitle", "actions", "back", "linkAs", "className"];
|
|
11
|
+
var _excluded = ["title", "subtitle", "actions", "actionsPlacement", "back", "linkAs", "className"];
|
|
9
12
|
// Extracted from taskpro/client/src/features/shared/PageHeader.jsx (31 imports) and the
|
|
10
13
|
// CampaignPro UX guide's page anatomy: one h1, a muted subtitle, actions top right.
|
|
14
|
+
// `actionsPlacement="bottom"` pins the actions in a BottomActionBar on phones (DTUI-52).
|
|
11
15
|
var PageHeader = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
12
16
|
var title = _ref.title,
|
|
13
17
|
subtitle = _ref.subtitle,
|
|
14
18
|
actions = _ref.actions,
|
|
19
|
+
_ref$actionsPlacement = _ref.actionsPlacement,
|
|
20
|
+
actionsPlacement = _ref$actionsPlacement === void 0 ? 'inline' : _ref$actionsPlacement,
|
|
15
21
|
back = _ref.back,
|
|
16
22
|
_ref$linkAs = _ref.linkAs,
|
|
17
23
|
Link = _ref$linkAs === void 0 ? 'a' : _ref$linkAs,
|
|
18
24
|
className = _ref.className,
|
|
19
25
|
props = _objectWithoutProperties(_ref, _excluded);
|
|
26
|
+
// 'sheet' = coarse pointer at phone width; 'popover' on the server and on desktop.
|
|
27
|
+
var isPhone = usePresentation() === 'sheet';
|
|
28
|
+
var pinned = Boolean(actions) && actionsPlacement === 'bottom' && isPhone;
|
|
20
29
|
return jsxs("div", _objectSpread2(_objectSpread2({
|
|
21
30
|
ref: ref,
|
|
22
31
|
className: cn('flex flex-col gap-3', className)
|
|
23
32
|
}, props), {}, {
|
|
24
33
|
children: [back && jsxs(Link, {
|
|
25
34
|
href: back.href,
|
|
26
|
-
className:
|
|
35
|
+
className: cn('inline-flex w-fit items-center gap-1.5 rounded-control text-sm text-muted hover:text-foreground', 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2', TOUCH_TARGET),
|
|
27
36
|
children: [jsx(ArrowLeft, {
|
|
28
37
|
className: "h-4 w-4",
|
|
29
38
|
"aria-hidden": "true"
|
|
@@ -39,10 +48,14 @@ var PageHeader = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
39
48
|
className: "mt-1 max-w-2xl text-sm text-muted",
|
|
40
49
|
children: subtitle
|
|
41
50
|
})]
|
|
42
|
-
}), actions && jsx("div", {
|
|
51
|
+
}), actions && !pinned && jsx("div", {
|
|
43
52
|
className: "flex flex-wrap items-center gap-3",
|
|
44
53
|
children: actions
|
|
45
54
|
})]
|
|
55
|
+
}), pinned && jsx(BottomActionBar, {
|
|
56
|
+
fullWidth: true,
|
|
57
|
+
"data-page-header-actions": "",
|
|
58
|
+
children: actions
|
|
46
59
|
})]
|
|
47
60
|
}));
|
|
48
61
|
});
|
|
@@ -4,8 +4,9 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
4
4
|
import { forwardRef, useId, useRef, useState, useEffect, useCallback } from 'react';
|
|
5
5
|
import { Check, Minus } from 'lucide-react';
|
|
6
6
|
import { cn } from '../../utils/cn.js';
|
|
7
|
+
import { useHaptics } from '../../hooks/useHaptics.js';
|
|
7
8
|
|
|
8
|
-
var _excluded = ["id", "name", "label", "checked", "defaultChecked", "onChange", "disabled", "required", "className", "size", "labelPosition", "value", "ariaLabel", "variant", "indeterminate", "
|
|
9
|
+
var _excluded = ["id", "name", "label", "checked", "defaultChecked", "onChange", "disabled", "required", "className", "size", "labelPosition", "value", "ariaLabel", "variant", "indeterminate", "color", "iconClass", "checkedClass", "wrapperProps", "haptics"];
|
|
9
10
|
var SIZE_CLASSES = {
|
|
10
11
|
sm: {
|
|
11
12
|
box: "h-4 w-4",
|
|
@@ -25,8 +26,8 @@ var SIZE_CLASSES = {
|
|
|
25
26
|
};
|
|
26
27
|
// `checked` paints the box from the native :checked state; `fill` is the same
|
|
27
28
|
// paint applied from React state for the indeterminate (mixed) state.
|
|
28
|
-
//
|
|
29
|
-
//
|
|
29
|
+
// Token presets only: the raw-palette presets (blue / indigo / purple) were
|
|
30
|
+
// removed in 2.0.0 (DTUI-65).
|
|
30
31
|
var COLOR_PRESETS = {
|
|
31
32
|
primary: {
|
|
32
33
|
checked: "peer-checked:bg-primary-600 peer-checked:border-primary-600 peer-checked:text-white dark:peer-checked:bg-primary-500 dark:peer-checked:border-primary-500",
|
|
@@ -67,21 +68,6 @@ var COLOR_PRESETS = {
|
|
|
67
68
|
checked: "peer-checked:bg-warning-600 peer-checked:border-warning-600 peer-checked:text-white dark:peer-checked:bg-warning-500 dark:peer-checked:border-warning-500",
|
|
68
69
|
fill: "bg-warning-600 border-warning-600 text-white dark:bg-warning-500 dark:border-warning-500",
|
|
69
70
|
ring: "peer-focus-visible:ring-warning-500"
|
|
70
|
-
},
|
|
71
|
-
blue: {
|
|
72
|
-
checked: "peer-checked:bg-blue-600 peer-checked:border-blue-600 peer-checked:text-white dark:peer-checked:bg-blue-500 dark:peer-checked:border-blue-500",
|
|
73
|
-
fill: "bg-blue-600 border-blue-600 text-white dark:bg-blue-500 dark:border-blue-500",
|
|
74
|
-
ring: "peer-focus-visible:ring-blue-500"
|
|
75
|
-
},
|
|
76
|
-
indigo: {
|
|
77
|
-
checked: "peer-checked:bg-indigo-600 peer-checked:border-indigo-600 peer-checked:text-white dark:peer-checked:bg-indigo-500 dark:peer-checked:border-indigo-500",
|
|
78
|
-
fill: "bg-indigo-600 border-indigo-600 text-white dark:bg-indigo-500 dark:border-indigo-500",
|
|
79
|
-
ring: "peer-focus-visible:ring-indigo-500"
|
|
80
|
-
},
|
|
81
|
-
purple: {
|
|
82
|
-
checked: "peer-checked:bg-purple-600 peer-checked:border-purple-600 peer-checked:text-white dark:peer-checked:bg-purple-500 dark:peer-checked:border-purple-500",
|
|
83
|
-
fill: "bg-purple-600 border-purple-600 text-white dark:bg-purple-500 dark:border-purple-500",
|
|
84
|
-
ring: "peer-focus-visible:ring-purple-500"
|
|
85
71
|
}
|
|
86
72
|
};
|
|
87
73
|
// The invisible native input is the hit area: the box size with a mouse,
|
|
@@ -110,12 +96,13 @@ var Checkbox = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
110
96
|
_ref.variant;
|
|
111
97
|
var _ref$indeterminate = _ref.indeterminate,
|
|
112
98
|
indeterminate = _ref$indeterminate === void 0 ? false : _ref$indeterminate,
|
|
113
|
-
borderColor = _ref.borderColor,
|
|
114
99
|
_ref$color = _ref.color,
|
|
115
100
|
color = _ref$color === void 0 ? "primary" : _ref$color,
|
|
116
101
|
iconClass = _ref.iconClass,
|
|
117
102
|
checkedClass = _ref.checkedClass,
|
|
118
103
|
wrapperProps = _ref.wrapperProps,
|
|
104
|
+
_ref$haptics = _ref.haptics,
|
|
105
|
+
haptics = _ref$haptics === void 0 ? false : _ref$haptics,
|
|
119
106
|
props = _objectWithoutProperties(_ref, _excluded);
|
|
120
107
|
var autoId = useId();
|
|
121
108
|
var inputId = id || "".concat(autoId, "-checkbox");
|
|
@@ -136,10 +123,15 @@ var Checkbox = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
136
123
|
if (!inputRef.current) return;
|
|
137
124
|
inputRef.current.indeterminate = Boolean(indeterminate);
|
|
138
125
|
}, [indeterminate]);
|
|
126
|
+
var _useHaptics = useHaptics({
|
|
127
|
+
enabled: haptics
|
|
128
|
+
}),
|
|
129
|
+
haptic = _useHaptics.trigger;
|
|
139
130
|
var handleChange = useCallback(function (e) {
|
|
140
131
|
if (!isControlled) setInternalChecked(e.target.checked);
|
|
132
|
+
haptic("selection");
|
|
141
133
|
if (typeof onChange === "function") onChange(e);
|
|
142
|
-
}, [isControlled, onChange]);
|
|
134
|
+
}, [isControlled, onChange, haptic]);
|
|
143
135
|
var sizeClass = SIZE_CLASSES[size] || SIZE_CLASSES.md;
|
|
144
136
|
var isPreset = COLOR_PRESETS[color];
|
|
145
137
|
var isMixed = Boolean(indeterminate);
|
|
@@ -162,10 +154,7 @@ var Checkbox = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
162
154
|
className: cn(sizeClass.label, "select-none mr-2 text-foreground"),
|
|
163
155
|
children: label
|
|
164
156
|
}), jsxs("div", {
|
|
165
|
-
className: cn("relative inline-flex shrink-0 items-center justify-center rounded-sm border transition-shadow duration-fast motion-reduce:transition-none", sizeClass.box, disabled ? "opacity-60 cursor-not-allowed" : "cursor-pointer hover:shadow-sm", !disabled && showBoxBorder &&
|
|
166
|
-
style: disabled || !showBoxBorder || !borderColor ? {} : {
|
|
167
|
-
borderColor: borderColor
|
|
168
|
-
},
|
|
157
|
+
className: cn("relative inline-flex shrink-0 items-center justify-center rounded-sm border transition-shadow duration-fast motion-reduce:transition-none", sizeClass.box, disabled ? "opacity-60 cursor-not-allowed" : "cursor-pointer hover:shadow-sm", !disabled && showBoxBorder && "border-gray-300 dark:border-gray-600"),
|
|
169
158
|
"aria-disabled": disabled,
|
|
170
159
|
children: [jsx("input", _objectSpread2({
|
|
171
160
|
id: inputId,
|