@llui/components 0.4.10 → 0.5.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/components/accordion.d.ts +13 -13
- package/dist/components/accordion.d.ts.map +1 -1
- package/dist/components/accordion.js +9 -9
- package/dist/components/accordion.js.map +1 -1
- package/dist/components/alert-dialog.d.ts +8 -8
- package/dist/components/alert-dialog.d.ts.map +1 -1
- package/dist/components/alert-dialog.js +2 -2
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/angle-slider.d.ts +13 -13
- package/dist/components/angle-slider.d.ts.map +1 -1
- package/dist/components/angle-slider.js +11 -11
- package/dist/components/angle-slider.js.map +1 -1
- package/dist/components/async-list.d.ts +7 -7
- package/dist/components/async-list.d.ts.map +1 -1
- package/dist/components/async-list.js +5 -8
- package/dist/components/async-list.js.map +1 -1
- package/dist/components/avatar.d.ts +9 -9
- package/dist/components/avatar.d.ts.map +1 -1
- package/dist/components/avatar.js +7 -7
- package/dist/components/avatar.js.map +1 -1
- package/dist/components/carousel.d.ts +18 -18
- package/dist/components/carousel.d.ts.map +1 -1
- package/dist/components/carousel.js +12 -12
- package/dist/components/carousel.js.map +1 -1
- package/dist/components/cascade-select.d.ts +12 -12
- package/dist/components/cascade-select.d.ts.map +1 -1
- package/dist/components/cascade-select.js +8 -8
- package/dist/components/cascade-select.js.map +1 -1
- package/dist/components/checkbox.d.ts +14 -14
- package/dist/components/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox.js +12 -12
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/clipboard.d.ts +8 -8
- package/dist/components/clipboard.d.ts.map +1 -1
- package/dist/components/clipboard.js +6 -6
- package/dist/components/clipboard.js.map +1 -1
- package/dist/components/collapsible.d.ts +11 -11
- package/dist/components/collapsible.d.ts.map +1 -1
- package/dist/components/collapsible.js +9 -9
- package/dist/components/collapsible.js.map +1 -1
- package/dist/components/color-picker.d.ts +19 -19
- package/dist/components/color-picker.d.ts.map +1 -1
- package/dist/components/color-picker.js +21 -21
- package/dist/components/color-picker.js.map +1 -1
- package/dist/components/combobox.d.ts +25 -25
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/combobox.js +54 -59
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/context-menu.d.ts +14 -14
- package/dist/components/context-menu.d.ts.map +1 -1
- package/dist/components/context-menu.js +15 -19
- package/dist/components/context-menu.js.map +1 -1
- package/dist/components/date-input.d.ts +13 -13
- package/dist/components/date-input.d.ts.map +1 -1
- package/dist/components/date-input.js +11 -11
- package/dist/components/date-input.js.map +1 -1
- package/dist/components/date-picker.d.ts +11 -11
- package/dist/components/date-picker.d.ts.map +1 -1
- package/dist/components/date-picker.js +7 -7
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/dialog.d.ts +15 -15
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/dialog.js +45 -50
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/drawer.d.ts +13 -13
- package/dist/components/drawer.d.ts.map +1 -1
- package/dist/components/drawer.js +44 -49
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/editable.d.ts +11 -11
- package/dist/components/editable.d.ts.map +1 -1
- package/dist/components/editable.js +9 -9
- package/dist/components/editable.js.map +1 -1
- package/dist/components/file-upload.d.ts +19 -19
- package/dist/components/file-upload.d.ts.map +1 -1
- package/dist/components/file-upload.js +14 -14
- package/dist/components/file-upload.js.map +1 -1
- package/dist/components/floating-panel.d.ts +14 -14
- package/dist/components/floating-panel.d.ts.map +1 -1
- package/dist/components/floating-panel.js +13 -14
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form.d.ts +9 -9
- package/dist/components/form.d.ts.map +1 -1
- package/dist/components/form.js +7 -7
- package/dist/components/form.js.map +1 -1
- package/dist/components/hover-card.d.ts +9 -9
- package/dist/components/hover-card.d.ts.map +1 -1
- package/dist/components/hover-card.js +12 -13
- package/dist/components/hover-card.js.map +1 -1
- package/dist/components/image-cropper.d.ts +8 -8
- package/dist/components/image-cropper.d.ts.map +1 -1
- package/dist/components/image-cropper.js +7 -8
- package/dist/components/image-cropper.js.map +1 -1
- package/dist/components/in-view.d.ts +6 -6
- package/dist/components/in-view.d.ts.map +1 -1
- package/dist/components/in-view.js +2 -2
- package/dist/components/in-view.js.map +1 -1
- package/dist/components/listbox.d.ts +16 -16
- package/dist/components/listbox.d.ts.map +1 -1
- package/dist/components/listbox.js +16 -16
- package/dist/components/listbox.js.map +1 -1
- package/dist/components/marquee.d.ts +8 -8
- package/dist/components/marquee.d.ts.map +1 -1
- package/dist/components/marquee.js +8 -11
- package/dist/components/marquee.js.map +1 -1
- package/dist/components/menu.d.ts +15 -15
- package/dist/components/menu.d.ts.map +1 -1
- package/dist/components/menu.js +16 -17
- package/dist/components/menu.js.map +1 -1
- package/dist/components/navigation-menu.d.ts +12 -12
- package/dist/components/navigation-menu.d.ts.map +1 -1
- package/dist/components/navigation-menu.js +8 -8
- package/dist/components/navigation-menu.js.map +1 -1
- package/dist/components/number-input.d.ts +18 -18
- package/dist/components/number-input.d.ts.map +1 -1
- package/dist/components/number-input.js +16 -20
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/pagination.d.ts +13 -13
- package/dist/components/pagination.d.ts.map +1 -1
- package/dist/components/pagination.js +11 -17
- package/dist/components/pagination.js.map +1 -1
- package/dist/components/password-input.d.ts +11 -11
- package/dist/components/password-input.d.ts.map +1 -1
- package/dist/components/password-input.js +11 -11
- package/dist/components/password-input.js.map +1 -1
- package/dist/components/pin-input.d.ts +9 -9
- package/dist/components/pin-input.d.ts.map +1 -1
- package/dist/components/pin-input.js +9 -9
- package/dist/components/pin-input.js.map +1 -1
- package/dist/components/popover.d.ts +11 -11
- package/dist/components/popover.d.ts.map +1 -1
- package/dist/components/popover.js +61 -60
- package/dist/components/popover.js.map +1 -1
- package/dist/components/presence.d.ts +7 -5
- package/dist/components/presence.d.ts.map +1 -1
- package/dist/components/presence.js +5 -3
- package/dist/components/presence.js.map +1 -1
- package/dist/components/progress.d.ts +14 -14
- package/dist/components/progress.d.ts.map +1 -1
- package/dist/components/progress.js +12 -12
- package/dist/components/progress.js.map +1 -1
- package/dist/components/qr-code.d.ts +7 -7
- package/dist/components/qr-code.d.ts.map +1 -1
- package/dist/components/qr-code.js +7 -7
- package/dist/components/qr-code.js.map +1 -1
- package/dist/components/radio-group.d.ts +15 -15
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js +12 -13
- package/dist/components/radio-group.js.map +1 -1
- package/dist/components/rating-group.d.ts +13 -13
- package/dist/components/rating-group.d.ts.map +1 -1
- package/dist/components/rating-group.js +10 -11
- package/dist/components/rating-group.js.map +1 -1
- package/dist/components/scroll-area.d.ts +10 -10
- package/dist/components/scroll-area.d.ts.map +1 -1
- package/dist/components/scroll-area.js +10 -15
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/select.d.ts +26 -26
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +29 -33
- package/dist/components/select.js.map +1 -1
- package/dist/components/signature-pad.d.ts +12 -12
- package/dist/components/signature-pad.d.ts.map +1 -1
- package/dist/components/signature-pad.js +10 -10
- package/dist/components/signature-pad.js.map +1 -1
- package/dist/components/slider.d.ts +22 -22
- package/dist/components/slider.d.ts.map +1 -1
- package/dist/components/slider.js +17 -17
- package/dist/components/slider.js.map +1 -1
- package/dist/components/sortable.d.ts +11 -11
- package/dist/components/sortable.d.ts.map +1 -1
- package/dist/components/sortable.js +20 -20
- package/dist/components/sortable.js.map +1 -1
- package/dist/components/splitter.d.ts +15 -15
- package/dist/components/splitter.d.ts.map +1 -1
- package/dist/components/splitter.js +15 -15
- package/dist/components/splitter.js.map +1 -1
- package/dist/components/steps.d.ts +14 -14
- package/dist/components/steps.d.ts.map +1 -1
- package/dist/components/steps.js +10 -16
- package/dist/components/steps.js.map +1 -1
- package/dist/components/switch.d.ts +12 -12
- package/dist/components/switch.d.ts.map +1 -1
- package/dist/components/switch.js +10 -10
- package/dist/components/switch.js.map +1 -1
- package/dist/components/tabs.d.ts +15 -15
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +11 -11
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/tags-input.d.ts +14 -14
- package/dist/components/tags-input.d.ts.map +1 -1
- package/dist/components/tags-input.js +10 -10
- package/dist/components/tags-input.js.map +1 -1
- package/dist/components/theme-switch.d.ts +5 -5
- package/dist/components/theme-switch.d.ts.map +1 -1
- package/dist/components/theme-switch.js +3 -3
- package/dist/components/theme-switch.js.map +1 -1
- package/dist/components/time-picker.d.ts +19 -19
- package/dist/components/time-picker.d.ts.map +1 -1
- package/dist/components/time-picker.js +17 -17
- package/dist/components/time-picker.js.map +1 -1
- package/dist/components/timer.d.ts +10 -10
- package/dist/components/timer.d.ts.map +1 -1
- package/dist/components/timer.js +8 -8
- package/dist/components/timer.js.map +1 -1
- package/dist/components/toast.d.ts +8 -8
- package/dist/components/toast.d.ts.map +1 -1
- package/dist/components/toast.js +4 -4
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toc.d.ts +12 -12
- package/dist/components/toc.d.ts.map +1 -1
- package/dist/components/toc.js +8 -8
- package/dist/components/toc.js.map +1 -1
- package/dist/components/toggle-group.d.ts +13 -13
- package/dist/components/toggle-group.d.ts.map +1 -1
- package/dist/components/toggle-group.js +9 -9
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle.d.ts +8 -8
- package/dist/components/toggle.d.ts.map +1 -1
- package/dist/components/toggle.js +6 -6
- package/dist/components/toggle.js.map +1 -1
- package/dist/components/tooltip.d.ts +10 -10
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +13 -14
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/tour.d.ts +7 -7
- package/dist/components/tour.d.ts.map +1 -1
- package/dist/components/tour.js +5 -5
- package/dist/components/tour.js.map +1 -1
- package/dist/components/tree-view.d.ts +19 -19
- package/dist/components/tree-view.d.ts.map +1 -1
- package/dist/components/tree-view.js +23 -23
- package/dist/components/tree-view.js.map +1 -1
- package/dist/patterns/confirm-dialog.d.ts +4 -4
- package/dist/patterns/confirm-dialog.d.ts.map +1 -1
- package/dist/patterns/confirm-dialog.js +7 -9
- package/dist/patterns/confirm-dialog.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/enter-view.d.ts +0 -73
- package/dist/components/enter-view.d.ts.map +0 -1
- package/dist/components/enter-view.js +0 -51
- package/dist/utils/validators.d.ts +0 -34
- package/dist/utils/validators.d.ts.map +0 -1
- package/dist/utils/validators.js +0 -83
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Send, TransitionOptions } from '@llui/dom';
|
|
1
|
+
import type { Send, Signal, TransitionOptions } from '@llui/dom';
|
|
2
2
|
import { type Placement } from '../utils/floating.js';
|
|
3
3
|
/**
|
|
4
4
|
* Menu — a dropdown list of items triggered by a button. Keyboard navigation
|
|
@@ -82,13 +82,13 @@ export interface MenuInit {
|
|
|
82
82
|
}
|
|
83
83
|
export declare function init(opts?: MenuInit): MenuState;
|
|
84
84
|
export declare function update(state: MenuState, msg: MenuMsg): [MenuState, never[]];
|
|
85
|
-
export interface MenuItemParts
|
|
85
|
+
export interface MenuItemParts {
|
|
86
86
|
item: {
|
|
87
87
|
role: 'menuitem';
|
|
88
88
|
id: string;
|
|
89
|
-
'aria-disabled':
|
|
90
|
-
'data-state':
|
|
91
|
-
'data-disabled':
|
|
89
|
+
'aria-disabled': Signal<'true' | undefined>;
|
|
90
|
+
'data-state': Signal<'highlighted' | undefined>;
|
|
91
|
+
'data-disabled': Signal<'' | undefined>;
|
|
92
92
|
'data-scope': 'menu';
|
|
93
93
|
'data-part': 'item';
|
|
94
94
|
'data-value': string;
|
|
@@ -97,14 +97,14 @@ export interface MenuItemParts<S> {
|
|
|
97
97
|
onPointerMove: (e: PointerEvent) => void;
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
-
export interface MenuParts
|
|
100
|
+
export interface MenuParts {
|
|
101
101
|
trigger: {
|
|
102
102
|
type: 'button';
|
|
103
103
|
'aria-haspopup': 'menu';
|
|
104
|
-
'aria-expanded':
|
|
104
|
+
'aria-expanded': Signal<boolean>;
|
|
105
105
|
'aria-controls': string;
|
|
106
106
|
id: string;
|
|
107
|
-
'data-state':
|
|
107
|
+
'data-state': Signal<'open' | 'closed'>;
|
|
108
108
|
'data-scope': 'menu';
|
|
109
109
|
'data-part': 'trigger';
|
|
110
110
|
onClick: (e: MouseEvent) => void;
|
|
@@ -120,23 +120,23 @@ export interface MenuParts<S> {
|
|
|
120
120
|
id: string;
|
|
121
121
|
'aria-labelledby': string;
|
|
122
122
|
tabIndex: -1;
|
|
123
|
-
'data-state':
|
|
123
|
+
'data-state': Signal<'open' | 'closed'>;
|
|
124
124
|
'data-scope': 'menu';
|
|
125
125
|
'data-part': 'content';
|
|
126
126
|
onKeyDown: (e: KeyboardEvent) => void;
|
|
127
127
|
};
|
|
128
|
-
item: (value: string) => MenuItemParts
|
|
128
|
+
item: (value: string) => MenuItemParts;
|
|
129
129
|
}
|
|
130
130
|
export interface ConnectOptions {
|
|
131
131
|
id: string;
|
|
132
132
|
/** Called when an item is activated (Enter/Space/click). */
|
|
133
133
|
onSelect?: (value: string) => void;
|
|
134
134
|
}
|
|
135
|
-
export declare function connect
|
|
136
|
-
export interface OverlayOptions
|
|
137
|
-
|
|
135
|
+
export declare function connect(state: Signal<MenuState>, send: Send<MenuMsg>, opts: ConnectOptions): MenuParts;
|
|
136
|
+
export interface OverlayOptions {
|
|
137
|
+
state: Signal<MenuState>;
|
|
138
138
|
send: Send<MenuMsg>;
|
|
139
|
-
parts: MenuParts
|
|
139
|
+
parts: MenuParts;
|
|
140
140
|
content: () => Node[];
|
|
141
141
|
placement?: Placement;
|
|
142
142
|
offset?: number;
|
|
@@ -145,7 +145,7 @@ export interface OverlayOptions<S> {
|
|
|
145
145
|
transition?: TransitionOptions;
|
|
146
146
|
target?: string | HTMLElement;
|
|
147
147
|
}
|
|
148
|
-
export declare function overlay
|
|
148
|
+
export declare function overlay(opts: OverlayOptions): Node;
|
|
149
149
|
export declare const menu: {
|
|
150
150
|
init: typeof init;
|
|
151
151
|
update: typeof update;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/components/menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/components/menu.ts"],"names":[],"mappings":"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"}
|
package/dist/components/menu.js
CHANGED
|
@@ -109,7 +109,7 @@ export function update(state, msg) {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
-
export function connect(
|
|
112
|
+
export function connect(state, send, opts) {
|
|
113
113
|
const base = opts.id;
|
|
114
114
|
const triggerId = `${base}:trigger`;
|
|
115
115
|
const contentId = `${base}:content`;
|
|
@@ -165,10 +165,10 @@ export function connect(get, send, opts) {
|
|
|
165
165
|
trigger: {
|
|
166
166
|
type: 'button',
|
|
167
167
|
'aria-haspopup': 'menu',
|
|
168
|
-
'aria-expanded': (s) =>
|
|
168
|
+
'aria-expanded': state.map((s) => s.open),
|
|
169
169
|
'aria-controls': contentId,
|
|
170
170
|
id: triggerId,
|
|
171
|
-
'data-state': (s) => (
|
|
171
|
+
'data-state': state.map((s) => (s.open ? 'open' : 'closed')),
|
|
172
172
|
'data-scope': 'menu',
|
|
173
173
|
'data-part': 'trigger',
|
|
174
174
|
onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),
|
|
@@ -194,7 +194,7 @@ export function connect(get, send, opts) {
|
|
|
194
194
|
id: contentId,
|
|
195
195
|
'aria-labelledby': triggerId,
|
|
196
196
|
tabIndex: -1,
|
|
197
|
-
'data-state': (s) => (
|
|
197
|
+
'data-state': state.map((s) => (s.open ? 'open' : 'closed')),
|
|
198
198
|
'data-scope': 'menu',
|
|
199
199
|
'data-part': 'content',
|
|
200
200
|
onKeyDown: handleMenuKey,
|
|
@@ -203,9 +203,9 @@ export function connect(get, send, opts) {
|
|
|
203
203
|
item: {
|
|
204
204
|
role: 'menuitem',
|
|
205
205
|
id: itemId(value),
|
|
206
|
-
'aria-disabled': (s) => (
|
|
207
|
-
'data-state': (s) => (
|
|
208
|
-
'data-disabled': (s) => (
|
|
206
|
+
'aria-disabled': state.map((s) => (s.disabledItems.includes(value) ? 'true' : undefined)),
|
|
207
|
+
'data-state': state.map((s) => (s.highlighted === value ? 'highlighted' : undefined)),
|
|
208
|
+
'data-disabled': state.map((s) => (s.disabledItems.includes(value) ? '' : undefined)),
|
|
209
209
|
'data-scope': 'menu',
|
|
210
210
|
'data-part': 'item',
|
|
211
211
|
'data-value': value,
|
|
@@ -220,7 +220,7 @@ export function connect(get, send, opts) {
|
|
|
220
220
|
};
|
|
221
221
|
}
|
|
222
222
|
export function overlay(opts) {
|
|
223
|
-
const
|
|
223
|
+
const rawTarget = opts.target ?? 'body';
|
|
224
224
|
const placement = opts.placement ?? 'bottom-start';
|
|
225
225
|
const offset = opts.offset ?? 4;
|
|
226
226
|
const flip = opts.flip !== false;
|
|
@@ -228,11 +228,12 @@ export function overlay(opts) {
|
|
|
228
228
|
const parts = opts.parts;
|
|
229
229
|
const contentId = parts.content.id;
|
|
230
230
|
const triggerId = parts.trigger.id;
|
|
231
|
-
return show({
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
return show(opts.state.map((s) => s.open), () => {
|
|
232
|
+
const targetEl = typeof rawTarget === 'string'
|
|
233
|
+
? (document.querySelector(rawTarget) ?? document.body)
|
|
234
|
+
: rawTarget;
|
|
235
|
+
return [
|
|
236
|
+
portal(() => {
|
|
236
237
|
onMount(() => {
|
|
237
238
|
const contentEl = document.getElementById(contentId);
|
|
238
239
|
const triggerEl = document.getElementById(triggerId);
|
|
@@ -267,10 +268,8 @@ export function overlay(opts) {
|
|
|
267
268
|
};
|
|
268
269
|
});
|
|
269
270
|
return [div(parts.positioner, opts.content())];
|
|
270
|
-
},
|
|
271
|
-
|
|
272
|
-
enter: opts.transition?.enter,
|
|
273
|
-
leave: opts.transition?.leave,
|
|
271
|
+
}, targetEl),
|
|
272
|
+
];
|
|
274
273
|
});
|
|
275
274
|
}
|
|
276
275
|
export const menu = { init, update, connect, overlay };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/components/menu.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, TransitionOptions } from '@llui/dom'\nimport { show, portal, onMount, div, tagSend } from '@llui/dom'\nimport { pushDismissable } from '../utils/dismissable.js'\nimport { attachFloating, type Placement } from '../utils/floating.js'\nimport {\n typeaheadAccumulate,\n typeaheadMatchByItems,\n isTypeaheadKey,\n TYPEAHEAD_TIMEOUT_MS,\n} from '../utils/typeahead.js'\n\n/**\n * Menu — a dropdown list of items triggered by a button. Keyboard navigation\n * (arrows, Home, End), typeahead (first-letter matching), Enter/Space to\n * activate the focused item, Escape to close.\n *\n * Items are opaque string values (keys); the user's view renders the\n * label/icon/etc. The machine tracks which item is currently \"highlighted\"\n * (= the one that will activate on Enter). On open, the first item is\n * highlighted by default unless `defaultHighlighted` is provided.\n */\n\nexport interface MenuState {\n open: boolean\n items: string[]\n disabledItems: string[]\n highlighted: string | null\n /** Accumulator for typeahead search. */\n typeahead: string\n typeaheadExpiresAt: number\n}\n\nexport type MenuMsg =\n /** @intent(\"Open the menu\") */\n | { type: 'open' }\n /** @intent(\"Close the menu\") */\n | { type: 'close' }\n /** @intent(\"Toggle the menu open/closed\") */\n | { type: 'toggle' }\n /** @humanOnly */\n | { type: 'highlight'; value: string | null }\n /** @humanOnly */\n | { type: 'highlightNext' }\n /** @humanOnly */\n | { type: 'highlightPrev' }\n /** @humanOnly */\n | { type: 'highlightFirst' }\n /** @humanOnly */\n | { type: 'highlightLast' }\n /** @intent(\"Activate the currently-highlighted menu item\") */\n | { type: 'selectHighlighted' }\n /** @intent(\"Activate the menu item with the given value\") */\n | { type: 'select'; value: string }\n /** @humanOnly */\n | { type: 'setItems'; items: string[]; disabled?: string[] }\n /** @humanOnly */\n | { type: 'typeahead'; char: string; now: number }\n\nexport interface MenuInit {\n open?: boolean\n items?: string[]\n disabledItems?: string[]\n highlighted?: string | null\n}\n\nexport function init(opts: MenuInit = {}): MenuState {\n return {\n open: opts.open ?? false,\n items: opts.items ?? [],\n disabledItems: opts.disabledItems ?? [],\n highlighted: opts.highlighted ?? null,\n typeahead: '',\n typeaheadExpiresAt: 0,\n }\n}\n\nfunction firstEnabled(items: string[], disabled: string[]): string | null {\n for (const v of items) if (!disabled.includes(v)) return v\n return null\n}\n\nfunction lastEnabled(items: string[], disabled: string[]): string | null {\n for (let i = items.length - 1; i >= 0; i--) {\n const v = items[i]!\n if (!disabled.includes(v)) return v\n }\n return null\n}\n\nfunction nextEnabled(\n items: string[],\n disabled: string[],\n from: string | null,\n delta: 1 | -1,\n): string | null {\n if (items.length === 0) return null\n const start = from === null ? -1 : items.indexOf(from)\n const n = items.length\n for (let i = 1; i <= n; i++) {\n const idx = start === -1 && delta === 1 ? i - 1 : (start + delta * i + n * n) % n\n const v = items[idx]!\n if (!disabled.includes(v)) return v\n }\n return null\n}\n\nexport function update(state: MenuState, msg: MenuMsg): [MenuState, never[]] {\n switch (msg.type) {\n case 'open': {\n const highlighted = state.highlighted ?? firstEnabled(state.items, state.disabledItems)\n return [{ ...state, open: true, highlighted }, []]\n }\n case 'close':\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'toggle':\n if (state.open) {\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n }\n return [\n {\n ...state,\n open: true,\n highlighted: state.highlighted ?? firstEnabled(state.items, state.disabledItems),\n },\n [],\n ]\n case 'highlight':\n if (msg.value !== null && state.disabledItems.includes(msg.value)) return [state, []]\n return [{ ...state, highlighted: msg.value }, []]\n case 'highlightNext': {\n const to = nextEnabled(state.items, state.disabledItems, state.highlighted, 1)\n return [{ ...state, highlighted: to }, []]\n }\n case 'highlightPrev': {\n const to = nextEnabled(state.items, state.disabledItems, state.highlighted, -1)\n return [{ ...state, highlighted: to }, []]\n }\n case 'highlightFirst':\n return [{ ...state, highlighted: firstEnabled(state.items, state.disabledItems) }, []]\n case 'highlightLast':\n return [{ ...state, highlighted: lastEnabled(state.items, state.disabledItems) }, []]\n case 'selectHighlighted':\n if (state.highlighted === null) return [state, []]\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'select':\n if (state.disabledItems.includes(msg.value)) return [state, []]\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'setItems': {\n const disabled = msg.disabled ?? state.disabledItems\n const highlighted =\n state.highlighted &&\n msg.items.includes(state.highlighted) &&\n !disabled.includes(state.highlighted)\n ? state.highlighted\n : null\n return [{ ...state, items: msg.items, disabledItems: disabled, highlighted }, []]\n }\n case 'typeahead': {\n const acc = typeaheadAccumulate(state.typeahead, msg.char, msg.now, state.typeaheadExpiresAt)\n const startIdx = state.highlighted ? state.items.indexOf(state.highlighted) : null\n const matchIdx = typeaheadMatchByItems(state.items, state.disabledItems, acc, startIdx)\n const match = matchIdx === null ? null : state.items[matchIdx]!\n return [\n {\n ...state,\n typeahead: acc,\n typeaheadExpiresAt: msg.now + TYPEAHEAD_TIMEOUT_MS,\n highlighted: match ?? state.highlighted,\n },\n [],\n ]\n }\n }\n}\n\nexport interface MenuItemParts<S> {\n item: {\n role: 'menuitem'\n id: string\n 'aria-disabled': (s: S) => 'true' | undefined\n 'data-state': (s: S) => 'highlighted' | undefined\n 'data-disabled': (s: S) => '' | undefined\n 'data-scope': 'menu'\n 'data-part': 'item'\n 'data-value': string\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n onPointerMove: (e: PointerEvent) => void\n }\n}\n\nexport interface MenuParts<S> {\n trigger: {\n type: 'button'\n 'aria-haspopup': 'menu'\n 'aria-expanded': (s: S) => boolean\n 'aria-controls': string\n id: string\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'menu'\n 'data-part': 'trigger'\n onClick: (e: MouseEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n positioner: {\n 'data-scope': 'menu'\n 'data-part': 'positioner'\n style: string\n }\n content: {\n role: 'menu'\n id: string\n 'aria-labelledby': string\n tabIndex: -1\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'menu'\n 'data-part': 'content'\n onKeyDown: (e: KeyboardEvent) => void\n }\n item: (value: string) => MenuItemParts<S>\n}\n\nexport interface ConnectOptions {\n id: string\n /** Called when an item is activated (Enter/Space/click). */\n onSelect?: (value: string) => void\n}\n\nexport function connect<S>(\n get: (s: S) => MenuState,\n send: Send<MenuMsg>,\n opts: ConnectOptions,\n): MenuParts<S> {\n const base = opts.id\n const triggerId = `${base}:trigger`\n const contentId = `${base}:content`\n const itemId = (v: string): string => `${base}:item:${v}`\n\n // Keyboard navigation dispatches a fixed vocabulary of MenuMsg\n // variants. `tagSend` propagates the user's translator tag (when\n // `send` is a tagged dispatch translator) onto this handler so the\n // agent's `list_actions` surfaces the user-side variants the\n // translator forwards. Without a translator, the library variants\n // listed here are what `update()` actually receives.\n const handleMenuKey = tagSend(\n send,\n [\n 'highlightNext',\n 'highlightPrev',\n 'highlightFirst',\n 'highlightLast',\n 'selectHighlighted',\n 'close',\n 'typeahead',\n ],\n (e: KeyboardEvent): void => {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n send({ type: 'highlightNext' })\n return\n case 'ArrowUp':\n e.preventDefault()\n send({ type: 'highlightPrev' })\n return\n case 'Home':\n e.preventDefault()\n send({ type: 'highlightFirst' })\n return\n case 'End':\n e.preventDefault()\n send({ type: 'highlightLast' })\n return\n case 'Enter':\n case ' ':\n e.preventDefault()\n send({ type: 'selectHighlighted' })\n return\n case 'Escape':\n e.preventDefault()\n send({ type: 'close' })\n return\n default:\n if (isTypeaheadKey(e)) {\n send({ type: 'typeahead', char: e.key, now: Date.now() })\n }\n }\n },\n )\n\n return {\n trigger: {\n type: 'button',\n 'aria-haspopup': 'menu',\n 'aria-expanded': (s) => get(s).open,\n 'aria-controls': contentId,\n id: triggerId,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'menu',\n 'data-part': 'trigger',\n onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),\n onKeyDown: tagSend(send, ['open', 'highlightLast'], (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n send({ type: 'open' })\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n send({ type: 'open' })\n send({ type: 'highlightLast' })\n }\n }),\n },\n positioner: {\n 'data-scope': 'menu',\n 'data-part': 'positioner',\n style: 'position:absolute;top:0;left:0;',\n },\n content: {\n role: 'menu',\n id: contentId,\n 'aria-labelledby': triggerId,\n tabIndex: -1,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'menu',\n 'data-part': 'content',\n onKeyDown: handleMenuKey,\n },\n item: (value: string): MenuItemParts<S> => ({\n item: {\n role: 'menuitem',\n id: itemId(value),\n 'aria-disabled': (s) => (get(s).disabledItems.includes(value) ? 'true' : undefined),\n 'data-state': (s) => (get(s).highlighted === value ? 'highlighted' : undefined),\n 'data-disabled': (s) => (get(s).disabledItems.includes(value) ? '' : undefined),\n 'data-scope': 'menu',\n 'data-part': 'item',\n 'data-value': value,\n tabIndex: -1,\n onClick: tagSend(send, ['select'], () => {\n send({ type: 'select', value })\n opts.onSelect?.(value)\n }),\n onPointerMove: tagSend(send, ['highlight'], () => send({ type: 'highlight', value })),\n },\n }),\n }\n}\n\nexport interface OverlayOptions<S> {\n get: (s: S) => MenuState\n send: Send<MenuMsg>\n parts: MenuParts<S>\n content: () => Node[]\n placement?: Placement\n offset?: number\n flip?: boolean\n shift?: boolean\n transition?: TransitionOptions\n target?: string | HTMLElement\n}\n\nexport function overlay<S>(opts: OverlayOptions<S>): Node[] {\n const target = opts.target ?? 'body'\n const placement = opts.placement ?? 'bottom-start'\n const offset = opts.offset ?? 4\n const flip = opts.flip !== false\n const shift = opts.shift !== false\n const parts = opts.parts\n const contentId = parts.content.id\n const triggerId = parts.trigger.id\n\n return show<S, MenuMsg>({\n when: (s) => opts.get(s).open,\n render: () =>\n portal({\n target,\n render: () => {\n onMount(() => {\n const contentEl = document.getElementById(contentId)\n const triggerEl = document.getElementById(triggerId)\n if (!contentEl || !triggerEl) return\n\n const cleanups: Array<() => void> = []\n\n const positioner = contentEl.closest('[data-part=\"positioner\"]') as HTMLElement | null\n const floatingEl = positioner ?? contentEl\n cleanups.push(\n attachFloating({\n anchor: triggerEl,\n floating: floatingEl,\n placement,\n offset,\n flip,\n shift,\n }),\n )\n\n cleanups.push(\n pushDismissable({\n element: contentEl,\n ignore: () => [triggerEl],\n onDismiss: () => {\n opts.send({ type: 'close' })\n triggerEl.focus()\n },\n }),\n )\n\n // Auto-focus content so keyboard navigation works immediately.\n // preventScroll avoids a page jump when the portaled content\n // is briefly at position (0,0) before floating-ui positions it.\n contentEl.focus({ preventScroll: true })\n\n return () => {\n for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i]!()\n }\n })\n return [div(parts.positioner, opts.content())]\n },\n }),\n enter: opts.transition?.enter,\n leave: opts.transition?.leave,\n })\n}\n\nexport const menu = { init, update, connect, overlay }\n"]}
|
|
1
|
+
{"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/components/menu.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, Signal, TransitionOptions } from '@llui/dom'\nimport { show, portal, onMount, div, tagSend } from '@llui/dom'\nimport { pushDismissable } from '../utils/dismissable.js'\nimport { attachFloating, type Placement } from '../utils/floating.js'\nimport {\n typeaheadAccumulate,\n typeaheadMatchByItems,\n isTypeaheadKey,\n TYPEAHEAD_TIMEOUT_MS,\n} from '../utils/typeahead.js'\n\n/**\n * Menu — a dropdown list of items triggered by a button. Keyboard navigation\n * (arrows, Home, End), typeahead (first-letter matching), Enter/Space to\n * activate the focused item, Escape to close.\n *\n * Items are opaque string values (keys); the user's view renders the\n * label/icon/etc. The machine tracks which item is currently \"highlighted\"\n * (= the one that will activate on Enter). On open, the first item is\n * highlighted by default unless `defaultHighlighted` is provided.\n */\n\nexport interface MenuState {\n open: boolean\n items: string[]\n disabledItems: string[]\n highlighted: string | null\n /** Accumulator for typeahead search. */\n typeahead: string\n typeaheadExpiresAt: number\n}\n\nexport type MenuMsg =\n /** @intent(\"Open the menu\") */\n | { type: 'open' }\n /** @intent(\"Close the menu\") */\n | { type: 'close' }\n /** @intent(\"Toggle the menu open/closed\") */\n | { type: 'toggle' }\n /** @humanOnly */\n | { type: 'highlight'; value: string | null }\n /** @humanOnly */\n | { type: 'highlightNext' }\n /** @humanOnly */\n | { type: 'highlightPrev' }\n /** @humanOnly */\n | { type: 'highlightFirst' }\n /** @humanOnly */\n | { type: 'highlightLast' }\n /** @intent(\"Activate the currently-highlighted menu item\") */\n | { type: 'selectHighlighted' }\n /** @intent(\"Activate the menu item with the given value\") */\n | { type: 'select'; value: string }\n /** @humanOnly */\n | { type: 'setItems'; items: string[]; disabled?: string[] }\n /** @humanOnly */\n | { type: 'typeahead'; char: string; now: number }\n\nexport interface MenuInit {\n open?: boolean\n items?: string[]\n disabledItems?: string[]\n highlighted?: string | null\n}\n\nexport function init(opts: MenuInit = {}): MenuState {\n return {\n open: opts.open ?? false,\n items: opts.items ?? [],\n disabledItems: opts.disabledItems ?? [],\n highlighted: opts.highlighted ?? null,\n typeahead: '',\n typeaheadExpiresAt: 0,\n }\n}\n\nfunction firstEnabled(items: string[], disabled: string[]): string | null {\n for (const v of items) if (!disabled.includes(v)) return v\n return null\n}\n\nfunction lastEnabled(items: string[], disabled: string[]): string | null {\n for (let i = items.length - 1; i >= 0; i--) {\n const v = items[i]!\n if (!disabled.includes(v)) return v\n }\n return null\n}\n\nfunction nextEnabled(\n items: string[],\n disabled: string[],\n from: string | null,\n delta: 1 | -1,\n): string | null {\n if (items.length === 0) return null\n const start = from === null ? -1 : items.indexOf(from)\n const n = items.length\n for (let i = 1; i <= n; i++) {\n const idx = start === -1 && delta === 1 ? i - 1 : (start + delta * i + n * n) % n\n const v = items[idx]!\n if (!disabled.includes(v)) return v\n }\n return null\n}\n\nexport function update(state: MenuState, msg: MenuMsg): [MenuState, never[]] {\n switch (msg.type) {\n case 'open': {\n const highlighted = state.highlighted ?? firstEnabled(state.items, state.disabledItems)\n return [{ ...state, open: true, highlighted }, []]\n }\n case 'close':\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'toggle':\n if (state.open) {\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n }\n return [\n {\n ...state,\n open: true,\n highlighted: state.highlighted ?? firstEnabled(state.items, state.disabledItems),\n },\n [],\n ]\n case 'highlight':\n if (msg.value !== null && state.disabledItems.includes(msg.value)) return [state, []]\n return [{ ...state, highlighted: msg.value }, []]\n case 'highlightNext': {\n const to = nextEnabled(state.items, state.disabledItems, state.highlighted, 1)\n return [{ ...state, highlighted: to }, []]\n }\n case 'highlightPrev': {\n const to = nextEnabled(state.items, state.disabledItems, state.highlighted, -1)\n return [{ ...state, highlighted: to }, []]\n }\n case 'highlightFirst':\n return [{ ...state, highlighted: firstEnabled(state.items, state.disabledItems) }, []]\n case 'highlightLast':\n return [{ ...state, highlighted: lastEnabled(state.items, state.disabledItems) }, []]\n case 'selectHighlighted':\n if (state.highlighted === null) return [state, []]\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'select':\n if (state.disabledItems.includes(msg.value)) return [state, []]\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'setItems': {\n const disabled = msg.disabled ?? state.disabledItems\n const highlighted =\n state.highlighted &&\n msg.items.includes(state.highlighted) &&\n !disabled.includes(state.highlighted)\n ? state.highlighted\n : null\n return [{ ...state, items: msg.items, disabledItems: disabled, highlighted }, []]\n }\n case 'typeahead': {\n const acc = typeaheadAccumulate(state.typeahead, msg.char, msg.now, state.typeaheadExpiresAt)\n const startIdx = state.highlighted ? state.items.indexOf(state.highlighted) : null\n const matchIdx = typeaheadMatchByItems(state.items, state.disabledItems, acc, startIdx)\n const match = matchIdx === null ? null : state.items[matchIdx]!\n return [\n {\n ...state,\n typeahead: acc,\n typeaheadExpiresAt: msg.now + TYPEAHEAD_TIMEOUT_MS,\n highlighted: match ?? state.highlighted,\n },\n [],\n ]\n }\n }\n}\n\nexport interface MenuItemParts {\n item: {\n role: 'menuitem'\n id: string\n 'aria-disabled': Signal<'true' | undefined>\n 'data-state': Signal<'highlighted' | undefined>\n 'data-disabled': Signal<'' | undefined>\n 'data-scope': 'menu'\n 'data-part': 'item'\n 'data-value': string\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n onPointerMove: (e: PointerEvent) => void\n }\n}\n\nexport interface MenuParts {\n trigger: {\n type: 'button'\n 'aria-haspopup': 'menu'\n 'aria-expanded': Signal<boolean>\n 'aria-controls': string\n id: string\n 'data-state': Signal<'open' | 'closed'>\n 'data-scope': 'menu'\n 'data-part': 'trigger'\n onClick: (e: MouseEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n positioner: {\n 'data-scope': 'menu'\n 'data-part': 'positioner'\n style: string\n }\n content: {\n role: 'menu'\n id: string\n 'aria-labelledby': string\n tabIndex: -1\n 'data-state': Signal<'open' | 'closed'>\n 'data-scope': 'menu'\n 'data-part': 'content'\n onKeyDown: (e: KeyboardEvent) => void\n }\n item: (value: string) => MenuItemParts\n}\n\nexport interface ConnectOptions {\n id: string\n /** Called when an item is activated (Enter/Space/click). */\n onSelect?: (value: string) => void\n}\n\nexport function connect(\n state: Signal<MenuState>,\n send: Send<MenuMsg>,\n opts: ConnectOptions,\n): MenuParts {\n const base = opts.id\n const triggerId = `${base}:trigger`\n const contentId = `${base}:content`\n const itemId = (v: string): string => `${base}:item:${v}`\n\n // Keyboard navigation dispatches a fixed vocabulary of MenuMsg\n // variants. `tagSend` propagates the user's translator tag (when\n // `send` is a tagged dispatch translator) onto this handler so the\n // agent's `list_actions` surfaces the user-side variants the\n // translator forwards. Without a translator, the library variants\n // listed here are what `update()` actually receives.\n const handleMenuKey = tagSend(\n send,\n [\n 'highlightNext',\n 'highlightPrev',\n 'highlightFirst',\n 'highlightLast',\n 'selectHighlighted',\n 'close',\n 'typeahead',\n ],\n (e: KeyboardEvent): void => {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n send({ type: 'highlightNext' })\n return\n case 'ArrowUp':\n e.preventDefault()\n send({ type: 'highlightPrev' })\n return\n case 'Home':\n e.preventDefault()\n send({ type: 'highlightFirst' })\n return\n case 'End':\n e.preventDefault()\n send({ type: 'highlightLast' })\n return\n case 'Enter':\n case ' ':\n e.preventDefault()\n send({ type: 'selectHighlighted' })\n return\n case 'Escape':\n e.preventDefault()\n send({ type: 'close' })\n return\n default:\n if (isTypeaheadKey(e)) {\n send({ type: 'typeahead', char: e.key, now: Date.now() })\n }\n }\n },\n )\n\n return {\n trigger: {\n type: 'button',\n 'aria-haspopup': 'menu',\n 'aria-expanded': state.map((s) => s.open),\n 'aria-controls': contentId,\n id: triggerId,\n 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),\n 'data-scope': 'menu',\n 'data-part': 'trigger',\n onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),\n onKeyDown: tagSend(send, ['open', 'highlightLast'], (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n send({ type: 'open' })\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n send({ type: 'open' })\n send({ type: 'highlightLast' })\n }\n }),\n },\n positioner: {\n 'data-scope': 'menu',\n 'data-part': 'positioner',\n style: 'position:absolute;top:0;left:0;',\n },\n content: {\n role: 'menu',\n id: contentId,\n 'aria-labelledby': triggerId,\n tabIndex: -1,\n 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),\n 'data-scope': 'menu',\n 'data-part': 'content',\n onKeyDown: handleMenuKey,\n },\n item: (value: string): MenuItemParts => ({\n item: {\n role: 'menuitem',\n id: itemId(value),\n 'aria-disabled': state.map((s) => (s.disabledItems.includes(value) ? 'true' : undefined)),\n 'data-state': state.map((s) => (s.highlighted === value ? 'highlighted' : undefined)),\n 'data-disabled': state.map((s) => (s.disabledItems.includes(value) ? '' : undefined)),\n 'data-scope': 'menu',\n 'data-part': 'item',\n 'data-value': value,\n tabIndex: -1,\n onClick: tagSend(send, ['select'], () => {\n send({ type: 'select', value })\n opts.onSelect?.(value)\n }),\n onPointerMove: tagSend(send, ['highlight'], () => send({ type: 'highlight', value })),\n },\n }),\n }\n}\n\nexport interface OverlayOptions {\n state: Signal<MenuState>\n send: Send<MenuMsg>\n parts: MenuParts\n content: () => Node[]\n placement?: Placement\n offset?: number\n flip?: boolean\n shift?: boolean\n transition?: TransitionOptions\n target?: string | HTMLElement\n}\n\nexport function overlay(opts: OverlayOptions): Node {\n const rawTarget = opts.target ?? 'body'\n const placement = opts.placement ?? 'bottom-start'\n const offset = opts.offset ?? 4\n const flip = opts.flip !== false\n const shift = opts.shift !== false\n const parts = opts.parts\n const contentId = parts.content.id\n const triggerId = parts.trigger.id\n\n return show(\n opts.state.map((s) => s.open),\n () => {\n const targetEl =\n typeof rawTarget === 'string'\n ? (document.querySelector(rawTarget) ?? document.body)\n : rawTarget\n return [\n portal(() => {\n onMount(() => {\n const contentEl = document.getElementById(contentId)\n const triggerEl = document.getElementById(triggerId)\n if (!contentEl || !triggerEl) return\n\n const cleanups: Array<() => void> = []\n\n const positioner = contentEl.closest('[data-part=\"positioner\"]') as HTMLElement | null\n const floatingEl = positioner ?? contentEl\n cleanups.push(\n attachFloating({\n anchor: triggerEl,\n floating: floatingEl,\n placement,\n offset,\n flip,\n shift,\n }),\n )\n\n cleanups.push(\n pushDismissable({\n element: contentEl,\n ignore: () => [triggerEl],\n onDismiss: () => {\n opts.send({ type: 'close' })\n triggerEl.focus()\n },\n }),\n )\n\n // Auto-focus content so keyboard navigation works immediately.\n // preventScroll avoids a page jump when the portaled content\n // is briefly at position (0,0) before floating-ui positions it.\n contentEl.focus({ preventScroll: true })\n\n return () => {\n for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i]!()\n }\n })\n return [div(parts.positioner, opts.content())]\n }, targetEl),\n ]\n },\n )\n}\n\nexport const menu = { init, update, connect, overlay }\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Send } from '@llui/dom';
|
|
1
|
+
import type { Send, Signal } from '@llui/dom';
|
|
2
2
|
/**
|
|
3
3
|
* Navigation menu — multi-level menu bar with hover/focus-triggered
|
|
4
4
|
* submenus. Unlike `menu` (a single dropdown), navigation-menu supports
|
|
@@ -61,18 +61,18 @@ export interface NavMenuInit {
|
|
|
61
61
|
export declare function init(opts?: NavMenuInit): NavMenuState;
|
|
62
62
|
export declare function update(state: NavMenuState, msg: NavMenuMsg): [NavMenuState, never[]];
|
|
63
63
|
export declare function isOpen(state: NavMenuState, id: string): boolean;
|
|
64
|
-
export interface NavItemParts
|
|
64
|
+
export interface NavItemParts {
|
|
65
65
|
trigger: {
|
|
66
66
|
type: 'button';
|
|
67
67
|
role: 'menuitem';
|
|
68
68
|
id: string;
|
|
69
69
|
'aria-haspopup': 'menu' | undefined;
|
|
70
|
-
'aria-expanded':
|
|
70
|
+
'aria-expanded': Signal<boolean | undefined>;
|
|
71
71
|
'data-scope': 'navigation-menu';
|
|
72
72
|
'data-part': 'trigger';
|
|
73
|
-
'data-state':
|
|
73
|
+
'data-state': Signal<'open' | 'closed'>;
|
|
74
74
|
'data-value': string;
|
|
75
|
-
tabIndex:
|
|
75
|
+
tabIndex: Signal<number>;
|
|
76
76
|
onClick: (e: MouseEvent) => void;
|
|
77
77
|
onPointerEnter: (e: PointerEvent) => void;
|
|
78
78
|
onFocus: (e: FocusEvent) => void;
|
|
@@ -83,25 +83,25 @@ export interface NavItemParts<S> {
|
|
|
83
83
|
'aria-labelledby': string;
|
|
84
84
|
'data-scope': 'navigation-menu';
|
|
85
85
|
'data-part': 'content';
|
|
86
|
-
'data-state':
|
|
87
|
-
hidden:
|
|
86
|
+
'data-state': Signal<'open' | 'closed'>;
|
|
87
|
+
hidden: Signal<boolean>;
|
|
88
88
|
onPointerEnter: (e: PointerEvent) => void;
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
|
-
export interface NavMenuParts
|
|
91
|
+
export interface NavMenuParts {
|
|
92
92
|
root: {
|
|
93
93
|
role: 'menubar';
|
|
94
|
-
'aria-label': string
|
|
94
|
+
'aria-label': string;
|
|
95
95
|
'data-scope': 'navigation-menu';
|
|
96
96
|
'data-part': 'root';
|
|
97
|
-
'data-disabled':
|
|
97
|
+
'data-disabled': Signal<'' | undefined>;
|
|
98
98
|
onPointerLeave: (e: PointerEvent) => void;
|
|
99
99
|
onPointerEnter: (e: PointerEvent) => void;
|
|
100
100
|
};
|
|
101
101
|
item: (id: string, options: {
|
|
102
102
|
isBranch: boolean;
|
|
103
103
|
ancestorIds?: string[];
|
|
104
|
-
}) => NavItemParts
|
|
104
|
+
}) => NavItemParts;
|
|
105
105
|
}
|
|
106
106
|
export interface ConnectOptions {
|
|
107
107
|
id: string;
|
|
@@ -113,7 +113,7 @@ export interface ConnectOptions {
|
|
|
113
113
|
*/
|
|
114
114
|
closeOnLeave?: boolean;
|
|
115
115
|
}
|
|
116
|
-
export declare function connect
|
|
116
|
+
export declare function connect(state: Signal<NavMenuState>, send: Send<NavMenuMsg>, opts: ConnectOptions): NavMenuParts;
|
|
117
117
|
export declare const navigationMenu: {
|
|
118
118
|
init: typeof init;
|
|
119
119
|
update: typeof update;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation-menu.d.ts","sourceRoot":"","sources":["../../src/components/navigation-menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"navigation-menu.d.ts","sourceRoot":"","sources":["../../src/components/navigation-menu.ts"],"names":[],"mappings":"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"}
|
|
@@ -46,7 +46,7 @@ export function update(state, msg) {
|
|
|
46
46
|
export function isOpen(state, id) {
|
|
47
47
|
return state.open.includes(id);
|
|
48
48
|
}
|
|
49
|
-
export function connect(
|
|
49
|
+
export function connect(state, send, opts) {
|
|
50
50
|
const locale = useContext(LocaleContext);
|
|
51
51
|
const triggerId = (v) => `${opts.id}:trigger:${v}`;
|
|
52
52
|
const contentId = (v) => `${opts.id}:content:${v}`;
|
|
@@ -71,10 +71,10 @@ export function connect(get, send, opts) {
|
|
|
71
71
|
return {
|
|
72
72
|
root: {
|
|
73
73
|
role: 'menubar',
|
|
74
|
-
'aria-label': opts.label ??
|
|
74
|
+
'aria-label': opts.label ?? locale.navigationMenu.label,
|
|
75
75
|
'data-scope': 'navigation-menu',
|
|
76
76
|
'data-part': 'root',
|
|
77
|
-
'data-disabled': (
|
|
77
|
+
'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),
|
|
78
78
|
onPointerLeave: () => scheduleClose(),
|
|
79
79
|
onPointerEnter: () => cancelClose(),
|
|
80
80
|
},
|
|
@@ -86,12 +86,12 @@ export function connect(get, send, opts) {
|
|
|
86
86
|
role: 'menuitem',
|
|
87
87
|
id: triggerId(id),
|
|
88
88
|
'aria-haspopup': options.isBranch ? 'menu' : undefined,
|
|
89
|
-
'aria-expanded': (
|
|
89
|
+
'aria-expanded': state.map((st) => (options.isBranch ? isOpen(st, id) : undefined)),
|
|
90
90
|
'data-scope': 'navigation-menu',
|
|
91
91
|
'data-part': 'trigger',
|
|
92
|
-
'data-state': (
|
|
92
|
+
'data-state': state.map((st) => (isOpen(st, id) ? 'open' : 'closed')),
|
|
93
93
|
'data-value': id,
|
|
94
|
-
tabIndex: (
|
|
94
|
+
tabIndex: state.map((st) => (st.focused === id ? 0 : -1)),
|
|
95
95
|
onClick: tagSend(send, ['toggleBranch'], () => {
|
|
96
96
|
if (options.isBranch) {
|
|
97
97
|
send({ type: 'toggleBranch', id, ancestorIds });
|
|
@@ -111,8 +111,8 @@ export function connect(get, send, opts) {
|
|
|
111
111
|
'aria-labelledby': triggerId(id),
|
|
112
112
|
'data-scope': 'navigation-menu',
|
|
113
113
|
'data-part': 'content',
|
|
114
|
-
'data-state': (
|
|
115
|
-
hidden: (
|
|
114
|
+
'data-state': state.map((st) => (isOpen(st, id) ? 'open' : 'closed')),
|
|
115
|
+
hidden: state.map((st) => !isOpen(st, id)),
|
|
116
116
|
onPointerEnter: tagSend(send, ['openBranch'], () => {
|
|
117
117
|
cancelClose();
|
|
118
118
|
if (options.isBranch) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation-menu.js","sourceRoot":"","sources":["../../src/components/navigation-menu.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Navigation menu — multi-level menu bar with hover/focus-triggered\n * submenus. Unlike `menu` (a single dropdown), navigation-menu supports\n * nested submenus arbitrarily deep and is typically used for primary\n * site navigation.\n *\n * State tracks the currently focused item id and the ids of all\n * currently-open branches. The consumer provides the tree structure\n * (items with optional children); the machine doesn't index the\n * hierarchy itself — it just maintains open-paths and lets the view\n * handle traversal.\n *\n * Typical interaction model (delay-based):\n * - Pointer enter on a branch → openBranch after openDelay\n * - Pointer leave of the whole tree → closeAll after closeDelay\n * - Click/keyboard activation → toggleBranch immediately\n *\n * The consumer is responsible for debouncing via setTimeout; the machine\n * just responds to the dispatched messages.\n */\n\nexport interface NavMenuState {\n /** Ids of open branches, in open order (root-first). Closing an\n * ancestor automatically closes its descendants. */\n open: string[]\n focused: string | null\n disabled: boolean\n}\n\nexport type NavMenuMsg =\n /** @intent(\"Open the submenu identified by id, closing any open siblings\") */\n | { type: 'openBranch'; id: string; ancestorIds: string[] }\n /** @intent(\"Close the submenu identified by id (also closes its descendants)\") */\n | { type: 'closeBranch'; id: string }\n /** @intent(\"Toggle the submenu identified by id open/closed\") */\n | { type: 'toggleBranch'; id: string; ancestorIds: string[] }\n /** @intent(\"Close every open submenu\") */\n | { type: 'closeAll' }\n /** @humanOnly */\n | { type: 'focus'; id: string | null }\n\nexport interface NavMenuInit {\n open?: string[]\n focused?: string | null\n disabled?: boolean\n}\n\nexport function init(opts: NavMenuInit = {}): NavMenuState {\n return {\n open: opts.open ?? [],\n focused: opts.focused ?? null,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function update(state: NavMenuState, msg: NavMenuMsg): [NavMenuState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'openBranch': {\n // Close any siblings of `id` at the same ancestor path, then add it.\n // Sibling detection: an entry is a sibling if its ancestor set matches\n // msg.ancestorIds and it isn't msg.id. We don't track ancestors in\n // state, so: filter `open` to keep only entries that are themselves\n // an ancestor of msg.id, plus msg.id.\n const keep = new Set([...msg.ancestorIds, msg.id])\n const open = state.open.filter((o) => keep.has(o))\n if (!open.includes(msg.id)) open.push(msg.id)\n return [{ ...state, open }, []]\n }\n case 'closeBranch': {\n // Close this branch and any descendants that follow it in the open\n // list. Since open is ordered root-first, descendants come after.\n const idx = state.open.indexOf(msg.id)\n if (idx === -1) return [state, []]\n const open = state.open.slice(0, idx)\n return [{ ...state, open }, []]\n }\n case 'toggleBranch':\n if (state.open.includes(msg.id)) {\n return update(state, { type: 'closeBranch', id: msg.id })\n }\n return update(state, { type: 'openBranch', id: msg.id, ancestorIds: msg.ancestorIds })\n case 'closeAll':\n return [{ ...state, open: [] }, []]\n case 'focus':\n return [{ ...state, focused: msg.id }, []]\n }\n}\n\nexport function isOpen(state: NavMenuState, id: string): boolean {\n return state.open.includes(id)\n}\n\nexport interface NavItemParts<S> {\n trigger: {\n type: 'button'\n role: 'menuitem'\n id: string\n 'aria-haspopup': 'menu' | undefined\n 'aria-expanded': (s: S) => boolean | undefined\n 'data-scope': 'navigation-menu'\n 'data-part': 'trigger'\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-value': string\n tabIndex: (s: S) => number\n onClick: (e: MouseEvent) => void\n onPointerEnter: (e: PointerEvent) => void\n onFocus: (e: FocusEvent) => void\n }\n content: {\n role: 'menu'\n id: string\n 'aria-labelledby': string\n 'data-scope': 'navigation-menu'\n 'data-part': 'content'\n 'data-state': (s: S) => 'open' | 'closed'\n hidden: (s: S) => boolean\n onPointerEnter: (e: PointerEvent) => void\n }\n}\n\nexport interface NavMenuParts<S> {\n root: {\n role: 'menubar'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'navigation-menu'\n 'data-part': 'root'\n 'data-disabled': (s: S) => '' | undefined\n onPointerLeave: (e: PointerEvent) => void\n onPointerEnter: (e: PointerEvent) => void\n }\n item: (id: string, options: { isBranch: boolean; ancestorIds?: string[] }) => NavItemParts<S>\n}\n\nexport interface ConnectOptions {\n id: string\n label?: string\n /**\n * Whether pointer-leaving the whole menu closes everything. Default: true.\n * The consumer can inject their own close delay by intercepting\n * onPointerLeave + calling setTimeout + dispatching closeAll.\n */\n closeOnLeave?: boolean\n}\n\nexport function connect<S>(\n get: (s: S) => NavMenuState,\n send: Send<NavMenuMsg>,\n opts: ConnectOptions,\n): NavMenuParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const triggerId = (v: string): string => `${opts.id}:trigger:${v}`\n const contentId = (v: string): string => `${opts.id}:content:${v}`\n const closeOnLeave = opts.closeOnLeave !== false\n let closeTimer: ReturnType<typeof setTimeout> | null = null\n\n const scheduleClose = (): void => {\n if (!closeOnLeave) return\n if (closeTimer) clearTimeout(closeTimer)\n closeTimer = setTimeout(() => {\n send({ type: 'closeAll' })\n closeTimer = null\n }, 150)\n }\n\n const cancelClose = (): void => {\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n }\n\n return {\n root: {\n role: 'menubar',\n 'aria-label': opts.label ?? ((s: S) => locale(s).navigationMenu.label),\n 'data-scope': 'navigation-menu',\n 'data-part': 'root',\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n onPointerLeave: () => scheduleClose(),\n onPointerEnter: () => cancelClose(),\n },\n item: (id: string, options: { isBranch: boolean; ancestorIds?: string[] }): NavItemParts<S> => {\n const ancestorIds = options.ancestorIds ?? []\n return {\n trigger: {\n type: 'button',\n role: 'menuitem',\n id: triggerId(id),\n 'aria-haspopup': options.isBranch ? 'menu' : undefined,\n 'aria-expanded': (s) => (options.isBranch ? isOpen(get(s), id) : undefined),\n 'data-scope': 'navigation-menu',\n 'data-part': 'trigger',\n 'data-state': (s) => (isOpen(get(s), id) ? 'open' : 'closed'),\n 'data-value': id,\n tabIndex: (s) => (get(s).focused === id ? 0 : -1),\n onClick: tagSend(send, ['toggleBranch'], () => {\n if (options.isBranch) {\n send({ type: 'toggleBranch', id, ancestorIds })\n }\n }),\n onPointerEnter: tagSend(send, ['openBranch'], () => {\n cancelClose()\n if (options.isBranch) {\n send({ type: 'openBranch', id, ancestorIds })\n }\n }),\n onFocus: tagSend(send, ['focus'], () => send({ type: 'focus', id })),\n },\n content: {\n role: 'menu',\n id: contentId(id),\n 'aria-labelledby': triggerId(id),\n 'data-scope': 'navigation-menu',\n 'data-part': 'content',\n 'data-state': (s) => (isOpen(get(s), id) ? 'open' : 'closed'),\n hidden: (s) => !isOpen(get(s), id),\n onPointerEnter: tagSend(send, ['openBranch'], () => {\n cancelClose()\n if (options.isBranch) {\n send({ type: 'openBranch', id, ancestorIds })\n }\n }),\n },\n }\n },\n }\n}\n\nexport const navigationMenu = { init, update, connect, isOpen }\n"]}
|
|
1
|
+
{"version":3,"file":"navigation-menu.js","sourceRoot":"","sources":["../../src/components/navigation-menu.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, Signal } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\n\n/**\n * Navigation menu — multi-level menu bar with hover/focus-triggered\n * submenus. Unlike `menu` (a single dropdown), navigation-menu supports\n * nested submenus arbitrarily deep and is typically used for primary\n * site navigation.\n *\n * State tracks the currently focused item id and the ids of all\n * currently-open branches. The consumer provides the tree structure\n * (items with optional children); the machine doesn't index the\n * hierarchy itself — it just maintains open-paths and lets the view\n * handle traversal.\n *\n * Typical interaction model (delay-based):\n * - Pointer enter on a branch → openBranch after openDelay\n * - Pointer leave of the whole tree → closeAll after closeDelay\n * - Click/keyboard activation → toggleBranch immediately\n *\n * The consumer is responsible for debouncing via setTimeout; the machine\n * just responds to the dispatched messages.\n */\n\nexport interface NavMenuState {\n /** Ids of open branches, in open order (root-first). Closing an\n * ancestor automatically closes its descendants. */\n open: string[]\n focused: string | null\n disabled: boolean\n}\n\nexport type NavMenuMsg =\n /** @intent(\"Open the submenu identified by id, closing any open siblings\") */\n | { type: 'openBranch'; id: string; ancestorIds: string[] }\n /** @intent(\"Close the submenu identified by id (also closes its descendants)\") */\n | { type: 'closeBranch'; id: string }\n /** @intent(\"Toggle the submenu identified by id open/closed\") */\n | { type: 'toggleBranch'; id: string; ancestorIds: string[] }\n /** @intent(\"Close every open submenu\") */\n | { type: 'closeAll' }\n /** @humanOnly */\n | { type: 'focus'; id: string | null }\n\nexport interface NavMenuInit {\n open?: string[]\n focused?: string | null\n disabled?: boolean\n}\n\nexport function init(opts: NavMenuInit = {}): NavMenuState {\n return {\n open: opts.open ?? [],\n focused: opts.focused ?? null,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function update(state: NavMenuState, msg: NavMenuMsg): [NavMenuState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'openBranch': {\n // Close any siblings of `id` at the same ancestor path, then add it.\n // Sibling detection: an entry is a sibling if its ancestor set matches\n // msg.ancestorIds and it isn't msg.id. We don't track ancestors in\n // state, so: filter `open` to keep only entries that are themselves\n // an ancestor of msg.id, plus msg.id.\n const keep = new Set([...msg.ancestorIds, msg.id])\n const open = state.open.filter((o) => keep.has(o))\n if (!open.includes(msg.id)) open.push(msg.id)\n return [{ ...state, open }, []]\n }\n case 'closeBranch': {\n // Close this branch and any descendants that follow it in the open\n // list. Since open is ordered root-first, descendants come after.\n const idx = state.open.indexOf(msg.id)\n if (idx === -1) return [state, []]\n const open = state.open.slice(0, idx)\n return [{ ...state, open }, []]\n }\n case 'toggleBranch':\n if (state.open.includes(msg.id)) {\n return update(state, { type: 'closeBranch', id: msg.id })\n }\n return update(state, { type: 'openBranch', id: msg.id, ancestorIds: msg.ancestorIds })\n case 'closeAll':\n return [{ ...state, open: [] }, []]\n case 'focus':\n return [{ ...state, focused: msg.id }, []]\n }\n}\n\nexport function isOpen(state: NavMenuState, id: string): boolean {\n return state.open.includes(id)\n}\n\nexport interface NavItemParts {\n trigger: {\n type: 'button'\n role: 'menuitem'\n id: string\n 'aria-haspopup': 'menu' | undefined\n 'aria-expanded': Signal<boolean | undefined>\n 'data-scope': 'navigation-menu'\n 'data-part': 'trigger'\n 'data-state': Signal<'open' | 'closed'>\n 'data-value': string\n tabIndex: Signal<number>\n onClick: (e: MouseEvent) => void\n onPointerEnter: (e: PointerEvent) => void\n onFocus: (e: FocusEvent) => void\n }\n content: {\n role: 'menu'\n id: string\n 'aria-labelledby': string\n 'data-scope': 'navigation-menu'\n 'data-part': 'content'\n 'data-state': Signal<'open' | 'closed'>\n hidden: Signal<boolean>\n onPointerEnter: (e: PointerEvent) => void\n }\n}\n\nexport interface NavMenuParts {\n root: {\n role: 'menubar'\n 'aria-label': string\n 'data-scope': 'navigation-menu'\n 'data-part': 'root'\n 'data-disabled': Signal<'' | undefined>\n onPointerLeave: (e: PointerEvent) => void\n onPointerEnter: (e: PointerEvent) => void\n }\n item: (id: string, options: { isBranch: boolean; ancestorIds?: string[] }) => NavItemParts\n}\n\nexport interface ConnectOptions {\n id: string\n label?: string\n /**\n * Whether pointer-leaving the whole menu closes everything. Default: true.\n * The consumer can inject their own close delay by intercepting\n * onPointerLeave + calling setTimeout + dispatching closeAll.\n */\n closeOnLeave?: boolean\n}\n\nexport function connect(\n state: Signal<NavMenuState>,\n send: Send<NavMenuMsg>,\n opts: ConnectOptions,\n): NavMenuParts {\n const locale = useContext(LocaleContext)\n const triggerId = (v: string): string => `${opts.id}:trigger:${v}`\n const contentId = (v: string): string => `${opts.id}:content:${v}`\n const closeOnLeave = opts.closeOnLeave !== false\n let closeTimer: ReturnType<typeof setTimeout> | null = null\n\n const scheduleClose = (): void => {\n if (!closeOnLeave) return\n if (closeTimer) clearTimeout(closeTimer)\n closeTimer = setTimeout(() => {\n send({ type: 'closeAll' })\n closeTimer = null\n }, 150)\n }\n\n const cancelClose = (): void => {\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n }\n\n return {\n root: {\n role: 'menubar',\n 'aria-label': opts.label ?? locale.navigationMenu.label,\n 'data-scope': 'navigation-menu',\n 'data-part': 'root',\n 'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),\n onPointerLeave: () => scheduleClose(),\n onPointerEnter: () => cancelClose(),\n },\n item: (id: string, options: { isBranch: boolean; ancestorIds?: string[] }): NavItemParts => {\n const ancestorIds = options.ancestorIds ?? []\n return {\n trigger: {\n type: 'button',\n role: 'menuitem',\n id: triggerId(id),\n 'aria-haspopup': options.isBranch ? 'menu' : undefined,\n 'aria-expanded': state.map((st) => (options.isBranch ? isOpen(st, id) : undefined)),\n 'data-scope': 'navigation-menu',\n 'data-part': 'trigger',\n 'data-state': state.map((st) => (isOpen(st, id) ? 'open' : 'closed')),\n 'data-value': id,\n tabIndex: state.map((st) => (st.focused === id ? 0 : -1)),\n onClick: tagSend(send, ['toggleBranch'], () => {\n if (options.isBranch) {\n send({ type: 'toggleBranch', id, ancestorIds })\n }\n }),\n onPointerEnter: tagSend(send, ['openBranch'], () => {\n cancelClose()\n if (options.isBranch) {\n send({ type: 'openBranch', id, ancestorIds })\n }\n }),\n onFocus: tagSend(send, ['focus'], () => send({ type: 'focus', id })),\n },\n content: {\n role: 'menu',\n id: contentId(id),\n 'aria-labelledby': triggerId(id),\n 'data-scope': 'navigation-menu',\n 'data-part': 'content',\n 'data-state': state.map((st) => (isOpen(st, id) ? 'open' : 'closed')),\n hidden: state.map((st) => !isOpen(st, id)),\n onPointerEnter: tagSend(send, ['openBranch'], () => {\n cancelClose()\n if (options.isBranch) {\n send({ type: 'openBranch', id, ancestorIds })\n }\n }),\n },\n }\n },\n }\n}\n\nexport const navigationMenu = { init, update, connect, isOpen }\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Send } from '@llui/dom';
|
|
1
|
+
import type { Send, Signal } from '@llui/dom';
|
|
2
2
|
/**
|
|
3
3
|
* Number input — numeric field with increment/decrement buttons. Clamps
|
|
4
4
|
* to min/max and snaps to step. Keyboard: Arrow Up/Down, PageUp/PageDown,
|
|
@@ -62,24 +62,24 @@ export interface NumberInputInit {
|
|
|
62
62
|
}
|
|
63
63
|
export declare function init(opts?: NumberInputInit): NumberInputState;
|
|
64
64
|
export declare function update(state: NumberInputState, msg: NumberInputMsg): [NumberInputState, never[]];
|
|
65
|
-
export interface NumberInputParts
|
|
65
|
+
export interface NumberInputParts {
|
|
66
66
|
root: {
|
|
67
67
|
'data-scope': 'number-input';
|
|
68
68
|
'data-part': 'root';
|
|
69
|
-
'data-disabled':
|
|
69
|
+
'data-disabled': Signal<'' | undefined>;
|
|
70
70
|
};
|
|
71
71
|
input: {
|
|
72
72
|
type: 'text';
|
|
73
73
|
role: 'spinbutton';
|
|
74
74
|
inputMode: 'decimal';
|
|
75
|
-
'aria-valuemin':
|
|
76
|
-
'aria-valuemax':
|
|
77
|
-
'aria-valuenow':
|
|
78
|
-
'aria-disabled':
|
|
79
|
-
'aria-readonly':
|
|
80
|
-
disabled:
|
|
81
|
-
readOnly:
|
|
82
|
-
value:
|
|
75
|
+
'aria-valuemin': Signal<number | undefined>;
|
|
76
|
+
'aria-valuemax': Signal<number | undefined>;
|
|
77
|
+
'aria-valuenow': Signal<number | undefined>;
|
|
78
|
+
'aria-disabled': Signal<'true' | undefined>;
|
|
79
|
+
'aria-readonly': Signal<'true' | undefined>;
|
|
80
|
+
disabled: Signal<boolean>;
|
|
81
|
+
readOnly: Signal<boolean>;
|
|
82
|
+
value: Signal<string>;
|
|
83
83
|
'data-scope': 'number-input';
|
|
84
84
|
'data-part': 'input';
|
|
85
85
|
onInput: (e: Event) => void;
|
|
@@ -88,9 +88,9 @@ export interface NumberInputParts<S> {
|
|
|
88
88
|
};
|
|
89
89
|
increment: {
|
|
90
90
|
type: 'button';
|
|
91
|
-
'aria-label': string
|
|
92
|
-
'aria-disabled':
|
|
93
|
-
disabled:
|
|
91
|
+
'aria-label': string;
|
|
92
|
+
'aria-disabled': Signal<'true' | undefined>;
|
|
93
|
+
disabled: Signal<boolean>;
|
|
94
94
|
'data-scope': 'number-input';
|
|
95
95
|
'data-part': 'increment';
|
|
96
96
|
tabIndex: -1;
|
|
@@ -98,9 +98,9 @@ export interface NumberInputParts<S> {
|
|
|
98
98
|
};
|
|
99
99
|
decrement: {
|
|
100
100
|
type: 'button';
|
|
101
|
-
'aria-label': string
|
|
102
|
-
'aria-disabled':
|
|
103
|
-
disabled:
|
|
101
|
+
'aria-label': string;
|
|
102
|
+
'aria-disabled': Signal<'true' | undefined>;
|
|
103
|
+
disabled: Signal<boolean>;
|
|
104
104
|
'data-scope': 'number-input';
|
|
105
105
|
'data-part': 'decrement';
|
|
106
106
|
tabIndex: -1;
|
|
@@ -113,7 +113,7 @@ export interface ConnectOptions {
|
|
|
113
113
|
/** Validate the numeric value before committing. Non-empty array blocks setValue. */
|
|
114
114
|
validate?: (value: number) => string[] | null;
|
|
115
115
|
}
|
|
116
|
-
export declare function connect
|
|
116
|
+
export declare function connect(state: Signal<NumberInputState>, send: Send<NumberInputMsg>, opts?: ConnectOptions): NumberInputParts;
|
|
117
117
|
export declare const numberInput: {
|
|
118
118
|
init: typeof init;
|
|
119
119
|
update: typeof update;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-input.d.ts","sourceRoot":"","sources":["../../src/components/number-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"number-input.d.ts","sourceRoot":"","sources":["../../src/components/number-input.ts"],"names":[],"mappings":"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"}
|