@dreamtree-org/twreact-ui 1.2.1 → 1.3.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/DESIGN.md +118 -0
- package/README.md +231 -44
- package/ai-skills/dreamtree-ui.md +98 -12
- package/dist/ai-schema.json +452 -17
- package/dist/components/blocks/AppShell.d.ts +4 -0
- package/dist/components/blocks/AppShell.d.ts.map +1 -0
- package/dist/components/blocks/ConfirmDialog.d.ts +4 -0
- package/dist/components/blocks/ConfirmDialog.d.ts.map +1 -0
- package/dist/components/blocks/EmptyState.d.ts +4 -0
- package/dist/components/blocks/EmptyState.d.ts.map +1 -0
- package/dist/components/blocks/ErrorState.d.ts +4 -0
- package/dist/components/blocks/ErrorState.d.ts.map +1 -0
- package/dist/components/blocks/LoadingState.d.ts +9 -0
- package/dist/components/blocks/LoadingState.d.ts.map +1 -0
- package/dist/components/blocks/PageHeader.d.ts +4 -0
- package/dist/components/blocks/PageHeader.d.ts.map +1 -0
- package/dist/components/blocks/StatCard.d.ts +4 -0
- package/dist/components/blocks/StatCard.d.ts.map +1 -0
- package/dist/components/blocks/StatusPill.d.ts +5 -0
- package/dist/components/blocks/StatusPill.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/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/LocationPicker.d.ts.map +1 -1
- package/dist/components/core/Popover.d.ts +4 -0
- package/dist/components/core/Popover.d.ts.map +1 -0
- 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/Select.d.ts.map +1 -1
- package/dist/components/core/Skeleton.d.ts.map +1 -1
- package/dist/components/core/Slider.d.ts +4 -0
- package/dist/components/core/Slider.d.ts.map +1 -0
- 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/ActionMenu.d.ts.map +1 -1
- package/dist/components/core/Table/ColumnMenu.d.ts +2 -1
- package/dist/components/core/Table/ColumnMenu.d.ts.map +1 -1
- package/dist/components/core/Table/MobileCard.d.ts +2 -2
- package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
- package/dist/components/core/Table/Table.d.ts.map +1 -1
- package/dist/components/core/Table/TableRow.d.ts +4 -2
- package/dist/components/core/Table/TableRow.d.ts.map +1 -1
- package/dist/components/core/Tabs.d.ts.map +1 -1
- package/dist/components/core/Textarea.d.ts +4 -0
- package/dist/components/core/Textarea.d.ts.map +1 -0
- package/dist/components/core/ThreeDotPopover.d.ts.map +1 -1
- package/dist/components/core/Tooltip.d.ts.map +1 -1
- package/dist/components/feedback/Dialog.d.ts.map +1 -1
- package/dist/components/feedback/Drawer.d.ts +4 -0
- package/dist/components/feedback/Drawer.d.ts.map +1 -0
- package/dist/components/feedback/Toast.d.ts +14 -5
- package/dist/components/feedback/Toast.d.ts.map +1 -1
- package/dist/components/feedback/Tour.d.ts +4 -0
- package/dist/components/feedback/Tour.d.ts.map +1 -0
- package/dist/components/feedback/TourSpotlight.d.ts +9 -0
- package/dist/components/feedback/TourSpotlight.d.ts.map +1 -0
- package/dist/components/navigation/Breadcrumbs.d.ts.map +1 -1
- package/dist/components/navigation/FootNav.d.ts.map +1 -1
- package/dist/components/navigation/Navbar.d.ts.map +1 -1
- package/dist/components/navigation/Sidebar.d.ts +8 -2
- package/dist/components/navigation/Sidebar.d.ts.map +1 -1
- package/dist/components/utility/Badge.d.ts.map +1 -1
- package/dist/components/utility/FileUpload.d.ts.map +1 -1
- package/dist/components/utility/Sortable.d.ts +4 -0
- package/dist/components/utility/Sortable.d.ts.map +1 -0
- package/dist/esm/_vendor/object-assign/index.js +99 -0
- package/dist/esm/_vendor/prop-types/_vendor/react-is/cjs/react-is.development.js +190 -0
- package/dist/esm/_vendor/prop-types/_vendor/react-is/cjs/react-is.production.min.js +26 -0
- package/dist/esm/_vendor/prop-types/_vendor/react-is/index.js +19 -0
- package/dist/esm/_vendor/prop-types/checkPropTypes.js +115 -0
- package/dist/esm/_vendor/prop-types/factoryWithThrowingShims.js +74 -0
- package/dist/esm/_vendor/prop-types/factoryWithTypeCheckers.js +625 -0
- package/dist/esm/_vendor/prop-types/index.js +30 -0
- package/dist/esm/_vendor/prop-types/lib/ReactPropTypesSecret.js +21 -0
- package/dist/esm/_vendor/prop-types/lib/has.js +11 -0
- package/dist/esm/_virtual/_commonjsHelpers.js +5 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +329 -0
- package/dist/esm/_virtual/index.js +3 -0
- package/dist/esm/_virtual/index2.js +3 -0
- package/dist/esm/_virtual/react-is.development.js +3 -0
- package/dist/esm/_virtual/react-is.production.min.js +3 -0
- package/dist/esm/components/blocks/AppShell.js +205 -0
- package/dist/esm/components/blocks/ConfirmDialog.js +57 -0
- package/dist/esm/components/blocks/EmptyState.js +44 -0
- package/dist/esm/components/blocks/ErrorState.js +53 -0
- package/dist/esm/components/blocks/LoadingState.js +134 -0
- package/dist/esm/components/blocks/PageHeader.js +51 -0
- package/dist/esm/components/blocks/StatCard.js +79 -0
- package/dist/esm/components/blocks/StatusPill.js +55 -0
- package/dist/esm/components/core/Accordion.js +260 -0
- package/dist/esm/components/core/Button.js +59 -0
- package/dist/esm/components/core/Checkbox.js +188 -0
- package/dist/esm/components/core/ColorPicker.js +348 -0
- package/dist/esm/components/core/DatePicker.js +436 -0
- package/dist/esm/components/core/DateRangePicker.js +494 -0
- package/dist/esm/components/core/Form.js +522 -0
- package/dist/esm/components/core/Input.js +179 -0
- package/dist/esm/components/core/Loader.js +141 -0
- package/dist/esm/components/core/LocationPicker.js +161 -0
- package/dist/esm/components/core/Popover.js +171 -0
- package/dist/esm/components/core/PriceRangePicker.js +376 -0
- package/dist/esm/components/core/ProgressBar.js +152 -0
- package/dist/esm/components/core/Radio.js +156 -0
- package/dist/esm/components/core/Rate.js +197 -0
- package/dist/esm/components/core/RoundedTag.js +118 -0
- package/dist/esm/components/core/Select.js +857 -0
- package/dist/esm/components/core/Skeleton.js +100 -0
- package/dist/esm/components/core/Slider.js +134 -0
- package/dist/esm/components/core/SpeechToText.js +226 -0
- package/dist/esm/components/core/Switch.js +207 -0
- package/dist/esm/components/core/Table/ActionMenu.js +251 -0
- package/dist/esm/components/core/Table/ColumnMenu.js +55 -0
- package/dist/esm/components/core/Table/FieldInput.js +157 -0
- package/dist/esm/components/core/Table/MobileCard.js +187 -0
- package/dist/esm/components/core/Table/MobileFilters.js +72 -0
- package/dist/esm/components/core/Table/Pagination.js +157 -0
- package/dist/esm/components/core/Table/Table.js +1533 -0
- package/dist/esm/components/core/Table/TableRow.js +254 -0
- package/dist/esm/components/core/Table/constants.js +35 -0
- package/dist/esm/components/core/Table/helpers.js +124 -0
- package/dist/esm/components/core/Table/useClickOutside.js +26 -0
- package/dist/esm/components/core/Tabs.js +289 -0
- package/dist/esm/components/core/TextToSpeech.js +52 -0
- package/dist/esm/components/core/Textarea.js +125 -0
- package/dist/esm/components/core/ThreeDotPopover.js +160 -0
- package/dist/esm/components/core/Tooltip.js +372 -0
- package/dist/esm/components/feedback/Alert.js +96 -0
- package/dist/esm/components/feedback/Dialog.js +200 -0
- package/dist/esm/components/feedback/Drawer.js +171 -0
- package/dist/esm/components/feedback/Toast.js +362 -0
- package/dist/esm/components/feedback/Tour.js +214 -0
- package/dist/esm/components/feedback/TourSpotlight.js +71 -0
- package/dist/esm/components/navigation/Breadcrumbs.js +75 -0
- package/dist/esm/components/navigation/Dropdown.js +53 -0
- package/dist/esm/components/navigation/FootNav.js +51 -0
- package/dist/esm/components/navigation/Navbar.js +437 -0
- package/dist/esm/components/navigation/Sidebar.js +567 -0
- package/dist/esm/components/utility/Avatar.js +89 -0
- package/dist/esm/components/utility/Badge.js +47 -0
- package/dist/esm/components/utility/Card.js +85 -0
- package/dist/esm/components/utility/Carousel.js +97 -0
- package/dist/esm/components/utility/Condition.js +9 -0
- package/dist/esm/components/utility/FileUpload.js +177 -0
- package/dist/esm/components/utility/Pagination.js +111 -0
- package/dist/esm/components/utility/Sortable.js +190 -0
- package/dist/esm/components/utility/Stepper.js +101 -0
- package/dist/esm/hooks/useApi.js +169 -0
- package/dist/esm/hooks/useControllableState.js +32 -0
- package/dist/esm/hooks/useFocusTrap.js +85 -0
- package/dist/esm/hooks/useLatestRef.js +20 -0
- package/dist/esm/hooks/useMixins.js +100 -0
- package/dist/esm/hooks/useScrollLock.js +26 -0
- package/dist/esm/hooks/useSliderValues.js +135 -0
- package/dist/esm/hooks/useSortable.js +188 -0
- package/dist/esm/hooks/useTheme.js +53 -0
- package/dist/esm/hooks/useTourTarget.js +92 -0
- package/dist/esm/index.js +65 -0
- package/dist/esm/store/index.js +26 -0
- package/dist/esm/store/store.js +107 -0
- package/dist/esm/store/storeSlice.js +45 -0
- package/dist/esm/utils/cn.js +11 -0
- package/dist/esm/utils/emitter.js +169 -0
- package/dist/esm/utils/helpers.js +161 -0
- package/dist/esm/utils/position.js +134 -0
- package/dist/hooks/useApi.d.ts +2 -1
- package/dist/hooks/useApi.d.ts.map +1 -1
- package/dist/hooks/useControllableState.d.ts +11 -0
- package/dist/hooks/useControllableState.d.ts.map +1 -0
- package/dist/hooks/useFocusTrap.d.ts +15 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/hooks/useLatestRef.d.ts +8 -0
- package/dist/hooks/useLatestRef.d.ts.map +1 -0
- package/dist/hooks/useMixins.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.d.ts +2 -0
- package/dist/hooks/useScrollLock.d.ts.map +1 -0
- package/dist/hooks/useSliderValues.d.ts +43 -0
- package/dist/hooks/useSliderValues.d.ts.map +1 -0
- package/dist/hooks/useSortable.d.ts +32 -0
- package/dist/hooks/useSortable.d.ts.map +1 -0
- package/dist/hooks/useTheme.d.ts.map +1 -1
- package/dist/hooks/useTourTarget.d.ts +15 -0
- package/dist/hooks/useTourTarget.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +55 -39
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +7937 -4659
- package/dist/index.js +7950 -4657
- package/dist/tokens/brands/default.css +1 -0
- package/dist/tokens/brands/default.json +5 -0
- package/dist/tokens/brands/practicepro.css +17 -0
- package/dist/tokens/brands/practicepro.json +27 -0
- package/dist/tokens/tailwind3-preset.cjs +214 -0
- package/dist/tokens/theme.css +193 -0
- package/dist/tokens/tokens.json +373 -0
- package/dist/tokens/vars.css +98 -0
- package/dist/types/blocks.d.ts +109 -0
- package/dist/types/blocks.d.ts.map +1 -0
- package/dist/types/index.d.ts +194 -5
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/position.d.ts +30 -0
- package/dist/utils/position.d.ts.map +1 -0
- package/doc/README.md +26 -1
- package/mcp/catalog.snapshot.json +1643 -549
- package/package.json +24 -6
- package/tokens/brands/default.json +5 -0
- package/tokens/brands/practicepro.json +27 -0
- package/tokens/lib.cjs +128 -0
- package/tokens/tokens.json +133 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, createForOfIteratorHelper as _createForOfIteratorHelper, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import React, { forwardRef, useRef, useState, useId, useCallback, useEffect, useMemo } from 'react';
|
|
5
|
+
import { createPortal } from 'react-dom';
|
|
6
|
+
import { cn } from '../../utils/cn.js';
|
|
7
|
+
|
|
8
|
+
var _excluded = ["position", "trigger", "content", "customTrigger", "children", "open", "defaultOpen", "onChange", "delay", "offset", "textClass", "bgClass", "className", "portal", "id"];
|
|
9
|
+
var NATIVE_FOCUSABLE_TAGS = new Set(["button", "input", "select", "textarea"]);
|
|
10
|
+
/**
|
|
11
|
+
* True when `el` is a single intrinsic element that is keyboard-focusable on
|
|
12
|
+
* its own (an enabled <button>/<input>/<select>/<textarea>, an <a href>, or any
|
|
13
|
+
* element with tabIndex >= 0). In that case the wrapper span must NOT add a
|
|
14
|
+
* second tab stop. Component elements (e.g. <Button>) can't be inspected
|
|
15
|
+
* statically, so they keep the focusable wrapper — use `customTrigger` there.
|
|
16
|
+
* Disabled controls are not focusable, so they also keep the wrapper (that is
|
|
17
|
+
* what makes a tooltip on a disabled button reachable by keyboard).
|
|
18
|
+
*/
|
|
19
|
+
var isNativelyFocusable = function isNativelyFocusable(el) {
|
|
20
|
+
if (! /*#__PURE__*/React.isValidElement(el) || typeof el.type !== "string") return false;
|
|
21
|
+
var p = el.props || {};
|
|
22
|
+
if (p.disabled) return false;
|
|
23
|
+
if (p.tabIndex !== undefined && p.tabIndex !== null) {
|
|
24
|
+
return Number(p.tabIndex) >= 0;
|
|
25
|
+
}
|
|
26
|
+
if (el.type === "a") return p.href != null;
|
|
27
|
+
if (el.type === "input") return p.type !== "hidden";
|
|
28
|
+
return NATIVE_FOCUSABLE_TAGS.has(el.type);
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Tooltip props
|
|
32
|
+
* - position: 'auto' | 'top' | 'bottom' | 'left' | 'right' (default 'auto')
|
|
33
|
+
* - trigger: 'hover' | 'click' | 'focus' | Array of those (default 'hover')
|
|
34
|
+
* - content: ReactNode | ( { close } ) => ReactNode
|
|
35
|
+
* - customTrigger: ReactElement (rendered in place of children as trigger)
|
|
36
|
+
* - children: ReactNode (trigger content if customTrigger not provided)
|
|
37
|
+
* - open: controlled boolean
|
|
38
|
+
* - defaultOpen: boolean
|
|
39
|
+
* - onChange: (open) => void
|
|
40
|
+
* - delay: number ms for hover open (default 80)
|
|
41
|
+
* - offset: spacing between trigger and tooltip (default 8)
|
|
42
|
+
* - textClass: string (CSS class for text color)
|
|
43
|
+
* - bgClass: string (CSS class for background color)
|
|
44
|
+
* - className: extra classes for tooltip box
|
|
45
|
+
* - portal: boolean (default true) -> render to document.body
|
|
46
|
+
*/
|
|
47
|
+
var Tooltip = /*#__PURE__*/forwardRef(function Tooltip(_ref, forwardedRef) {
|
|
48
|
+
var _customTrigger$props$, _customTrigger$props;
|
|
49
|
+
var _ref$position = _ref.position,
|
|
50
|
+
position = _ref$position === void 0 ? "auto" : _ref$position,
|
|
51
|
+
_ref$trigger = _ref.trigger,
|
|
52
|
+
trigger = _ref$trigger === void 0 ? "hover" : _ref$trigger,
|
|
53
|
+
content = _ref.content,
|
|
54
|
+
customTrigger = _ref.customTrigger,
|
|
55
|
+
children = _ref.children,
|
|
56
|
+
controlledOpen = _ref.open,
|
|
57
|
+
_ref$defaultOpen = _ref.defaultOpen,
|
|
58
|
+
defaultOpen = _ref$defaultOpen === void 0 ? false : _ref$defaultOpen,
|
|
59
|
+
onChange = _ref.onChange,
|
|
60
|
+
_ref$delay = _ref.delay,
|
|
61
|
+
delay = _ref$delay === void 0 ? 80 : _ref$delay,
|
|
62
|
+
_ref$offset = _ref.offset,
|
|
63
|
+
offset = _ref$offset === void 0 ? 8 : _ref$offset,
|
|
64
|
+
_ref$textClass = _ref.textClass,
|
|
65
|
+
textClass = _ref$textClass === void 0 ? "text-black" : _ref$textClass,
|
|
66
|
+
_ref$bgClass = _ref.bgClass,
|
|
67
|
+
bgClass = _ref$bgClass === void 0 ? "bg-white" : _ref$bgClass,
|
|
68
|
+
_ref$className = _ref.className,
|
|
69
|
+
className = _ref$className === void 0 ? "" : _ref$className,
|
|
70
|
+
_ref$portal = _ref.portal,
|
|
71
|
+
portal = _ref$portal === void 0 ? true : _ref$portal,
|
|
72
|
+
propsId = _ref.id,
|
|
73
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
74
|
+
var triggerRef = useRef(null);
|
|
75
|
+
var tooltipRef = useRef(null);
|
|
76
|
+
var delayRef = useRef(null);
|
|
77
|
+
var _useState = useState(Boolean(controlledOpen !== null && controlledOpen !== void 0 ? controlledOpen : defaultOpen)),
|
|
78
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
79
|
+
open = _useState2[0],
|
|
80
|
+
setOpen = _useState2[1];
|
|
81
|
+
var _useState3 = useState("top"),
|
|
82
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
83
|
+
setPlacement = _useState4[1];
|
|
84
|
+
var _useState5 = useState({
|
|
85
|
+
left: 0,
|
|
86
|
+
top: 0
|
|
87
|
+
}),
|
|
88
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
89
|
+
coords = _useState6[0],
|
|
90
|
+
setCoords = _useState6[1];
|
|
91
|
+
var _useState7 = useState(false),
|
|
92
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
93
|
+
mounted = _useState8[0],
|
|
94
|
+
setMounted = _useState8[1];
|
|
95
|
+
var reactId = useId();
|
|
96
|
+
var id = propsId !== null && propsId !== void 0 ? propsId : "tooltip-".concat(reactId);
|
|
97
|
+
var setTriggerRef = useCallback(function (node) {
|
|
98
|
+
triggerRef.current = node;
|
|
99
|
+
if (typeof forwardedRef === "function") forwardedRef(node);else if (forwardedRef) forwardedRef.current = node;
|
|
100
|
+
}, [forwardedRef]);
|
|
101
|
+
// sync controlled (adjust-during-render pattern)
|
|
102
|
+
var _useState9 = useState(controlledOpen),
|
|
103
|
+
_useState0 = _slicedToArray(_useState9, 2),
|
|
104
|
+
prevControlledOpen = _useState0[0],
|
|
105
|
+
setPrevControlledOpen = _useState0[1];
|
|
106
|
+
if (controlledOpen !== prevControlledOpen) {
|
|
107
|
+
setPrevControlledOpen(controlledOpen);
|
|
108
|
+
if (typeof controlledOpen === "boolean") setOpen(controlledOpen);
|
|
109
|
+
}
|
|
110
|
+
useEffect(function () {
|
|
111
|
+
return setMounted(true);
|
|
112
|
+
}, []);
|
|
113
|
+
var notify = useCallback(function (val) {
|
|
114
|
+
if (typeof onChange === "function") onChange(val);
|
|
115
|
+
}, [onChange]);
|
|
116
|
+
var computePosition = useCallback(function () {
|
|
117
|
+
var t = triggerRef.current;
|
|
118
|
+
var el = tooltipRef.current;
|
|
119
|
+
if (!t || !el) return;
|
|
120
|
+
var tr = t.getBoundingClientRect();
|
|
121
|
+
var ttW = el.offsetWidth;
|
|
122
|
+
var ttH = el.offsetHeight;
|
|
123
|
+
var winW = window.innerWidth;
|
|
124
|
+
var winH = window.innerHeight;
|
|
125
|
+
var candidates = ["top", "bottom", "left", "right"];
|
|
126
|
+
var chosen = position === "auto" ? "top" : position;
|
|
127
|
+
if (position === "auto") {
|
|
128
|
+
var _iterator = _createForOfIteratorHelper(candidates),
|
|
129
|
+
_step;
|
|
130
|
+
try {
|
|
131
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
132
|
+
var p = _step.value;
|
|
133
|
+
if (p === "top" && tr.top >= ttH + offset) {
|
|
134
|
+
chosen = "top";
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
if (p === "bottom" && winH - tr.bottom >= ttH + offset) {
|
|
138
|
+
chosen = "bottom";
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
if (p === "right" && winW - tr.right >= ttW + offset) {
|
|
142
|
+
chosen = "right";
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
if (p === "left" && tr.left >= ttW + offset) {
|
|
146
|
+
chosen = "left";
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} catch (err) {
|
|
151
|
+
_iterator.e(err);
|
|
152
|
+
} finally {
|
|
153
|
+
_iterator.f();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
var left = 0;
|
|
157
|
+
var top = 0;
|
|
158
|
+
switch (chosen) {
|
|
159
|
+
case "top":
|
|
160
|
+
left = tr.left + tr.width / 2 - ttW / 2;
|
|
161
|
+
top = tr.top - ttH - offset;
|
|
162
|
+
break;
|
|
163
|
+
case "bottom":
|
|
164
|
+
left = tr.left + tr.width / 2 - ttW / 2;
|
|
165
|
+
top = tr.bottom + offset;
|
|
166
|
+
break;
|
|
167
|
+
case "left":
|
|
168
|
+
left = tr.left - ttW - offset;
|
|
169
|
+
top = tr.top + tr.height / 2 - ttH / 2;
|
|
170
|
+
break;
|
|
171
|
+
case "right":
|
|
172
|
+
left = tr.right + offset;
|
|
173
|
+
top = tr.top + tr.height / 2 - ttH / 2;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
var pad = 8;
|
|
177
|
+
left = Math.max(pad, Math.min(left, winW - ttW - pad));
|
|
178
|
+
top = Math.max(pad, Math.min(top, winH - ttH - pad));
|
|
179
|
+
setPlacement(chosen);
|
|
180
|
+
setCoords({
|
|
181
|
+
left: Math.round(left) + window.scrollX,
|
|
182
|
+
top: Math.round(top) + window.scrollY
|
|
183
|
+
});
|
|
184
|
+
}, [offset, position]);
|
|
185
|
+
useEffect(function () {
|
|
186
|
+
if (!open) return;
|
|
187
|
+
computePosition();
|
|
188
|
+
var ro = new ResizeObserver(function () {
|
|
189
|
+
return computePosition();
|
|
190
|
+
});
|
|
191
|
+
if (triggerRef.current) ro.observe(triggerRef.current);
|
|
192
|
+
if (tooltipRef.current) ro.observe(tooltipRef.current);
|
|
193
|
+
var onScroll = function onScroll() {
|
|
194
|
+
return computePosition();
|
|
195
|
+
};
|
|
196
|
+
window.addEventListener("scroll", onScroll, true);
|
|
197
|
+
window.addEventListener("resize", computePosition);
|
|
198
|
+
return function () {
|
|
199
|
+
ro.disconnect();
|
|
200
|
+
window.removeEventListener("scroll", onScroll, true);
|
|
201
|
+
window.removeEventListener("resize", computePosition);
|
|
202
|
+
};
|
|
203
|
+
}, [open, computePosition]);
|
|
204
|
+
// open/close helpers
|
|
205
|
+
var openTooltip = useCallback(function () {
|
|
206
|
+
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
207
|
+
clearTimeout(delayRef.current);
|
|
208
|
+
if (immediate || !delay) {
|
|
209
|
+
setOpen(true);
|
|
210
|
+
notify(true);
|
|
211
|
+
} else {
|
|
212
|
+
delayRef.current = setTimeout(function () {
|
|
213
|
+
setOpen(true);
|
|
214
|
+
notify(true);
|
|
215
|
+
}, delay);
|
|
216
|
+
}
|
|
217
|
+
}, [delay, notify]);
|
|
218
|
+
var closeTooltip = useCallback(function () {
|
|
219
|
+
clearTimeout(delayRef.current);
|
|
220
|
+
setOpen(false);
|
|
221
|
+
notify(false);
|
|
222
|
+
}, [notify]);
|
|
223
|
+
// triggers normalization
|
|
224
|
+
var triggers = useMemo(function () {
|
|
225
|
+
return Array.isArray(trigger) ? trigger : [trigger];
|
|
226
|
+
}, [trigger]);
|
|
227
|
+
// hover handlers
|
|
228
|
+
useEffect(function () {
|
|
229
|
+
var t = triggerRef.current;
|
|
230
|
+
if (!t) return;
|
|
231
|
+
if (triggers.includes("hover")) {
|
|
232
|
+
var onMouseEnter = function onMouseEnter() {
|
|
233
|
+
return openTooltip();
|
|
234
|
+
};
|
|
235
|
+
var onMouseLeave = function onMouseLeave() {
|
|
236
|
+
return closeTooltip();
|
|
237
|
+
};
|
|
238
|
+
t.addEventListener("mouseenter", onMouseEnter);
|
|
239
|
+
t.addEventListener("mouseleave", onMouseLeave);
|
|
240
|
+
// also attach to tooltip to prevent flicker
|
|
241
|
+
var tip = function tip() {
|
|
242
|
+
return tooltipRef.current;
|
|
243
|
+
};
|
|
244
|
+
var tryTip = tip();
|
|
245
|
+
if (tryTip) {
|
|
246
|
+
tryTip.addEventListener("mouseenter", onMouseEnter);
|
|
247
|
+
tryTip.addEventListener("mouseleave", onMouseLeave);
|
|
248
|
+
}
|
|
249
|
+
return function () {
|
|
250
|
+
t.removeEventListener("mouseenter", onMouseEnter);
|
|
251
|
+
t.removeEventListener("mouseleave", onMouseLeave);
|
|
252
|
+
if (tryTip) {
|
|
253
|
+
tryTip.removeEventListener("mouseenter", onMouseEnter);
|
|
254
|
+
tryTip.removeEventListener("mouseleave", onMouseLeave);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}, [triggers, openTooltip, closeTooltip]);
|
|
259
|
+
// click handlers (toggle and outside click)
|
|
260
|
+
useEffect(function () {
|
|
261
|
+
var t = triggerRef.current;
|
|
262
|
+
if (!t) return;
|
|
263
|
+
if (triggers.includes("click")) {
|
|
264
|
+
var onClick = function onClick(e) {
|
|
265
|
+
e.stopPropagation();
|
|
266
|
+
setOpen(function (s) {
|
|
267
|
+
var next = !s;
|
|
268
|
+
notify(next);
|
|
269
|
+
return next;
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
var onDocClick = function onDocClick(e) {
|
|
273
|
+
if (!t.contains(e.target) && tooltipRef.current && !tooltipRef.current.contains(e.target)) {
|
|
274
|
+
setOpen(false);
|
|
275
|
+
notify(false);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
t.addEventListener("click", onClick);
|
|
279
|
+
document.addEventListener("click", onDocClick);
|
|
280
|
+
return function () {
|
|
281
|
+
t.removeEventListener("click", onClick);
|
|
282
|
+
document.removeEventListener("click", onDocClick);
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
}, [triggers, notify]);
|
|
286
|
+
// focus handlers: use focusin / focusout which bubble and handle inner focusables
|
|
287
|
+
useEffect(function () {
|
|
288
|
+
var t = triggerRef.current;
|
|
289
|
+
if (!t) return;
|
|
290
|
+
if (triggers.includes("focus")) {
|
|
291
|
+
var onFocusIn = function onFocusIn() {
|
|
292
|
+
return openTooltip(true);
|
|
293
|
+
};
|
|
294
|
+
var onFocusOut = function onFocusOut() {
|
|
295
|
+
return closeTooltip();
|
|
296
|
+
};
|
|
297
|
+
t.addEventListener("focusin", onFocusIn);
|
|
298
|
+
t.addEventListener("focusout", onFocusOut);
|
|
299
|
+
return function () {
|
|
300
|
+
t.removeEventListener("focusin", onFocusIn);
|
|
301
|
+
t.removeEventListener("focusout", onFocusOut);
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
}, [triggers, openTooltip, closeTooltip]);
|
|
305
|
+
// Escape key closes tooltip
|
|
306
|
+
useEffect(function () {
|
|
307
|
+
if (!open) return;
|
|
308
|
+
var onKey = function onKey(e) {
|
|
309
|
+
if (e.key === "Escape") closeTooltip();
|
|
310
|
+
};
|
|
311
|
+
document.addEventListener("keydown", onKey);
|
|
312
|
+
return function () {
|
|
313
|
+
return document.removeEventListener("keydown", onKey);
|
|
314
|
+
};
|
|
315
|
+
}, [open, closeTooltip]);
|
|
316
|
+
// content renderer
|
|
317
|
+
var renderContent = function renderContent() {
|
|
318
|
+
if (typeof content === "function") return content({
|
|
319
|
+
close: closeTooltip
|
|
320
|
+
});
|
|
321
|
+
return content;
|
|
322
|
+
};
|
|
323
|
+
// A lone natively-focusable child is already a tab stop: don't wrap it in a
|
|
324
|
+
// second one (doubled tab stops in grids/toolbars). It gets the
|
|
325
|
+
// aria-describedby instead, so screen readers still announce the tooltip.
|
|
326
|
+
var focusableChild = !customTrigger && isNativelyFocusable(children) ? children : null;
|
|
327
|
+
// trigger element (attach ref)
|
|
328
|
+
var triggerElement = customTrigger ? (
|
|
329
|
+
/*#__PURE__*/
|
|
330
|
+
// eslint-disable-next-line react-hooks/refs -- setTriggerRef is a callback ref, run by React at commit
|
|
331
|
+
React.cloneElement(customTrigger, {
|
|
332
|
+
ref: setTriggerRef,
|
|
333
|
+
"aria-describedby": id,
|
|
334
|
+
tabIndex: (_customTrigger$props$ = (_customTrigger$props = customTrigger.props) === null || _customTrigger$props === void 0 ? void 0 : _customTrigger$props.tabIndex) !== null && _customTrigger$props$ !== void 0 ? _customTrigger$props$ : 0
|
|
335
|
+
})) : focusableChild ? jsx("span", {
|
|
336
|
+
ref: setTriggerRef,
|
|
337
|
+
className: "inline-flex",
|
|
338
|
+
children: /*#__PURE__*/React.cloneElement(focusableChild, {
|
|
339
|
+
"aria-describedby": [focusableChild.props["aria-describedby"], id].filter(Boolean).join(" ")
|
|
340
|
+
})
|
|
341
|
+
}) : jsx("span", {
|
|
342
|
+
ref: setTriggerRef,
|
|
343
|
+
className: "inline-flex",
|
|
344
|
+
tabIndex: 0,
|
|
345
|
+
"aria-describedby": id,
|
|
346
|
+
children: children
|
|
347
|
+
});
|
|
348
|
+
// Tooltip box element
|
|
349
|
+
var tooltipNode = open ? jsx("div", _objectSpread2(_objectSpread2({
|
|
350
|
+
ref: tooltipRef,
|
|
351
|
+
id: id,
|
|
352
|
+
role: "tooltip"
|
|
353
|
+
}, rest), {}, {
|
|
354
|
+
className: cn("absolute z-50 transform-gpu transition-opacity duration-150", className),
|
|
355
|
+
style: {
|
|
356
|
+
left: coords.left,
|
|
357
|
+
top: coords.top,
|
|
358
|
+
position: "absolute"
|
|
359
|
+
},
|
|
360
|
+
children: jsx("div", {
|
|
361
|
+
className: cn("max-w-xs rounded-md border border-gray-200 px-3 py-2 text-sm shadow-lg shadow-black/5", bgClass, textClass),
|
|
362
|
+
children: renderContent()
|
|
363
|
+
})
|
|
364
|
+
})) : null;
|
|
365
|
+
// Render either inline or as portal
|
|
366
|
+
return jsxs(Fragment, {
|
|
367
|
+
children: [triggerElement, mounted && portal ? /*#__PURE__*/createPortal(tooltipNode, document.body) : tooltipNode]
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
Tooltip.displayName = "Tooltip";
|
|
371
|
+
|
|
372
|
+
export { Tooltip as default };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { cn } from '../../utils/cn.js';
|
|
6
|
+
import { Info, AlertTriangle, AlertCircle, CheckCircle, X } from 'lucide-react';
|
|
7
|
+
|
|
8
|
+
var _excluded = ["variant", "title", "children", "dismissible", "onDismiss", "className"];
|
|
9
|
+
var Alert = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
10
|
+
var _ref$variant = _ref.variant,
|
|
11
|
+
variant = _ref$variant === void 0 ? 'info' : _ref$variant,
|
|
12
|
+
title = _ref.title,
|
|
13
|
+
children = _ref.children,
|
|
14
|
+
_ref$dismissible = _ref.dismissible,
|
|
15
|
+
dismissible = _ref$dismissible === void 0 ? false : _ref$dismissible,
|
|
16
|
+
onDismiss = _ref.onDismiss,
|
|
17
|
+
className = _ref.className,
|
|
18
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
19
|
+
var variants = {
|
|
20
|
+
success: {
|
|
21
|
+
container: 'bg-success-50 border-success-200',
|
|
22
|
+
icon: jsx(CheckCircle, {
|
|
23
|
+
className: "h-5 w-5 text-success-500"
|
|
24
|
+
}),
|
|
25
|
+
title: 'text-success-800',
|
|
26
|
+
content: 'text-success-700'
|
|
27
|
+
},
|
|
28
|
+
error: {
|
|
29
|
+
container: 'bg-error-50 border-error-200',
|
|
30
|
+
icon: jsx(AlertCircle, {
|
|
31
|
+
className: "h-5 w-5 text-error-500"
|
|
32
|
+
}),
|
|
33
|
+
title: 'text-error-800',
|
|
34
|
+
content: 'text-error-700'
|
|
35
|
+
},
|
|
36
|
+
warning: {
|
|
37
|
+
container: 'bg-warning-50 border-warning-200',
|
|
38
|
+
icon: jsx(AlertTriangle, {
|
|
39
|
+
className: "h-5 w-5 text-warning-500"
|
|
40
|
+
}),
|
|
41
|
+
title: 'text-warning-800',
|
|
42
|
+
content: 'text-warning-700'
|
|
43
|
+
},
|
|
44
|
+
info: {
|
|
45
|
+
container: 'bg-primary-50 border-primary-200',
|
|
46
|
+
icon: jsx(Info, {
|
|
47
|
+
className: "h-5 w-5 text-primary-500"
|
|
48
|
+
}),
|
|
49
|
+
title: 'text-primary-800',
|
|
50
|
+
content: 'text-primary-700'
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
var variantStyles = variants[variant];
|
|
54
|
+
return jsx("div", _objectSpread2(_objectSpread2({
|
|
55
|
+
ref: ref,
|
|
56
|
+
className: cn('rounded-md border p-4', variantStyles.container, className),
|
|
57
|
+
role: "alert"
|
|
58
|
+
}, props), {}, {
|
|
59
|
+
children: jsxs("div", {
|
|
60
|
+
className: "flex",
|
|
61
|
+
children: [jsx("div", {
|
|
62
|
+
className: "flex-shrink-0",
|
|
63
|
+
children: variantStyles.icon
|
|
64
|
+
}), jsxs("div", {
|
|
65
|
+
className: "ml-3 flex-1",
|
|
66
|
+
children: [title && jsx("h3", {
|
|
67
|
+
className: cn('text-sm font-medium', variantStyles.title),
|
|
68
|
+
children: title
|
|
69
|
+
}), jsx("div", {
|
|
70
|
+
className: cn('text-sm', variantStyles.content, {
|
|
71
|
+
'mt-1': title
|
|
72
|
+
}),
|
|
73
|
+
children: children
|
|
74
|
+
})]
|
|
75
|
+
}), dismissible && jsx("div", {
|
|
76
|
+
className: "ml-auto pl-3",
|
|
77
|
+
children: jsx("button", {
|
|
78
|
+
type: "button",
|
|
79
|
+
className: cn('inline-flex rounded-md p-1.5 focus:outline-none focus:ring-2 focus:ring-offset-2', {
|
|
80
|
+
'text-success-500 hover:bg-success-100 focus:ring-success-600': variant === 'success',
|
|
81
|
+
'text-error-500 hover:bg-error-100 focus:ring-error-600': variant === 'error',
|
|
82
|
+
'text-warning-500 hover:bg-warning-100 focus:ring-warning-600': variant === 'warning',
|
|
83
|
+
'text-primary-500 hover:bg-primary-100 focus:ring-primary-600': variant === 'info'
|
|
84
|
+
}),
|
|
85
|
+
onClick: onDismiss,
|
|
86
|
+
children: jsx(X, {
|
|
87
|
+
className: "h-4 w-4"
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
})]
|
|
91
|
+
})
|
|
92
|
+
}));
|
|
93
|
+
});
|
|
94
|
+
Alert.displayName = 'Alert';
|
|
95
|
+
|
|
96
|
+
export { Alert as default };
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
import React, { useRef, useEffect } from 'react';
|
|
5
|
+
import { createPortal } from 'react-dom';
|
|
6
|
+
import { cn } from '../../utils/cn.js';
|
|
7
|
+
import { X } from 'lucide-react';
|
|
8
|
+
import { useLatestRef } from '../../hooks/useLatestRef.js';
|
|
9
|
+
|
|
10
|
+
var _excluded = ["isOpen", "onClose", "title", "children", "size", "dismissible", "showCloseButton", "footer", "className", "onOpen"],
|
|
11
|
+
_excluded2 = ["children", "className"],
|
|
12
|
+
_excluded3 = ["children", "className"],
|
|
13
|
+
_excluded4 = ["children", "className"];
|
|
14
|
+
// Elements that can receive keyboard focus. Used to drive the focus trap and to
|
|
15
|
+
// pick the first element to focus when the dialog opens (WAI-ARIA APG dialog).
|
|
16
|
+
var FOCUSABLE_SELECTOR = ['a[href]', 'button:not([disabled])', 'textarea:not([disabled])', 'input:not([disabled])', 'select:not([disabled])', '[tabindex]:not([tabindex="-1"])'].join(',');
|
|
17
|
+
var getFocusable = function getFocusable(root) {
|
|
18
|
+
return root ? Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR)).filter(function (el) {
|
|
19
|
+
return el.getAttribute('aria-hidden') !== 'true';
|
|
20
|
+
}) : [];
|
|
21
|
+
};
|
|
22
|
+
// Assign one node to several refs (callback or object). Lets the dialog keep
|
|
23
|
+
// its internal `dialogRef` for the focus trap while still exposing the panel
|
|
24
|
+
// node to a consumer-supplied `ref` (issue #56).
|
|
25
|
+
var setRefs = function setRefs(node) {
|
|
26
|
+
for (var _len = arguments.length, refs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
27
|
+
refs[_key - 1] = arguments[_key];
|
|
28
|
+
}
|
|
29
|
+
refs.forEach(function (ref) {
|
|
30
|
+
if (!ref) return;
|
|
31
|
+
if (typeof ref === 'function') ref(node);else ref.current = node;
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var Dialog = /*#__PURE__*/React.forwardRef(function (_ref, _ref3) {
|
|
35
|
+
var isOpen = _ref.isOpen,
|
|
36
|
+
onClose = _ref.onClose,
|
|
37
|
+
title = _ref.title,
|
|
38
|
+
children = _ref.children,
|
|
39
|
+
_ref$size = _ref.size,
|
|
40
|
+
size = _ref$size === void 0 ? 'md' : _ref$size,
|
|
41
|
+
_ref$dismissible = _ref.dismissible,
|
|
42
|
+
dismissible = _ref$dismissible === void 0 ? true : _ref$dismissible,
|
|
43
|
+
_ref$showCloseButton = _ref.showCloseButton,
|
|
44
|
+
showCloseButton = _ref$showCloseButton === void 0 ? true : _ref$showCloseButton,
|
|
45
|
+
footer = _ref.footer,
|
|
46
|
+
className = _ref.className,
|
|
47
|
+
onOpen = _ref.onOpen,
|
|
48
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
49
|
+
var dialogRef = useRef(null);
|
|
50
|
+
// The element that had focus when the dialog opened, so we can restore it on close.
|
|
51
|
+
var lastFocusedRef = useRef(null);
|
|
52
|
+
// Latest onOpen without re-running the open effect when the prop identity changes.
|
|
53
|
+
var onOpenRef = useLatestRef(onOpen);
|
|
54
|
+
useEffect(function () {
|
|
55
|
+
var _ref2, _focusables$, _onOpenRef$current;
|
|
56
|
+
if (!isOpen) return undefined;
|
|
57
|
+
// Remember the opener so focus can return to it when the dialog closes.
|
|
58
|
+
lastFocusedRef.current = document.activeElement;
|
|
59
|
+
document.body.style.overflow = 'hidden';
|
|
60
|
+
// Move focus into the panel: first focusable descendant, else the panel itself.
|
|
61
|
+
var panel = dialogRef.current;
|
|
62
|
+
var focusables = getFocusable(panel);
|
|
63
|
+
(_ref2 = (_focusables$ = focusables[0]) !== null && _focusables$ !== void 0 ? _focusables$ : panel) === null || _ref2 === void 0 || _ref2.focus();
|
|
64
|
+
(_onOpenRef$current = onOpenRef.current) === null || _onOpenRef$current === void 0 || _onOpenRef$current.call(onOpenRef, {
|
|
65
|
+
dialogRef: panel
|
|
66
|
+
});
|
|
67
|
+
return function () {
|
|
68
|
+
var _lastFocusedRef$curre, _lastFocusedRef$curre2;
|
|
69
|
+
document.body.style.overflow = 'unset';
|
|
70
|
+
// Restore focus to whatever opened the dialog (APG focus-restore requirement).
|
|
71
|
+
(_lastFocusedRef$curre = lastFocusedRef.current) === null || _lastFocusedRef$curre === void 0 || (_lastFocusedRef$curre2 = _lastFocusedRef$curre.focus) === null || _lastFocusedRef$curre2 === void 0 || _lastFocusedRef$curre2.call(_lastFocusedRef$curre);
|
|
72
|
+
};
|
|
73
|
+
}, [isOpen, onOpenRef]);
|
|
74
|
+
// Escape-to-close + Tab focus trap. An aria-modal element must keep keyboard
|
|
75
|
+
// focus inside the panel; without this, Tab walks into the page behind it.
|
|
76
|
+
useEffect(function () {
|
|
77
|
+
if (!isOpen) return undefined;
|
|
78
|
+
var handleKeyDown = function handleKeyDown(e) {
|
|
79
|
+
if (e.key === 'Escape') {
|
|
80
|
+
if (dismissible) onClose === null || onClose === void 0 || onClose();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (e.key !== 'Tab') return;
|
|
84
|
+
var panel = dialogRef.current;
|
|
85
|
+
if (!panel) return;
|
|
86
|
+
var focusables = getFocusable(panel);
|
|
87
|
+
if (focusables.length === 0) {
|
|
88
|
+
// Nothing focusable inside — pin focus to the panel.
|
|
89
|
+
e.preventDefault();
|
|
90
|
+
panel.focus();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
var first = focusables[0];
|
|
94
|
+
var last = focusables[focusables.length - 1];
|
|
95
|
+
var active = document.activeElement;
|
|
96
|
+
var outside = !panel.contains(active) || active === panel;
|
|
97
|
+
if (e.shiftKey && (active === first || outside)) {
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
last.focus();
|
|
100
|
+
} else if (!e.shiftKey && (active === last || outside)) {
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
first.focus();
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
106
|
+
return function () {
|
|
107
|
+
return document.removeEventListener('keydown', handleKeyDown);
|
|
108
|
+
};
|
|
109
|
+
}, [isOpen, dismissible, onClose]);
|
|
110
|
+
if (!isOpen) return null;
|
|
111
|
+
var sizeClasses = {
|
|
112
|
+
sm: 'max-w-md',
|
|
113
|
+
md: 'max-w-lg',
|
|
114
|
+
lg: 'max-w-2xl',
|
|
115
|
+
xl: 'max-w-4xl',
|
|
116
|
+
full: 'max-w-full mx-4'
|
|
117
|
+
};
|
|
118
|
+
var handleBackdropClick = function handleBackdropClick(e) {
|
|
119
|
+
if (dismissible && e.target === e.currentTarget) {
|
|
120
|
+
onClose === null || onClose === void 0 || onClose();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
return /*#__PURE__*/createPortal(jsx("div", {
|
|
124
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 p-4",
|
|
125
|
+
onClick: handleBackdropClick,
|
|
126
|
+
children: jsxs("div", _objectSpread2(_objectSpread2({
|
|
127
|
+
ref: function ref(node) {
|
|
128
|
+
return setRefs(node, dialogRef, _ref3);
|
|
129
|
+
},
|
|
130
|
+
className: cn('w-full rounded-lg bg-white shadow-xl animate-scale-in motion-reduce:animate-none', sizeClasses[size], className),
|
|
131
|
+
tabIndex: -1,
|
|
132
|
+
role: "dialog",
|
|
133
|
+
"aria-modal": "true",
|
|
134
|
+
"aria-labelledby": title ? 'dialog-title' : undefined
|
|
135
|
+
}, props), {}, {
|
|
136
|
+
children: [(title || showCloseButton) && jsxs("div", {
|
|
137
|
+
className: "flex items-center justify-between border-b border-gray-200 px-6 py-4",
|
|
138
|
+
children: [title && jsx("h2", {
|
|
139
|
+
id: "dialog-title",
|
|
140
|
+
className: "text-lg font-semibold text-primary-900",
|
|
141
|
+
children: title
|
|
142
|
+
}), showCloseButton && jsx("button", {
|
|
143
|
+
type: "button",
|
|
144
|
+
className: "rounded-md p-1 text-primary-400 hover:text-primary-600 hover:bg-gray-100",
|
|
145
|
+
onClick: onClose,
|
|
146
|
+
"aria-label": "Close dialog",
|
|
147
|
+
children: jsx(X, {
|
|
148
|
+
className: "h-5 w-5"
|
|
149
|
+
})
|
|
150
|
+
})]
|
|
151
|
+
}), jsx("div", {
|
|
152
|
+
className: "px-6 py-4",
|
|
153
|
+
children: children
|
|
154
|
+
}), footer && jsx("div", {
|
|
155
|
+
className: "flex items-center justify-end gap-3 border-t border-gray-200 px-6 py-4",
|
|
156
|
+
children: footer
|
|
157
|
+
})]
|
|
158
|
+
}))
|
|
159
|
+
}), document.body);
|
|
160
|
+
});
|
|
161
|
+
Dialog.displayName = 'Dialog';
|
|
162
|
+
// Dialog components for composition
|
|
163
|
+
var DialogHeader = function DialogHeader(_ref4) {
|
|
164
|
+
var children = _ref4.children,
|
|
165
|
+
className = _ref4.className,
|
|
166
|
+
props = _objectWithoutProperties(_ref4, _excluded2);
|
|
167
|
+
return jsx("div", _objectSpread2(_objectSpread2({
|
|
168
|
+
className: cn('border-b border-gray-200 px-6 py-4', className)
|
|
169
|
+
}, props), {}, {
|
|
170
|
+
children: children
|
|
171
|
+
}));
|
|
172
|
+
};
|
|
173
|
+
var DialogBody = function DialogBody(_ref5) {
|
|
174
|
+
var children = _ref5.children,
|
|
175
|
+
className = _ref5.className,
|
|
176
|
+
props = _objectWithoutProperties(_ref5, _excluded3);
|
|
177
|
+
return jsx("div", _objectSpread2(_objectSpread2({
|
|
178
|
+
className: cn('px-6 py-4', className)
|
|
179
|
+
}, props), {}, {
|
|
180
|
+
children: children
|
|
181
|
+
}));
|
|
182
|
+
};
|
|
183
|
+
var DialogFooter = function DialogFooter(_ref6) {
|
|
184
|
+
var children = _ref6.children,
|
|
185
|
+
className = _ref6.className,
|
|
186
|
+
props = _objectWithoutProperties(_ref6, _excluded4);
|
|
187
|
+
return jsx("div", _objectSpread2(_objectSpread2({
|
|
188
|
+
className: cn('flex items-center justify-end gap-3 border-t border-gray-200 px-6 py-4', className)
|
|
189
|
+
}, props), {}, {
|
|
190
|
+
children: children
|
|
191
|
+
}));
|
|
192
|
+
};
|
|
193
|
+
DialogHeader.displayName = 'Dialog.Header';
|
|
194
|
+
DialogBody.displayName = 'Dialog.Body';
|
|
195
|
+
DialogFooter.displayName = 'Dialog.Footer';
|
|
196
|
+
Dialog.Header = DialogHeader;
|
|
197
|
+
Dialog.Body = DialogBody;
|
|
198
|
+
Dialog.Footer = DialogFooter;
|
|
199
|
+
|
|
200
|
+
export { Dialog as default };
|