@adminiumjs/ui 0.2.5 → 0.2.7
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/dist/components/combobox/Combobox.d.ts +4 -0
- package/dist/components/combobox/Combobox.d.ts.map +1 -1
- package/dist/components/combobox/Combobox.js +8 -2
- package/dist/components/combobox/Combobox.js.map +1 -1
- package/dist/components/confirm-modal/ConfirmModal.d.ts +19 -3
- package/dist/components/confirm-modal/ConfirmModal.d.ts.map +1 -1
- package/dist/components/confirm-modal/ConfirmModal.js +42 -6
- package/dist/components/confirm-modal/ConfirmModal.js.map +1 -1
- package/dist/components/drawer/Drawer.d.ts +9 -2
- package/dist/components/drawer/Drawer.d.ts.map +1 -1
- package/dist/components/drawer/Drawer.js +14 -4
- package/dist/components/drawer/Drawer.js.map +1 -1
- package/dist/components/dropdown-menu/DropdownMenu.d.ts +1 -1
- package/dist/components/dropdown-menu/DropdownMenu.d.ts.map +1 -1
- package/dist/components/dropdown-menu/DropdownMenu.js +8 -2
- package/dist/components/dropdown-menu/DropdownMenu.js.map +1 -1
- package/dist/components/popover/Popover.d.ts +1 -1
- package/dist/components/popover/Popover.d.ts.map +1 -1
- package/dist/components/popover/Popover.js +7 -2
- package/dist/components/popover/Popover.js.map +1 -1
- package/dist/components/radio-card/RadioCard.d.ts +13 -1
- package/dist/components/radio-card/RadioCard.d.ts.map +1 -1
- package/dist/components/radio-card/RadioCard.js +25 -2
- package/dist/components/radio-card/RadioCard.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useScrollLockBypass.d.ts +26 -0
- package/dist/hooks/useScrollLockBypass.d.ts.map +1 -0
- package/dist/hooks/useScrollLockBypass.js +52 -0
- package/dist/hooks/useScrollLockBypass.js.map +1 -0
- package/package.json +2 -2
|
@@ -49,6 +49,10 @@ export interface ComboboxProps {
|
|
|
49
49
|
* the input keeps focus (`role="combobox"`, `aria-expanded`,
|
|
50
50
|
* `aria-activedescendant`); ↑/↓ move the active option, ↵ selects, Esc
|
|
51
51
|
* closes, Tab/outside-click dismisses.
|
|
52
|
+
*
|
|
53
|
+
* The panel carries `useScrollLockBypass` and the list `overscroll-contain`:
|
|
54
|
+
* without them a dialog's scroll lock cancels every wheel and trackpad swipe
|
|
55
|
+
* over this list. The hook explains why.
|
|
52
56
|
*/
|
|
53
57
|
export declare function Combobox({ options, value, defaultValue, onValueChange, emptyText, placeholder, filter, disabled, error, mono, className, id, name, ref, ...aria }: ComboboxProps): React.JSX.Element;
|
|
54
58
|
//# sourceMappingURL=Combobox.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox.d.ts","sourceRoot":"","sources":["../../../src/components/combobox/Combobox.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Combobox.d.ts","sourceRoot":"","sources":["../../../src/components/combobox/Combobox.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAKpC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,wEAAwE;IACxE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IACnC,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,aAAa,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC7D,iFAAiF;IACjF,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;IAC1E,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,oDAAoD;IACpD,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,kEAAkE;IAClE,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC;IAC9C,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,qDAAqD;IACrD,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,cAAc,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAClE,eAAe,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,GAAG,SAAS,CAAC;CACrE;AAKD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,KAAK,EACL,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,EACX,MAAsB,EACtB,QAAgB,EAChB,KAAa,EACb,IAAY,EACZ,SAAS,EACT,EAAE,EACF,IAAI,EACJ,GAAG,EACH,GAAG,IAAI,EACR,EAAE,aAAa,qBAuMf"}
|
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
4
4
|
import { Check, ChevronDown } from 'lucide-react';
|
|
5
5
|
import { useEffect, useId, useRef, useState } from 'react';
|
|
6
|
+
import { useScrollLockBypass } from '../../hooks/useScrollLockBypass.js';
|
|
6
7
|
import { cn } from '../../lib/cn.js';
|
|
7
8
|
const defaultFilter = (option, query) => option.label.toLowerCase().includes(query.trim().toLowerCase());
|
|
8
9
|
/**
|
|
@@ -15,6 +16,10 @@ const defaultFilter = (option, query) => option.label.toLowerCase().includes(que
|
|
|
15
16
|
* the input keeps focus (`role="combobox"`, `aria-expanded`,
|
|
16
17
|
* `aria-activedescendant`); ↑/↓ move the active option, ↵ selects, Esc
|
|
17
18
|
* closes, Tab/outside-click dismisses.
|
|
19
|
+
*
|
|
20
|
+
* The panel carries `useScrollLockBypass` and the list `overscroll-contain`:
|
|
21
|
+
* without them a dialog's scroll lock cancels every wheel and trackpad swipe
|
|
22
|
+
* over this list. The hook explains why.
|
|
18
23
|
*/
|
|
19
24
|
export function Combobox({ options, value, defaultValue, onValueChange, emptyText, placeholder, filter = defaultFilter, disabled = false, error = false, mono = false, className, id, name, ref, ...aria }) {
|
|
20
25
|
const generatedId = useId();
|
|
@@ -22,6 +27,7 @@ export function Combobox({ options, value, defaultValue, onValueChange, emptyTex
|
|
|
22
27
|
const listboxId = `${inputId}-listbox`;
|
|
23
28
|
const rootRef = useRef(null);
|
|
24
29
|
const inputRef = useRef(null);
|
|
30
|
+
const setPanel = useScrollLockBypass();
|
|
25
31
|
const [internalValue, setInternalValue] = useState(defaultValue ?? null);
|
|
26
32
|
const selectedValue = value !== undefined ? value : internalValue;
|
|
27
33
|
const selectedOption = options.find((option) => option.value === selectedValue);
|
|
@@ -112,11 +118,11 @@ export function Combobox({ options, value, defaultValue, onValueChange, emptyTex
|
|
|
112
118
|
setOpen(true);
|
|
113
119
|
setQuery(event.target.value);
|
|
114
120
|
setActiveIndex(0);
|
|
115
|
-
}, onKeyDown: handleKeyDown, className: cn('h-full w-full min-w-0 flex-1 bg-transparent text-[13px] text-fg placeholder:text-fg-subtle focus:outline-none', mono && 'font-mono tabular-nums') }), _jsx(ChevronDown, { "aria-hidden": "true", className: cn('size-3.5 shrink-0 text-fg-subtle transition-transform duration-150', open && 'rotate-180') })] }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { sideOffset: 5, align: "start", onOpenAutoFocus: (event) => event.preventDefault(), onInteractOutside: (event) => {
|
|
121
|
+
}, onKeyDown: handleKeyDown, className: cn('h-full w-full min-w-0 flex-1 bg-transparent text-[13px] text-fg placeholder:text-fg-subtle focus:outline-none', mono && 'font-mono tabular-nums') }), _jsx(ChevronDown, { "aria-hidden": "true", className: cn('size-3.5 shrink-0 text-fg-subtle transition-transform duration-150', open && 'rotate-180') })] }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { ref: setPanel, sideOffset: 5, align: "start", onOpenAutoFocus: (event) => event.preventDefault(), onInteractOutside: (event) => {
|
|
116
122
|
// clicks on the anchor input must not count as "outside"
|
|
117
123
|
if (rootRef.current?.contains(event.target))
|
|
118
124
|
event.preventDefault();
|
|
119
|
-
}, className: cn('z-50 w-[var(--radix-popper-anchor-width)] rounded-lg border border-border bg-surface p-1 shadow-menu ', 'animate-[nb-pop_.16s_cubic-bezier(.2,.7,.3,1)]'), children: _jsxs("div", { role: "listbox", id: listboxId, className: "nb-scroll max-h-[260px] overflow-y-auto", children: [filtered.map((option, index) => {
|
|
125
|
+
}, className: cn('z-50 w-[var(--radix-popper-anchor-width)] rounded-lg border border-border bg-surface p-1 shadow-menu ', 'animate-[nb-pop_.16s_cubic-bezier(.2,.7,.3,1)]'), children: _jsxs("div", { role: "listbox", id: listboxId, className: "nb-scroll max-h-[260px] overflow-y-auto overscroll-contain", children: [filtered.map((option, index) => {
|
|
120
126
|
const selected = option.value === selectedValue;
|
|
121
127
|
const active = index === activeIndex;
|
|
122
128
|
return (_jsxs("div", { id: optionId(index), role: "option", "aria-selected": selected, ...(option.disabled ? { 'aria-disabled': true } : {}), "data-active": active ? '' : undefined, onPointerDown: (event) => event.preventDefault(), onPointerMove: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox.js","sourceRoot":"","sources":["../../../src/components/combobox/Combobox.tsx"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAG3D,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AA4CrC,MAAM,aAAa,GAAG,CAAC,MAAsB,EAAE,KAAa,EAAW,EAAE,CACvE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAElE
|
|
1
|
+
{"version":3,"file":"Combobox.js","sourceRoot":"","sources":["../../../src/components/combobox/Combobox.tsx"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,22 @@ export interface ConfirmModalProps extends Omit<ModalProps, 'children' | 'size'>
|
|
|
12
12
|
confirmWord: string;
|
|
13
13
|
/** Label above the type-to-confirm input, e.g. `Type "acme-prod" to confirm`. */
|
|
14
14
|
promptLabel: ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* A second, independent type-to-confirm field (35-schema-authoring.md D18:
|
|
17
|
+
* the Super-Admin door over the row ceiling asks for a second, differently
|
|
18
|
+
* derived token in the same confirm). Both fields must match before the
|
|
19
|
+
* danger button enables, so this is an authorisation to ask for, never a
|
|
20
|
+
* decoration — a caller that renders it without meaning it deadlocks its own
|
|
21
|
+
* dialog. When absent, no second field reaches the DOM at all.
|
|
22
|
+
*/
|
|
23
|
+
secondPrompt?: {
|
|
24
|
+
/** Label above the second field, already localised by the caller. */
|
|
25
|
+
label: ReactNode;
|
|
26
|
+
/** The exact string that must be typed. */
|
|
27
|
+
expected: string;
|
|
28
|
+
/** Optional hint rendered under the field when it does not yet match. */
|
|
29
|
+
hint?: ReactNode;
|
|
30
|
+
} | undefined;
|
|
15
31
|
/** Danger button label (required — i18n). */
|
|
16
32
|
confirmLabel: string;
|
|
17
33
|
/** Cancel button label (required — i18n). */
|
|
@@ -31,8 +47,8 @@ export interface ConfirmModalProps extends Omit<ModalProps, 'children' | 'size'>
|
|
|
31
47
|
}
|
|
32
48
|
/**
|
|
33
49
|
* ConfirmModal — destructive confirmation with a type-to-confirm input gating
|
|
34
|
-
* the danger button (research/design-system.md §3 Tier 3)
|
|
35
|
-
*
|
|
50
|
+
* the danger button (research/design-system.md §3 Tier 3), optionally a second
|
|
51
|
+
* one (`secondPrompt`, D18). Typed values reset whenever the modal closes.
|
|
36
52
|
*/
|
|
37
|
-
export declare function ConfirmModal({ title, body, confirmWord, promptLabel, confirmLabel, cancelLabel, closeLabel, onConfirm, busy, icon, open, onOpenChange, ...modalProps }: ConfirmModalProps): import("react").JSX.Element;
|
|
53
|
+
export declare function ConfirmModal({ title, body, confirmWord, promptLabel, secondPrompt, confirmLabel, cancelLabel, closeLabel, onConfirm, busy, icon, open, onOpenChange, ...modalProps }: ConfirmModalProps): import("react").JSX.Element;
|
|
38
54
|
//# sourceMappingURL=ConfirmModal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmModal.d.ts","sourceRoot":"","sources":["../../../src/components/confirm-modal/ConfirmModal.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,EAA8C,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConfirmModal.d.ts","sourceRoot":"","sources":["../../../src/components/confirm-modal/ConfirmModal.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,EAA8C,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAehG,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAC;IAC9E,4CAA4C;IAC5C,KAAK,EAAE,SAAS,CAAC;IACjB,kFAAkF;IAClF,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,WAAW,EAAE,SAAS,CAAC;IACvB;;;;;;;OAOG;IACH,YAAY,CAAC,EACT;QACE,qEAAqE;QACrE,KAAK,EAAE,SAAS,CAAC;QACjB,2CAA2C;QAC3C,QAAQ,EAAE,MAAM,CAAC;QACjB,yEAAyE;QACzE,IAAI,CAAC,EAAE,SAAS,CAAC;KAClB,GACD,SAAS,CAAC;IACd,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,qEAAqE;IACrE,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,gEAAgE;IAChE,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,IAAI,EACJ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,GAAG,UAAU,EACd,EAAE,iBAAiB,+BAwInB"}
|
|
@@ -5,21 +5,53 @@ import { useEffect, useId, useState } from 'react';
|
|
|
5
5
|
import { cn } from '../../lib/cn.js';
|
|
6
6
|
import { Button } from '../button/Button.js';
|
|
7
7
|
import { Modal, ModalBody, ModalFooter, ModalHeader } from '../modal/Modal.js';
|
|
8
|
+
/**
|
|
9
|
+
* Both type-to-confirm fields share one declaration so they cannot drift into
|
|
10
|
+
* looking like a primary gate and a footnote — they are equal gates, and the
|
|
11
|
+
* second one is the harder of the two to satisfy.
|
|
12
|
+
*/
|
|
13
|
+
const fieldClass = cn('h-[34px] w-full rounded-md border border-border-strong bg-surface px-3 font-mono text-body text-fg', 'outline-none placeholder:text-fg-subtle disabled:opacity-40', 'focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-danger');
|
|
14
|
+
const labelClass = 'mb-1.5 block text-caption font-bold text-fg-muted';
|
|
8
15
|
/**
|
|
9
16
|
* ConfirmModal — destructive confirmation with a type-to-confirm input gating
|
|
10
|
-
* the danger button (research/design-system.md §3 Tier 3)
|
|
11
|
-
*
|
|
17
|
+
* the danger button (research/design-system.md §3 Tier 3), optionally a second
|
|
18
|
+
* one (`secondPrompt`, D18). Typed values reset whenever the modal closes.
|
|
12
19
|
*/
|
|
13
|
-
export function ConfirmModal({ title, body, confirmWord, promptLabel, confirmLabel, cancelLabel, closeLabel, onConfirm, busy, icon, open, onOpenChange, ...modalProps }) {
|
|
20
|
+
export function ConfirmModal({ title, body, confirmWord, promptLabel, secondPrompt, confirmLabel, cancelLabel, closeLabel, onConfirm, busy, icon, open, onOpenChange, ...modalProps }) {
|
|
14
21
|
const inputId = useId();
|
|
22
|
+
// Each field needs its own id. Reusing `inputId` would point both `htmlFor`
|
|
23
|
+
// attributes at the first input: a screen reader then announces the override
|
|
24
|
+
// field under the first field's label, and `getByLabelText` keeps returning
|
|
25
|
+
// the first input, so the tests stay green while the labelling is wrong.
|
|
26
|
+
const secondInputId = useId();
|
|
27
|
+
const hintId = useId();
|
|
15
28
|
const [typed, setTyped] = useState('');
|
|
29
|
+
const [secondTyped, setSecondTyped] = useState('');
|
|
16
30
|
const [pending, setPending] = useState(false);
|
|
17
31
|
const isBusy = busy ?? pending;
|
|
18
|
-
const
|
|
32
|
+
const secondExpected = secondPrompt?.expected;
|
|
33
|
+
// An empty `expected` would be satisfied by a field nobody touched, which is
|
|
34
|
+
// exactly what a value lost in transit looks like — a response serializer
|
|
35
|
+
// that strips the number, a caller interpolating something never measured.
|
|
36
|
+
// A gate that opens for free is worse than one that cannot open, so an empty
|
|
37
|
+
// target counts as unmet.
|
|
38
|
+
const secondMatches = secondExpected !== undefined && secondExpected !== '' && secondTyped === secondExpected;
|
|
39
|
+
const ready = typed === confirmWord && (secondPrompt === undefined || secondMatches);
|
|
40
|
+
const hint = secondPrompt?.hint;
|
|
41
|
+
const showHint = !secondMatches && hint !== undefined && hint !== null && hint !== false;
|
|
19
42
|
useEffect(() => {
|
|
20
|
-
if (open === false)
|
|
43
|
+
if (open === false) {
|
|
21
44
|
setTyped('');
|
|
45
|
+
setSecondTyped('');
|
|
46
|
+
}
|
|
22
47
|
}, [open]);
|
|
48
|
+
// The second field authorises one specific value. If the caller swaps that
|
|
49
|
+
// value while the dialog stays open — a re-plan behind an open confirm — a
|
|
50
|
+
// match carried over from the previous target would authorise something
|
|
51
|
+
// nobody ever read, so what was typed dies with the value it was typed for.
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
setSecondTyped('');
|
|
54
|
+
}, [secondExpected]);
|
|
23
55
|
const handleConfirm = async () => {
|
|
24
56
|
const result = onConfirm();
|
|
25
57
|
if (result instanceof Promise) {
|
|
@@ -36,6 +68,10 @@ export function ConfirmModal({ title, body, confirmWord, promptLabel, confirmLab
|
|
|
36
68
|
if (isBusy && !next)
|
|
37
69
|
return; // don't dismiss mid-flight
|
|
38
70
|
onOpenChange?.(next);
|
|
39
|
-
}, ...modalProps, children: [_jsx(ModalHeader, { tone: "danger", icon: icon ?? _jsx(TriangleAlert, {}), title: title, subtitle: body, closeLabel: closeLabel }), _jsxs(ModalBody, { children: [_jsx("label", { htmlFor: inputId, className:
|
|
71
|
+
}, ...modalProps, children: [_jsx(ModalHeader, { tone: "danger", icon: icon ?? _jsx(TriangleAlert, {}), title: title, subtitle: body, closeLabel: closeLabel }), _jsxs(ModalBody, { children: [_jsx("label", { htmlFor: inputId, className: labelClass, children: promptLabel }), _jsx("input", { id: inputId, type: "text", value: typed, disabled: isBusy, onChange: (event) => setTyped(event.target.value), autoComplete: "off", autoCapitalize: "off", autoCorrect: "off", spellCheck: false, "data-part": "confirm-input", className: fieldClass }), secondPrompt === undefined ? null : (
|
|
72
|
+
// Ruled off rather than stacked: two identical mono inputs in a
|
|
73
|
+
// 410px dialog read as the same challenge asked twice, and the
|
|
74
|
+
// operator answers the second one from muscle memory.
|
|
75
|
+
_jsxs("div", { className: "mt-4 border-t border-border pt-4", children: [_jsx("label", { htmlFor: secondInputId, className: labelClass, children: secondPrompt.label }), _jsx("input", { id: secondInputId, type: "text", value: secondTyped, disabled: isBusy, onChange: (event) => setSecondTyped(event.target.value), autoComplete: "off", autoCapitalize: "off", autoCorrect: "off", spellCheck: false, "data-part": "confirm-input-second", ...(showHint ? { 'aria-describedby': hintId } : {}), className: fieldClass }), showHint ? (_jsx("p", { id: hintId, className: "mt-1.5 text-[11.5px] leading-4 text-fg-muted", children: hint })) : null] }))] }), _jsxs(ModalFooter, { children: [_jsx(Button, { variant: "ghost", disabled: isBusy, onClick: () => onOpenChange?.(false), children: cancelLabel }), _jsx(Button, { variant: "destructive", disabled: !ready, loading: isBusy, onClick: () => void handleConfirm(), children: confirmLabel })] })] }));
|
|
40
76
|
}
|
|
41
77
|
//# sourceMappingURL=ConfirmModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmModal.js","sourceRoot":"","sources":["../../../src/components/confirm-modal/ConfirmModal.tsx"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGnD,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAmB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConfirmModal.js","sourceRoot":"","sources":["../../../src/components/confirm-modal/ConfirmModal.tsx"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,16 @@ export type DrawerSize = 'sm' | 'md' | 'lg';
|
|
|
6
6
|
export declare const DrawerTrigger: import("react").ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
7
7
|
/** Close wrapper for footer buttons (`asChild` supported). */
|
|
8
8
|
export declare const DrawerClose: import("react").ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
9
|
+
export type DrawerSide = 'end' | 'bottom';
|
|
9
10
|
export interface DrawerProps extends ComponentPropsWithRef<typeof DialogPrimitive.Root> {
|
|
10
|
-
/** Inline size: sm 380 / md 480 / lg 640. */
|
|
11
|
+
/** Inline size: sm 380 / md 480 / lg 640. Ignored for a bottom sheet, which is full-width. */
|
|
11
12
|
size?: DrawerSize | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Where the sheet comes from. `end` (default) is the side drawer; `bottom`
|
|
15
|
+
* is the phone-width sheet the Export Builder comp draws (41-export-builder.md
|
|
16
|
+
* D13): full width, 84vh tall at most, 20px top radius, sliding up.
|
|
17
|
+
*/
|
|
18
|
+
side?: DrawerSide | undefined;
|
|
12
19
|
/** Extra classes for the sheet panel. */
|
|
13
20
|
className?: string | undefined;
|
|
14
21
|
/** Extra classes for the scrim overlay. */
|
|
@@ -21,7 +28,7 @@ export interface DrawerProps extends ComponentPropsWithRef<typeof DialogPrimitiv
|
|
|
21
28
|
* compose with `DrawerHeader` / `DrawerBody` / `DrawerFooter`
|
|
22
29
|
* (research/design-system.md §3 Tier 3).
|
|
23
30
|
*/
|
|
24
|
-
export declare function Drawer({ size, className, overlayClassName, children, ...rootProps }: DrawerProps): import("react").JSX.Element;
|
|
31
|
+
export declare function Drawer({ size, side, className, overlayClassName, children, ...rootProps }: DrawerProps): import("react").JSX.Element;
|
|
25
32
|
export interface DrawerHeaderProps extends Omit<ComponentPropsWithRef<'div'>, 'title'> {
|
|
26
33
|
/** Lucide icon rendered in a tinted IconTile next to the title. */
|
|
27
34
|
icon?: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/drawer/Drawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAA4B,KAAK,qBAAqB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG7F,OAAO,EAAY,KAAK,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAS5C,2DAA2D;AAC3D,eAAO,MAAM,aAAa,kIAA0B,CAAC;AACrD,8DAA8D;AAC9D,eAAO,MAAM,WAAW,gIAAwB,CAAC;AAEjD,MAAM,WAAW,WAAY,SAAQ,qBAAqB,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC;IACrF,
|
|
1
|
+
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/drawer/Drawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAA4B,KAAK,qBAAqB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG7F,OAAO,EAAY,KAAK,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAS5C,2DAA2D;AAC3D,eAAO,MAAM,aAAa,kIAA0B,CAAC;AACrD,8DAA8D;AAC9D,eAAO,MAAM,WAAW,gIAAwB,CAAC;AAEjD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE1C,MAAM,WAAW,WAAY,SAAQ,qBAAqB,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC;IACrF,8FAA8F;IAC9F,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9B;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9B,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,EACrB,IAAW,EACX,IAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,QAAQ,EACR,GAAG,SAAS,EACb,EAAE,WAAW,+BAyCb;AAED,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACpF,mEAAmE;IACnE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IACxB,yEAAyE;IACzE,KAAK,EAAE,SAAS,CAAC;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,IAAe,EACf,KAAK,EACL,QAAQ,EACR,UAAU,EACV,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,iBAAiB,+BA4BnB;AAED,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;AAE3D,8BAA8B;AAC9B,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,+BAOlE;AAED,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;AAE7D,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,+BAUtE"}
|
|
@@ -21,15 +21,25 @@ export const DrawerClose = DialogPrimitive.Close;
|
|
|
21
21
|
* compose with `DrawerHeader` / `DrawerBody` / `DrawerFooter`
|
|
22
22
|
* (research/design-system.md §3 Tier 3).
|
|
23
23
|
*/
|
|
24
|
-
export function Drawer({ size = 'md', className, overlayClassName, children, ...rootProps }) {
|
|
24
|
+
export function Drawer({ size = 'md', side = 'end', className, overlayClassName, children, ...rootProps }) {
|
|
25
25
|
// Triggers must stay outside the Portal (unmounted while closed) — same
|
|
26
26
|
// pattern as Modal.
|
|
27
27
|
const childArray = Children.toArray(children);
|
|
28
28
|
const triggers = childArray.filter((c) => isValidElement(c) && c.type === DrawerTrigger);
|
|
29
29
|
const content = childArray.filter((c) => !(isValidElement(c) && c.type === DrawerTrigger));
|
|
30
|
-
return (_jsxs(DialogPrimitive.Root, { ...rootProps, children: [triggers, _jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Overlay, { className: cn('fixed inset-0 z-50 bg-[var(--scrim)] backdrop-blur-[3px]', 'animate-[nb-fade_.2s_cubic-bezier(.2,.7,.3,1)]', overlayClassName) }), _jsx(DialogPrimitive.Content, { className: cn(
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
return (_jsxs(DialogPrimitive.Root, { ...rootProps, children: [triggers, _jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Overlay, { className: cn('fixed inset-0 z-50 bg-[var(--scrim)] backdrop-blur-[3px]', 'animate-[nb-fade_.2s_cubic-bezier(.2,.7,.3,1)]', overlayClassName) }), _jsx(DialogPrimitive.Content, { "data-side": side, className: cn(side === 'bottom'
|
|
31
|
+
? [
|
|
32
|
+
'fixed inset-x-0 bottom-0 z-50 flex max-h-[84vh] w-full flex-col',
|
|
33
|
+
'rounded-t-[20px] border-t border-border bg-surface shadow-modal outline-none',
|
|
34
|
+
'animate-[nb-sheetup_.24s_cubic-bezier(.2,.8,.2,1)]',
|
|
35
|
+
]
|
|
36
|
+
: [
|
|
37
|
+
'fixed inset-y-0 end-0 z-50 flex h-full max-w-[calc(100vw-32px)] flex-col',
|
|
38
|
+
'border-s border-border bg-surface shadow-modal outline-none',
|
|
39
|
+
// nb-slide translates from --nb-slide-from (24px); flip for RTL.
|
|
40
|
+
'animate-[nb-slide_.22s_cubic-bezier(.2,.7,.3,1)] rtl:[--nb-slide-from:-24px]',
|
|
41
|
+
drawerSizeClasses[size],
|
|
42
|
+
], className), children: content })] })] }));
|
|
33
43
|
}
|
|
34
44
|
/** Drawer header: tinted icon tile + title/subtitle + close, bottom hairline. */
|
|
35
45
|
export function DrawerHeader({ icon, tone = 'accent', title, subtitle, closeLabel, className, children, ...props }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Drawer.js","sourceRoot":"","sources":["../../../src/components/drawer/Drawer.tsx"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAA8C,MAAM,OAAO,CAAC;AAE7F,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAa,MAAM,uBAAuB,CAAC;AAI5D,6EAA6E;AAC7E,MAAM,iBAAiB,GAA+B;IACpD,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,WAAW;CAChB,CAAC;AAEF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC;AACrD,8DAA8D;AAC9D,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"Drawer.js","sourceRoot":"","sources":["../../../src/components/drawer/Drawer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ export type DropdownMenuContentProps = Omit<React.ComponentPropsWithRef<typeof D
|
|
|
12
12
|
* (research/design-system.md §3 Tier 3). Rendered in a portal; typeahead,
|
|
13
13
|
* arrow-key roving and Esc/outside dismissal are Radix built-ins.
|
|
14
14
|
*/
|
|
15
|
-
export declare function DropdownMenuContent({ className, sideOffset, ...props }: DropdownMenuContentProps): React.JSX.Element;
|
|
15
|
+
export declare function DropdownMenuContent({ className, sideOffset, ref, ...props }: DropdownMenuContentProps): React.JSX.Element;
|
|
16
16
|
export interface DropdownMenuItemProps extends Omit<React.ComponentPropsWithRef<typeof DropdownMenuPrimitive.Item>, 'style'> {
|
|
17
17
|
/** Leading Lucide icon (decorative, muted). */
|
|
18
18
|
icon?: React.ReactNode | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../../src/components/dropdown-menu/DropdownMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,qBAAqB,MAAM,+BAA+B,CAAC;AAEvE,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../../src/components/dropdown-menu/DropdownMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,qBAAqB,MAAM,+BAA+B,CAAC;AAEvE,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAKpC,wEAAwE;AACxE,eAAO,MAAM,YAAY,mDAA6B,CAAC;AAEvD,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,0HAAgC,CAAC;AAEjE,6CAA6C;AAC7C,eAAO,MAAM,iBAAiB,qHAA8B,CAAC;AAE7D,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,KAAK,CAAC,qBAAqB,CAAC,OAAO,qBAAqB,CAAC,OAAO,CAAC,EACjE,OAAO,CACR,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,SAAS,EAAE,UAAc,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,wBAAwB,qBAoBzG;AAOD,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,OAAO,qBAAqB,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACrF,+CAA+C;IAC/C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACnC,mEAAmE;IACnE,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;CACxC;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,WAAmB,EACnB,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,qBAAqB,qBAoBvB;AAED,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAC9C,KAAK,CAAC,qBAAqB,CAAC,OAAO,qBAAqB,CAAC,YAAY,CAAC,EACtE,OAAO,CACR,CAAC;AAEF,sFAAsF;AACtF,wBAAgB,wBAAwB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,6BAA6B,qBAYxG;AAED,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,KAAK,CAAC,qBAAqB,CAAC,OAAO,qBAAqB,CAAC,KAAK,CAAC,EAC/D,OAAO,CACR,CAAC;AAEF,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,sBAAsB,qBAOhF;AAED,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,KAAK,CAAC,qBAAqB,CAAC,OAAO,qBAAqB,CAAC,SAAS,CAAC,EACnE,OAAO,CACR,CAAC;AAEF,uCAAuC;AACvC,wBAAgB,qBAAqB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,0BAA0B,qBAOxF"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
4
4
|
import { Check } from 'lucide-react';
|
|
5
|
+
import { useScrollLockBypass } from '../../hooks/useScrollLockBypass.js';
|
|
5
6
|
import { cn } from '../../lib/cn.js';
|
|
6
7
|
/** Root — controls open state (`open`/`onOpenChange`/`defaultOpen`). */
|
|
7
8
|
export const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
@@ -14,8 +15,13 @@ export const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
|
14
15
|
* (research/design-system.md §3 Tier 3). Rendered in a portal; typeahead,
|
|
15
16
|
* arrow-key roving and Esc/outside dismissal are Radix built-ins.
|
|
16
17
|
*/
|
|
17
|
-
export function DropdownMenuContent({ className, sideOffset = 6, ...props }) {
|
|
18
|
-
|
|
18
|
+
export function DropdownMenuContent({ className, sideOffset = 6, ref, ...props }) {
|
|
19
|
+
// The panel is portalled beside a dialog, not inside it, so a dialog's
|
|
20
|
+
// scroll lock would cancel every wheel over it. Nothing here scrolls today
|
|
21
|
+
// — this is what makes a `max-h-… overflow-y-auto` menu work when one
|
|
22
|
+
// arrives, instead of silently being dead to the wheel.
|
|
23
|
+
const setPanel = useScrollLockBypass(ref);
|
|
24
|
+
return (_jsx(DropdownMenuPrimitive.Portal, { children: _jsx(DropdownMenuPrimitive.Content, { ref: setPanel, sideOffset: sideOffset, className: cn('z-50 min-w-[190px] overscroll-contain rounded-lg border border-border bg-surface p-1 shadow-menu ', 'animate-[nb-pop_.16s_cubic-bezier(.2,.7,.3,1)]', className), ...props }) }));
|
|
19
25
|
}
|
|
20
26
|
const itemClasses = 'flex cursor-default select-none items-center gap-2 rounded-[8px] px-2.5 py-1.5 text-[13px] text-fg outline-none ' +
|
|
21
27
|
'data-[highlighted]:bg-surface-2 data-[disabled]:pointer-events-none data-[disabled]:opacity-40 ' +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMenu.js","sourceRoot":"","sources":["../../../src/components/dropdown-menu/DropdownMenu.tsx"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,OAAO,KAAK,qBAAqB,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAGrC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAErC,wEAAwE;AACxE,MAAM,CAAC,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAC;AAEvD,sFAAsF;AACtF,MAAM,CAAC,MAAM,mBAAmB,GAAG,qBAAqB,CAAC,OAAO,CAAC;AAEjE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,KAAK,CAAC;AAO7D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAE,SAAS,EAAE,UAAU,GAAG,CAAC,EAAE,GAAG,KAAK,EAA4B;
|
|
1
|
+
{"version":3,"file":"DropdownMenu.js","sourceRoot":"","sources":["../../../src/components/dropdown-menu/DropdownMenu.tsx"],"names":[],"mappings":"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"}
|
|
@@ -15,5 +15,5 @@ export type PopoverContentProps = Omit<React.ComponentPropsWithRef<typeof Popove
|
|
|
15
15
|
* Focus is moved into the panel and trapped by Radix; Esc/outside-click
|
|
16
16
|
* dismiss and return focus to the trigger.
|
|
17
17
|
*/
|
|
18
|
-
export declare function PopoverContent({ className, sideOffset, align, ...props }: PopoverContentProps): React.JSX.Element;
|
|
18
|
+
export declare function PopoverContent({ className, sideOffset, align, ref, ...props }: PopoverContentProps): React.JSX.Element;
|
|
19
19
|
//# sourceMappingURL=Popover.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../../src/components/popover/Popover.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../../src/components/popover/Popover.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAKpC,wEAAwE;AACxE,eAAO,MAAM,OAAO,yCAAwB,CAAC;AAE7C,+EAA+E;AAC/E,eAAO,MAAM,cAAc,gHAA2B,CAAC;AAEvD,wFAAwF;AACxF,eAAO,MAAM,aAAa,4GAA0B,CAAC;AAErD,qEAAqE;AACrE,eAAO,MAAM,YAAY,8GAAyB,CAAC;AAEnD,MAAM,MAAM,mBAAmB,GAAG,IAAI,CACpC,KAAK,CAAC,qBAAqB,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,EAC5D,OAAO,CACR,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,UAAc,EAAE,KAAgB,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,qBAoBjH"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
3
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
4
|
+
import { useScrollLockBypass } from '../../hooks/useScrollLockBypass.js';
|
|
4
5
|
import { cn } from '../../lib/cn.js';
|
|
5
6
|
/** Root — controls open state (`open`/`onOpenChange`/`defaultOpen`). */
|
|
6
7
|
export const Popover = PopoverPrimitive.Root;
|
|
@@ -16,7 +17,11 @@ export const PopoverClose = PopoverPrimitive.Close;
|
|
|
16
17
|
* Focus is moved into the panel and trapped by Radix; Esc/outside-click
|
|
17
18
|
* dismiss and return focus to the trigger.
|
|
18
19
|
*/
|
|
19
|
-
export function PopoverContent({ className, sideOffset = 6, align = 'center', ...props }) {
|
|
20
|
-
|
|
20
|
+
export function PopoverContent({ className, sideOffset = 6, align = 'center', ref, ...props }) {
|
|
21
|
+
// See `DropdownMenuContent`: the panel is portalled beside a dialog, so a
|
|
22
|
+
// dialog's scroll lock would cancel every wheel over it. Nothing here
|
|
23
|
+
// scrolls today; this is what makes a scrollable panel work when one lands.
|
|
24
|
+
const setPanel = useScrollLockBypass(ref);
|
|
25
|
+
return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { ref: setPanel, sideOffset: sideOffset, align: align, className: cn('z-50 w-[280px] overscroll-contain rounded-lg border border-border bg-surface p-3.5 shadow-menu outline-none ', 'animate-[nb-pop_.16s_cubic-bezier(.2,.7,.3,1)]', className), ...props }) }));
|
|
21
26
|
}
|
|
22
27
|
//# sourceMappingURL=Popover.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","sourceRoot":"","sources":["../../../src/components/popover/Popover.tsx"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAErC,wEAAwE;AACxE,MAAM,CAAC,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC;AAE7C,+EAA+E;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,OAAO,CAAC;AAEvD,wFAAwF;AACxF,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC;AAErD,qEAAqE;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAC,KAAK,CAAC;AAOnD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,SAAS,EAAE,UAAU,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAuB;
|
|
1
|
+
{"version":3,"file":"Popover.js","sourceRoot":"","sources":["../../../src/components/popover/Popover.tsx"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAErC,wEAAwE;AACxE,MAAM,CAAC,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC;AAE7C,+EAA+E;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,OAAO,CAAC;AAEvD,wFAAwF;AACxF,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC;AAErD,qEAAqE;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAC,KAAK,CAAC;AAOnD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,SAAS,EAAE,UAAU,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,EAAE,GAAG,EAAE,GAAG,KAAK,EAAuB;IAChH,0EAA0E;IAC1E,sEAAsE;IACtE,4EAA4E;IAC5E,MAAM,QAAQ,GAAG,mBAAmB,CAAiB,GAAG,CAAC,CAAC;IAC1D,OAAO,CACL,KAAC,gBAAgB,CAAC,MAAM,cACtB,KAAC,gBAAgB,CAAC,OAAO,IACvB,GAAG,EAAE,QAAQ,EACb,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,EAAE,CACX,8GAA8G,EAC9G,gDAAgD,EAChD,SAAS,CACV,KACG,KAAK,GACT,GACsB,CAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -11,6 +11,18 @@ export interface RadioCardProps extends Omit<React.ComponentPropsWithRef<typeof
|
|
|
11
11
|
trailing?: React.ReactNode | undefined;
|
|
12
12
|
/** Hide the top-end check indicator shown when selected. */
|
|
13
13
|
hideIndicator?: boolean | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Card shape.
|
|
16
|
+
*
|
|
17
|
+
* `row` (default) is the one every existing caller renders: a bare leading
|
|
18
|
+
* glyph beside a 13px title. `tile` and `stack` are the two the onboarding
|
|
19
|
+
* comps draw (`designs/Onboarding.dc.html`, 45-onboarding.md §3) — a 40px
|
|
20
|
+
* accent-filling icon tile, leading with a description or centred above a
|
|
21
|
+
* label — and they are here rather than hand-rolled in the wizard because
|
|
22
|
+
* the Radix item underneath is what makes arrow keys and `aria-checked`
|
|
23
|
+
* work, and it is not exported.
|
|
24
|
+
*/
|
|
25
|
+
layout?: 'row' | 'tile' | 'stack' | undefined;
|
|
14
26
|
}
|
|
15
27
|
/**
|
|
16
28
|
* RadioCard — selectable card variant of the radio item
|
|
@@ -18,5 +30,5 @@ export interface RadioCardProps extends Omit<React.ComponentPropsWithRef<typeof
|
|
|
18
30
|
* accent border + accent-soft bg + check indicator. Must be rendered inside
|
|
19
31
|
* a `RadioGroup` (../radio); arrow keys move and select between cards.
|
|
20
32
|
*/
|
|
21
|
-
export declare function RadioCard({ title, description, icon, trailing, hideIndicator, className, ...props }: RadioCardProps): React.JSX.Element;
|
|
33
|
+
export declare function RadioCard({ layout, title, description, icon, trailing, hideIndicator, className, ...props }: RadioCardProps): React.JSX.Element;
|
|
22
34
|
//# sourceMappingURL=RadioCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadioCard.d.ts","sourceRoot":"","sources":["../../../src/components/radio-card/RadioCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,mBAAmB,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAIpC,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IACtH,2EAA2E;IAC3E,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uCAAuC;IACvC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IAC1C,6DAA6D;IAC7D,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACvC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"RadioCard.d.ts","sourceRoot":"","sources":["../../../src/components/radio-card/RadioCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,mBAAmB,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAIpC,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IACtH,2EAA2E;IAC3E,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uCAAuC;IACvC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IAC1C,6DAA6D;IAC7D,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACvC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CAC/C;AA4BD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,MAAc,EACd,KAAK,EACL,WAAW,EACX,IAAI,EACJ,QAAQ,EACR,aAAqB,EACrB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,qBAsDhB"}
|
|
@@ -3,14 +3,37 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
4
4
|
import { Check } from 'lucide-react';
|
|
5
5
|
import { cn } from '../../lib/cn.js';
|
|
6
|
+
/** Per-layout geometry, from the comp: padding, radius, and the icon's box. */
|
|
7
|
+
const LAYOUT = {
|
|
8
|
+
row: {
|
|
9
|
+
card: 'items-start gap-3 rounded-lg p-3.5',
|
|
10
|
+
icon: 'items-center [&_svg]:size-[18px]',
|
|
11
|
+
title: 'text-[13px] font-semibold text-fg',
|
|
12
|
+
description: 'text-[11.5px] leading-4 text-fg-muted',
|
|
13
|
+
},
|
|
14
|
+
tile: {
|
|
15
|
+
card: 'items-start gap-3 rounded-[13px] p-[15px]',
|
|
16
|
+
icon: 'size-10 items-center justify-center rounded-[11px] bg-surface-3 ' +
|
|
17
|
+
'group-data-[state=checked]:bg-accent group-data-[state=checked]:text-accent-fg [&_svg]:size-[18px]',
|
|
18
|
+
title: 'text-[13.5px] font-bold text-fg',
|
|
19
|
+
description: 'mt-1 text-[11.5px] leading-[1.5] text-fg-subtle',
|
|
20
|
+
},
|
|
21
|
+
stack: {
|
|
22
|
+
card: 'flex-col items-center gap-[9px] rounded-[13px] p-[15px] text-center',
|
|
23
|
+
icon: 'size-10 items-center justify-center rounded-[11px] bg-surface-3 ' +
|
|
24
|
+
'group-data-[state=checked]:bg-accent group-data-[state=checked]:text-accent-fg [&_svg]:size-5',
|
|
25
|
+
title: 'text-[13px] font-bold text-fg',
|
|
26
|
+
description: 'mt-1 text-[11.5px] leading-[1.5] text-fg-subtle',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
6
29
|
/**
|
|
7
30
|
* RadioCard — selectable card variant of the radio item
|
|
8
31
|
* (research/design-system.md §3 Tier 2): full-card click target, selected =
|
|
9
32
|
* accent border + accent-soft bg + check indicator. Must be rendered inside
|
|
10
33
|
* a `RadioGroup` (../radio); arrow keys move and select between cards.
|
|
11
34
|
*/
|
|
12
|
-
export function RadioCard({ title, description, icon, trailing, hideIndicator = false, className, ...props }) {
|
|
13
|
-
return (_jsxs(RadioGroupPrimitive.Item, { className: cn('group relative flex w-full
|
|
35
|
+
export function RadioCard({ layout = 'row', title, description, icon, trailing, hideIndicator = false, className, ...props }) {
|
|
36
|
+
return (_jsxs(RadioGroupPrimitive.Item, { className: cn('group relative flex w-full cursor-pointer border border-border-strong bg-surface text-start ', LAYOUT[layout].card, layout === 'stack' ? '' : 'text-start ', 'transition-[border-color,background-color,box-shadow] duration-150 hover:border-fg-subtle ', 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent ', 'disabled:pointer-events-none disabled:opacity-40 ', 'data-[state=checked]:border-accent data-[state=checked]:bg-accent-soft', className), ...props, children: [icon ? (_jsx("span", { "aria-hidden": "true", className: cn('flex shrink-0 text-fg-muted group-data-[state=checked]:text-accent', LAYOUT[layout].icon), children: icon })) : null, _jsxs("span", { className: cn('flex min-w-0 flex-col gap-0.5', layout === 'stack' ? 'items-center' : 'flex-1'), children: [_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: LAYOUT[layout].title, children: title }), trailing ? _jsx("span", { className: "ms-auto flex shrink-0 items-center", children: trailing }) : null] }), description === undefined || description === null ? null : (_jsx("span", { className: LAYOUT[layout].description, children: description }))] }), hideIndicator ? null : (_jsx(RadioGroupPrimitive.Indicator, { "aria-hidden": "true", className: cn('absolute end-2.5 top-2.5 flex size-[18px] items-center justify-center rounded-full bg-accent text-accent-fg',
|
|
14
37
|
// keep the check clear of the trailing slot when both are present
|
|
15
38
|
trailing ? 'top-auto bottom-2.5' : ''), children: _jsx(Check, { strokeWidth: 3, className: "size-3" }) }))] }));
|
|
16
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadioCard.js","sourceRoot":"","sources":["../../../src/components/radio-card/RadioCard.tsx"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,OAAO,KAAK,mBAAmB,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAGrC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"RadioCard.js","sourceRoot":"","sources":["../../../src/components/radio-card/RadioCard.tsx"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,OAAO,KAAK,mBAAmB,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAGrC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AA4BrC,+EAA+E;AAC/E,MAAM,MAAM,GAAG;IACb,GAAG,EAAE;QACH,IAAI,EAAE,oCAAoC;QAC1C,IAAI,EAAE,kCAAkC;QACxC,KAAK,EAAE,mCAAmC;QAC1C,WAAW,EAAE,uCAAuC;KACrD;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,2CAA2C;QACjD,IAAI,EACF,kEAAkE;YAClE,oGAAoG;QACtG,KAAK,EAAE,iCAAiC;QACxC,WAAW,EAAE,iDAAiD;KAC/D;IACD,KAAK,EAAE;QACL,IAAI,EAAE,qEAAqE;QAC3E,IAAI,EACF,kEAAkE;YAClE,+FAA+F;QACjG,KAAK,EAAE,+BAA+B;QACtC,WAAW,EAAE,iDAAiD;KAC/D;CACO,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,MAAM,GAAG,KAAK,EACd,KAAK,EACL,WAAW,EACX,IAAI,EACJ,QAAQ,EACR,aAAa,GAAG,KAAK,EACrB,SAAS,EACT,GAAG,KAAK,EACO;IACf,OAAO,CACL,MAAC,mBAAmB,CAAC,IAAI,IACvB,SAAS,EAAE,EAAE,CACX,8FAA8F,EAC9F,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EACnB,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,EACvC,4FAA4F,EAC5F,sFAAsF,EACtF,mDAAmD,EACnD,wEAAwE,EACxE,SAAS,CACV,KACG,KAAK,aAER,IAAI,CAAC,CAAC,CAAC,CACN,8BACc,MAAM,EAClB,SAAS,EAAE,EAAE,CACX,oEAAoE,EACpE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CACpB,YAEA,IAAI,GACA,CACR,CAAC,CAAC,CAAC,IAAI,EACR,gBACE,SAAS,EAAE,EAAE,CACX,+BAA+B,EAC/B,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAC/C,aAED,gBAAM,SAAS,EAAC,yBAAyB,aACvC,eAAM,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,YAAG,KAAK,GAAQ,EACpD,QAAQ,CAAC,CAAC,CAAC,eAAM,SAAS,EAAC,oCAAoC,YAAE,QAAQ,GAAQ,CAAC,CAAC,CAAC,IAAI,IACpF,EACN,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC1D,eAAM,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,YAAG,WAAW,GAAQ,CAClE,IACI,EACN,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACtB,KAAC,mBAAmB,CAAC,SAAS,mBAChB,MAAM,EAClB,SAAS,EAAE,EAAE,CACX,6GAA6G;gBAC7G,kEAAkE;gBAClE,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,CACtC,YAED,KAAC,KAAK,IAAC,WAAW,EAAE,CAAC,EAAE,SAAS,EAAC,QAAQ,GAAG,GACd,CACjC,IACwB,CAC5B,CAAC;AACJ,CAAC"}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { useScrollLockBypass } from './useScrollLockBypass.js';
|
|
1
2
|
export { UNDO_WINDOW_MS, useUndoableAction } from './useUndoableAction.js';
|
|
2
3
|
export type { UndoableRun, UndoableState, UseUndoableActionOptions, UseUndoableActionReturn, } from './useUndoableAction.js';
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3E,YAAY,EACV,WAAW,EACX,aAAa,EACb,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3E,YAAY,EACV,WAAW,EACX,aAAa,EACb,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,wBAAwB,CAAC"}
|
package/dist/hooks/index.js
CHANGED
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Ref, type RefCallback } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Let a PORTALLED panel be scrolled by wheel and touch while a dialog's
|
|
4
|
+
* scroll lock is active.
|
|
5
|
+
*
|
|
6
|
+
* `Modal` and `Drawer` are Radix dialogs, and Radix locks background scroll
|
|
7
|
+
* with `react-remove-scroll`. That lock lives on the OVERLAY and whitelists
|
|
8
|
+
* ("shards") only the dialog panel, then registers `wheel`/`touchmove` on
|
|
9
|
+
* `document` and cancels every one whose target is in neither — WITHOUT
|
|
10
|
+
* asking whether the target could be scrolled. An anchored panel is portalled
|
|
11
|
+
* to `body` as a SIBLING of the dialog, so it is always "neither": a
|
|
12
|
+
* scrollable one could be dragged by its scrollbar and moved by ↑/↓, but a
|
|
13
|
+
* mouse wheel or a trackpad swipe did nothing at all.
|
|
14
|
+
*
|
|
15
|
+
* The lock's listener is on `document` in the BUBBLE phase, so stopping the
|
|
16
|
+
* event at the panel means it is never seen and never cancelled, and the
|
|
17
|
+
* browser scrolls the panel natively. Pair this with `overscroll-contain` on
|
|
18
|
+
* the scroll container, which is what keeps the freed scroll from chaining to
|
|
19
|
+
* the page at either end.
|
|
20
|
+
*
|
|
21
|
+
* Returns the `ref` to put on the panel; pass a forwarded `ref` in and it is
|
|
22
|
+
* called too. Outside a dialog this changes nothing — there is no lock, and
|
|
23
|
+
* `stopPropagation` does not stop the browser's own scrolling.
|
|
24
|
+
*/
|
|
25
|
+
export declare function useScrollLockBypass<T extends HTMLElement>(forwarded?: Ref<T> | undefined): RefCallback<T>;
|
|
26
|
+
//# sourceMappingURL=useScrollLockBypass.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScrollLockBypass.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollLockBypass.ts"],"names":[],"mappings":"AACA,OAAO,EAAoC,KAAK,GAAG,EAAE,KAAK,WAAW,EAAE,MAAM,OAAO,CAAC;AAErF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,WAAW,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,CA2BzG"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Let a PORTALLED panel be scrolled by wheel and touch while a dialog's
|
|
5
|
+
* scroll lock is active.
|
|
6
|
+
*
|
|
7
|
+
* `Modal` and `Drawer` are Radix dialogs, and Radix locks background scroll
|
|
8
|
+
* with `react-remove-scroll`. That lock lives on the OVERLAY and whitelists
|
|
9
|
+
* ("shards") only the dialog panel, then registers `wheel`/`touchmove` on
|
|
10
|
+
* `document` and cancels every one whose target is in neither — WITHOUT
|
|
11
|
+
* asking whether the target could be scrolled. An anchored panel is portalled
|
|
12
|
+
* to `body` as a SIBLING of the dialog, so it is always "neither": a
|
|
13
|
+
* scrollable one could be dragged by its scrollbar and moved by ↑/↓, but a
|
|
14
|
+
* mouse wheel or a trackpad swipe did nothing at all.
|
|
15
|
+
*
|
|
16
|
+
* The lock's listener is on `document` in the BUBBLE phase, so stopping the
|
|
17
|
+
* event at the panel means it is never seen and never cancelled, and the
|
|
18
|
+
* browser scrolls the panel natively. Pair this with `overscroll-contain` on
|
|
19
|
+
* the scroll container, which is what keeps the freed scroll from chaining to
|
|
20
|
+
* the page at either end.
|
|
21
|
+
*
|
|
22
|
+
* Returns the `ref` to put on the panel; pass a forwarded `ref` in and it is
|
|
23
|
+
* called too. Outside a dialog this changes nothing — there is no lock, and
|
|
24
|
+
* `stopPropagation` does not stop the browser's own scrolling.
|
|
25
|
+
*/
|
|
26
|
+
export function useScrollLockBypass(forwarded) {
|
|
27
|
+
// State, not a ref: Radix mounts the portalled panel in a LATER commit than
|
|
28
|
+
// the one that opens it, so an effect keyed on the open flag reads null and
|
|
29
|
+
// never runs again. The node itself has to be the dependency.
|
|
30
|
+
const [panel, setPanel] = useState(null);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (panel === null)
|
|
33
|
+
return undefined;
|
|
34
|
+
const stop = (event) => {
|
|
35
|
+
event.stopPropagation();
|
|
36
|
+
};
|
|
37
|
+
panel.addEventListener('wheel', stop);
|
|
38
|
+
panel.addEventListener('touchmove', stop);
|
|
39
|
+
return () => {
|
|
40
|
+
panel.removeEventListener('wheel', stop);
|
|
41
|
+
panel.removeEventListener('touchmove', stop);
|
|
42
|
+
};
|
|
43
|
+
}, [panel]);
|
|
44
|
+
return useCallback((node) => {
|
|
45
|
+
setPanel(node);
|
|
46
|
+
if (typeof forwarded === 'function')
|
|
47
|
+
forwarded(node);
|
|
48
|
+
else if (forwarded !== null && forwarded !== undefined)
|
|
49
|
+
forwarded.current = node;
|
|
50
|
+
}, [forwarded]);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=useScrollLockBypass.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScrollLockBypass.js","sourceRoot":"","sources":["../../src/hooks/useScrollLockBypass.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAA8B,MAAM,OAAO,CAAC;AAErF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,mBAAmB,CAAwB,SAA8B;IACvF,4EAA4E;IAC5E,4EAA4E;IAC5E,8DAA8D;IAC9D,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAW,IAAI,CAAC,CAAC;IAEnD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,SAAS,CAAC;QACrC,MAAM,IAAI,GAAG,CAAC,KAAY,EAAQ,EAAE;YAClC,KAAK,CAAC,eAAe,EAAE,CAAC;QAC1B,CAAC,CAAC;QACF,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACtC,KAAK,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC1C,OAAO,GAAG,EAAE;YACV,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACzC,KAAK,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,OAAO,WAAW,CAChB,CAAC,IAAc,EAAE,EAAE;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,OAAO,SAAS,KAAK,UAAU;YAAE,SAAS,CAAC,IAAI,CAAC,CAAC;aAChD,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS;YAAE,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;IACnF,CAAC,EACD,CAAC,SAAS,CAAC,CACZ,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminiumjs/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@adminium/tokens": "npm:@adminiumjs/tokens@0.2.
|
|
26
|
+
"@adminium/tokens": "npm:@adminiumjs/tokens@0.2.7",
|
|
27
27
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
28
28
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
29
29
|
"@radix-ui/react-direction": "^1.1.1",
|