@k2b/ui 0.40.0 → 0.42.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/base.css +22 -0
- package/dist/browser/actions/Dropdown.js +220 -110
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/index.js.map +1 -1
- package/dist/browser/actions/menu-search.js +166 -0
- package/dist/browser/actions/menu-search.js.map +1 -0
- package/dist/browser/actions/menu-sheet.js +107 -13
- package/dist/browser/actions/menu-sheet.js.map +1 -1
- package/dist/browser/chat/ChatComposer.js +759 -570
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/content/CalendarWeekView.js +13 -1
- package/dist/browser/content/CalendarWeekView.js.map +1 -1
- package/dist/browser/inputs/ChoiceGroups.js +30 -18
- package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
- package/dist/browser/inputs/IconChoices.js +121 -0
- package/dist/browser/inputs/IconChoices.js.map +1 -0
- package/dist/browser/inputs/Select.js +32 -19
- package/dist/browser/inputs/Select.js.map +1 -1
- package/dist/browser/inputs/SpecialInputs.js +54 -25
- package/dist/browser/inputs/SpecialInputs.js.map +1 -1
- package/dist/browser/inputs/choice.js +4 -1
- package/dist/browser/inputs/choice.js.map +1 -1
- package/dist/browser/inputs/dictation/Dictation.js +546 -0
- package/dist/browser/inputs/dictation/Dictation.js.map +1 -0
- package/dist/browser/inputs/dictation/create-dictation.js +324 -0
- package/dist/browser/inputs/dictation/create-dictation.js.map +1 -0
- package/dist/browser/inputs/dictation/dictation-messages.js +115 -0
- package/dist/browser/inputs/dictation/dictation-messages.js.map +1 -0
- package/dist/browser/inputs/dictation/text-dictation.js +152 -0
- package/dist/browser/inputs/dictation/text-dictation.js.map +1 -0
- package/dist/browser/inputs/dictation/types.js +2 -0
- package/dist/browser/inputs/dictation/types.js.map +1 -0
- package/dist/browser/inputs/icon-messages.js +29 -2
- package/dist/browser/inputs/icon-messages.js.map +1 -1
- package/dist/browser/inputs/icon-texts.js +172 -0
- package/dist/browser/inputs/icon-texts.js.map +1 -0
- package/dist/browser/inputs/index.js +3 -0
- package/dist/browser/inputs/index.js.map +1 -1
- package/dist/browser/intl/messages.js +6 -0
- package/dist/browser/intl/messages.js.map +1 -1
- package/dist/browser/layout/AnchoredPopover.js +1 -1
- package/dist/browser/layout/AnchoredPopover.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +118 -93
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/SettingsModal.js +10 -5
- package/dist/browser/layout/SettingsModal.js.map +1 -1
- package/dist/browser/text-editor/TextEditor.js +74 -25
- package/dist/browser/text-editor/TextEditor.js.map +1 -1
- package/dist/browser/text-editor/dictation.js +166 -0
- package/dist/browser/text-editor/dictation.js.map +1 -0
- package/dist/browser/text-editor/format.js +11 -7
- package/dist/browser/text-editor/format.js.map +1 -1
- package/dist/browser/text-editor/table.js +39 -11
- package/dist/browser/text-editor/table.js.map +1 -1
- package/dist/browser/text-editor.js +2 -1
- package/dist/browser/text-editor.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +118 -40
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/index.js.map +1 -1
- package/dist/ssr/actions/menu-search.js +113 -0
- package/dist/ssr/actions/menu-search.js.map +1 -0
- package/dist/ssr/actions/menu-sheet.js +82 -13
- package/dist/ssr/actions/menu-sheet.js.map +1 -1
- package/dist/ssr/chat/ChatComposer.js +271 -99
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/content/CalendarWeekView.js +13 -1
- package/dist/ssr/content/CalendarWeekView.js.map +1 -1
- package/dist/ssr/inputs/ChoiceGroups.js +12 -3
- package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
- package/dist/ssr/inputs/IconChoices.js +59 -0
- package/dist/ssr/inputs/IconChoices.js.map +1 -0
- package/dist/ssr/inputs/Select.js +8 -2
- package/dist/ssr/inputs/Select.js.map +1 -1
- package/dist/ssr/inputs/SpecialInputs.js +54 -25
- package/dist/ssr/inputs/SpecialInputs.js.map +1 -1
- package/dist/ssr/inputs/choice.js +4 -1
- package/dist/ssr/inputs/choice.js.map +1 -1
- package/dist/ssr/inputs/dictation/Dictation.js +386 -0
- package/dist/ssr/inputs/dictation/Dictation.js.map +1 -0
- package/dist/ssr/inputs/dictation/create-dictation.js +324 -0
- package/dist/ssr/inputs/dictation/create-dictation.js.map +1 -0
- package/dist/ssr/inputs/dictation/dictation-messages.js +115 -0
- package/dist/ssr/inputs/dictation/dictation-messages.js.map +1 -0
- package/dist/ssr/inputs/dictation/text-dictation.js +152 -0
- package/dist/ssr/inputs/dictation/text-dictation.js.map +1 -0
- package/dist/ssr/inputs/dictation/types.js +2 -0
- package/dist/ssr/inputs/dictation/types.js.map +1 -0
- package/dist/ssr/inputs/icon-messages.js +29 -2
- package/dist/ssr/inputs/icon-messages.js.map +1 -1
- package/dist/ssr/inputs/icon-texts.js +172 -0
- package/dist/ssr/inputs/icon-texts.js.map +1 -0
- package/dist/ssr/inputs/index.js +3 -0
- package/dist/ssr/inputs/index.js.map +1 -1
- package/dist/ssr/intl/messages.js +6 -0
- package/dist/ssr/intl/messages.js.map +1 -1
- package/dist/ssr/layout/AnchoredPopover.js +1 -1
- package/dist/ssr/layout/AnchoredPopover.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +40 -20
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/SettingsModal.js +10 -5
- package/dist/ssr/layout/SettingsModal.js.map +1 -1
- package/dist/ssr/text-editor/TextEditor.js +74 -25
- package/dist/ssr/text-editor/TextEditor.js.map +1 -1
- package/dist/ssr/text-editor/dictation.js +166 -0
- package/dist/ssr/text-editor/dictation.js.map +1 -0
- package/dist/ssr/text-editor/format.js +11 -7
- package/dist/ssr/text-editor/format.js.map +1 -1
- package/dist/ssr/text-editor/table.js +39 -11
- package/dist/ssr/text-editor/table.js.map +1 -1
- package/dist/ssr/text-editor.js +2 -1
- package/dist/ssr/text-editor.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/Dropdown.d.ts +34 -3
- package/dist/types/actions/index.d.ts +1 -1
- package/dist/types/actions/menu-search.d.ts +27 -0
- package/dist/types/actions/menu-sheet.d.ts +5 -1
- package/dist/types/chat/ChatComposer.d.ts +9 -0
- package/dist/types/inputs/IconChoices.d.ts +19 -0
- package/dist/types/inputs/SpecialInputs.d.ts +8 -0
- package/dist/types/inputs/dictation/Dictation.d.ts +26 -0
- package/dist/types/inputs/dictation/create-dictation.d.ts +77 -0
- package/dist/types/inputs/dictation/dictation-messages.d.ts +54 -0
- package/dist/types/inputs/dictation/text-dictation.d.ts +36 -0
- package/dist/types/inputs/dictation/types.d.ts +74 -0
- package/dist/types/inputs/icon-messages.d.ts +14 -0
- package/dist/types/inputs/icon-texts.d.ts +13 -0
- package/dist/types/inputs/index.d.ts +7 -0
- package/dist/types/intl/messages.d.ts +3 -0
- package/dist/types/layout/AnchoredPopover.d.ts +5 -0
- package/dist/types/layout/AppWorkspace.d.ts +6 -1
- package/dist/types/text-editor/TextEditor.d.ts +10 -1
- package/dist/types/text-editor/dictation.d.ts +20 -0
- package/dist/types/text-editor/table.d.ts +2 -0
- package/dist/types/text-editor.d.ts +2 -1
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["actions/index.ts"],"sourcesContent":["export type { ButtonAlign, ButtonLinkProps, ButtonProps, ButtonSize, ButtonVariant, IconButtonLinkProps, IconButtonProps } from \"./Button\";\nexport { Button, ButtonLink, IconButton, IconButtonLink } from \"./Button\";\nexport type { ContextMenuProps } from \"./ContextMenu\";\nexport { ContextMenu } from \"./ContextMenu\";\nexport type { CopyButtonProps, CopyButtonValue } from \"./CopyButton\";\nexport { CopyButton } from \"./CopyButton\";\nexport type { DisclosureProps } from \"./Disclosure\";\nexport { Disclosure } from \"./Disclosure\";\nexport type { DragPayload, DragSourceProps, DropTargetProps } from \"./DragAndDrop\";\nexport { activeDrag, DragSource, DropTarget, useKeyboardDrag } from \"./DragAndDrop\";\nexport type {\n DropdownAction,\n DropdownActionBase,\n DropdownAnchor,\n DropdownChoice,\n DropdownItemProps,\n DropdownPosition,\n DropdownProps,\n DropdownReturnFocus,\n DropdownSection,\n DropdownTriggerProps,\n} from \"./Dropdown\";\nexport { Dropdown, DropdownItem, dropdownPosition } from \"./Dropdown\";\nexport type { FilterChipOption, FilterChipProps, FilterChipSection, FilterToggleProps } from \"./FilterChip\";\nexport { FilterChip, FilterToggle } from \"./FilterChip\";\nexport type { GestureKind, GestureMenuAction, GestureMenuItem, GestureMenuProps, GestureMenuSection } from \"./GestureMenu\";\nexport { GestureMenu } from \"./GestureMenu\";\nexport type { RemoveButtonProps } from \"./RemoveButton\";\nexport { RemoveButton } from \"./RemoveButton\";\nexport type { SegmentedControlProps, SegmentOption } from \"./SegmentedControl\";\nexport { SegmentedControl } from \"./SegmentedControl\";\nexport type { SelectionToolbarProps } from \"./SelectionToolbar\";\nexport { SelectionToolbar } from \"./SelectionToolbar\";\nexport type { SplitButtonProps } from \"./SplitButton\";\nexport { SplitButton } from \"./SplitButton\";\nexport type {\n SpotlightButtonProps,\n SpotlightButtonVariant,\n SpotlightSearchOptions,\n SpotlightSearchResolver,\n} from \"./SpotlightSearch\";\nexport {\n openSpotlightSearch,\n SpotlightButton,\n} from \"./SpotlightSearch\";\nexport type { TabOption, TabsItemProps, TabsProps } from \"./Tabs\";\nexport { Tabs } from \"./Tabs\";\nexport type { ToolbarActionProps, ToolbarGroupProps, ToolbarLabelProps, ToolbarProps, ToolbarSeparatorProps } from \"./Toolbar\";\nexport { Toolbar } from \"./Toolbar\";\nexport type { ViewTab, ViewTabsProps } from \"./ViewTabs\";\nexport { ViewTabs } from \"./ViewTabs\";\n"],"mappings":"AACA,SAAS,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,QAAQ,UAAU;AAEzE,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,QAAQ,eAAe;
|
|
1
|
+
{"version":3,"names":[],"sources":["actions/index.ts"],"sourcesContent":["export type { ButtonAlign, ButtonLinkProps, ButtonProps, ButtonSize, ButtonVariant, IconButtonLinkProps, IconButtonProps } from \"./Button\";\nexport { Button, ButtonLink, IconButton, IconButtonLink } from \"./Button\";\nexport type { ContextMenuProps } from \"./ContextMenu\";\nexport { ContextMenu } from \"./ContextMenu\";\nexport type { CopyButtonProps, CopyButtonValue } from \"./CopyButton\";\nexport { CopyButton } from \"./CopyButton\";\nexport type { DisclosureProps } from \"./Disclosure\";\nexport { Disclosure } from \"./Disclosure\";\nexport type { DragPayload, DragSourceProps, DropTargetProps } from \"./DragAndDrop\";\nexport { activeDrag, DragSource, DropTarget, useKeyboardDrag } from \"./DragAndDrop\";\nexport type {\n DropdownAction,\n DropdownActionBase,\n DropdownAnchor,\n DropdownChoice,\n DropdownItemProps,\n DropdownPosition,\n DropdownProps,\n DropdownReturnFocus,\n DropdownSearch,\n DropdownSection,\n DropdownTriggerProps,\n} from \"./Dropdown\";\nexport { Dropdown, DropdownItem, dropdownPosition } from \"./Dropdown\";\nexport type { FilterChipOption, FilterChipProps, FilterChipSection, FilterToggleProps } from \"./FilterChip\";\nexport { FilterChip, FilterToggle } from \"./FilterChip\";\nexport type { GestureKind, GestureMenuAction, GestureMenuItem, GestureMenuProps, GestureMenuSection } from \"./GestureMenu\";\nexport { GestureMenu } from \"./GestureMenu\";\nexport type { RemoveButtonProps } from \"./RemoveButton\";\nexport { RemoveButton } from \"./RemoveButton\";\nexport type { SegmentedControlProps, SegmentOption } from \"./SegmentedControl\";\nexport { SegmentedControl } from \"./SegmentedControl\";\nexport type { SelectionToolbarProps } from \"./SelectionToolbar\";\nexport { SelectionToolbar } from \"./SelectionToolbar\";\nexport type { SplitButtonProps } from \"./SplitButton\";\nexport { SplitButton } from \"./SplitButton\";\nexport type {\n SpotlightButtonProps,\n SpotlightButtonVariant,\n SpotlightSearchOptions,\n SpotlightSearchResolver,\n} from \"./SpotlightSearch\";\nexport {\n openSpotlightSearch,\n SpotlightButton,\n} from \"./SpotlightSearch\";\nexport type { TabOption, TabsItemProps, TabsProps } from \"./Tabs\";\nexport { Tabs } from \"./Tabs\";\nexport type { ToolbarActionProps, ToolbarGroupProps, ToolbarLabelProps, ToolbarProps, ToolbarSeparatorProps } from \"./Toolbar\";\nexport { Toolbar } from \"./Toolbar\";\nexport type { ViewTab, ViewTabsProps } from \"./ViewTabs\";\nexport { ViewTabs } from \"./ViewTabs\";\n"],"mappings":"AACA,SAAS,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,QAAQ,UAAU;AAEzE,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,QAAQ,eAAe;AAcnF,SAAS,QAAQ,EAAE,YAAY,EAAE,gBAAgB,QAAQ,YAAY;AAErE,SAAS,UAAU,EAAE,YAAY,QAAQ,cAAc;AAEvD,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,gBAAgB,QAAQ,oBAAoB;AAErD,SAAS,gBAAgB,QAAQ,oBAAoB;AAErD,SAAS,WAAW,QAAQ,eAAe;AAO3C,SACE,mBAAmB,EACnB,eAAe,QACV,mBAAmB;AAE1B,SAAS,IAAI,QAAQ,QAAQ;AAE7B,SAAS,OAAO,QAAQ,WAAW;AAEnC,SAAS,QAAQ,QAAQ,YAAY","ignoreList":[]}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
2
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
3
|
+
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
4
|
+
import { escape as _$escape } from "solid-js/web";
|
|
5
|
+
var _tmpl$ = ["<label class=\"k2b-dropdown__search\"><i class=\"ti ti-search\" aria-hidden=\"true\"></i><input type=\"search\" role=\"combobox\"", " aria-expanded=\"true\"", " aria-autocomplete=\"list\" autocomplete=\"off\" spellcheck=\"false\" enterkeyhint=\"go\"", "></label>"],
|
|
6
|
+
_tmpl$2 = ["<div", " role=\"listbox\"", " class=\"k2b-dropdown__list\">", "</div>"],
|
|
7
|
+
_tmpl$3 = ["<span class=\"k2b-sr-only\" role=\"status\">", "</span>"],
|
|
8
|
+
_tmpl$4 = ["<p class=\"k2b-dropdown__empty\">", "</p>"];
|
|
9
|
+
import { createEffect, createMemo, createUniqueId, on, onMount, Show } from "solid-js";
|
|
10
|
+
import { useLocale } from "../intl/locale";
|
|
11
|
+
import { useUiMessages } from "../intl/messages";
|
|
12
|
+
const entriesOf = items => items.flatMap(item => "items" in item ? item.items : [item]);
|
|
13
|
+
|
|
14
|
+
/** The actions and choices whose label or description contains the query, kept in their sections. */
|
|
15
|
+
export const filterDropdownItems = (items, query, locale) => {
|
|
16
|
+
const needle = query.trim().toLocaleLowerCase(locale);
|
|
17
|
+
const matches = entry => `${entry.label} ${entry.description ?? ""}`.toLocaleLowerCase(locale).includes(needle);
|
|
18
|
+
return items.flatMap(item => {
|
|
19
|
+
if (!("items" in item)) return matches(item) ? [item] : [];
|
|
20
|
+
const kept = item.items.filter(matches);
|
|
21
|
+
return kept.length ? [{
|
|
22
|
+
...item,
|
|
23
|
+
items: kept
|
|
24
|
+
}] : [];
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const optionsOf = list => list ? Array.from(list.querySelectorAll("[role='option']:not([aria-disabled='true'])")) : [];
|
|
28
|
+
/**
|
|
29
|
+
* A search field over a list box of the menu's entries: the combobox pattern. The field keeps the focus, the marked
|
|
30
|
+
* entry is its active descendant, and a polite status says how many entries match.
|
|
31
|
+
*/
|
|
32
|
+
export function MenuSearch(props) {
|
|
33
|
+
const messages = useUiMessages();
|
|
34
|
+
const locale = useLocale();
|
|
35
|
+
const id = createUniqueId().replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
36
|
+
const listId = `k2b-dropdown-search-${id}`;
|
|
37
|
+
let input;
|
|
38
|
+
let list;
|
|
39
|
+
let active = 0;
|
|
40
|
+
const blank = () => props.query().trim() === "";
|
|
41
|
+
const shown = createMemo(() => blank() ? props.items : props.search.filter?.(props.query()) ?? filterDropdownItems(props.items, props.query(), locale()));
|
|
42
|
+
const matches = () => entriesOf(shown()).filter(entry => !entry.disabled).length;
|
|
43
|
+
const status = () => blank() ? "" : props.search.status?.(props.query(), matches()) ?? messages().searchMatches({
|
|
44
|
+
count: matches()
|
|
45
|
+
});
|
|
46
|
+
const mark = index => {
|
|
47
|
+
// An entry that became disabled keeps no stale ID or mark.
|
|
48
|
+
for (const stale of list.querySelectorAll("[role='option']")) {
|
|
49
|
+
stale.removeAttribute("id");
|
|
50
|
+
stale.removeAttribute("aria-selected");
|
|
51
|
+
stale.removeAttribute("data-active");
|
|
52
|
+
}
|
|
53
|
+
const options = optionsOf(list);
|
|
54
|
+
active = options.length ? (index + options.length) % options.length : 0;
|
|
55
|
+
options.forEach((option, position) => {
|
|
56
|
+
option.id = `${listId}-${position}`;
|
|
57
|
+
option.setAttribute("aria-selected", String(position === active));
|
|
58
|
+
option.toggleAttribute("data-active", position === active);
|
|
59
|
+
});
|
|
60
|
+
const current = options[active];
|
|
61
|
+
if (current) {
|
|
62
|
+
input.setAttribute("aria-activedescendant", current.id);
|
|
63
|
+
current.scrollIntoView?.({
|
|
64
|
+
block: "nearest"
|
|
65
|
+
});
|
|
66
|
+
} else input.removeAttribute("aria-activedescendant");
|
|
67
|
+
};
|
|
68
|
+
// A new query shows new entries: the first of them is marked again, after they rendered.
|
|
69
|
+
createEffect(on(shown, () => queueMicrotask(() => mark(0)), {
|
|
70
|
+
defer: true
|
|
71
|
+
}));
|
|
72
|
+
onMount(() => {
|
|
73
|
+
mark(0);
|
|
74
|
+
props.api?.({
|
|
75
|
+
focus: which => {
|
|
76
|
+
input.focus({
|
|
77
|
+
preventScroll: true
|
|
78
|
+
});
|
|
79
|
+
mark(which === "first" ? 0 : -1);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
const onKeyDown = event => {
|
|
84
|
+
if (event.isComposing) return;
|
|
85
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
mark(active + (event.key === "ArrowDown" ? 1 : -1));
|
|
88
|
+
} else if (event.key === "Enter") {
|
|
89
|
+
event.preventDefault();
|
|
90
|
+
optionsOf(list)[active]?.click();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return [_$ssr(_tmpl$, _$ssrAttribute("aria-label", _$escape(props.search.label, true), false), _$ssrAttribute("aria-controls", _$escape(listId, true), false), _$ssrAttribute("placeholder", _$escape(props.search.placeholder ?? props.search.label, true), false) + _$ssrAttribute("value", _$escape(props.query(), true), false)), _$ssr(_tmpl$2, _$ssrAttribute("id", _$escape(listId, true), false), _$ssrAttribute("aria-label", _$escape(props.label, true), false), _$escape(_$createComponent(Show, {
|
|
94
|
+
get when() {
|
|
95
|
+
return shown().length;
|
|
96
|
+
},
|
|
97
|
+
get fallback() {
|
|
98
|
+
return _$ssr(_tmpl$4, _$escape(messages().noResults));
|
|
99
|
+
},
|
|
100
|
+
get children() {
|
|
101
|
+
return _$createComponent(props.Items, {
|
|
102
|
+
get items() {
|
|
103
|
+
return shown();
|
|
104
|
+
},
|
|
105
|
+
get close() {
|
|
106
|
+
return props.close;
|
|
107
|
+
},
|
|
108
|
+
role: "option"
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}))), _$ssr(_tmpl$3, _$escape(status()))];
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=menu-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["actions/menu-search.tsx"],"sourcesContent":["import { type Accessor, createEffect, createMemo, createUniqueId, type JSX, on, onMount, Show } from \"solid-js\";\nimport { useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { DropdownItem, DropdownSearch } from \"./Dropdown\";\n\ntype Entry = Exclude<DropdownItem, { items: unknown }>;\n\nconst entriesOf = (items: readonly DropdownItem[]): Entry[] => items.flatMap((item) => (\"items\" in item ? item.items : [item]));\n\n/** The actions and choices whose label or description contains the query, kept in their sections. */\nexport const filterDropdownItems = (items: readonly DropdownItem[], query: string, locale?: string): DropdownItem[] => {\n const needle = query.trim().toLocaleLowerCase(locale);\n const matches = (entry: Entry) => `${entry.label} ${entry.description ?? \"\"}`.toLocaleLowerCase(locale).includes(needle);\n return items.flatMap((item): DropdownItem[] => {\n if (!(\"items\" in item)) return matches(item) ? [item] : [];\n const kept = item.items.filter(matches);\n return kept.length ? [{ ...item, items: kept }] : [];\n });\n};\n\nconst optionsOf = (list: HTMLElement | undefined): HTMLElement[] =>\n list ? Array.from(list.querySelectorAll<HTMLElement>(\"[role='option']:not([aria-disabled='true'])\")) : [];\n\nexport type MenuSearchApi = {\n /** Moves the focus into the field and marks the first or last entry. */\n focus: (mark: \"first\" | \"last\") => void;\n};\n\n/**\n * A search field over a list box of the menu's entries: the combobox pattern. The field keeps the focus, the marked\n * entry is its active descendant, and a polite status says how many entries match.\n */\nexport function MenuSearch(props: {\n Items: (props: { items: readonly DropdownItem[]; close: (restoreFocus?: boolean) => void; role?: \"menuitem\" | \"option\" }) => JSX.Element;\n items: readonly DropdownItem[];\n search: DropdownSearch;\n /** Names the list box. */\n label: string;\n query: Accessor<string>;\n setQuery: (query: string) => void;\n close: (restoreFocus?: boolean) => void;\n api?: (api: MenuSearchApi) => void;\n}): JSX.Element {\n const messages = useUiMessages();\n const locale = useLocale();\n const id = createUniqueId().replace(/[^a-zA-Z0-9_-]/g, \"-\");\n const listId = `k2b-dropdown-search-${id}`;\n let input!: HTMLInputElement;\n let list!: HTMLDivElement;\n let active = 0;\n const blank = () => props.query().trim() === \"\";\n const shown = createMemo(() =>\n blank() ? props.items : (props.search.filter?.(props.query()) ?? filterDropdownItems(props.items, props.query(), locale())),\n );\n const matches = () => entriesOf(shown()).filter((entry) => !entry.disabled).length;\n const status = () => (blank() ? \"\" : (props.search.status?.(props.query(), matches()) ?? messages().searchMatches({ count: matches() })));\n\n const mark = (index: number) => {\n // An entry that became disabled keeps no stale ID or mark.\n for (const stale of list.querySelectorAll<HTMLElement>(\"[role='option']\")) {\n stale.removeAttribute(\"id\");\n stale.removeAttribute(\"aria-selected\");\n stale.removeAttribute(\"data-active\");\n }\n const options = optionsOf(list);\n active = options.length ? (index + options.length) % options.length : 0;\n options.forEach((option, position) => {\n option.id = `${listId}-${position}`;\n option.setAttribute(\"aria-selected\", String(position === active));\n option.toggleAttribute(\"data-active\", position === active);\n });\n const current = options[active];\n if (current) {\n input.setAttribute(\"aria-activedescendant\", current.id);\n current.scrollIntoView?.({ block: \"nearest\" });\n } else input.removeAttribute(\"aria-activedescendant\");\n };\n // A new query shows new entries: the first of them is marked again, after they rendered.\n createEffect(on(shown, () => queueMicrotask(() => mark(0)), { defer: true }));\n onMount(() => {\n mark(0);\n props.api?.({\n focus: (which) => {\n input.focus({ preventScroll: true });\n mark(which === \"first\" ? 0 : -1);\n },\n });\n });\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.isComposing) return;\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n mark(active + (event.key === \"ArrowDown\" ? 1 : -1));\n } else if (event.key === \"Enter\") {\n event.preventDefault();\n optionsOf(list)[active]?.click();\n }\n };\n\n return (\n <>\n <label class=\"k2b-dropdown__search\">\n <i class=\"ti ti-search\" aria-hidden=\"true\" />\n <input\n ref={input}\n type=\"search\"\n role=\"combobox\"\n aria-label={props.search.label}\n aria-expanded=\"true\"\n aria-controls={listId}\n aria-autocomplete=\"list\"\n autocomplete=\"off\"\n spellcheck={false}\n enterkeyhint=\"go\"\n placeholder={props.search.placeholder ?? props.search.label}\n value={props.query()}\n onInput={(event) => props.setQuery(event.currentTarget.value)}\n onKeyDown={onKeyDown}\n />\n </label>\n <div\n ref={list}\n id={listId}\n role=\"listbox\"\n aria-label={props.label}\n class=\"k2b-dropdown__list\"\n // A press on an entry leaves the focus in the field, also for an entry that keeps the menu open.\n onMouseDown={(event) => event.preventDefault()}\n onPointerMove={(event) => {\n const option = (event.target as Element).closest<HTMLElement>(\"[role='option']\");\n const index = option ? optionsOf(list).indexOf(option) : -1;\n if (index >= 0 && index !== active) mark(index);\n }}\n >\n <Show when={shown().length} fallback={<p class=\"k2b-dropdown__empty\">{messages().noResults}</p>}>\n <props.Items items={shown()} close={props.close} role=\"option\" />\n </Show>\n </div>\n <span class=\"k2b-sr-only\" role=\"status\">\n {status()}\n </span>\n </>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,12 +2,15 @@ import { ssr as _$ssr } from "solid-js/web";
|
|
|
2
2
|
import { createComponent as _$createComponent } from "solid-js/web";
|
|
3
3
|
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
4
4
|
import { escape as _$escape } from "solid-js/web";
|
|
5
|
-
var _tmpl$ = ["<div class=\"k2b-gesture-menu__sheet-menu\" role=\"menu\"", ">", "</div>"]
|
|
6
|
-
|
|
5
|
+
var _tmpl$ = ["<div class=\"k2b-gesture-menu__sheet-menu\" role=\"menu\"", ">", "</div>"],
|
|
6
|
+
_tmpl$2 = ["<div class=\"k2b-gesture-menu__sheet-menu\" role=\"dialog\"", " data-search", ">", "</div>"],
|
|
7
|
+
_tmpl$3 = ["<p class=\"k2b-dropdown__note\">", "</p>"];
|
|
8
|
+
import { createSignal, onCleanup, onMount, Show } from "solid-js";
|
|
7
9
|
import { dialogCore } from "../feedback/dialog-core";
|
|
8
10
|
import { LocaleProvider } from "../intl/locale";
|
|
9
11
|
import BottomSheet, { bottomSheetOptions } from "../layout/BottomSheet";
|
|
10
12
|
import { focusMenuRow, focusRowSegment } from "./menu-rows";
|
|
13
|
+
import { filterDropdownItems, MenuSearch } from "./menu-search";
|
|
11
14
|
|
|
12
15
|
/** Phones, where a menu opens as a bottom sheet instead of beside its trigger. */
|
|
13
16
|
export const PHONE_SHEET_QUERY = "(max-width: 47.999rem)";
|
|
@@ -78,13 +81,40 @@ function SheetMenu(props) {
|
|
|
78
81
|
props.dialog.addEventListener("keydown", onSheetKeyDown);
|
|
79
82
|
onCleanup(() => props.dialog.removeEventListener("keydown", onSheetKeyDown));
|
|
80
83
|
});
|
|
81
|
-
return _$ssr(_tmpl$, _$ssrAttribute("aria-label", _$escape(props.label, true), false), _$escape(_$createComponent(props.Items, {
|
|
84
|
+
return _$ssr(_tmpl$, _$ssrAttribute("aria-label", _$escape(props.label, true), false) + _$ssrAttribute("data-icons", props.icons === "tile" ? "tile" : _$escape(undefined, true), false), _$escape(_$createComponent(props.Items, {
|
|
82
85
|
get items() {
|
|
83
86
|
return props.items;
|
|
84
87
|
},
|
|
85
88
|
close: () => props.close()
|
|
86
89
|
})));
|
|
87
90
|
}
|
|
91
|
+
/** A searchable menu in the sheet: the sheet's first field, so it takes the focus as the sheet opens, as in the menu. */
|
|
92
|
+
function SheetSearch(props) {
|
|
93
|
+
const [query, setQuery] = createSignal("");
|
|
94
|
+
const filter = props.search.filter;
|
|
95
|
+
return _$ssr(_tmpl$2, _$ssrAttribute("aria-label", _$escape(props.label, true), false), _$ssrAttribute("data-icons", props.icons === "tile" ? "tile" : _$escape(undefined, true), false), _$escape(_$createComponent(MenuSearch, {
|
|
96
|
+
get Items() {
|
|
97
|
+
return props.Items;
|
|
98
|
+
},
|
|
99
|
+
get items() {
|
|
100
|
+
return props.items;
|
|
101
|
+
},
|
|
102
|
+
get search() {
|
|
103
|
+
return {
|
|
104
|
+
...props.search,
|
|
105
|
+
// The sheet's own items are wrapped already; a host's filter returns its unwrapped entries.
|
|
106
|
+
filter: value => filter ? props.wrap(filter(value)) : filterDropdownItems(props.items, value, props.locale)
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
get label() {
|
|
110
|
+
return props.label;
|
|
111
|
+
},
|
|
112
|
+
query: query,
|
|
113
|
+
setQuery: setQuery,
|
|
114
|
+
close: () => props.close()
|
|
115
|
+
})));
|
|
116
|
+
}
|
|
117
|
+
|
|
88
118
|
/** Opens menu items as a bottom sheet; resolves after the sheet closed and the chosen action ran. */
|
|
89
119
|
export const openMenuSheet = options => {
|
|
90
120
|
let chosen;
|
|
@@ -103,19 +133,58 @@ export const openMenuSheet = options => {
|
|
|
103
133
|
get children() {
|
|
104
134
|
return _$createComponent(BottomSheet.Body, {
|
|
105
135
|
get children() {
|
|
106
|
-
return [options.top?.(() => close()), _$createComponent(
|
|
107
|
-
get
|
|
108
|
-
return options.
|
|
136
|
+
return [options.top?.(() => close()), _$createComponent(Show, {
|
|
137
|
+
get when() {
|
|
138
|
+
return options.search;
|
|
109
139
|
},
|
|
110
|
-
get
|
|
111
|
-
return
|
|
140
|
+
get fallback() {
|
|
141
|
+
return _$createComponent(SheetMenu, {
|
|
142
|
+
get Items() {
|
|
143
|
+
return options.Items;
|
|
144
|
+
},
|
|
145
|
+
get items() {
|
|
146
|
+
return afterClose(options.items, choose);
|
|
147
|
+
},
|
|
148
|
+
get label() {
|
|
149
|
+
return options.label;
|
|
150
|
+
},
|
|
151
|
+
close: () => close(),
|
|
152
|
+
get dialog() {
|
|
153
|
+
return context.dialog;
|
|
154
|
+
},
|
|
155
|
+
get icons() {
|
|
156
|
+
return options.icons;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
112
159
|
},
|
|
113
|
-
|
|
114
|
-
|
|
160
|
+
children: search => _$createComponent(SheetSearch, {
|
|
161
|
+
get Items() {
|
|
162
|
+
return options.Items;
|
|
163
|
+
},
|
|
164
|
+
get items() {
|
|
165
|
+
return afterClose(options.items, choose);
|
|
166
|
+
},
|
|
167
|
+
get search() {
|
|
168
|
+
return search();
|
|
169
|
+
},
|
|
170
|
+
wrap: items => afterClose(items, choose),
|
|
171
|
+
get label() {
|
|
172
|
+
return options.label;
|
|
173
|
+
},
|
|
174
|
+
get locale() {
|
|
175
|
+
return options.locale;
|
|
176
|
+
},
|
|
177
|
+
close: () => close(),
|
|
178
|
+
get icons() {
|
|
179
|
+
return options.icons;
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
}), _$createComponent(Show, {
|
|
183
|
+
get when() {
|
|
184
|
+
return options.note;
|
|
115
185
|
},
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return context.dialog;
|
|
186
|
+
get children() {
|
|
187
|
+
return _$ssr(_tmpl$3, _$escape(options.note));
|
|
119
188
|
}
|
|
120
189
|
})];
|
|
121
190
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["actions/menu-sheet.tsx"],"sourcesContent":["import { type JSX, onCleanup, onMount } from \"solid-js\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { LocaleProvider } from \"../intl/locale\";\nimport BottomSheet, { bottomSheetOptions } from \"../layout/BottomSheet\";\nimport type { DropdownAction, DropdownChoice, DropdownItem } from \"./Dropdown\";\nimport { focusMenuRow, focusRowSegment } from \"./menu-rows\";\n\n/** Phones, where a menu opens as a bottom sheet instead of beside its trigger. */\nexport const PHONE_SHEET_QUERY = \"(max-width: 47.999rem)\";\n\nexport const prefersMenuSheet = (): boolean => typeof matchMedia === \"function\" && matchMedia(PHONE_SHEET_QUERY).matches;\n\ntype SheetEntry = DropdownAction | DropdownChoice;\ntype SheetItem = SheetEntry | { items: readonly SheetEntry[] };\n\n/**\n * Follows a link the way a click on it would, so a page's own link handling, such as progressive navigation, still\n * applies; it runs only after the sheet has left the history.\n */\nconst followLink = (href: string) => {\n const link = document.createElement(\"a\");\n link.href = href;\n link.hidden = true;\n document.body.append(link);\n link.click();\n link.remove();\n};\n\n/**\n * The sheet's items hand their action to `run` instead of running it while the sheet closes: `dialogCore` settles the\n * sheet after it left the history, and only then may an action navigate or open the next dialog.\n * A choice or action that keeps the menu open, or an `immediate` action, runs at once.\n */\nconst afterClose = <T extends DropdownItem>(items: readonly T[], run: (action: () => void) => void): T[] => {\n const entry = (item: SheetEntry): SheetEntry => {\n // A plain link would navigate while the sheet's history entry is still being removed, and that Back could\n // undo the navigation; a plain click instead follows it once the sheet is gone. Modified clicks and external\n // links keep the browser's own behavior.\n if (!item.action && \"href\" in item && item.href && !(\"external\" in item && item.external)) {\n const href = item.href;\n return { ...item, action: () => run(() => followLink(href)) } as SheetEntry;\n }\n const action = item.action;\n if (!action || (\"closeOnSelect\" in item && item.closeOnSelect === false) || (\"immediate\" in item && item.immediate)) return item;\n return { ...item, action: () => run(action) } as SheetEntry;\n };\n return items.map((item) => {\n const sheetItem = item as SheetItem;\n return (\"items\" in sheetItem ? { ...sheetItem, items: sheetItem.items.map(entry) } : entry(sheetItem)) as T;\n });\n};\n\nconst menuItems = (menu: HTMLElement): HTMLElement[] =>\n Array.from(menu.querySelectorAll<HTMLElement>(\"[role^='menuitem']:not([aria-disabled='true'])\"));\n\n/**\n * The menu inside the sheet: the same items, at touch size, with arrow keys for a connected keyboard. Focus starts on\n * the sheet itself, which shows no ring on a phone; the first arrow key moves it into the menu.\n */\nfunction SheetMenu(props: {\n Items: MenuSheetOptions[\"Items\"];\n items: readonly DropdownItem[];\n label: string;\n close: () => void;\n dialog: HTMLDialogElement;\n}): JSX.Element {\n let menu!: HTMLDivElement;\n const onKeyDown = (event: KeyboardEvent) => {\n const items = menuItems(menu);\n if (!focusMenuRow(items, event.key) && !focusRowSegment(items, event.key)) return;\n event.preventDefault();\n };\n // Keys pressed on the sheet itself, while it is the top level of the shared dialog.\n const onSheetKeyDown = (event: KeyboardEvent) => {\n if (event.target === props.dialog && props.dialog.lastElementChild?.contains(menu)) onKeyDown(event);\n };\n onMount(() => {\n props.dialog.addEventListener(\"keydown\", onSheetKeyDown);\n onCleanup(() => props.dialog.removeEventListener(\"keydown\", onSheetKeyDown));\n });\n return (\n <div ref={menu} class=\"k2b-gesture-menu__sheet-menu\" role=\"menu\" aria-label={props.label} onKeyDown={onKeyDown}>\n <props.Items items={props.items} close={() => props.close()} />\n </div>\n );\n}\n\nexport type MenuSheetOptions = {\n /** Renders the rows: the dropdown's own `DropdownItems`, passed in so this module does not import it back. */\n Items: (props: { items: readonly DropdownItem[]; close: (restoreFocus?: boolean) => void }) => JSX.Element;\n items: readonly DropdownItem[];\n /** Names the sheet and its menu. */\n label: string;\n /** The render locale of the opener; the sheet renders outside its tree. */\n locale: string;\n /** Shown above the menu, for example a row of quick reactions. `close` closes the sheet. */\n top?: (close: () => void) => JSX.Element;\n signal?: AbortSignal;\n};\n\n/** Opens menu items as a bottom sheet; resolves after the sheet closed and the chosen action ran. */\nexport const openMenuSheet = (options: MenuSheetOptions): Promise<void> => {\n let chosen: (() => void) | undefined;\n const choose = (action: () => void) => {\n chosen = action;\n };\n return dialogCore\n .open<void>(\n (close, context) => (\n <LocaleProvider locale={options.locale}>\n <BottomSheet onDismiss={context.requestDismiss}>\n <BottomSheet.Body>\n {options.top?.(() => close())}\n <SheetMenu\n Items={options.Items}\n items={afterClose(options.items, choose)}\n label={options.label}\n close={() => close()}\n dialog={context.dialog}\n />\n </BottomSheet.Body>\n </BottomSheet>\n </LocaleProvider>\n ),\n { ...bottomSheetOptions, ariaLabel: options.label, history: true, signal: options.signal },\n )\n .then(() => chosen?.());\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["actions/menu-sheet.tsx"],"sourcesContent":["import { createSignal, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { LocaleProvider } from \"../intl/locale\";\nimport BottomSheet, { bottomSheetOptions } from \"../layout/BottomSheet\";\nimport type { DropdownAction, DropdownChoice, DropdownItem, DropdownSearch } from \"./Dropdown\";\nimport { focusMenuRow, focusRowSegment } from \"./menu-rows\";\nimport { filterDropdownItems, MenuSearch } from \"./menu-search\";\n\n/** Phones, where a menu opens as a bottom sheet instead of beside its trigger. */\nexport const PHONE_SHEET_QUERY = \"(max-width: 47.999rem)\";\n\nexport const prefersMenuSheet = (): boolean => typeof matchMedia === \"function\" && matchMedia(PHONE_SHEET_QUERY).matches;\n\ntype SheetEntry = DropdownAction | DropdownChoice;\ntype SheetItem = SheetEntry | { items: readonly SheetEntry[] };\n\n/**\n * Follows a link the way a click on it would, so a page's own link handling, such as progressive navigation, still\n * applies; it runs only after the sheet has left the history.\n */\nconst followLink = (href: string) => {\n const link = document.createElement(\"a\");\n link.href = href;\n link.hidden = true;\n document.body.append(link);\n link.click();\n link.remove();\n};\n\n/**\n * The sheet's items hand their action to `run` instead of running it while the sheet closes: `dialogCore` settles the\n * sheet after it left the history, and only then may an action navigate or open the next dialog.\n * A choice or action that keeps the menu open, or an `immediate` action, runs at once.\n */\nconst afterClose = <T extends DropdownItem>(items: readonly T[], run: (action: () => void) => void): T[] => {\n const entry = (item: SheetEntry): SheetEntry => {\n // A plain link would navigate while the sheet's history entry is still being removed, and that Back could\n // undo the navigation; a plain click instead follows it once the sheet is gone. Modified clicks and external\n // links keep the browser's own behavior.\n if (!item.action && \"href\" in item && item.href && !(\"external\" in item && item.external)) {\n const href = item.href;\n return { ...item, action: () => run(() => followLink(href)) } as SheetEntry;\n }\n const action = item.action;\n if (!action || (\"closeOnSelect\" in item && item.closeOnSelect === false) || (\"immediate\" in item && item.immediate)) return item;\n return { ...item, action: () => run(action) } as SheetEntry;\n };\n return items.map((item) => {\n const sheetItem = item as SheetItem;\n return (\"items\" in sheetItem ? { ...sheetItem, items: sheetItem.items.map(entry) } : entry(sheetItem)) as T;\n });\n};\n\nconst menuItems = (menu: HTMLElement): HTMLElement[] =>\n Array.from(menu.querySelectorAll<HTMLElement>(\"[role^='menuitem']:not([aria-disabled='true'])\"));\n\n/**\n * The menu inside the sheet: the same items, at touch size, with arrow keys for a connected keyboard. Focus starts on\n * the sheet itself, which shows no ring on a phone; the first arrow key moves it into the menu.\n */\nfunction SheetMenu(props: {\n Items: MenuSheetOptions[\"Items\"];\n items: readonly DropdownItem[];\n label: string;\n close: () => void;\n dialog: HTMLDialogElement;\n icons?: \"plain\" | \"tile\";\n}): JSX.Element {\n let menu!: HTMLDivElement;\n const onKeyDown = (event: KeyboardEvent) => {\n const items = menuItems(menu);\n if (!focusMenuRow(items, event.key) && !focusRowSegment(items, event.key)) return;\n event.preventDefault();\n };\n // Keys pressed on the sheet itself, while it is the top level of the shared dialog.\n const onSheetKeyDown = (event: KeyboardEvent) => {\n if (event.target === props.dialog && props.dialog.lastElementChild?.contains(menu)) onKeyDown(event);\n };\n onMount(() => {\n props.dialog.addEventListener(\"keydown\", onSheetKeyDown);\n onCleanup(() => props.dialog.removeEventListener(\"keydown\", onSheetKeyDown));\n });\n return (\n <div\n ref={menu}\n class=\"k2b-gesture-menu__sheet-menu\"\n role=\"menu\"\n aria-label={props.label}\n data-icons={props.icons === \"tile\" ? \"tile\" : undefined}\n onKeyDown={onKeyDown}\n >\n <props.Items items={props.items} close={() => props.close()} />\n </div>\n );\n}\n\nexport type MenuSheetOptions = {\n /** Renders the rows: the dropdown's own `DropdownItems`, passed in so this module does not import it back. */\n Items: (props: { items: readonly DropdownItem[]; close: (restoreFocus?: boolean) => void }) => JSX.Element;\n items: readonly DropdownItem[];\n /** Names the sheet and its menu. */\n label: string;\n /** The render locale of the opener; the sheet renders outside its tree. */\n locale: string;\n /** Shown above the menu, for example a row of quick reactions. `close` closes the sheet. */\n top?: (close: () => void) => JSX.Element;\n search?: DropdownSearch;\n icons?: \"plain\" | \"tile\";\n /** A quiet sentence below the entries. */\n note?: string;\n signal?: AbortSignal;\n};\n\n/** A searchable menu in the sheet: the sheet's first field, so it takes the focus as the sheet opens, as in the menu. */\nfunction SheetSearch(props: {\n Items: MenuSheetOptions[\"Items\"];\n items: readonly DropdownItem[];\n search: DropdownSearch;\n wrap: <T extends DropdownItem>(items: readonly T[]) => T[];\n label: string;\n locale: string;\n close: () => void;\n icons?: \"plain\" | \"tile\";\n}): JSX.Element {\n const [query, setQuery] = createSignal(\"\");\n const filter = props.search.filter;\n return (\n <div\n class=\"k2b-gesture-menu__sheet-menu\"\n role=\"dialog\"\n aria-label={props.label}\n data-search=\"\"\n data-icons={props.icons === \"tile\" ? \"tile\" : undefined}\n >\n <MenuSearch\n Items={props.Items}\n items={props.items}\n search={{\n ...props.search,\n // The sheet's own items are wrapped already; a host's filter returns its unwrapped entries.\n filter: (value) => (filter ? props.wrap(filter(value)) : filterDropdownItems(props.items, value, props.locale)),\n }}\n label={props.label}\n query={query}\n setQuery={setQuery}\n close={() => props.close()}\n />\n </div>\n );\n}\n\n/** Opens menu items as a bottom sheet; resolves after the sheet closed and the chosen action ran. */\nexport const openMenuSheet = (options: MenuSheetOptions): Promise<void> => {\n let chosen: (() => void) | undefined;\n const choose = (action: () => void) => {\n chosen = action;\n };\n return dialogCore\n .open<void>(\n (close, context) => (\n <LocaleProvider locale={options.locale}>\n <BottomSheet onDismiss={context.requestDismiss}>\n <BottomSheet.Body>\n {options.top?.(() => close())}\n <Show\n when={options.search}\n fallback={\n <SheetMenu\n Items={options.Items}\n items={afterClose(options.items, choose)}\n label={options.label}\n close={() => close()}\n dialog={context.dialog}\n icons={options.icons}\n />\n }\n >\n {(search) => (\n <SheetSearch\n Items={options.Items}\n items={afterClose(options.items, choose)}\n search={search()}\n wrap={(items) => afterClose(items, choose)}\n label={options.label}\n locale={options.locale}\n close={() => close()}\n icons={options.icons}\n />\n )}\n </Show>\n <Show when={options.note}>\n <p class=\"k2b-dropdown__note\">{options.note}</p>\n </Show>\n </BottomSheet.Body>\n </BottomSheet>\n </LocaleProvider>\n ),\n { ...bottomSheetOptions, ariaLabel: options.label, history: true, signal: options.signal },\n )\n .then(() => chosen?.());\n};\n"],"mappings":"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","ignoreList":[]}
|