bits-ui 1.7.0 → 2.1.0
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/bits/accordion/accordion.svelte.d.ts +56 -53
- package/dist/bits/accordion/accordion.svelte.js +78 -89
- package/dist/bits/accordion/components/accordion-content.svelte +5 -3
- package/dist/bits/accordion/components/accordion-header.svelte +4 -2
- package/dist/bits/accordion/components/accordion-item.svelte +6 -3
- package/dist/bits/accordion/components/accordion-trigger.svelte +4 -2
- package/dist/bits/accordion/components/accordion.svelte +4 -2
- package/dist/bits/alert-dialog/components/alert-dialog-action.svelte +4 -2
- package/dist/bits/alert-dialog/components/alert-dialog-cancel.svelte +4 -2
- package/dist/bits/alert-dialog/components/alert-dialog-content.svelte +8 -3
- package/dist/bits/aspect-ratio/aspect-ratio.svelte.js +2 -2
- package/dist/bits/aspect-ratio/components/aspect-ratio.svelte +4 -2
- package/dist/bits/avatar/avatar.svelte.js +4 -4
- package/dist/bits/avatar/components/avatar-fallback.svelte +4 -2
- package/dist/bits/avatar/components/avatar-image.svelte +4 -2
- package/dist/bits/avatar/components/avatar.svelte +4 -2
- package/dist/bits/button/components/button.svelte +1 -1
- package/dist/bits/calendar/calendar.svelte.d.ts +1 -9
- package/dist/bits/calendar/calendar.svelte.js +47 -38
- package/dist/bits/calendar/components/calendar-cell.svelte +4 -2
- package/dist/bits/calendar/components/calendar-day.svelte +4 -2
- package/dist/bits/calendar/components/calendar-grid-body.svelte +4 -2
- package/dist/bits/calendar/components/calendar-grid-head.svelte +4 -2
- package/dist/bits/calendar/components/calendar-grid-row.svelte +4 -2
- package/dist/bits/calendar/components/calendar-grid.svelte +4 -2
- package/dist/bits/calendar/components/calendar-head-cell.svelte +4 -2
- package/dist/bits/calendar/components/calendar-header.svelte +4 -2
- package/dist/bits/calendar/components/calendar-heading.svelte +4 -2
- package/dist/bits/calendar/components/calendar-next-button.svelte +4 -2
- package/dist/bits/calendar/components/calendar-prev-button.svelte +4 -2
- package/dist/bits/checkbox/checkbox.svelte.js +4 -14
- package/dist/bits/checkbox/components/checkbox-group-label.svelte +4 -2
- package/dist/bits/checkbox/components/checkbox-group.svelte +4 -2
- package/dist/bits/checkbox/components/checkbox.svelte +4 -2
- package/dist/bits/collapsible/collapsible.svelte.js +4 -10
- package/dist/bits/collapsible/components/collapsible-content.svelte +5 -3
- package/dist/bits/collapsible/components/collapsible-trigger.svelte +4 -2
- package/dist/bits/collapsible/components/collapsible.svelte +4 -2
- package/dist/bits/combobox/components/combobox-input.svelte +1 -1
- package/dist/bits/combobox/components/combobox.svelte +1 -1
- package/dist/bits/command/command.svelte.js +13 -45
- package/dist/bits/command/components/_command-label.svelte +6 -7
- package/dist/bits/command/components/_command-label.svelte.d.ts +1 -1
- package/dist/bits/command/components/command-empty.svelte +4 -2
- package/dist/bits/command/components/command-group-heading.svelte +4 -2
- package/dist/bits/command/components/command-group-items.svelte +4 -2
- package/dist/bits/command/components/command-group.svelte +4 -2
- package/dist/bits/command/components/command-input.svelte +4 -2
- package/dist/bits/command/components/command-item.svelte +4 -2
- package/dist/bits/command/components/command-link-item.svelte +4 -2
- package/dist/bits/command/components/command-list.svelte +4 -2
- package/dist/bits/command/components/command-loading.svelte +4 -2
- package/dist/bits/command/components/command-separator.svelte +4 -2
- package/dist/bits/command/components/command-viewport.svelte +4 -2
- package/dist/bits/command/components/command.svelte +4 -2
- package/dist/bits/context-menu/components/context-menu-content-static.svelte +2 -3
- package/dist/bits/context-menu/components/context-menu-content.svelte +2 -3
- package/dist/bits/context-menu/components/context-menu-trigger.svelte +1 -1
- package/dist/bits/date-field/components/date-field-input.svelte +4 -2
- package/dist/bits/date-field/components/date-field-label.svelte +4 -2
- package/dist/bits/date-field/components/date-field-segment.svelte +4 -2
- package/dist/bits/date-field/date-field.svelte.d.ts +4 -4
- package/dist/bits/date-field/date-field.svelte.js +15 -33
- package/dist/bits/date-picker/components/date-picker-calendar.svelte +4 -2
- package/dist/bits/date-range-field/components/date-range-field-input.svelte +4 -2
- package/dist/bits/date-range-field/components/date-range-field-label.svelte +4 -2
- package/dist/bits/date-range-field/components/date-range-field.svelte +4 -2
- package/dist/bits/date-range-field/date-range-field.svelte.js +3 -13
- package/dist/bits/date-range-picker/components/date-range-picker-calendar.svelte +4 -2
- package/dist/bits/dialog/components/dialog-close.svelte +4 -2
- package/dist/bits/dialog/components/dialog-content.svelte +8 -2
- package/dist/bits/dialog/components/dialog-description.svelte +4 -2
- package/dist/bits/dialog/components/dialog-overlay.svelte +8 -3
- package/dist/bits/dialog/components/dialog-title.svelte +4 -2
- package/dist/bits/dialog/components/dialog-trigger.svelte +4 -2
- package/dist/bits/dialog/dialog.svelte.d.ts +1 -1
- package/dist/bits/dialog/dialog.svelte.js +19 -47
- package/dist/bits/dropdown-menu/components/dropdown-menu-content-static.svelte +6 -5
- package/dist/bits/dropdown-menu/components/dropdown-menu-content.svelte +6 -5
- package/dist/bits/index.d.ts +2 -0
- package/dist/bits/index.js +2 -0
- package/dist/bits/label/components/label.svelte +4 -2
- package/dist/bits/label/label.svelte.js +2 -2
- package/dist/bits/link-preview/components/link-preview-content-static.svelte +6 -2
- package/dist/bits/link-preview/components/link-preview-content.svelte +6 -2
- package/dist/bits/link-preview/components/link-preview-trigger.svelte +5 -3
- package/dist/bits/link-preview/link-preview.svelte.js +3 -14
- package/dist/bits/menu/components/menu-checkbox-group.svelte +4 -2
- package/dist/bits/menu/components/menu-checkbox-item.svelte +6 -4
- package/dist/bits/menu/components/menu-content-static.svelte +6 -5
- package/dist/bits/menu/components/menu-content.svelte +6 -5
- package/dist/bits/menu/components/menu-group-heading.svelte +4 -2
- package/dist/bits/menu/components/menu-group.svelte +4 -2
- package/dist/bits/menu/components/menu-item.svelte +4 -2
- package/dist/bits/menu/components/menu-radio-group.svelte +4 -2
- package/dist/bits/menu/components/menu-radio-item.svelte +4 -2
- package/dist/bits/menu/components/menu-separator.svelte +4 -2
- package/dist/bits/menu/components/menu-sub-content-static.svelte +6 -5
- package/dist/bits/menu/components/menu-sub-content.svelte +6 -5
- package/dist/bits/menu/components/menu-sub-trigger.svelte +6 -3
- package/dist/bits/menu/components/menu-trigger.svelte +5 -3
- package/dist/bits/menu/menu.svelte.d.ts +7 -20
- package/dist/bits/menu/menu.svelte.js +26 -54
- package/dist/bits/menubar/components/menubar-content-static.svelte +4 -2
- package/dist/bits/menubar/components/menubar-content.svelte +4 -2
- package/dist/bits/menubar/components/menubar-menu.svelte +4 -2
- package/dist/bits/menubar/components/menubar-trigger.svelte +14 -6
- package/dist/bits/menubar/components/menubar.svelte +4 -2
- package/dist/bits/menubar/menubar.svelte.d.ts +24 -20
- package/dist/bits/menubar/menubar.svelte.js +40 -56
- package/dist/bits/meter/components/meter.svelte +4 -2
- package/dist/bits/meter/meter.svelte.js +2 -2
- package/dist/bits/navigation-menu/components/navigation-menu-content-impl.svelte +5 -2
- package/dist/bits/navigation-menu/components/navigation-menu-content.svelte +8 -3
- package/dist/bits/navigation-menu/components/navigation-menu-indicator-impl.svelte +4 -2
- package/dist/bits/navigation-menu/components/navigation-menu-indicator.svelte +6 -4
- package/dist/bits/navigation-menu/components/navigation-menu-item.svelte +8 -3
- package/dist/bits/navigation-menu/components/navigation-menu-link.svelte +4 -2
- package/dist/bits/navigation-menu/components/navigation-menu-list.svelte +4 -2
- package/dist/bits/navigation-menu/components/navigation-menu-sub.svelte +4 -2
- package/dist/bits/navigation-menu/components/navigation-menu-trigger.svelte +4 -2
- package/dist/bits/navigation-menu/components/navigation-menu-viewport.svelte +7 -3
- package/dist/bits/navigation-menu/components/navigation-menu.svelte +4 -2
- package/dist/bits/navigation-menu/navigation-menu.svelte.d.ts +29 -17
- package/dist/bits/navigation-menu/navigation-menu.svelte.js +107 -74
- package/dist/bits/navigation-menu/types.d.ts +14 -7
- package/dist/bits/pagination/components/pagination-next-button.svelte +4 -2
- package/dist/bits/pagination/components/pagination-page.svelte +4 -2
- package/dist/bits/pagination/components/pagination-prev-button.svelte +4 -2
- package/dist/bits/pagination/components/pagination.svelte +4 -2
- package/dist/bits/pagination/pagination.svelte.js +4 -4
- package/dist/bits/pin-input/components/pin-input-cell.svelte +4 -2
- package/dist/bits/pin-input/components/pin-input.svelte +5 -3
- package/dist/bits/pin-input/pin-input.svelte.js +4 -10
- package/dist/bits/popover/components/popover-close.svelte +4 -2
- package/dist/bits/popover/components/popover-content-static.svelte +6 -2
- package/dist/bits/popover/components/popover-content.svelte +6 -2
- package/dist/bits/popover/components/popover-trigger.svelte +5 -3
- package/dist/bits/popover/popover.svelte.js +4 -18
- package/dist/bits/progress/components/progress.svelte +4 -2
- package/dist/bits/progress/progress.svelte.js +2 -2
- package/dist/bits/radio-group/components/radio-group-item.svelte +4 -2
- package/dist/bits/radio-group/components/radio-group.svelte +4 -2
- package/dist/bits/radio-group/radio-group.svelte.js +4 -7
- package/dist/bits/range-calendar/components/range-calendar-cell.svelte +4 -2
- package/dist/bits/range-calendar/components/range-calendar-day.svelte +4 -2
- package/dist/bits/range-calendar/components/range-calendar.svelte +4 -2
- package/dist/bits/range-calendar/range-calendar.svelte.js +4 -4
- package/dist/bits/scroll-area/components/scroll-area-corner.svelte +8 -2
- package/dist/bits/scroll-area/components/scroll-area-scrollbar-auto.svelte +4 -1
- package/dist/bits/scroll-area/components/scroll-area-scrollbar-hover.svelte +1 -1
- package/dist/bits/scroll-area/components/scroll-area-scrollbar-scroll.svelte +5 -1
- package/dist/bits/scroll-area/components/scroll-area-scrollbar.svelte +4 -2
- package/dist/bits/scroll-area/components/scroll-area-thumb.svelte +8 -3
- package/dist/bits/scroll-area/components/scroll-area-viewport.svelte +4 -2
- package/dist/bits/scroll-area/components/scroll-area.svelte +4 -2
- package/dist/bits/scroll-area/scroll-area.svelte.js +13 -47
- package/dist/bits/select/components/select-content-static.svelte +6 -2
- package/dist/bits/select/components/select-content.svelte +6 -2
- package/dist/bits/select/components/select-group-heading.svelte +3 -2
- package/dist/bits/select/components/select-group.svelte +4 -2
- package/dist/bits/select/components/select-item.svelte +4 -2
- package/dist/bits/select/components/select-scroll-down-button.svelte +4 -2
- package/dist/bits/select/components/select-scroll-up-button.svelte +4 -2
- package/dist/bits/select/components/select-trigger.svelte +5 -3
- package/dist/bits/select/components/select-viewport.svelte +4 -2
- package/dist/bits/select/components/select.svelte +1 -1
- package/dist/bits/select/select.svelte.d.ts +0 -18
- package/dist/bits/select/select.svelte.js +10 -43
- package/dist/bits/separator/components/separator.svelte +4 -2
- package/dist/bits/separator/separator.svelte.js +2 -2
- package/dist/bits/slider/components/slider-range.svelte +4 -2
- package/dist/bits/slider/components/slider-thumb-label.svelte +50 -0
- package/dist/bits/slider/components/slider-thumb-label.svelte.d.ts +4 -0
- package/dist/bits/slider/components/slider-thumb.svelte +4 -2
- package/dist/bits/slider/components/slider-tick-label.svelte +50 -0
- package/dist/bits/slider/components/slider-tick-label.svelte.d.ts +4 -0
- package/dist/bits/slider/components/slider-tick.svelte +4 -2
- package/dist/bits/slider/components/slider.svelte +26 -5
- package/dist/bits/slider/exports.d.ts +3 -1
- package/dist/bits/slider/exports.js +2 -0
- package/dist/bits/slider/helpers.d.ts +14 -0
- package/dist/bits/slider/helpers.js +122 -0
- package/dist/bits/slider/slider.svelte.d.ts +93 -6
- package/dist/bits/slider/slider.svelte.js +198 -101
- package/dist/bits/slider/types.d.ts +111 -11
- package/dist/bits/switch/components/switch-thumb.svelte +4 -2
- package/dist/bits/switch/components/switch.svelte +4 -2
- package/dist/bits/switch/switch.svelte.js +3 -3
- package/dist/bits/tabs/components/tabs-content.svelte +4 -2
- package/dist/bits/tabs/components/tabs-list.svelte +4 -2
- package/dist/bits/tabs/components/tabs-trigger.svelte +4 -2
- package/dist/bits/tabs/components/tabs.svelte +4 -2
- package/dist/bits/tabs/tabs.svelte.js +6 -6
- package/dist/bits/time-field/components/time-field-hidden-input.svelte +10 -0
- package/dist/bits/{date-field/components/date-field-error.svelte.d.ts → time-field/components/time-field-hidden-input.svelte.d.ts} +6 -14
- package/dist/bits/time-field/components/time-field-input.svelte +39 -0
- package/dist/bits/time-field/components/time-field-input.svelte.d.ts +4 -0
- package/dist/bits/time-field/components/time-field-label.svelte +34 -0
- package/dist/bits/time-field/components/time-field-label.svelte.d.ts +4 -0
- package/dist/bits/time-field/components/time-field-segment.svelte +37 -0
- package/dist/bits/time-field/components/time-field-segment.svelte.d.ts +4 -0
- package/dist/bits/time-field/components/time-field.svelte +94 -0
- package/dist/bits/time-field/components/time-field.svelte.d.ts +20 -0
- package/dist/bits/time-field/exports.d.ts +5 -0
- package/dist/bits/time-field/exports.js +4 -0
- package/dist/bits/time-field/index.d.ts +1 -0
- package/dist/bits/time-field/index.js +1 -0
- package/dist/bits/time-field/time-field.svelte.d.ts +415 -0
- package/dist/bits/time-field/time-field.svelte.js +971 -0
- package/dist/bits/time-field/types.d.ts +137 -0
- package/dist/bits/time-field/types.js +1 -0
- package/dist/bits/time-range-field/components/time-range-field-input.svelte +43 -0
- package/dist/bits/time-range-field/components/time-range-field-input.svelte.d.ts +4 -0
- package/dist/bits/time-range-field/components/time-range-field-label.svelte +34 -0
- package/dist/bits/time-range-field/components/time-range-field-label.svelte.d.ts +4 -0
- package/dist/bits/time-range-field/components/time-range-field.svelte +144 -0
- package/dist/bits/time-range-field/components/time-range-field.svelte.d.ts +20 -0
- package/dist/bits/time-range-field/exports.d.ts +5 -0
- package/dist/bits/time-range-field/exports.js +4 -0
- package/dist/bits/time-range-field/index.d.ts +1 -0
- package/dist/bits/time-range-field/index.js +1 -0
- package/dist/bits/time-range-field/time-range-field.svelte.d.ts +90 -0
- package/dist/bits/time-range-field/time-range-field.svelte.js +210 -0
- package/dist/bits/time-range-field/types.d.ts +150 -0
- package/dist/bits/time-range-field/types.js +1 -0
- package/dist/bits/toggle/components/toggle.svelte +4 -2
- package/dist/bits/toggle/toggle.svelte.js +2 -2
- package/dist/bits/toggle-group/components/toggle-group-item.svelte +4 -2
- package/dist/bits/toggle-group/components/toggle-group.svelte +4 -2
- package/dist/bits/toggle-group/toggle-group.svelte.js +4 -4
- package/dist/bits/toolbar/components/toolbar-button.svelte +4 -2
- package/dist/bits/toolbar/components/toolbar-group-item.svelte +4 -2
- package/dist/bits/toolbar/components/toolbar-group.svelte +4 -2
- package/dist/bits/toolbar/components/toolbar-link.svelte +4 -2
- package/dist/bits/toolbar/components/toolbar.svelte +4 -2
- package/dist/bits/toolbar/toolbar.svelte.js +7 -7
- package/dist/bits/tooltip/components/tooltip-content-static.svelte +6 -2
- package/dist/bits/tooltip/components/tooltip-content.svelte +6 -2
- package/dist/bits/tooltip/components/tooltip-trigger.svelte +5 -3
- package/dist/bits/tooltip/tooltip.svelte.js +3 -14
- package/dist/bits/utilities/dismissible-layer/dismissible-layer.svelte +2 -0
- package/dist/bits/utilities/dismissible-layer/types.d.ts +2 -0
- package/dist/bits/utilities/dismissible-layer/use-dismissable-layer.svelte.d.ts +3 -3
- package/dist/bits/utilities/dismissible-layer/use-dismissable-layer.svelte.js +16 -25
- package/dist/bits/utilities/floating-layer/components/floating-layer-anchor.svelte +2 -1
- package/dist/bits/utilities/floating-layer/types.d.ts +1 -0
- package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.d.ts +3 -2
- package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.js +5 -26
- package/dist/bits/utilities/focus-scope/focus-scope.svelte +2 -0
- package/dist/bits/utilities/focus-scope/types.d.ts +2 -0
- package/dist/bits/utilities/focus-scope/use-focus-scope.svelte.d.ts +2 -1
- package/dist/bits/utilities/focus-scope/use-focus-scope.svelte.js +2 -8
- package/dist/bits/utilities/popper-layer/popper-layer-inner.svelte +4 -0
- package/dist/bits/utilities/popper-layer/popper-layer.svelte +3 -1
- package/dist/bits/utilities/presence-layer/presence-layer.svelte +2 -2
- package/dist/bits/utilities/presence-layer/types.d.ts +2 -1
- package/dist/bits/utilities/presence-layer/use-presence.svelte.d.ts +1 -1
- package/dist/bits/utilities/presence-layer/use-presence.svelte.js +19 -36
- package/dist/bits/utilities/text-selection-layer/text-selection-layer.svelte +2 -0
- package/dist/bits/utilities/text-selection-layer/types.d.ts +2 -0
- package/dist/bits/utilities/text-selection-layer/use-text-selection-layer.svelte.d.ts +3 -1
- package/dist/bits/utilities/text-selection-layer/use-text-selection-layer.svelte.js +2 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/create-id.d.ts +8 -0
- package/dist/internal/create-id.js +5 -0
- package/dist/internal/date-time/field/helpers.d.ts +1 -0
- package/dist/internal/date-time/field/helpers.js +8 -2
- package/dist/internal/date-time/field/parts.d.ts +3 -1
- package/dist/internal/date-time/field/parts.js +10 -2
- package/dist/internal/date-time/field/segments.d.ts +9 -0
- package/dist/internal/date-time/field/segments.js +65 -0
- package/dist/internal/date-time/field/time-helpers.d.ts +77 -0
- package/dist/internal/date-time/field/time-helpers.js +301 -0
- package/dist/internal/date-time/field/types.d.ts +2 -2
- package/dist/internal/date-time/formatter.d.ts +11 -1
- package/dist/internal/date-time/formatter.js +56 -0
- package/dist/internal/date-time/utils.d.ts +7 -2
- package/dist/internal/date-time/utils.js +15 -1
- package/dist/internal/dom-context.svelte.d.ts +9 -0
- package/dist/internal/dom-context.svelte.js +26 -0
- package/dist/internal/use-roving-focus.svelte.d.ts +3 -3
- package/dist/internal/use-roving-focus.svelte.js +10 -11
- package/dist/shared/date/types.d.ts +27 -4
- package/dist/shared/index.d.ts +9 -2
- package/dist/types.d.ts +2 -0
- package/package.json +18 -16
- package/dist/bits/date-field/components/date-field-error.svelte +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { NavigationMenuViewportProps } from "../types.js";
|
|
3
3
|
import { useNavigationMenuViewport } from "../navigation-menu.svelte.js";
|
|
4
|
-
import {
|
|
4
|
+
import { createId } from "../../../internal/create-id.js";
|
|
5
5
|
import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
|
|
6
6
|
import { box, mergeProps } from "svelte-toolbelt";
|
|
7
|
+
import { Mounted } from "../../utilities/index.js";
|
|
8
|
+
|
|
9
|
+
const uid = $props.id();
|
|
7
10
|
|
|
8
11
|
let {
|
|
9
|
-
id =
|
|
12
|
+
id = createId(uid),
|
|
10
13
|
ref = $bindable(null),
|
|
11
14
|
forceMount = false,
|
|
12
15
|
child,
|
|
@@ -25,7 +28,7 @@
|
|
|
25
28
|
const mergedProps = $derived(mergeProps(restProps, viewportState.props));
|
|
26
29
|
</script>
|
|
27
30
|
|
|
28
|
-
<PresenceLayer
|
|
31
|
+
<PresenceLayer present={forceMount || viewportState.open} ref={viewportState.opts.ref}>
|
|
29
32
|
{#snippet presence()}
|
|
30
33
|
{#if child}
|
|
31
34
|
{@render child({ props: mergedProps })}
|
|
@@ -34,5 +37,6 @@
|
|
|
34
37
|
{@render children?.()}
|
|
35
38
|
</div>
|
|
36
39
|
{/if}
|
|
40
|
+
<Mounted bind:mounted={viewportState.mounted} />
|
|
37
41
|
{/snippet}
|
|
38
42
|
</PresenceLayer>
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
import { box, mergeProps } from "svelte-toolbelt";
|
|
3
3
|
import type { NavigationMenuRootProps } from "../types.js";
|
|
4
4
|
import { useNavigationMenuRoot } from "../navigation-menu.svelte.js";
|
|
5
|
-
import {
|
|
5
|
+
import { createId } from "../../../internal/create-id.js";
|
|
6
6
|
import { noop } from "../../../internal/noop.js";
|
|
7
7
|
|
|
8
|
+
const uid = $props.id();
|
|
9
|
+
|
|
8
10
|
let {
|
|
9
11
|
child,
|
|
10
12
|
children,
|
|
11
|
-
id =
|
|
13
|
+
id = createId(uid),
|
|
12
14
|
ref = $bindable(null),
|
|
13
15
|
value = $bindable(""),
|
|
14
16
|
onValueChange = noop,
|
|
@@ -9,6 +9,7 @@ import { SvelteMap } from "svelte/reactivity";
|
|
|
9
9
|
import { type Direction, type Orientation } from "../../shared/index.js";
|
|
10
10
|
import type { BitsFocusEvent, BitsKeyboardEvent, BitsMouseEvent, BitsPointerEvent } from "../../internal/types.js";
|
|
11
11
|
import { useRovingFocus } from "../../internal/use-roving-focus.svelte.js";
|
|
12
|
+
import type { FocusEventHandler, KeyboardEventHandler, MouseEventHandler, PointerEventHandler } from "svelte/elements";
|
|
12
13
|
type NavigationMenuProviderStateProps = ReadableBoxedValues<{
|
|
13
14
|
dir: Direction;
|
|
14
15
|
orientation: Orientation;
|
|
@@ -18,11 +19,11 @@ type NavigationMenuProviderStateProps = ReadableBoxedValues<{
|
|
|
18
19
|
previousValue: string;
|
|
19
20
|
}> & {
|
|
20
21
|
isRootMenu: boolean;
|
|
21
|
-
onTriggerEnter: (itemValue: string) => void;
|
|
22
|
+
onTriggerEnter: (itemValue: string, itemState: NavigationMenuItemState | null) => void;
|
|
22
23
|
onTriggerLeave?: () => void;
|
|
23
24
|
onContentEnter?: () => void;
|
|
24
25
|
onContentLeave?: () => void;
|
|
25
|
-
onItemSelect: (itemValue: string) => void;
|
|
26
|
+
onItemSelect: (itemValue: string, itemState: NavigationMenuItemState | null) => void;
|
|
26
27
|
onItemDismiss: () => void;
|
|
27
28
|
};
|
|
28
29
|
declare class NavigationMenuProviderState {
|
|
@@ -36,7 +37,10 @@ declare class NavigationMenuProviderState {
|
|
|
36
37
|
onContentLeave: () => void;
|
|
37
38
|
onItemSelect: NavigationMenuProviderStateProps["onItemSelect"];
|
|
38
39
|
onItemDismiss: NavigationMenuProviderStateProps["onItemDismiss"];
|
|
40
|
+
activeItem: NavigationMenuItemState | null;
|
|
41
|
+
prevActiveItem: NavigationMenuItemState | null;
|
|
39
42
|
constructor(opts: NavigationMenuProviderStateProps);
|
|
43
|
+
setActiveItem: (item: NavigationMenuItemState | null) => void;
|
|
40
44
|
}
|
|
41
45
|
type NavigationMenuRootStateProps = WithRefProps<WritableBoxedValues<{
|
|
42
46
|
value: string;
|
|
@@ -53,7 +57,7 @@ declare class NavigationMenuRootState {
|
|
|
53
57
|
previousValue: WritableBox<string>;
|
|
54
58
|
isDelaySkipped: WritableBox<boolean>;
|
|
55
59
|
constructor(opts: NavigationMenuRootStateProps);
|
|
56
|
-
setValue: (newValue: string) => void;
|
|
60
|
+
setValue: (newValue: string, itemState: NavigationMenuItemState | null) => void;
|
|
57
61
|
props: {
|
|
58
62
|
readonly id: string;
|
|
59
63
|
readonly "data-orientation": "horizontal" | "vertical";
|
|
@@ -71,8 +75,9 @@ declare class NavigationMenuSubState {
|
|
|
71
75
|
readonly opts: NavigationMenuSubStateProps;
|
|
72
76
|
readonly context: NavigationMenuProviderState;
|
|
73
77
|
previousValue: WritableBox<string>;
|
|
78
|
+
subProvider: NavigationMenuProviderState;
|
|
74
79
|
constructor(opts: NavigationMenuSubStateProps, context: NavigationMenuProviderState);
|
|
75
|
-
setValue: (newValue: string) => void;
|
|
80
|
+
setValue: (newValue: string, itemState: NavigationMenuItemState | null) => void;
|
|
76
81
|
props: {
|
|
77
82
|
readonly id: string;
|
|
78
83
|
readonly "data-orientation": "horizontal" | "vertical";
|
|
@@ -102,6 +107,7 @@ declare class NavigationMenuListState {
|
|
|
102
107
|
}
|
|
103
108
|
type NavigationMenuItemStateProps = WithRefProps<ReadableBoxedValues<{
|
|
104
109
|
value: string;
|
|
110
|
+
openOnHover: boolean;
|
|
105
111
|
}>>;
|
|
106
112
|
export declare class NavigationMenuItemState {
|
|
107
113
|
#private;
|
|
@@ -147,13 +153,14 @@ declare class NavigationMenuTriggerState {
|
|
|
147
153
|
provider: NavigationMenuProviderState;
|
|
148
154
|
item: NavigationMenuItemState;
|
|
149
155
|
list: NavigationMenuListState;
|
|
156
|
+
sub: NavigationMenuSubState | null;
|
|
150
157
|
});
|
|
151
158
|
onpointerenter: (_: BitsPointerEvent<HTMLButtonElement>) => void;
|
|
152
|
-
onpointermove:
|
|
153
|
-
onpointerleave:
|
|
154
|
-
onclick:
|
|
155
|
-
onkeydown:
|
|
156
|
-
focusProxyOnFocus:
|
|
159
|
+
onpointermove: PointerEventHandler<HTMLElement>;
|
|
160
|
+
onpointerleave: PointerEventHandler<HTMLElement>;
|
|
161
|
+
onclick: MouseEventHandler<HTMLButtonElement>;
|
|
162
|
+
onkeydown: KeyboardEventHandler<HTMLButtonElement>;
|
|
163
|
+
focusProxyOnFocus: FocusEventHandler<HTMLElement>;
|
|
157
164
|
props: {
|
|
158
165
|
readonly id: string;
|
|
159
166
|
readonly disabled: boolean | null | undefined;
|
|
@@ -163,16 +170,16 @@ declare class NavigationMenuTriggerState {
|
|
|
163
170
|
readonly "aria-expanded": "true" | "false";
|
|
164
171
|
readonly "aria-controls": string | undefined;
|
|
165
172
|
readonly "data-navigation-menu-trigger": "";
|
|
166
|
-
readonly onpointermove:
|
|
167
|
-
readonly onpointerleave:
|
|
173
|
+
readonly onpointermove: PointerEventHandler<HTMLElement>;
|
|
174
|
+
readonly onpointerleave: PointerEventHandler<HTMLElement>;
|
|
168
175
|
readonly onpointerenter: (_: BitsPointerEvent<HTMLButtonElement>) => void;
|
|
169
|
-
readonly onclick:
|
|
170
|
-
readonly onkeydown:
|
|
176
|
+
readonly onclick: MouseEventHandler<HTMLButtonElement>;
|
|
177
|
+
readonly onkeydown: KeyboardEventHandler<HTMLButtonElement>;
|
|
171
178
|
};
|
|
172
179
|
focusProxyProps: {
|
|
173
180
|
readonly id: string;
|
|
174
181
|
readonly tabindex: 0;
|
|
175
|
-
readonly onfocus:
|
|
182
|
+
readonly onfocus: FocusEventHandler<HTMLElement>;
|
|
176
183
|
};
|
|
177
184
|
restructureSpanProps: {
|
|
178
185
|
readonly "aria-owns": string | undefined;
|
|
@@ -183,6 +190,7 @@ type NavigationMenuLinkStateProps = WithRefProps & ReadableBoxedValues<{
|
|
|
183
190
|
onSelect: (e: Event) => void;
|
|
184
191
|
}>;
|
|
185
192
|
declare class NavigationMenuLinkState {
|
|
193
|
+
#private;
|
|
186
194
|
readonly opts: NavigationMenuLinkStateProps;
|
|
187
195
|
readonly context: {
|
|
188
196
|
provider: NavigationMenuProviderState;
|
|
@@ -197,6 +205,8 @@ declare class NavigationMenuLinkState {
|
|
|
197
205
|
onkeydown: (e: BitsKeyboardEvent) => void;
|
|
198
206
|
onfocus: (_: BitsFocusEvent) => void;
|
|
199
207
|
onblur: (_: BitsFocusEvent) => void;
|
|
208
|
+
onpointerenter: PointerEventHandler<HTMLAnchorElement>;
|
|
209
|
+
onpointermove: PointerEventHandler<HTMLElement>;
|
|
200
210
|
props: {
|
|
201
211
|
readonly id: string;
|
|
202
212
|
readonly "data-active": "" | undefined;
|
|
@@ -206,6 +216,8 @@ declare class NavigationMenuLinkState {
|
|
|
206
216
|
readonly onkeydown: (e: BitsKeyboardEvent) => void;
|
|
207
217
|
readonly onfocus: (_: BitsFocusEvent) => void;
|
|
208
218
|
readonly onblur: (_: BitsFocusEvent) => void;
|
|
219
|
+
readonly onpointerenter: PointerEventHandler<HTMLAnchorElement>;
|
|
220
|
+
readonly onpointermove: PointerEventHandler<HTMLElement>;
|
|
209
221
|
readonly "data-navigation-menu-link": "";
|
|
210
222
|
};
|
|
211
223
|
}
|
|
@@ -266,11 +278,11 @@ declare class NavigationMenuContentState {
|
|
|
266
278
|
list: NavigationMenuListState;
|
|
267
279
|
});
|
|
268
280
|
onpointerenter: (_: BitsPointerEvent) => void;
|
|
269
|
-
onpointerleave:
|
|
281
|
+
onpointerleave: PointerEventHandler<HTMLElement>;
|
|
270
282
|
props: {
|
|
271
283
|
readonly id: string;
|
|
272
284
|
readonly onpointerenter: (_: BitsPointerEvent) => void;
|
|
273
|
-
readonly onpointerleave:
|
|
285
|
+
readonly onpointerleave: PointerEventHandler<HTMLElement>;
|
|
274
286
|
};
|
|
275
287
|
}
|
|
276
288
|
type MotionAttribute = "to-start" | "to-end" | "from-start" | "from-end";
|
|
@@ -309,6 +321,7 @@ declare class NavigationMenuViewportState {
|
|
|
309
321
|
viewportWidth: string | undefined;
|
|
310
322
|
viewportHeight: string | undefined;
|
|
311
323
|
activeContentValue: string;
|
|
324
|
+
mounted: boolean;
|
|
312
325
|
constructor(opts: NavigationMenuViewportImplStateProps, context: NavigationMenuProviderState);
|
|
313
326
|
props: {
|
|
314
327
|
readonly id: string;
|
|
@@ -338,5 +351,4 @@ export declare function useNavigationMenuLink(props: NavigationMenuLinkStateProp
|
|
|
338
351
|
export declare function useNavigationMenuContentImpl(props: NavigationMenuContentImplStateProps, itemState?: NavigationMenuItemState): NavigationMenuContentImplState;
|
|
339
352
|
export declare function useNavigationMenuViewport(props: NavigationMenuViewportImplStateProps): NavigationMenuViewportState;
|
|
340
353
|
export declare function useNavigationMenuIndicator(): NavigationMenuIndicatorState;
|
|
341
|
-
type BitsPointerEventHandler<T extends HTMLElement = HTMLElement> = (e: BitsPointerEvent<T>) => void;
|
|
342
354
|
export {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Based on Radix UI's Navigation Menu
|
|
3
3
|
* https://www.radix-ui.com/docs/primitives/components/navigation-menu
|
|
4
4
|
*/
|
|
5
|
-
import { afterSleep, afterTick, box,
|
|
5
|
+
import { afterSleep, afterTick, box, attachRef, } from "svelte-toolbelt";
|
|
6
6
|
import { Context, useDebounce, watch } from "runed";
|
|
7
7
|
import { untrack } from "svelte";
|
|
8
8
|
import { SvelteMap } from "svelte/reactivity";
|
|
@@ -38,6 +38,8 @@ class NavigationMenuProviderState {
|
|
|
38
38
|
onContentLeave = noop;
|
|
39
39
|
onItemSelect;
|
|
40
40
|
onItemDismiss;
|
|
41
|
+
activeItem = null;
|
|
42
|
+
prevActiveItem = null;
|
|
41
43
|
constructor(opts) {
|
|
42
44
|
this.opts = opts;
|
|
43
45
|
this.onTriggerEnter = opts.onTriggerEnter;
|
|
@@ -47,6 +49,10 @@ class NavigationMenuProviderState {
|
|
|
47
49
|
this.onItemDismiss = opts.onItemDismiss;
|
|
48
50
|
this.onItemSelect = opts.onItemSelect;
|
|
49
51
|
}
|
|
52
|
+
setActiveItem = (item) => {
|
|
53
|
+
this.prevActiveItem = this.activeItem;
|
|
54
|
+
this.activeItem = item;
|
|
55
|
+
};
|
|
50
56
|
}
|
|
51
57
|
class NavigationMenuRootState {
|
|
52
58
|
opts;
|
|
@@ -66,7 +72,6 @@ class NavigationMenuRootState {
|
|
|
66
72
|
constructor(opts) {
|
|
67
73
|
this.opts = opts;
|
|
68
74
|
this.isDelaySkipped = boxAutoReset(false, this.opts.skipDelayDuration.current);
|
|
69
|
-
useRefById(opts);
|
|
70
75
|
this.provider = useNavigationMenuProvider({
|
|
71
76
|
value: this.opts.value,
|
|
72
77
|
previousValue: this.previousValue,
|
|
@@ -74,8 +79,8 @@ class NavigationMenuRootState {
|
|
|
74
79
|
orientation: this.opts.orientation,
|
|
75
80
|
rootNavigationMenuRef: this.opts.ref,
|
|
76
81
|
isRootMenu: true,
|
|
77
|
-
onTriggerEnter: (itemValue) => {
|
|
78
|
-
this.#onTriggerEnter(itemValue);
|
|
82
|
+
onTriggerEnter: (itemValue, itemState) => {
|
|
83
|
+
this.#onTriggerEnter(itemValue, itemState);
|
|
79
84
|
},
|
|
80
85
|
onTriggerLeave: this.#onTriggerLeave,
|
|
81
86
|
onContentEnter: this.#onContentEnter,
|
|
@@ -84,34 +89,44 @@ class NavigationMenuRootState {
|
|
|
84
89
|
onItemDismiss: this.#onItemDismiss,
|
|
85
90
|
});
|
|
86
91
|
}
|
|
87
|
-
#debouncedFn = useDebounce((val) => {
|
|
92
|
+
#debouncedFn = useDebounce((val, itemState) => {
|
|
88
93
|
// passing `undefined` meant to reset the debounce timer
|
|
89
94
|
if (typeof val === "string") {
|
|
90
|
-
this.setValue(val);
|
|
95
|
+
this.setValue(val, itemState);
|
|
91
96
|
}
|
|
92
97
|
}, () => this.#derivedDelay);
|
|
93
|
-
#onTriggerEnter = (itemValue) => {
|
|
94
|
-
this.#debouncedFn(itemValue);
|
|
98
|
+
#onTriggerEnter = (itemValue, itemState) => {
|
|
99
|
+
this.#debouncedFn(itemValue, itemState);
|
|
95
100
|
};
|
|
96
101
|
#onTriggerLeave = () => {
|
|
97
102
|
this.isDelaySkipped.current = false;
|
|
98
|
-
this.#debouncedFn("");
|
|
103
|
+
this.#debouncedFn("", null);
|
|
99
104
|
};
|
|
100
105
|
#onContentEnter = () => {
|
|
101
|
-
this.#debouncedFn();
|
|
106
|
+
this.#debouncedFn(undefined, null);
|
|
102
107
|
};
|
|
103
108
|
#onContentLeave = () => {
|
|
104
|
-
this
|
|
109
|
+
if (this.provider.activeItem &&
|
|
110
|
+
this.provider.activeItem.opts.openOnHover.current === false) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.#debouncedFn("", null);
|
|
105
114
|
};
|
|
106
|
-
#onItemSelect = (itemValue) => {
|
|
107
|
-
this.setValue(itemValue);
|
|
115
|
+
#onItemSelect = (itemValue, itemState) => {
|
|
116
|
+
this.setValue(itemValue, itemState);
|
|
108
117
|
};
|
|
109
118
|
#onItemDismiss = () => {
|
|
110
|
-
this.setValue("");
|
|
119
|
+
this.setValue("", null);
|
|
111
120
|
};
|
|
112
|
-
setValue = (newValue) => {
|
|
121
|
+
setValue = (newValue, itemState) => {
|
|
113
122
|
this.previousValue.current = this.opts.value.current;
|
|
114
123
|
this.opts.value.current = newValue;
|
|
124
|
+
this.provider.setActiveItem(itemState);
|
|
125
|
+
// When all menus are closed, we want to reset previousValue to prevent
|
|
126
|
+
// weird transitions from old positions when opening fresh
|
|
127
|
+
if (newValue === "") {
|
|
128
|
+
this.previousValue.current = "";
|
|
129
|
+
}
|
|
115
130
|
};
|
|
116
131
|
props = $derived.by(() => ({
|
|
117
132
|
id: this.opts.id.current,
|
|
@@ -119,17 +134,18 @@ class NavigationMenuRootState {
|
|
|
119
134
|
dir: this.opts.dir.current,
|
|
120
135
|
[NAVIGATION_MENU_ROOT_ATTR]: "",
|
|
121
136
|
[NAVIGATION_MENU_ATTR]: "",
|
|
137
|
+
...attachRef(this.opts.ref),
|
|
122
138
|
}));
|
|
123
139
|
}
|
|
124
140
|
class NavigationMenuSubState {
|
|
125
141
|
opts;
|
|
126
142
|
context;
|
|
127
143
|
previousValue = box("");
|
|
144
|
+
subProvider;
|
|
128
145
|
constructor(opts, context) {
|
|
129
146
|
this.opts = opts;
|
|
130
147
|
this.context = context;
|
|
131
|
-
|
|
132
|
-
useNavigationMenuProvider({
|
|
148
|
+
this.subProvider = useNavigationMenuProvider({
|
|
133
149
|
isRootMenu: false,
|
|
134
150
|
value: this.opts.value,
|
|
135
151
|
dir: this.context.opts.dir,
|
|
@@ -137,18 +153,26 @@ class NavigationMenuSubState {
|
|
|
137
153
|
rootNavigationMenuRef: this.opts.ref,
|
|
138
154
|
onTriggerEnter: this.setValue,
|
|
139
155
|
onItemSelect: this.setValue,
|
|
140
|
-
onItemDismiss: () => this.setValue(""),
|
|
156
|
+
onItemDismiss: () => this.setValue("", null),
|
|
141
157
|
previousValue: this.previousValue,
|
|
142
158
|
});
|
|
143
159
|
}
|
|
144
|
-
setValue = (newValue) => {
|
|
160
|
+
setValue = (newValue, itemState) => {
|
|
161
|
+
this.previousValue.current = this.opts.value.current;
|
|
145
162
|
this.opts.value.current = newValue;
|
|
163
|
+
this.subProvider.setActiveItem(itemState);
|
|
164
|
+
// When all menus are closed, we want to reset previousValue to prevent
|
|
165
|
+
// weird transitions from old positions when opening fresh
|
|
166
|
+
if (newValue === "") {
|
|
167
|
+
this.previousValue.current = "";
|
|
168
|
+
}
|
|
146
169
|
};
|
|
147
170
|
props = $derived.by(() => ({
|
|
148
171
|
id: this.opts.id.current,
|
|
149
172
|
"data-orientation": getDataOrientation(this.opts.orientation.current),
|
|
150
173
|
[NAVIGATION_MENU_SUB_ATTR]: "",
|
|
151
174
|
[NAVIGATION_MENU_ATTR]: "",
|
|
175
|
+
...attachRef(this.opts.ref),
|
|
152
176
|
}));
|
|
153
177
|
}
|
|
154
178
|
class NavigationMenuListState {
|
|
@@ -162,17 +186,8 @@ class NavigationMenuListState {
|
|
|
162
186
|
constructor(opts, context) {
|
|
163
187
|
this.opts = opts;
|
|
164
188
|
this.context = context;
|
|
165
|
-
useRefById(opts);
|
|
166
|
-
useRefById({
|
|
167
|
-
id: this.wrapperId,
|
|
168
|
-
ref: this.wrapperRef,
|
|
169
|
-
onRefChange: (node) => {
|
|
170
|
-
this.context.indicatorTrackRef.current = node;
|
|
171
|
-
},
|
|
172
|
-
deps: () => this.wrapperMounted,
|
|
173
|
-
});
|
|
174
189
|
this.rovingFocusGroup = useRovingFocus({
|
|
175
|
-
|
|
190
|
+
rootNode: opts.ref,
|
|
176
191
|
candidateSelector: `[${NAVIGATION_MENU_TRIGGER_ATTR}]:not([data-disabled]), [${NAVIGATION_MENU_LINK_ATTR}]:not([data-disabled])`,
|
|
177
192
|
loop: box.with(() => false),
|
|
178
193
|
orientation: this.context.opts.orientation,
|
|
@@ -187,11 +202,13 @@ class NavigationMenuListState {
|
|
|
187
202
|
}
|
|
188
203
|
wrapperProps = $derived.by(() => ({
|
|
189
204
|
id: this.wrapperId.current,
|
|
205
|
+
...attachRef(this.wrapperRef, (v) => (this.context.indicatorTrackRef.current = v)),
|
|
190
206
|
}));
|
|
191
207
|
props = $derived.by(() => ({
|
|
192
208
|
id: this.opts.id.current,
|
|
193
209
|
"data-orientation": getDataOrientation(this.context.opts.orientation.current),
|
|
194
210
|
[NAVIGATION_MENU_LIST_ATTR]: "",
|
|
211
|
+
...attachRef(this.opts.ref),
|
|
195
212
|
}));
|
|
196
213
|
}
|
|
197
214
|
export class NavigationMenuItemState {
|
|
@@ -252,20 +269,6 @@ class NavigationMenuTriggerState {
|
|
|
252
269
|
this.context = context.provider;
|
|
253
270
|
this.itemContext = context.item;
|
|
254
271
|
this.listContext = context.list;
|
|
255
|
-
useRefById({
|
|
256
|
-
...opts,
|
|
257
|
-
onRefChange: (node) => {
|
|
258
|
-
this.itemContext.triggerNode = node;
|
|
259
|
-
},
|
|
260
|
-
});
|
|
261
|
-
useRefById({
|
|
262
|
-
id: this.focusProxyId,
|
|
263
|
-
ref: this.focusProxyRef,
|
|
264
|
-
onRefChange: (node) => {
|
|
265
|
-
this.itemContext.focusProxyNode = node;
|
|
266
|
-
},
|
|
267
|
-
deps: () => this.focusProxyMounted,
|
|
268
|
-
});
|
|
269
272
|
watch(() => this.opts.ref.current, () => {
|
|
270
273
|
const node = this.opts.ref.current;
|
|
271
274
|
if (!node)
|
|
@@ -281,28 +284,30 @@ class NavigationMenuTriggerState {
|
|
|
281
284
|
if (this.opts.disabled.current ||
|
|
282
285
|
this.wasClickClose ||
|
|
283
286
|
this.itemContext.wasEscapeClose ||
|
|
284
|
-
this.hasPointerMoveOpened.current
|
|
287
|
+
this.hasPointerMoveOpened.current ||
|
|
288
|
+
!this.itemContext.opts.openOnHover.current) {
|
|
285
289
|
return;
|
|
286
290
|
}
|
|
287
|
-
this.context.onTriggerEnter(this.itemContext.opts.value.current);
|
|
291
|
+
this.context.onTriggerEnter(this.itemContext.opts.value.current, this.itemContext);
|
|
288
292
|
this.hasPointerMoveOpened.current = true;
|
|
289
293
|
});
|
|
290
294
|
onpointerleave = whenMouse(() => {
|
|
291
|
-
if (this.opts.disabled.current)
|
|
295
|
+
if (this.opts.disabled.current || !this.itemContext.opts.openOnHover.current)
|
|
292
296
|
return;
|
|
293
297
|
this.context.onTriggerLeave();
|
|
294
298
|
this.hasPointerMoveOpened.current = false;
|
|
295
299
|
});
|
|
296
|
-
onclick = (
|
|
300
|
+
onclick = () => {
|
|
297
301
|
// if opened via pointer move, we prevent the click event
|
|
298
302
|
if (this.hasPointerMoveOpened.current)
|
|
299
303
|
return;
|
|
300
|
-
const shouldClose = this.open &&
|
|
304
|
+
const shouldClose = this.open &&
|
|
305
|
+
(!this.itemContext.opts.openOnHover.current || this.context.opts.isRootMenu);
|
|
301
306
|
if (shouldClose) {
|
|
302
|
-
this.context.onItemSelect("");
|
|
307
|
+
this.context.onItemSelect("", null);
|
|
303
308
|
}
|
|
304
309
|
else if (!this.open) {
|
|
305
|
-
this.context.onItemSelect(this.itemContext.opts.value.current);
|
|
310
|
+
this.context.onItemSelect(this.itemContext.opts.value.current, this.itemContext);
|
|
306
311
|
}
|
|
307
312
|
this.wasClickClose = shouldClose;
|
|
308
313
|
};
|
|
@@ -340,11 +345,13 @@ class NavigationMenuTriggerState {
|
|
|
340
345
|
onpointerenter: this.onpointerenter,
|
|
341
346
|
onclick: this.onclick,
|
|
342
347
|
onkeydown: this.onkeydown,
|
|
348
|
+
...attachRef(this.opts.ref, (v) => (this.itemContext.triggerNode = v)),
|
|
343
349
|
}));
|
|
344
350
|
focusProxyProps = $derived.by(() => ({
|
|
345
351
|
id: this.focusProxyId.current,
|
|
346
352
|
tabindex: 0,
|
|
347
353
|
onfocus: this.focusProxyOnFocus,
|
|
354
|
+
...attachRef(this.focusProxyRef, (v) => (this.itemContext.focusProxyNode = v)),
|
|
348
355
|
}));
|
|
349
356
|
restructureSpanProps = $derived.by(() => ({
|
|
350
357
|
"aria-owns": this.itemContext.contentId,
|
|
@@ -365,7 +372,6 @@ class NavigationMenuLinkState {
|
|
|
365
372
|
constructor(opts, context) {
|
|
366
373
|
this.opts = opts;
|
|
367
374
|
this.context = context;
|
|
368
|
-
useRefById(opts);
|
|
369
375
|
}
|
|
370
376
|
onclick = (e) => {
|
|
371
377
|
const currTarget = e.currentTarget;
|
|
@@ -386,6 +392,23 @@ class NavigationMenuLinkState {
|
|
|
386
392
|
onblur = (_) => {
|
|
387
393
|
this.isFocused = false;
|
|
388
394
|
};
|
|
395
|
+
#handlePointerDismiss = () => {
|
|
396
|
+
// only close submenu if this link is not inside the currently open submenu content
|
|
397
|
+
const currentlyOpenValue = this.context.provider.opts.value.current;
|
|
398
|
+
const isInsideOpenSubmenu = this.context.item.opts.value.current === currentlyOpenValue;
|
|
399
|
+
const activeItem = this.context.item.listContext.context.activeItem;
|
|
400
|
+
if (activeItem && !activeItem.opts.openOnHover.current)
|
|
401
|
+
return;
|
|
402
|
+
if (currentlyOpenValue && !isInsideOpenSubmenu) {
|
|
403
|
+
this.context.provider.onItemDismiss();
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
onpointerenter = () => {
|
|
407
|
+
this.#handlePointerDismiss();
|
|
408
|
+
};
|
|
409
|
+
onpointermove = whenMouse(() => {
|
|
410
|
+
this.#handlePointerDismiss();
|
|
411
|
+
});
|
|
389
412
|
props = $derived.by(() => ({
|
|
390
413
|
id: this.opts.id.current,
|
|
391
414
|
"data-active": this.opts.active.current ? "" : undefined,
|
|
@@ -395,7 +418,10 @@ class NavigationMenuLinkState {
|
|
|
395
418
|
onkeydown: this.onkeydown,
|
|
396
419
|
onfocus: this.onfocus,
|
|
397
420
|
onblur: this.onblur,
|
|
421
|
+
onpointerenter: this.onpointerenter,
|
|
422
|
+
onpointermove: this.onpointermove,
|
|
398
423
|
[NAVIGATION_MENU_LINK_ATTR]: "",
|
|
424
|
+
...attachRef(this.opts.ref),
|
|
399
425
|
}));
|
|
400
426
|
}
|
|
401
427
|
class NavigationMenuIndicatorState {
|
|
@@ -424,10 +450,6 @@ class NavigationMenuIndicatorImplState {
|
|
|
424
450
|
this.listContext = context.list;
|
|
425
451
|
useResizeObserver(() => this.activeTrigger, this.handlePositionChange);
|
|
426
452
|
useResizeObserver(() => this.context.indicatorTrackRef.current, this.handlePositionChange);
|
|
427
|
-
useRefById({
|
|
428
|
-
...opts,
|
|
429
|
-
deps: () => this.context.opts.value.current,
|
|
430
|
-
});
|
|
431
453
|
}
|
|
432
454
|
handlePositionChange = () => {
|
|
433
455
|
if (!this.activeTrigger)
|
|
@@ -460,6 +482,7 @@ class NavigationMenuIndicatorImplState {
|
|
|
460
482
|
}),
|
|
461
483
|
},
|
|
462
484
|
[NAVIGATION_MENU_INDICATOR_ATTR]: "",
|
|
485
|
+
...attachRef(this.opts.ref),
|
|
463
486
|
}));
|
|
464
487
|
}
|
|
465
488
|
class NavigationMenuContentState {
|
|
@@ -485,24 +508,20 @@ class NavigationMenuContentState {
|
|
|
485
508
|
this.context = context.provider;
|
|
486
509
|
this.itemContext = context.item;
|
|
487
510
|
this.listContext = context.list;
|
|
488
|
-
useRefById({
|
|
489
|
-
...opts,
|
|
490
|
-
onRefChange: (node) => {
|
|
491
|
-
this.itemContext.contentNode = node;
|
|
492
|
-
},
|
|
493
|
-
deps: () => this.mounted,
|
|
494
|
-
});
|
|
495
511
|
}
|
|
496
512
|
onpointerenter = (_) => {
|
|
497
513
|
this.context.onContentEnter();
|
|
498
514
|
};
|
|
499
515
|
onpointerleave = whenMouse(() => {
|
|
516
|
+
if (!this.itemContext.opts.openOnHover.current)
|
|
517
|
+
return;
|
|
500
518
|
this.context.onContentLeave();
|
|
501
519
|
});
|
|
502
520
|
props = $derived.by(() => ({
|
|
503
521
|
id: this.opts.id.current,
|
|
504
522
|
onpointerenter: this.onpointerenter,
|
|
505
523
|
onpointerleave: this.onpointerleave,
|
|
524
|
+
...attachRef(this.opts.ref, (v) => (this.itemContext.contentNode = v)),
|
|
506
525
|
}));
|
|
507
526
|
}
|
|
508
527
|
class NavigationMenuContentImplState {
|
|
@@ -520,6 +539,11 @@ class NavigationMenuContentImplState {
|
|
|
520
539
|
const prevIndex = values.indexOf(this.context.opts.previousValue.current);
|
|
521
540
|
const isSelected = this.itemContext.opts.value.current === this.context.opts.value.current;
|
|
522
541
|
const wasSelected = prevIndex === values.indexOf(this.itemContext.opts.value.current);
|
|
542
|
+
// When all menus are closed, we want to reset motion state to prevent residual animations
|
|
543
|
+
if (!this.context.opts.value.current && !this.context.opts.previousValue.current) {
|
|
544
|
+
untrack(() => (this.prevMotionAttribute = null));
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
523
547
|
// We only want to update selected and the last selected content
|
|
524
548
|
// this avoids animations being interrupted outside of that range
|
|
525
549
|
if (!isSelected && !wasSelected)
|
|
@@ -546,10 +570,6 @@ class NavigationMenuContentImplState {
|
|
|
546
570
|
this.itemContext = itemContext;
|
|
547
571
|
this.listContext = itemContext.listContext;
|
|
548
572
|
this.context = itemContext.listContext.context;
|
|
549
|
-
useRefById({
|
|
550
|
-
...opts,
|
|
551
|
-
deps: () => this.context.opts.value.current,
|
|
552
|
-
});
|
|
553
573
|
watch([
|
|
554
574
|
() => this.itemContext.opts.value.current,
|
|
555
575
|
() => this.itemContext.triggerNode,
|
|
@@ -585,8 +605,17 @@ class NavigationMenuContentImplState {
|
|
|
585
605
|
const target = e.target;
|
|
586
606
|
const isTrigger = this.listContext.listTriggers.some((trigger) => trigger.contains(target));
|
|
587
607
|
const isRootViewport = this.context.opts.isRootMenu && this.context.viewportRef.current?.contains(target);
|
|
588
|
-
if (
|
|
608
|
+
if (!this.context.opts.isRootMenu && !isTrigger) {
|
|
609
|
+
this.context.onItemDismiss();
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
if (isTrigger || isRootViewport) {
|
|
589
613
|
e.preventDefault();
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
if (!this.itemContext.opts.openOnHover.current) {
|
|
617
|
+
this.context.onItemSelect("", null);
|
|
618
|
+
}
|
|
590
619
|
};
|
|
591
620
|
onkeydown = (e) => {
|
|
592
621
|
// prevent parent menus handling sub-menu keydown events
|
|
@@ -650,6 +679,7 @@ class NavigationMenuContentImplState {
|
|
|
650
679
|
"data-state": getDataOpenClosed(this.context.opts.value.current === this.itemContext.opts.value.current),
|
|
651
680
|
onkeydown: this.onkeydown,
|
|
652
681
|
[NAVIGATION_MENU_CONTENT_ATTR]: "",
|
|
682
|
+
...attachRef(this.opts.ref),
|
|
653
683
|
}));
|
|
654
684
|
}
|
|
655
685
|
class NavigationMenuViewportState {
|
|
@@ -661,16 +691,10 @@ class NavigationMenuViewportState {
|
|
|
661
691
|
viewportWidth = $derived.by(() => (this.size ? `${this.size.width}px` : undefined));
|
|
662
692
|
viewportHeight = $derived.by(() => (this.size ? `${this.size.height}px` : undefined));
|
|
663
693
|
activeContentValue = $derived.by(() => this.context.opts.value.current);
|
|
694
|
+
mounted = $state(false);
|
|
664
695
|
constructor(opts, context) {
|
|
665
696
|
this.opts = opts;
|
|
666
697
|
this.context = context;
|
|
667
|
-
useRefById({
|
|
668
|
-
...opts,
|
|
669
|
-
onRefChange: (node) => {
|
|
670
|
-
this.context.viewportRef.current = node;
|
|
671
|
-
},
|
|
672
|
-
deps: () => this.open,
|
|
673
|
-
});
|
|
674
698
|
watch([() => this.activeContentValue, () => this.open], () => {
|
|
675
699
|
afterTick(() => {
|
|
676
700
|
const currNode = this.context.viewportRef.current;
|
|
@@ -695,6 +719,12 @@ class NavigationMenuViewportState {
|
|
|
695
719
|
};
|
|
696
720
|
}
|
|
697
721
|
});
|
|
722
|
+
// reset size when viewport closes to prevent residual size animations
|
|
723
|
+
watch(() => this.mounted, () => {
|
|
724
|
+
if (!this.mounted && this.size) {
|
|
725
|
+
this.size = null;
|
|
726
|
+
}
|
|
727
|
+
});
|
|
698
728
|
}
|
|
699
729
|
props = $derived.by(() => ({
|
|
700
730
|
id: this.opts.id.current,
|
|
@@ -708,12 +738,14 @@ class NavigationMenuViewportState {
|
|
|
708
738
|
[NAVIGATION_MENU_VIEWPORT_ATTR]: "",
|
|
709
739
|
onpointerenter: this.context.onContentEnter,
|
|
710
740
|
onpointerleave: this.context.onContentLeave,
|
|
741
|
+
...attachRef(this.opts.ref, (v) => (this.context.viewportRef.current = v)),
|
|
711
742
|
}));
|
|
712
743
|
}
|
|
713
744
|
const NavigationMenuProviderContext = new Context("NavigationMenu.Root");
|
|
714
745
|
export const NavigationMenuItemContext = new Context("NavigationMenu.Item");
|
|
715
746
|
const NavigationMenuListContext = new Context("NavigationMenu.List");
|
|
716
747
|
const NavigationMenuContentContext = new Context("NavigationMenu.Content");
|
|
748
|
+
const NavigationMenuSubContext = new Context("NavigationMenu.Sub");
|
|
717
749
|
export function useNavigationMenuRoot(props) {
|
|
718
750
|
return new NavigationMenuRootState(props);
|
|
719
751
|
}
|
|
@@ -740,6 +772,7 @@ export function useNavigationMenuTrigger(props) {
|
|
|
740
772
|
provider: NavigationMenuProviderContext.get(),
|
|
741
773
|
item: NavigationMenuItemContext.get(),
|
|
742
774
|
list: NavigationMenuListContext.get(),
|
|
775
|
+
sub: NavigationMenuSubContext.getOr(null),
|
|
743
776
|
});
|
|
744
777
|
}
|
|
745
778
|
export function useNavigationMenuContent(props) {
|