@human-kit/svelte-components 1.0.0-alpha.2 → 1.0.0-alpha.4
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/FOCUS_STATE_CONTRACT.md +63 -0
- package/dist/FOCUS_STATE_REVIEW_TEMPLATE.md +70 -0
- package/dist/calendar/README.md +2 -1
- package/dist/calendar/TODO.md +21 -107
- package/dist/calendar/body-cell/README.md +15 -0
- package/dist/calendar/body-cell/calendar-body-cell.svelte +116 -41
- package/dist/calendar/grid/README.md +13 -0
- package/dist/calendar/grid-body/README.md +13 -0
- package/dist/calendar/grid-header/README.md +13 -0
- package/dist/calendar/header-cell/README.md +14 -0
- package/dist/calendar/heading/README.md +13 -0
- package/dist/calendar/root/README.md +24 -0
- package/dist/calendar/root/calendar-root-test.svelte +4 -0
- package/dist/calendar/root/calendar-root-test.svelte.d.ts +1 -0
- package/dist/calendar/root/calendar-root.svelte +3 -0
- package/dist/calendar/root/calendar-root.svelte.d.ts +1 -0
- package/dist/calendar/root/context.d.ts +4 -0
- package/dist/calendar/root/context.js +28 -25
- package/dist/calendar/root/date-utils.d.ts +1 -1
- package/dist/calendar/root/date-utils.js +16 -26
- package/dist/calendar/trigger-next/README.md +14 -0
- package/dist/calendar/trigger-previous/README.md +14 -0
- package/dist/clock/README.md +75 -0
- package/dist/clock/axis/README.md +24 -0
- package/dist/clock/axis/clock-axis.svelte +37 -0
- package/dist/clock/axis/clock-axis.svelte.d.ts +8 -0
- package/dist/clock/hooks/use-wheel-scroll.svelte.d.ts +16 -0
- package/dist/clock/hooks/use-wheel-scroll.svelte.js +336 -0
- package/dist/clock/index.d.ts +10 -0
- package/dist/clock/index.js +10 -0
- package/dist/clock/index.parts.d.ts +4 -0
- package/dist/clock/index.parts.js +4 -0
- package/dist/clock/root/README.md +38 -0
- package/dist/clock/root/clock-root-test.svelte +62 -0
- package/dist/clock/root/clock-root-test.svelte.d.ts +14 -0
- package/dist/clock/root/clock-root.svelte +329 -0
- package/dist/clock/root/clock-root.svelte.d.ts +25 -0
- package/dist/clock/root/context.d.ts +22 -0
- package/dist/clock/root/context.js +15 -0
- package/dist/clock/root/resolve-visible-columns.d.ts +7 -0
- package/dist/clock/root/resolve-visible-columns.js +16 -0
- package/dist/clock/root/time-utils.d.ts +48 -0
- package/dist/clock/root/time-utils.js +314 -0
- package/dist/clock/root/wheel-options.d.ts +17 -0
- package/dist/clock/root/wheel-options.js +63 -0
- package/dist/clock/wheel-column/README.md +25 -0
- package/dist/clock/wheel-column/clock-wheel-column-bindable-test.svelte +16 -0
- package/dist/clock/wheel-column/clock-wheel-column-bindable-test.svelte.d.ts +3 -0
- package/dist/clock/wheel-column/clock-wheel-column-custom-snippet-test.svelte +29 -0
- package/dist/clock/wheel-column/clock-wheel-column-custom-snippet-test.svelte.d.ts +6 -0
- package/dist/clock/wheel-column/clock-wheel-column-default-height-test.svelte +11 -0
- package/dist/clock/wheel-column/clock-wheel-column-default-height-test.svelte.d.ts +3 -0
- package/dist/clock/wheel-column/clock-wheel-column-test.svelte +38 -0
- package/dist/clock/wheel-column/clock-wheel-column-test.svelte.d.ts +12 -0
- package/dist/clock/wheel-column/clock-wheel-column-tp-test.svelte +38 -0
- package/dist/clock/wheel-column/clock-wheel-column-tp-test.svelte.d.ts +12 -0
- package/dist/clock/wheel-column/clock-wheel-column-untagged-snippet-test.svelte +29 -0
- package/dist/clock/wheel-column/clock-wheel-column-untagged-snippet-test.svelte.d.ts +6 -0
- package/dist/clock/wheel-column/clock-wheel-column.svelte +499 -0
- package/dist/clock/wheel-column/clock-wheel-column.svelte.d.ts +17 -0
- package/dist/clock/wheel-item/README.md +17 -0
- package/dist/clock/wheel-item/clock-wheel-item.svelte +49 -0
- package/dist/clock/wheel-item/clock-wheel-item.svelte.d.ts +17 -0
- package/dist/combobox/TODO.md +28 -175
- package/dist/combobox/button/combobox-button.svelte +2 -0
- package/dist/combobox/root/combobox.svelte +30 -0
- package/dist/datepicker/README.md +100 -0
- package/dist/datepicker/TODO.md +28 -0
- package/dist/datepicker/calendar/README.md +19 -0
- package/dist/datepicker/calendar/date-picker-calendar-unsafe-props-test.svelte +60 -0
- package/dist/datepicker/calendar/date-picker-calendar-unsafe-props-test.svelte.d.ts +3 -0
- package/dist/datepicker/calendar/date-picker-calendar.svelte +65 -0
- package/dist/datepicker/calendar/date-picker-calendar.svelte.d.ts +10 -0
- package/dist/datepicker/index.d.ts +18 -0
- package/dist/datepicker/index.js +18 -0
- package/dist/datepicker/index.parts.d.ts +14 -0
- package/dist/datepicker/index.parts.js +14 -0
- package/dist/datepicker/input/README.md +15 -0
- package/dist/datepicker/input/date-picker-input.svelte +108 -0
- package/dist/datepicker/input/date-picker-input.svelte.d.ts +11 -0
- package/dist/datepicker/internal/strict-props.d.ts +2 -0
- package/dist/datepicker/internal/strict-props.js +28 -0
- package/dist/datepicker/popover/README.md +20 -0
- package/dist/datepicker/popover/date-picker-popover-handler-test.svelte +57 -0
- package/dist/datepicker/popover/date-picker-popover-handler-test.svelte.d.ts +3 -0
- package/dist/datepicker/popover/date-picker-popover-unsafe-props-test.svelte +45 -0
- package/dist/datepicker/popover/date-picker-popover-unsafe-props-test.svelte.d.ts +18 -0
- package/dist/datepicker/popover/date-picker-popover.svelte +87 -0
- package/dist/datepicker/popover/date-picker-popover.svelte.d.ts +7 -0
- package/dist/datepicker/root/README.md +38 -0
- package/dist/datepicker/root/context.d.ts +43 -0
- package/dist/datepicker/root/context.js +15 -0
- package/dist/datepicker/root/date-picker-bindable-empty-test.svelte +24 -0
- package/dist/datepicker/root/date-picker-bindable-empty-test.svelte.d.ts +3 -0
- package/dist/datepicker/root/date-picker-bindable-test.svelte +41 -0
- package/dist/datepicker/root/date-picker-bindable-test.svelte.d.ts +3 -0
- package/dist/datepicker/root/date-picker-empty-test.svelte +47 -0
- package/dist/datepicker/root/date-picker-empty-test.svelte.d.ts +3 -0
- package/dist/datepicker/root/date-picker-locale-typing-test.svelte +47 -0
- package/dist/datepicker/root/date-picker-locale-typing-test.svelte.d.ts +3 -0
- package/dist/datepicker/root/date-picker-open-cancel-test.svelte +54 -0
- package/dist/datepicker/root/date-picker-open-cancel-test.svelte.d.ts +8 -0
- package/dist/datepicker/root/date-picker-root.svelte +495 -0
- package/dist/datepicker/root/date-picker-root.svelte.d.ts +24 -0
- package/dist/datepicker/root/date-picker-test.svelte +86 -0
- package/dist/datepicker/root/date-picker-test.svelte.d.ts +13 -0
- package/dist/datepicker/root/date-utils.d.ts +17 -0
- package/dist/datepicker/root/date-utils.js +138 -0
- package/dist/datepicker/root/draft-evaluation.d.ts +13 -0
- package/dist/datepicker/root/draft-evaluation.js +56 -0
- package/dist/datepicker/root/focus-controller.d.ts +3 -0
- package/dist/datepicker/root/focus-controller.js +15 -0
- package/dist/datepicker/root/open-change.d.ts +5 -0
- package/dist/datepicker/root/open-change.js +13 -0
- package/dist/datepicker/root/open-controller.d.ts +7 -0
- package/dist/datepicker/root/open-controller.js +15 -0
- package/dist/datepicker/root/segment-controller.d.ts +8 -0
- package/dist/datepicker/root/segment-controller.js +53 -0
- package/dist/datepicker/root/segment-state.d.ts +18 -0
- package/dist/datepicker/root/segment-state.js +134 -0
- package/dist/datepicker/root/value-commit.d.ts +4 -0
- package/dist/datepicker/root/value-commit.js +8 -0
- package/dist/datepicker/segment/README.md +14 -0
- package/dist/datepicker/segment/date-picker-segment.svelte +319 -0
- package/dist/datepicker/segment/date-picker-segment.svelte.d.ts +9 -0
- package/dist/datepicker/trigger/README.md +14 -0
- package/dist/datepicker/trigger/date-picker-trigger.svelte +110 -0
- package/dist/datepicker/trigger/date-picker-trigger.svelte.d.ts +9 -0
- package/dist/dialog/content/dialog-content.svelte +6 -6
- package/dist/dialog/root/context.d.ts +2 -1
- package/dist/dialog/root/dialog-root.svelte +9 -2
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/listbox/root/listbox.svelte +44 -0
- package/dist/popover/README.md +10 -0
- package/dist/popover/content/popover-content-standalone-test.svelte +28 -0
- package/dist/popover/content/popover-content-standalone-test.svelte.d.ts +6 -0
- package/dist/popover/content/popover-content-test.svelte +2 -1
- package/dist/popover/content/popover-content-test.svelte.d.ts +2 -1
- package/dist/popover/content/popover-content.svelte +91 -18
- package/dist/popover/content/popover-content.svelte.d.ts +5 -1
- package/dist/popover/index.d.ts +1 -1
- package/dist/popover/index.js +1 -3
- package/dist/popover/root/README.md +10 -15
- package/dist/popover/root/context.d.ts +16 -7
- package/dist/popover/root/context.js +0 -2
- package/dist/popover/root/focus-state.d.ts +4 -0
- package/dist/popover/root/focus-state.js +33 -0
- package/dist/popover/root/popover-root.svelte +90 -17
- package/dist/popover/root/popover-root.svelte.d.ts +2 -1
- package/dist/popover/root/popover-test.svelte +2 -1
- package/dist/popover/root/popover-test.svelte.d.ts +2 -1
- package/dist/popover/trigger/popover-trigger-button.svelte +4 -4
- package/dist/popover/trigger/popover-trigger.svelte +1 -1
- package/dist/portal/portal.svelte +3 -1
- package/dist/primitives/click-outside.d.ts +1 -1
- package/dist/primitives/click-outside.js +1 -1
- package/dist/primitives/focus-trap.d.ts +7 -2
- package/dist/primitives/focus-trap.js +50 -17
- package/dist/primitives/index.d.ts +1 -0
- package/dist/primitives/index.js +1 -0
- package/dist/primitives/input-modality.d.ts +7 -0
- package/dist/primitives/input-modality.js +125 -0
- package/dist/test-utils/focus-contract.d.ts +3 -0
- package/dist/test-utils/focus-contract.js +26 -0
- package/dist/timepicker/IMPLEMENTATION_PLAN.md +254 -0
- package/dist/timepicker/README.md +97 -0
- package/dist/timepicker/TODO.md +86 -0
- package/dist/timepicker/clock/README.md +14 -0
- package/dist/timepicker/clock/time-picker-clock-test.svelte +45 -0
- package/dist/timepicker/clock/time-picker-clock-test.svelte.d.ts +11 -0
- package/dist/timepicker/clock/time-picker-clock.svelte +65 -0
- package/dist/timepicker/clock/time-picker-clock.svelte.d.ts +10 -0
- package/dist/timepicker/index.d.ts +14 -0
- package/dist/timepicker/index.js +14 -0
- package/dist/timepicker/index.parts.d.ts +8 -0
- package/dist/timepicker/index.parts.js +8 -0
- package/dist/timepicker/input/README.md +15 -0
- package/dist/timepicker/input/time-picker-input-forwarding-test.svelte +40 -0
- package/dist/timepicker/input/time-picker-input-forwarding-test.svelte.d.ts +3 -0
- package/dist/timepicker/input/time-picker-input.svelte +109 -0
- package/dist/timepicker/input/time-picker-input.svelte.d.ts +11 -0
- package/dist/timepicker/internal/strict-props.d.ts +4 -0
- package/dist/timepicker/internal/strict-props.js +51 -0
- package/dist/timepicker/popover/README.md +20 -0
- package/dist/timepicker/popover/time-picker-popover-unsafe-props-test.svelte +22 -0
- package/dist/timepicker/popover/time-picker-popover-unsafe-props-test.svelte.d.ts +3 -0
- package/dist/timepicker/popover/time-picker-popover.svelte +89 -0
- package/dist/timepicker/popover/time-picker-popover.svelte.d.ts +7 -0
- package/dist/timepicker/root/README.md +42 -0
- package/dist/timepicker/root/context.d.ts +51 -0
- package/dist/timepicker/root/context.js +15 -0
- package/dist/timepicker/root/time-picker-12h-test.svelte +22 -0
- package/dist/timepicker/root/time-picker-12h-test.svelte.d.ts +3 -0
- package/dist/timepicker/root/time-picker-bindable-test.svelte +25 -0
- package/dist/timepicker/root/time-picker-bindable-test.svelte.d.ts +3 -0
- package/dist/timepicker/root/time-picker-empty-test.svelte +20 -0
- package/dist/timepicker/root/time-picker-empty-test.svelte.d.ts +3 -0
- package/dist/timepicker/root/time-picker-root.svelte +625 -0
- package/dist/timepicker/root/time-picker-root.svelte.d.ts +28 -0
- package/dist/timepicker/root/time-picker-test.svelte +72 -0
- package/dist/timepicker/root/time-picker-test.svelte.d.ts +15 -0
- package/dist/timepicker/root/time-utils.d.ts +1 -0
- package/dist/timepicker/root/time-utils.js +3 -0
- package/dist/timepicker/segment/README.md +14 -0
- package/dist/timepicker/segment/time-picker-segment.svelte +365 -0
- package/dist/timepicker/segment/time-picker-segment.svelte.d.ts +9 -0
- package/dist/timepicker/trigger/README.md +14 -0
- package/dist/timepicker/trigger/time-picker-trigger-forwarding-test.svelte +35 -0
- package/dist/timepicker/trigger/time-picker-trigger-forwarding-test.svelte.d.ts +3 -0
- package/dist/timepicker/trigger/time-picker-trigger.svelte +122 -0
- package/dist/timepicker/trigger/time-picker-trigger.svelte.d.ts +9 -0
- package/dist/utils/date-only.d.ts +11 -0
- package/dist/utils/date-only.js +53 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +16 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Popover } from '../index';
|
|
3
|
+
import type { PopoverOpenChangeDetails } from '../root/context';
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
preventClose?: boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
let { preventClose = true }: Props = $props();
|
|
10
|
+
|
|
11
|
+
let open = $state(true);
|
|
12
|
+
let triggerRef = $state<HTMLElement | null>(null);
|
|
13
|
+
|
|
14
|
+
function handleOpenChange(nextOpen: boolean, details: PopoverOpenChangeDetails) {
|
|
15
|
+
if (!nextOpen && preventClose) {
|
|
16
|
+
details.cancel();
|
|
17
|
+
}
|
|
18
|
+
if (!details.isCanceled) {
|
|
19
|
+
open = nextOpen;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<button bind:this={triggerRef} type="button">Standalone Trigger</button>
|
|
25
|
+
|
|
26
|
+
<Popover.Content {open} {triggerRef} onOpenChange={handleOpenChange}>
|
|
27
|
+
<div>Standalone content</div>
|
|
28
|
+
</Popover.Content>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Popover } from '../index';
|
|
3
|
+
import type { PopoverOpenChangeDetails } from '../root/context';
|
|
3
4
|
|
|
4
5
|
type Props = {
|
|
5
6
|
open?: boolean;
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
shouldCloseOnInteractOutside?: boolean;
|
|
9
10
|
shouldCloseOnEscape?: boolean;
|
|
10
11
|
shouldCloseOnBlur?: boolean;
|
|
11
|
-
onOpenChange?: (open: boolean) => void;
|
|
12
|
+
onOpenChange?: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
let {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PopoverOpenChangeDetails } from '../root/context';
|
|
1
2
|
type Props = {
|
|
2
3
|
open?: boolean;
|
|
3
4
|
defaultOpen?: boolean;
|
|
@@ -5,7 +6,7 @@ type Props = {
|
|
|
5
6
|
shouldCloseOnInteractOutside?: boolean;
|
|
6
7
|
shouldCloseOnEscape?: boolean;
|
|
7
8
|
shouldCloseOnBlur?: boolean;
|
|
8
|
-
onOpenChange?: (open: boolean) => void;
|
|
9
|
+
onOpenChange?: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
9
10
|
};
|
|
10
11
|
declare const PopoverContentTest: import("svelte").Component<Props, {}, "">;
|
|
11
12
|
type PopoverContentTest = ReturnType<typeof PopoverContentTest>;
|
|
@@ -4,12 +4,21 @@
|
|
|
4
4
|
import { onMount, onDestroy } from 'svelte';
|
|
5
5
|
import { browser } from '$app/environment';
|
|
6
6
|
import { floating, type ExtendedPlacement } from '../../primitives/floating';
|
|
7
|
-
import { focusTrap } from '../../primitives/focus-trap';
|
|
7
|
+
import { focusTrap, type FocusTrapOptions } from '../../primitives/focus-trap';
|
|
8
8
|
import { scrollLock } from '../../primitives/scroll-lock';
|
|
9
9
|
import { clickOutside } from '../../primitives/click-outside';
|
|
10
10
|
import { ariaHideOutside } from '../../primitives/aria-hide-outside';
|
|
11
11
|
import { Portal } from '../../portal';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
getPopoverContext,
|
|
14
|
+
type PopoverOpenChangeDetails,
|
|
15
|
+
type PopoverCloseReason
|
|
16
|
+
} from '../root/context';
|
|
17
|
+
import {
|
|
18
|
+
addTriggerBlurCleanup,
|
|
19
|
+
applyTriggerCloseFocusState,
|
|
20
|
+
clearTriggerFocusState
|
|
21
|
+
} from '../root/focus-state';
|
|
13
22
|
|
|
14
23
|
/**
|
|
15
24
|
* Popover.Content - The floating content panel.
|
|
@@ -36,13 +45,15 @@
|
|
|
36
45
|
shouldCloseOnEscape?: boolean;
|
|
37
46
|
/** Whether losing focus (blur) should close the popover. Defaults to true for non-modal popovers. */
|
|
38
47
|
shouldCloseOnBlur?: boolean;
|
|
48
|
+
/** Element or selector to focus first when modal trap activates. */
|
|
49
|
+
initialFocus?: FocusTrapOptions['initialFocus'];
|
|
39
50
|
// Standalone mode props (used when not inside Popover.Root)
|
|
40
51
|
/** Controlled open state (standalone mode). */
|
|
41
52
|
open?: boolean;
|
|
42
53
|
/** Reference to the trigger element (standalone mode). */
|
|
43
54
|
triggerRef?: HTMLElement | null;
|
|
44
55
|
/** Callback when open state changes (standalone mode). */
|
|
45
|
-
onOpenChange?: (open: boolean) => void;
|
|
56
|
+
onOpenChange?: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
46
57
|
} & Omit<HTMLAttributes<HTMLDivElement>, 'class' | 'children'>;
|
|
47
58
|
|
|
48
59
|
let {
|
|
@@ -56,6 +67,7 @@
|
|
|
56
67
|
shouldCloseOnInteractOutside = true,
|
|
57
68
|
shouldCloseOnEscape = true,
|
|
58
69
|
shouldCloseOnBlur,
|
|
70
|
+
initialFocus,
|
|
59
71
|
// Standalone mode props
|
|
60
72
|
open: openProp,
|
|
61
73
|
triggerRef: triggerRefProp = null,
|
|
@@ -73,28 +85,64 @@
|
|
|
73
85
|
const shouldCloseOnBlurResolved = $derived(shouldCloseOnBlur ?? isNonModal);
|
|
74
86
|
|
|
75
87
|
let popoverRef: HTMLElement | undefined = $state();
|
|
88
|
+
let cleanupStandaloneTriggerBlurListener: (() => void) | undefined;
|
|
89
|
+
let pendingStandaloneTriggerCloseFocusFrame: number | undefined;
|
|
90
|
+
let trackedStandaloneTrigger: HTMLElement | null = null;
|
|
91
|
+
|
|
92
|
+
function clearPendingStandaloneTriggerCloseFocus() {
|
|
93
|
+
if (pendingStandaloneTriggerCloseFocusFrame === undefined) return;
|
|
94
|
+
cancelAnimationFrame(pendingStandaloneTriggerCloseFocusFrame);
|
|
95
|
+
pendingStandaloneTriggerCloseFocusFrame = undefined;
|
|
96
|
+
}
|
|
76
97
|
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
} else {
|
|
82
|
-
ctx!.close();
|
|
83
|
-
}
|
|
98
|
+
function clearStandaloneTriggerTracking() {
|
|
99
|
+
clearPendingStandaloneTriggerCloseFocus();
|
|
100
|
+
cleanupStandaloneTriggerBlurListener?.();
|
|
101
|
+
cleanupStandaloneTriggerBlurListener = undefined;
|
|
84
102
|
}
|
|
85
103
|
|
|
86
|
-
function
|
|
104
|
+
function applyStandaloneTriggerCloseState(
|
|
105
|
+
trigger: HTMLElement,
|
|
106
|
+
reason: PopoverCloseReason,
|
|
107
|
+
event?: Event
|
|
108
|
+
) {
|
|
109
|
+
clearStandaloneTriggerTracking();
|
|
110
|
+
pendingStandaloneTriggerCloseFocusFrame = requestAnimationFrame(() => {
|
|
111
|
+
pendingStandaloneTriggerCloseFocusFrame = undefined;
|
|
112
|
+
if (!trigger.isConnected) return;
|
|
113
|
+
applyTriggerCloseFocusState(trigger, reason, event);
|
|
114
|
+
cleanupStandaloneTriggerBlurListener = addTriggerBlurCleanup(trigger, true);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function close(reason: PopoverCloseReason = 'imperative-action', event?: Event) {
|
|
87
119
|
if (isStandalone) {
|
|
88
|
-
|
|
120
|
+
let canceled = false;
|
|
121
|
+
const details: PopoverOpenChangeDetails = {
|
|
122
|
+
reason,
|
|
123
|
+
event,
|
|
124
|
+
cancel: () => {
|
|
125
|
+
canceled = true;
|
|
126
|
+
},
|
|
127
|
+
get isCanceled() {
|
|
128
|
+
return canceled;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
onOpenChangeProp?.(false, details);
|
|
133
|
+
if (details.isCanceled) return;
|
|
134
|
+
if (triggerRefProp) {
|
|
135
|
+
applyStandaloneTriggerCloseState(triggerRefProp, reason, event);
|
|
136
|
+
}
|
|
89
137
|
} else {
|
|
90
|
-
ctx!.
|
|
138
|
+
ctx!.close(reason, event);
|
|
91
139
|
}
|
|
92
140
|
}
|
|
93
141
|
|
|
94
142
|
function handleKeydown(event: KeyboardEvent) {
|
|
95
143
|
if (event.key === 'Escape' && isOpen && shouldCloseOnEscape) {
|
|
96
144
|
event.preventDefault();
|
|
97
|
-
close();
|
|
145
|
+
close('escape-key', event);
|
|
98
146
|
}
|
|
99
147
|
}
|
|
100
148
|
|
|
@@ -107,7 +155,7 @@
|
|
|
107
155
|
const focusInTrigger = triggerRef?.contains(target) || target === triggerRef;
|
|
108
156
|
|
|
109
157
|
if (!focusInPopover && !focusInTrigger) {
|
|
110
|
-
|
|
158
|
+
close('focus-out', event);
|
|
111
159
|
}
|
|
112
160
|
}
|
|
113
161
|
|
|
@@ -121,10 +169,28 @@
|
|
|
121
169
|
|
|
122
170
|
// Only close on external scroll
|
|
123
171
|
if (!isInsidePopover && !isInsideTrigger) {
|
|
124
|
-
close();
|
|
172
|
+
close('outside-press', event);
|
|
125
173
|
}
|
|
126
174
|
}
|
|
127
175
|
|
|
176
|
+
$effect(() => {
|
|
177
|
+
if (!isStandalone) {
|
|
178
|
+
if (trackedStandaloneTrigger) {
|
|
179
|
+
clearTriggerFocusState(trackedStandaloneTrigger);
|
|
180
|
+
}
|
|
181
|
+
trackedStandaloneTrigger = null;
|
|
182
|
+
clearStandaloneTriggerTracking();
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (trackedStandaloneTrigger && trackedStandaloneTrigger !== triggerRefProp) {
|
|
187
|
+
clearTriggerFocusState(trackedStandaloneTrigger);
|
|
188
|
+
clearStandaloneTriggerTracking();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
trackedStandaloneTrigger = triggerRefProp;
|
|
192
|
+
});
|
|
193
|
+
|
|
128
194
|
onMount(() => {
|
|
129
195
|
if (!browser) return;
|
|
130
196
|
document.addEventListener('keydown', handleKeydown);
|
|
@@ -134,6 +200,10 @@
|
|
|
134
200
|
|
|
135
201
|
onDestroy(() => {
|
|
136
202
|
if (!browser) return;
|
|
203
|
+
if (trackedStandaloneTrigger) {
|
|
204
|
+
clearTriggerFocusState(trackedStandaloneTrigger);
|
|
205
|
+
}
|
|
206
|
+
clearStandaloneTriggerTracking();
|
|
137
207
|
document.removeEventListener('keydown', handleKeydown);
|
|
138
208
|
document.removeEventListener('focusin', handleDocumentFocusIn);
|
|
139
209
|
document.removeEventListener('scroll', handleScroll, true);
|
|
@@ -149,11 +219,14 @@
|
|
|
149
219
|
aria-modal={isModal}
|
|
150
220
|
use:floating={{ anchor: triggerRef, offset, placement, shouldFlip, boundaryElement }}
|
|
151
221
|
use:clickOutside={{
|
|
152
|
-
handler:
|
|
222
|
+
handler: (event) => {
|
|
223
|
+
event.preventDefault();
|
|
224
|
+
close('outside-press', event);
|
|
225
|
+
},
|
|
153
226
|
enabled: shouldCloseOnInteractOutside,
|
|
154
227
|
ignore: [triggerRef]
|
|
155
228
|
}}
|
|
156
|
-
use:focusTrap={isModal}
|
|
229
|
+
use:focusTrap={{ enabled: isModal, restoreFocus: false, initialFocus }}
|
|
157
230
|
use:scrollLock={isModal}
|
|
158
231
|
use:ariaHideOutside={isModal}
|
|
159
232
|
style="position: fixed; z-index: 9999;"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
import { type ExtendedPlacement } from '../../primitives/floating';
|
|
4
|
+
import { type FocusTrapOptions } from '../../primitives/focus-trap';
|
|
5
|
+
import { type PopoverOpenChangeDetails } from '../root/context';
|
|
4
6
|
/**
|
|
5
7
|
* Popover.Content - The floating content panel.
|
|
6
8
|
* Can be used inside Popover.Root (reads context) or standalone (props required).
|
|
@@ -26,12 +28,14 @@ type PopoverContentProps = {
|
|
|
26
28
|
shouldCloseOnEscape?: boolean;
|
|
27
29
|
/** Whether losing focus (blur) should close the popover. Defaults to true for non-modal popovers. */
|
|
28
30
|
shouldCloseOnBlur?: boolean;
|
|
31
|
+
/** Element or selector to focus first when modal trap activates. */
|
|
32
|
+
initialFocus?: FocusTrapOptions['initialFocus'];
|
|
29
33
|
/** Controlled open state (standalone mode). */
|
|
30
34
|
open?: boolean;
|
|
31
35
|
/** Reference to the trigger element (standalone mode). */
|
|
32
36
|
triggerRef?: HTMLElement | null;
|
|
33
37
|
/** Callback when open state changes (standalone mode). */
|
|
34
|
-
onOpenChange?: (open: boolean) => void;
|
|
38
|
+
onOpenChange?: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
35
39
|
} & Omit<HTMLAttributes<HTMLDivElement>, 'class' | 'children'>;
|
|
36
40
|
declare const PopoverContent: import("svelte").Component<PopoverContentProps, {}, "">;
|
|
37
41
|
type PopoverContent = ReturnType<typeof PopoverContent>;
|
package/dist/popover/index.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export { default as PopoverRoot } from './root/popover-root.svelte';
|
|
|
3
3
|
export { default as PopoverContent } from './content/popover-content.svelte';
|
|
4
4
|
export { default as PopoverTrigger } from './trigger/popover-trigger.svelte';
|
|
5
5
|
export { default as PopoverTriggerButton } from './trigger/popover-trigger-button.svelte';
|
|
6
|
-
export { getPopoverContext, setPopoverContext, type PopoverContext,
|
|
6
|
+
export { getPopoverContext, setPopoverContext, type PopoverContext, type PopoverCanonicalCloseReason, type PopoverCloseReason, type PopoverOpenReason, type PopoverChangeReason, type PopoverOpenChangeDetails } from './root/context.ts';
|
|
7
7
|
import * as PopoverParts from './index.parts.ts';
|
|
8
8
|
export default PopoverParts;
|
package/dist/popover/index.js
CHANGED
|
@@ -6,9 +6,7 @@ export { default as PopoverContent } from './content/popover-content.svelte';
|
|
|
6
6
|
export { default as PopoverTrigger } from './trigger/popover-trigger.svelte';
|
|
7
7
|
export { default as PopoverTriggerButton } from './trigger/popover-trigger-button.svelte';
|
|
8
8
|
// Context and types
|
|
9
|
-
export { getPopoverContext, setPopoverContext
|
|
10
|
-
// Legacy aliases
|
|
11
|
-
getPopoverTriggerContext, setPopoverTriggerContext } from './root/context.ts';
|
|
9
|
+
export { getPopoverContext, setPopoverContext } from './root/context.ts';
|
|
12
10
|
// Default export as namespace object
|
|
13
11
|
import * as PopoverParts from './index.parts.ts';
|
|
14
12
|
export default PopoverParts;
|
|
@@ -7,24 +7,19 @@
|
|
|
7
7
|
Name: `Popover.Root`
|
|
8
8
|
Description: Root state container that controls open state, trigger ref, and toggle/open/close actions.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
| `triggerRef` | `HTMLElement \| null` | `null` | Trigger reference. Supports `bind:triggerRef`. |
|
|
16
|
-
| `children` | `Snippet` | `undefined` | Composed trigger and content parts. |
|
|
10
|
+
- `open`: `boolean` (default: `undefined`) — Controlled open state. Supports `bind:open`.
|
|
11
|
+
- `defaultOpen`: `boolean` (default: `false`) — Initial open state in uncontrolled mode.
|
|
12
|
+
- `onOpenChange`: `(open: boolean, details) => void` (default: `undefined`) — Called whenever open state changes. `details` includes `reason`, optional `event`, `cancel()`, and `isCanceled`.
|
|
13
|
+
- `triggerRef`: `HTMLElement | null` (default: `null`) — Trigger reference. Supports `bind:triggerRef`.
|
|
14
|
+
- `children`: `Snippet` (default: `undefined`) — Composed trigger and content parts.
|
|
17
15
|
|
|
18
16
|
### Context utilities
|
|
19
17
|
|
|
20
18
|
Name: `context.ts` helpers
|
|
21
19
|
Description: Context APIs used by trigger and content parts.
|
|
22
20
|
|
|
23
|
-
| Prop
|
|
24
|
-
|
|
|
25
|
-
| `setPopoverContext`
|
|
26
|
-
| `getPopoverContext`
|
|
27
|
-
| `PopoverContext`
|
|
28
|
-
| `PopoverTriggerContext` | `type alias` | `PopoverContext` | Backward-compatible alias. |
|
|
29
|
-
| `setPopoverTriggerContext` | `alias` | `setPopoverContext` | Backward-compatible alias. |
|
|
30
|
-
| `getPopoverTriggerContext` | `alias` | `getPopoverContext` | Backward-compatible alias. |
|
|
21
|
+
| Prop | Type | Default | Description |
|
|
22
|
+
| ------------------- | ----------------------------------- | ------- | ---------------------------------------- |
|
|
23
|
+
| `setPopoverContext` | `(ctx: PopoverContext) => void` | `-` | Registers popover context. |
|
|
24
|
+
| `getPopoverContext` | `() => PopoverContext \| undefined` | `-` | Returns popover context when available. |
|
|
25
|
+
| `PopoverContext` | `type` | `-` | Context contract with state and actions. |
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
export type PopoverCanonicalCloseReason = 'escape-key' | 'outside-press' | 'focus-out' | 'close-press' | 'imperative-action' | 'none';
|
|
2
|
+
export type PopoverCloseReason = PopoverCanonicalCloseReason;
|
|
3
|
+
export type PopoverOpenReason = 'trigger-press' | 'imperative-action' | 'none';
|
|
4
|
+
export type PopoverChangeReason = PopoverOpenReason | PopoverCloseReason;
|
|
5
|
+
export type PopoverOpenChangeDetails = {
|
|
6
|
+
reason: PopoverChangeReason;
|
|
7
|
+
event?: Event;
|
|
8
|
+
cancel: () => void;
|
|
9
|
+
isCanceled: boolean;
|
|
10
|
+
};
|
|
1
11
|
/**
|
|
2
12
|
* Context shared between Popover components (Root, Trigger, Content).
|
|
3
13
|
*/
|
|
4
14
|
export type PopoverContext = {
|
|
15
|
+
/** Reason why popover is closing */
|
|
16
|
+
closeReason: PopoverCanonicalCloseReason;
|
|
5
17
|
/** Whether the popover is open */
|
|
6
18
|
isOpen: boolean;
|
|
7
19
|
/** Reference to the trigger element */
|
|
@@ -9,16 +21,13 @@ export type PopoverContext = {
|
|
|
9
21
|
/** Set the trigger ref (used by Trigger component) */
|
|
10
22
|
setTriggerRef: (el: HTMLElement | null) => void;
|
|
11
23
|
/** Toggle popover open state */
|
|
12
|
-
toggle: () => void;
|
|
24
|
+
toggle: (reason?: PopoverOpenReason, event?: Event) => void;
|
|
13
25
|
/** Open the popover */
|
|
14
|
-
open: () => void;
|
|
26
|
+
open: (reason?: PopoverOpenReason, event?: Event) => void;
|
|
15
27
|
/** Close the popover and return focus to trigger */
|
|
16
|
-
close: () => void;
|
|
28
|
+
close: (reason?: PopoverCloseReason, event?: Event) => void;
|
|
17
29
|
/** Called when popover open state changes */
|
|
18
|
-
onOpenChange: (open: boolean) => void;
|
|
30
|
+
onOpenChange: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
19
31
|
};
|
|
20
32
|
export declare function setPopoverContext(ctx: PopoverContext): void;
|
|
21
33
|
export declare function getPopoverContext(): PopoverContext | undefined;
|
|
22
|
-
export type PopoverTriggerContext = PopoverContext;
|
|
23
|
-
export declare const setPopoverTriggerContext: typeof setPopoverContext;
|
|
24
|
-
export declare const getPopoverTriggerContext: typeof getPopoverContext;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PopoverCloseReason } from './context';
|
|
2
|
+
export declare function clearTriggerFocusState(trigger: HTMLElement): void;
|
|
3
|
+
export declare function applyTriggerCloseFocusState(trigger: HTMLElement, reason: PopoverCloseReason, event?: Event): void;
|
|
4
|
+
export declare function addTriggerBlurCleanup(trigger: HTMLElement, once?: boolean): () => void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { focusWithModality, resolveCloseInteractionModality } from '../../primitives/input-modality';
|
|
2
|
+
export function clearTriggerFocusState(trigger) {
|
|
3
|
+
delete trigger.dataset.focused;
|
|
4
|
+
delete trigger.dataset.focusVisible;
|
|
5
|
+
}
|
|
6
|
+
export function applyTriggerCloseFocusState(trigger, reason, event) {
|
|
7
|
+
const closeModality = resolveCloseInteractionModality(reason, event);
|
|
8
|
+
focusWithModality(trigger, closeModality);
|
|
9
|
+
if (reason === 'outside-press' || reason === 'escape-key') {
|
|
10
|
+
trigger.dataset.focused = 'true';
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
delete trigger.dataset.focused;
|
|
14
|
+
}
|
|
15
|
+
if (closeModality === 'keyboard') {
|
|
16
|
+
trigger.dataset.focusVisible = 'true';
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
delete trigger.dataset.focusVisible;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function addTriggerBlurCleanup(trigger, once = false) {
|
|
23
|
+
const handleBlur = () => {
|
|
24
|
+
clearTriggerFocusState(trigger);
|
|
25
|
+
if (once) {
|
|
26
|
+
trigger.removeEventListener('blur', handleBlur);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
trigger.addEventListener('blur', handleBlur);
|
|
30
|
+
return () => {
|
|
31
|
+
trigger.removeEventListener('blur', handleBlur);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import {
|
|
3
|
+
import { onDestroy } from 'svelte';
|
|
4
|
+
import {
|
|
5
|
+
setPopoverContext,
|
|
6
|
+
type PopoverCanonicalCloseReason,
|
|
7
|
+
type PopoverChangeReason,
|
|
8
|
+
type PopoverCloseReason,
|
|
9
|
+
type PopoverOpenChangeDetails,
|
|
10
|
+
type PopoverOpenReason,
|
|
11
|
+
type PopoverContext
|
|
12
|
+
} from './context';
|
|
13
|
+
import {
|
|
14
|
+
addTriggerBlurCleanup,
|
|
15
|
+
applyTriggerCloseFocusState,
|
|
16
|
+
clearTriggerFocusState
|
|
17
|
+
} from './focus-state';
|
|
4
18
|
|
|
5
19
|
/**
|
|
6
20
|
* Popover.Root - State management wrapper for Popover components.
|
|
@@ -12,7 +26,7 @@
|
|
|
12
26
|
/** Initial open state for uncontrolled mode. */
|
|
13
27
|
defaultOpen?: boolean;
|
|
14
28
|
/** Callback when open state changes. */
|
|
15
|
-
onOpenChange?: (open: boolean) => void;
|
|
29
|
+
onOpenChange?: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
16
30
|
/** Reference to the trigger element. Can be set manually or via Popover.Trigger. */
|
|
17
31
|
triggerRef?: HTMLElement | null;
|
|
18
32
|
/** Children (Trigger and Content) */
|
|
@@ -26,6 +40,9 @@
|
|
|
26
40
|
triggerRef = $bindable<HTMLElement | null>(null),
|
|
27
41
|
children
|
|
28
42
|
}: PopoverRootProps = $props();
|
|
43
|
+
let closeReason: PopoverCanonicalCloseReason = $state('none');
|
|
44
|
+
let cleanupTriggerBlurListener: (() => void) | undefined;
|
|
45
|
+
let pendingTriggerCloseFocusFrame: number | undefined;
|
|
29
46
|
|
|
30
47
|
// Use function to capture initial value only (not reactive)
|
|
31
48
|
let isOpenInternal = $state((() => defaultOpen)());
|
|
@@ -33,39 +50,90 @@
|
|
|
33
50
|
const isControlled = $derived(open !== undefined);
|
|
34
51
|
const isOpen = $derived(isControlled ? open! : isOpenInternal);
|
|
35
52
|
|
|
36
|
-
function
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
function setOpenWithDetails(
|
|
54
|
+
value: boolean,
|
|
55
|
+
incomingDetails: { reason: PopoverChangeReason; event?: Event }
|
|
56
|
+
) {
|
|
57
|
+
let canceled = false;
|
|
58
|
+
const details: PopoverOpenChangeDetails = {
|
|
59
|
+
reason: incomingDetails.reason,
|
|
60
|
+
event: incomingDetails.event,
|
|
61
|
+
cancel: () => {
|
|
62
|
+
canceled = true;
|
|
63
|
+
},
|
|
64
|
+
get isCanceled() {
|
|
65
|
+
return canceled;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
onOpenChange?.(value, details);
|
|
70
|
+
if (details.isCanceled) return;
|
|
71
|
+
|
|
72
|
+
if (!isControlled) {
|
|
40
73
|
isOpenInternal = value;
|
|
41
|
-
onOpenChange?.(value);
|
|
42
74
|
}
|
|
43
|
-
|
|
75
|
+
|
|
44
76
|
open = value;
|
|
45
77
|
}
|
|
46
78
|
|
|
47
|
-
function toggle() {
|
|
48
|
-
|
|
79
|
+
function toggle(reason: PopoverOpenReason = 'trigger-press', event?: Event) {
|
|
80
|
+
setOpenWithDetails(!isOpen, { reason, event });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function openPopover(reason: PopoverOpenReason = 'imperative-action', event?: Event) {
|
|
84
|
+
closeReason = 'none';
|
|
85
|
+
setOpenWithDetails(true, { reason, event });
|
|
49
86
|
}
|
|
50
87
|
|
|
51
|
-
function
|
|
52
|
-
|
|
88
|
+
function clearPendingTriggerCloseFocus() {
|
|
89
|
+
if (pendingTriggerCloseFocusFrame === undefined) return;
|
|
90
|
+
cancelAnimationFrame(pendingTriggerCloseFocusFrame);
|
|
91
|
+
pendingTriggerCloseFocusFrame = undefined;
|
|
53
92
|
}
|
|
54
93
|
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
|
|
94
|
+
function scheduleTriggerCloseFocus(
|
|
95
|
+
trigger: HTMLElement,
|
|
96
|
+
reason: PopoverCanonicalCloseReason,
|
|
97
|
+
event?: Event
|
|
98
|
+
) {
|
|
99
|
+
clearPendingTriggerCloseFocus();
|
|
100
|
+
pendingTriggerCloseFocusFrame = requestAnimationFrame(() => {
|
|
101
|
+
pendingTriggerCloseFocusFrame = undefined;
|
|
102
|
+
if (!trigger.isConnected) return;
|
|
103
|
+
applyTriggerCloseFocusState(trigger, reason, event);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function closePopover(reason: PopoverCloseReason = 'imperative-action', event?: Event) {
|
|
108
|
+
closeReason = reason;
|
|
109
|
+
const wasOpen = isOpen;
|
|
110
|
+
setOpenWithDetails(false, { reason, event });
|
|
111
|
+
if (!wasOpen || isOpen) return;
|
|
112
|
+
if (!triggerRef) return;
|
|
113
|
+
scheduleTriggerCloseFocus(triggerRef, reason, event);
|
|
58
114
|
}
|
|
59
115
|
|
|
60
116
|
function setTriggerRef(el: HTMLElement | null) {
|
|
117
|
+
clearPendingTriggerCloseFocus();
|
|
118
|
+
cleanupTriggerBlurListener?.();
|
|
119
|
+
cleanupTriggerBlurListener = undefined;
|
|
120
|
+
if (triggerRef && triggerRef !== el) {
|
|
121
|
+
clearTriggerFocusState(triggerRef);
|
|
122
|
+
}
|
|
61
123
|
triggerRef = el;
|
|
124
|
+
if (!triggerRef) return;
|
|
125
|
+
const currentTrigger = triggerRef;
|
|
126
|
+
cleanupTriggerBlurListener = addTriggerBlurCleanup(currentTrigger);
|
|
62
127
|
}
|
|
63
128
|
|
|
64
|
-
function handleOpenChange(newOpen: boolean) {
|
|
65
|
-
|
|
129
|
+
function handleOpenChange(newOpen: boolean, details: PopoverOpenChangeDetails) {
|
|
130
|
+
setOpenWithDetails(newOpen, { reason: details.reason, event: details.event });
|
|
66
131
|
}
|
|
67
132
|
|
|
68
133
|
const ctx: PopoverContext = {
|
|
134
|
+
get closeReason() {
|
|
135
|
+
return closeReason;
|
|
136
|
+
},
|
|
69
137
|
get isOpen() {
|
|
70
138
|
return isOpen;
|
|
71
139
|
},
|
|
@@ -80,6 +148,11 @@
|
|
|
80
148
|
};
|
|
81
149
|
|
|
82
150
|
setPopoverContext(ctx);
|
|
151
|
+
|
|
152
|
+
onDestroy(() => {
|
|
153
|
+
clearPendingTriggerCloseFocus();
|
|
154
|
+
cleanupTriggerBlurListener?.();
|
|
155
|
+
});
|
|
83
156
|
</script>
|
|
84
157
|
|
|
85
158
|
{#if children}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type PopoverOpenChangeDetails } from './context';
|
|
2
3
|
/**
|
|
3
4
|
* Popover.Root - State management wrapper for Popover components.
|
|
4
5
|
* Provides context for Trigger and Content children.
|
|
@@ -9,7 +10,7 @@ type PopoverRootProps = {
|
|
|
9
10
|
/** Initial open state for uncontrolled mode. */
|
|
10
11
|
defaultOpen?: boolean;
|
|
11
12
|
/** Callback when open state changes. */
|
|
12
|
-
onOpenChange?: (open: boolean) => void;
|
|
13
|
+
onOpenChange?: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
13
14
|
/** Reference to the trigger element. Can be set manually or via Popover.Trigger. */
|
|
14
15
|
triggerRef?: HTMLElement | null;
|
|
15
16
|
/** Children (Trigger and Content) */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Popover } from '../index';
|
|
3
|
+
import type { PopoverOpenChangeDetails } from './context';
|
|
3
4
|
|
|
4
5
|
type Props = {
|
|
5
6
|
open?: boolean;
|
|
@@ -7,7 +8,7 @@
|
|
|
7
8
|
isNonModal?: boolean;
|
|
8
9
|
shouldCloseOnInteractOutside?: boolean;
|
|
9
10
|
shouldCloseOnEscape?: boolean;
|
|
10
|
-
onOpenChange?: (open: boolean) => void;
|
|
11
|
+
onOpenChange?: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
let {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type { PopoverOpenChangeDetails } from './context';
|
|
1
2
|
type Props = {
|
|
2
3
|
open?: boolean;
|
|
3
4
|
defaultOpen?: boolean;
|
|
4
5
|
isNonModal?: boolean;
|
|
5
6
|
shouldCloseOnInteractOutside?: boolean;
|
|
6
7
|
shouldCloseOnEscape?: boolean;
|
|
7
|
-
onOpenChange?: (open: boolean) => void;
|
|
8
|
+
onOpenChange?: (open: boolean, details: PopoverOpenChangeDetails) => void;
|
|
8
9
|
};
|
|
9
10
|
declare const PopoverTest: import("svelte").Component<Props, {}, "">;
|
|
10
11
|
type PopoverTest = ReturnType<typeof PopoverTest>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
-
import {
|
|
4
|
+
import { getPopoverContext } from '../root/context';
|
|
5
5
|
|
|
6
6
|
type PopoverTriggerButtonProps = Omit<
|
|
7
7
|
HTMLButtonAttributes,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
let { children, class: className = '', ...restProps }: PopoverTriggerButtonProps = $props();
|
|
18
18
|
|
|
19
19
|
let buttonRef: HTMLButtonElement | null = $state(null);
|
|
20
|
-
const ctx =
|
|
20
|
+
const ctx = getPopoverContext();
|
|
21
21
|
|
|
22
22
|
$effect(() => {
|
|
23
23
|
if (buttonRef && ctx) {
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
}
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
function handleClick() {
|
|
29
|
-
ctx?.toggle();
|
|
28
|
+
function handleClick(event: MouseEvent) {
|
|
29
|
+
ctx?.toggle('trigger-press', event);
|
|
30
30
|
}
|
|
31
31
|
</script>
|
|
32
32
|
|