@torpor/ui 0.4.0 → 1.0.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/README.md +83 -7
- package/dist/Accordion/Accordion.torp +42 -165
- package/dist/Accordion/AccordionContent.torp +6 -6
- package/dist/Accordion/AccordionHeader.torp +7 -11
- package/dist/Accordion/AccordionItem.torp +24 -24
- package/dist/Accordion/AccordionTrigger.torp +17 -8
- package/dist/Accordion/AccordionTypes.ts +1 -1
- package/dist/Accordion/index.d.ts +23 -25
- package/dist/Accordion/index.js +6 -22
- package/dist/Breadcrumb/Breadcrumb.torp +12 -10
- package/dist/Breadcrumb/BreadcrumbItem.torp +6 -6
- package/dist/Breadcrumb/BreadcrumbList.torp +21 -0
- package/dist/Breadcrumb/BreadcrumbSeparator.torp +4 -4
- package/dist/Breadcrumb/index.d.ts +39 -15
- package/dist/Breadcrumb/index.js +5 -14
- package/dist/Calendar/Calendar.torp +163 -156
- package/dist/Calendar/CalendarDay.torp +91 -45
- package/dist/Calendar/CalendarDayHeader.torp +36 -0
- package/dist/Calendar/CalendarGrid.torp +104 -0
- package/dist/Calendar/CalendarGridHeader.torp +43 -0
- package/dist/Calendar/CalendarHeader.torp +48 -0
- package/dist/Calendar/CalendarHeaderTrigger.torp +54 -0
- package/dist/Calendar/CalendarTypes.ts +24 -3
- package/dist/Calendar/buildDays.ts +54 -0
- package/dist/Calendar/index.d.ts +191 -5
- package/dist/Calendar/index.js +8 -10
- package/dist/Carousel/Carousel.torp +180 -0
- package/dist/Carousel/CarouselIndicators.torp +65 -0
- package/dist/Carousel/CarouselNext.torp +43 -0
- package/dist/Carousel/CarouselPrevious.torp +44 -0
- package/dist/Carousel/CarouselSlide.torp +57 -0
- package/dist/Carousel/CarouselTypes.ts +28 -0
- package/dist/Carousel/index.d.ts +147 -0
- package/dist/Carousel/index.js +6 -0
- package/dist/Charts/BarChart.torp +55 -144
- package/dist/Charts/Chart.torp +120 -0
- package/dist/Charts/ChartBars.torp +78 -0
- package/dist/Charts/ChartColumns.torp +66 -0
- package/dist/Charts/ChartGrid.torp +54 -0
- package/dist/Charts/ChartLines.torp +60 -0
- package/dist/Charts/ChartTypes.ts +25 -0
- package/dist/Charts/ChartXAxis.torp +83 -0
- package/dist/Charts/ChartYAxis.torp +105 -0
- package/dist/Charts/ColumnChart.torp +70 -0
- package/dist/Charts/GridLines.torp +4 -4
- package/dist/Charts/LineChart.torp +55 -178
- package/dist/Charts/PieChart.torp +14 -20
- package/dist/Charts/ScatterChart.torp +45 -38
- package/dist/Charts/SparkLine.torp +16 -19
- package/dist/Charts/XAxis.torp +11 -11
- package/dist/Charts/YAxis.torp +8 -8
- package/dist/Charts/index.d.ts +328 -79
- package/dist/Charts/index.js +17 -34
- package/dist/ColorPicker/ColorPalette.torp +154 -0
- package/dist/ColorPicker/ColorPicker.torp +157 -0
- package/dist/ColorPicker/index.d.ts +85 -0
- package/dist/ColorPicker/index.js +3 -0
- package/dist/ComboBox/ComboBox.torp +205 -0
- package/dist/ComboBox/ComboBoxContent.torp +112 -0
- package/dist/ComboBox/ComboBoxInput.torp +145 -0
- package/dist/ComboBox/ComboBoxTrigger.torp +49 -0
- package/dist/ComboBox/ComboBoxTypes.ts +39 -0
- package/dist/ComboBox/index.d.ts +152 -0
- package/dist/ComboBox/index.js +6 -0
- package/dist/CommandPalette/CommandPalette.torp +220 -0
- package/dist/CommandPalette/CommandTypes.ts +14 -0
- package/dist/CommandPalette/index.d.ts +45 -0
- package/dist/CommandPalette/index.js +2 -0
- package/dist/Contextual/Contextual.torp +32 -50
- package/dist/Contextual/ContextualContent.torp +29 -73
- package/dist/Contextual/ContextualHover.torp +112 -0
- package/dist/Contextual/ContextualTrigger.torp +31 -42
- package/dist/Contextual/ContextualTypes.ts +4 -17
- package/dist/Contextual/index.d.ts +44 -27
- package/dist/Contextual/index.js +5 -14
- package/dist/DataGrid/DataGrid.torp +496 -0
- package/dist/DataGrid/DataGridTypes.ts +25 -0
- package/dist/DataGrid/index.d.ts +90 -0
- package/dist/DataGrid/index.js +3 -0
- package/dist/DataGrid/sortRows.ts +32 -0
- package/dist/DatePicker/DatePicker.torp +222 -0
- package/dist/DatePicker/DatePickerHeader.torp +20 -0
- package/dist/DatePicker/index.d.ts +55 -0
- package/dist/DatePicker/index.js +2 -0
- package/dist/DateRangePicker/DateRangePicker.torp +311 -0
- package/dist/DateRangePicker/DateRangePickerDay.torp +137 -0
- package/dist/DateRangePicker/DateRangePickerTypes.ts +21 -0
- package/dist/DateRangePicker/index.d.ts +76 -0
- package/dist/DateRangePicker/index.js +3 -0
- package/dist/Dialog/Dialog.torp +24 -17
- package/dist/Dialog/DialogBody.torp +5 -9
- package/dist/Dialog/DialogButton.torp +12 -12
- package/dist/Dialog/DialogFooter.torp +3 -7
- package/dist/Dialog/DialogHeader.torp +6 -10
- package/dist/Dialog/index.d.ts +27 -27
- package/dist/Dialog/index.js +6 -22
- package/dist/Disclosure/Disclosure.torp +18 -18
- package/dist/Disclosure/DisclosureContent.torp +5 -6
- package/dist/Disclosure/DisclosureHeader.torp +7 -11
- package/dist/Disclosure/DisclosureTrigger.torp +4 -5
- package/dist/Disclosure/index.d.ts +14 -16
- package/dist/Disclosure/index.js +5 -18
- package/dist/Drawer/Drawer.torp +19 -49
- package/dist/Drawer/DrawerContent.torp +67 -13
- package/dist/Drawer/DrawerOverlay.torp +4 -4
- package/dist/Drawer/DrawerTrigger.torp +16 -4
- package/dist/Drawer/DrawerTypes.ts +3 -0
- package/dist/Drawer/index.d.ts +16 -20
- package/dist/Drawer/index.js +5 -18
- package/dist/FocusGroup/FocusGroup.torp +70 -0
- package/dist/FocusGroup/FocusGroupButton.torp +59 -0
- package/dist/FocusGroup/FocusGroupTypes.ts +14 -0
- package/dist/FocusGroup/index.d.ts +44 -0
- package/dist/FocusGroup/index.js +3 -0
- package/dist/Form/CheckBox.torp +27 -18
- package/dist/Form/Field.torp +17 -17
- package/dist/Form/File.torp +31 -22
- package/dist/Form/FileDrop.torp +187 -0
- package/dist/Form/Form.torp +24 -22
- package/dist/Form/FormTypes.ts +2 -0
- package/dist/Form/FormValues.torp +37 -0
- package/dist/Form/Hidden.torp +4 -12
- package/dist/Form/Input.torp +38 -32
- package/dist/Form/Label.torp +3 -3
- package/dist/Form/Message.torp +13 -5
- package/dist/Form/MessageSummary.torp +5 -4
- package/dist/Form/Option.torp +11 -7
- package/dist/Form/Select.torp +32 -28
- package/dist/Form/TextArea.torp +35 -31
- package/dist/Form/Toggle.torp +109 -0
- package/dist/Form/index.d.ts +178 -79
- package/dist/Form/index.js +16 -50
- package/dist/ListBox/ListBox.torp +253 -150
- package/dist/ListBox/ListBoxItem.torp +54 -30
- package/dist/ListBox/ListBoxSeparator.torp +5 -2
- package/dist/ListBox/ListBoxTypes.ts +23 -5
- package/dist/ListBox/LoadedListBoxItems.torp +41 -0
- package/dist/ListBox/index.d.ts +56 -17
- package/dist/ListBox/index.js +4 -14
- package/dist/MaskedInput/MaskedInput.torp +143 -0
- package/dist/MaskedInput/index.d.ts +52 -0
- package/dist/MaskedInput/index.js +2 -0
- package/dist/Menu/Menu.torp +86 -71
- package/dist/Menu/MenuButton.torp +17 -10
- package/dist/Menu/MenuCheck.torp +22 -18
- package/dist/Menu/MenuGroup.torp +4 -4
- package/dist/Menu/MenuIndicator.torp +5 -13
- package/dist/Menu/MenuPopout.torp +20 -50
- package/dist/Menu/MenuPopoutContent.torp +15 -66
- package/dist/Menu/MenuPopoutTrigger.torp +19 -100
- package/dist/Menu/MenuRadio.torp +25 -26
- package/dist/Menu/MenuRadioGroup.torp +25 -68
- package/dist/Menu/MenuSeparator.torp +3 -2
- package/dist/Menu/MenuTypes.ts +9 -19
- package/dist/Menu/index.d.ts +45 -51
- package/dist/Menu/index.js +12 -46
- package/dist/MenuBar/MenuBar.torp +31 -83
- package/dist/MenuBar/MenuBarItem.torp +33 -51
- package/dist/MenuBar/MenuBarItemContent.torp +15 -101
- package/dist/MenuBar/MenuBarItemTrigger.torp +20 -55
- package/dist/MenuBar/MenuBarTypes.ts +11 -10
- package/dist/MenuBar/index.d.ts +17 -19
- package/dist/MenuBar/index.js +5 -18
- package/dist/Modal/Modal.torp +22 -47
- package/dist/Modal/ModalContent.torp +21 -44
- package/dist/Modal/ModalOverlay.torp +4 -4
- package/dist/Modal/ModalTrigger.torp +16 -32
- package/dist/Modal/ModalTypes.ts +5 -16
- package/dist/Modal/index.d.ts +17 -29
- package/dist/Modal/index.js +29 -28
- package/dist/Modal/index.js.map +1 -1
- package/dist/Modal/showPrompt.ts +2 -2
- package/dist/NavMenu/NavMenu.torp +22 -111
- package/dist/NavMenu/NavMenuButton.torp +7 -8
- package/dist/NavMenu/NavMenuElement.torp +6 -7
- package/dist/NavMenu/NavMenuGroup.torp +5 -5
- package/dist/NavMenu/NavMenuGroupHeader.torp +5 -8
- package/dist/NavMenu/NavMenuLink.torp +7 -10
- package/dist/NavMenu/NavMenuPopout.torp +15 -60
- package/dist/NavMenu/NavMenuPopoutContent.torp +14 -73
- package/dist/NavMenu/NavMenuPopoutTrigger.torp +17 -99
- package/dist/NavMenu/NavMenuSeparator.torp +3 -7
- package/dist/NavMenu/NavMenuTypes.ts +4 -14
- package/dist/NavMenu/index.d.ts +40 -44
- package/dist/NavMenu/index.js +11 -42
- package/dist/Notification/Notification.torp +12 -24
- package/dist/Notification/NotificationClose.torp +6 -3
- package/dist/Notification/NotificationContainer.torp +3 -7
- package/dist/Notification/NotificationContent.torp +3 -7
- package/dist/Notification/NotificationTypes.ts +1 -1
- package/dist/Notification/index.d.ts +15 -12
- package/dist/Notification/index.js +22 -32
- package/dist/Notification/index.js.map +1 -1
- package/dist/NumberInput/NumberInput.torp +255 -0
- package/dist/NumberInput/index.d.ts +44 -0
- package/dist/NumberInput/index.js +2 -0
- package/dist/Pagination/Pagination.torp +41 -34
- package/dist/Pagination/PaginationItem.torp +50 -13
- package/dist/Pagination/PaginationTypes.ts +3 -6
- package/dist/Pagination/buildPages.ts +9 -5
- package/dist/Pagination/index.d.ts +19 -9
- package/dist/Pagination/index.js +3 -40
- package/dist/Popover/Popover.torp +32 -50
- package/dist/Popover/PopoverContent.torp +27 -76
- package/dist/Popover/PopoverHover.torp +90 -0
- package/dist/Popover/PopoverTrigger.torp +17 -40
- package/dist/Popover/PopoverTypes.ts +4 -17
- package/dist/Popover/index.d.ts +40 -25
- package/dist/Popover/index.js +18 -18
- package/dist/Popover/index.js.map +1 -1
- package/dist/Progress/Progress.torp +88 -0
- package/dist/Progress/index.d.ts +37 -0
- package/dist/Progress/index.js +2 -0
- package/dist/Rating/Rating.torp +225 -0
- package/dist/Rating/index.d.ts +44 -0
- package/dist/Rating/index.js +2 -0
- package/dist/SegmentedControl/SegmentedControl.torp +233 -0
- package/dist/SegmentedControl/SegmentedControlTypes.ts +26 -0
- package/dist/SegmentedControl/SegmentedItem.torp +78 -0
- package/dist/SegmentedControl/index.d.ts +74 -0
- package/dist/SegmentedControl/index.js +3 -0
- package/dist/SelectBox/SelectBox.torp +107 -53
- package/dist/SelectBox/SelectBoxContent.torp +45 -19
- package/dist/SelectBox/SelectBoxTrigger.torp +108 -8
- package/dist/SelectBox/SelectBoxTypes.ts +26 -11
- package/dist/SelectBox/index.d.ts +39 -54
- package/dist/SelectBox/index.js +5 -18
- package/dist/Slider/Slider.torp +248 -0
- package/dist/Slider/index.d.ts +45 -0
- package/dist/Slider/index.js +2 -0
- package/dist/Splitter/Splitter.torp +156 -0
- package/dist/Splitter/SplitterHandle.torp +161 -0
- package/dist/Splitter/SplitterPane.torp +63 -0
- package/dist/Splitter/SplitterTypes.ts +31 -0
- package/dist/Splitter/index.d.ts +103 -0
- package/dist/Splitter/index.js +4 -0
- package/dist/Stepper/Stepper.torp +146 -0
- package/dist/Stepper/StepperMarker.torp +24 -0
- package/dist/Stepper/StepperNext.torp +44 -0
- package/dist/Stepper/StepperPrevious.torp +44 -0
- package/dist/Stepper/StepperStep.torp +90 -0
- package/dist/Stepper/StepperTypes.ts +30 -0
- package/dist/Stepper/index.d.ts +149 -0
- package/dist/Stepper/index.js +6 -0
- package/dist/TabGroup/TabContent.torp +6 -6
- package/dist/TabGroup/TabGroup.torp +97 -113
- package/dist/TabGroup/TabGroupTypes.ts +1 -1
- package/dist/TabGroup/TabHeader.torp +23 -19
- package/dist/TabGroup/TabList.torp +8 -21
- package/dist/TabGroup/TabTrigger.torp +6 -7
- package/dist/TabGroup/index.d.ts +26 -26
- package/dist/TabGroup/index.js +6 -22
- package/dist/TagInput/TagInput.torp +378 -0
- package/dist/TagInput/index.d.ts +48 -0
- package/dist/TagInput/index.js +2 -0
- package/dist/TimePicker/TimePicker.torp +462 -0
- package/dist/TimePicker/index.d.ts +53 -0
- package/dist/TimePicker/index.js +2 -0
- package/dist/ToolBar/ToolBar.torp +29 -110
- package/dist/ToolBar/ToolBarButton.torp +7 -8
- package/dist/ToolBar/ToolBarElement.torp +7 -11
- package/dist/ToolBar/ToolBarPopout.torp +16 -68
- package/dist/ToolBar/ToolBarPopoutContent.torp +15 -73
- package/dist/ToolBar/ToolBarPopoutTrigger.torp +19 -110
- package/dist/ToolBar/ToolBarSeparator.torp +3 -7
- package/dist/ToolBar/ToolBarTypes.ts +7 -14
- package/dist/ToolBar/index.d.ts +30 -32
- package/dist/ToolBar/index.js +8 -30
- package/dist/Tree/Tree.torp +395 -0
- package/dist/Tree/TreeItem.torp +176 -0
- package/dist/Tree/TreeItemChildren.torp +60 -0
- package/dist/Tree/TreeItemContent.torp +46 -0
- package/dist/Tree/TreeItemLabel.torp +94 -0
- package/dist/Tree/TreeItemTrigger.torp +78 -0
- package/dist/Tree/TreeLoadedChildren.torp +122 -0
- package/dist/Tree/TreeTypes.ts +63 -0
- package/dist/Tree/index.d.ts +262 -0
- package/dist/Tree/index.js +7 -0
- package/dist/icons/ChevronDoubleLeft.torp +19 -0
- package/dist/icons/ChevronDoubleRight.torp +19 -0
- package/dist/icons/index.d.ts +61 -1
- package/dist/icons/index.js +17 -58
- package/dist/loader-DEeG5vFY.js +44 -0
- package/dist/loader-DEeG5vFY.js.map +1 -0
- package/dist/motion/index.d.ts +12 -8
- package/dist/motion/index.d.ts.map +1 -0
- package/dist/motion/index.js +72 -88
- package/dist/motion/index.js.map +1 -1
- package/dist/mount/draggable.ts +63 -0
- package/dist/mount/dropTarget.ts +108 -0
- package/dist/mount/hoverTrigger.ts +1 -1
- package/dist/utils/$handle.ts +23 -0
- package/dist/utils/LoadedItems.torp +47 -0
- package/dist/utils/PopoutClickTrigger.torp +99 -0
- package/dist/utils/PopoutTypes.ts +59 -12
- package/dist/utils/SubmenuPopout.torp +89 -0
- package/dist/utils/SubmenuPopoutContent.torp +87 -0
- package/dist/utils/SubmenuPopoutTrigger.torp +160 -0
- package/dist/utils/chartColors.ts +13 -13
- package/dist/utils/chartLayout.ts +143 -0
- package/dist/utils/colorUtils.ts +103 -0
- package/dist/utils/createItemGroup.ts +152 -0
- package/dist/utils/dateUtils.ts +8 -7
- package/dist/utils/documentEvents.ts +4 -4
- package/dist/utils/dragState.ts +86 -0
- package/dist/utils/focusGroup.ts +204 -0
- package/dist/utils/focusItem.ts +44 -0
- package/dist/utils/formField.ts +70 -0
- package/dist/utils/hoverOpen.ts +50 -0
- package/dist/utils/hoverReveal.ts +194 -0
- package/dist/utils/loader.ts +113 -0
- package/dist/utils/maskUtils.ts +98 -0
- package/dist/utils/popoutContent.ts +137 -0
- package/dist/utils/reorderList.ts +52 -0
- package/package.json +97 -22
- package/dist/Accordion/index.js.map +0 -1
- package/dist/Breadcrumb/index.js.map +0 -1
- package/dist/Calendar/index.js.map +0 -1
- package/dist/Charts/index.js.map +0 -1
- package/dist/Contextual/index.js.map +0 -1
- package/dist/Dialog/index.js.map +0 -1
- package/dist/Disclosure/index.js.map +0 -1
- package/dist/Drawer/index.js.map +0 -1
- package/dist/Form/index.js.map +0 -1
- package/dist/ListBox/index.js.map +0 -1
- package/dist/Menu/index.js.map +0 -1
- package/dist/MenuBar/index.js.map +0 -1
- package/dist/NavMenu/index.js.map +0 -1
- package/dist/Pagination/index.js.map +0 -1
- package/dist/SelectBox/SelectBoxInput.torp +0 -95
- package/dist/SelectBox/index.js.map +0 -1
- package/dist/TabGroup/index.js.map +0 -1
- package/dist/ToolBar/index.js.map +0 -1
- package/dist/icons/index.js.map +0 -1
- package/dist/index.d.ts +0 -19
- package/dist/metafile-esm.json +0 -1
- package/dist/motion/fade.ts +0 -16
- package/dist/motion/grow.ts +0 -23
- package/dist/motion/measure.ts +0 -28
- package/dist/motion/slide.ts +0 -45
- package/dist/mount/index.d.ts +0 -2
- package/dist/utils/index.d.ts +0 -2
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
1
|
+
import type { Bindable, ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
+
import $handle from "../utils/$handle";
|
|
3
|
+
import {
|
|
4
|
+
type FieldContext,
|
|
5
|
+
FieldContextName,
|
|
6
|
+
type FormContext,
|
|
7
|
+
FormContextName,
|
|
8
|
+
} from "../Form/FormTypes";
|
|
9
|
+
import FormValues from "../Form/FormValues.torp";
|
|
10
|
+
import { type LoadResult, type Loader, createItemLoader } from "../utils/loader";
|
|
11
|
+
import { createItemGroup } from "../utils/createItemGroup";
|
|
2
12
|
import getId from "../utils/getId";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
13
|
+
import createFormField from "../utils/formField";
|
|
14
|
+
import { type HandleButtonPress, type PopoutContext, PopoutContextName } from "../utils/PopoutTypes";
|
|
15
|
+
import LoadedListBoxItems from "./LoadedListBoxItems.torp";
|
|
16
|
+
import { type ItemState, type ListBoxContext, ListBoxContextName } from "./ListBoxTypes";
|
|
5
17
|
|
|
6
18
|
// TODO: orientation
|
|
7
19
|
|
|
@@ -9,19 +21,39 @@ interface ListBoxProps {
|
|
|
9
21
|
/** An ID for the root element */
|
|
10
22
|
id?: string;
|
|
11
23
|
/** Classes for the root element */
|
|
12
|
-
class?: ClassValue
|
|
24
|
+
class?: ClassValue;
|
|
13
25
|
/** Styles for the root element */
|
|
14
|
-
style?: StyleValue
|
|
26
|
+
style?: StyleValue;
|
|
15
27
|
/** Whether a single ListBoxItem or multiple ListBoxItems can be selected at the same time */
|
|
16
|
-
type?: "single" | "multiple"
|
|
28
|
+
type?: "single" | "multiple";
|
|
17
29
|
/** The value of the selected ListBoxItem, or an array of values if the type is "multiple" */
|
|
18
|
-
value
|
|
30
|
+
value: Bindable<any | any[]>;
|
|
19
31
|
/** If set to true, the user cannot interact with any items in the ListBox */
|
|
20
|
-
disabled?: boolean
|
|
32
|
+
disabled?: boolean;
|
|
21
33
|
/** An ARIA label for describing the ListBox to screen readers */
|
|
22
|
-
ariaLabel?: string | undefined
|
|
34
|
+
ariaLabel?: string | undefined;
|
|
35
|
+
/** An ID of an element that labels the ListBox */
|
|
36
|
+
ariaLabelledBy?: string | undefined;
|
|
37
|
+
/** The orientation of the ListBox */
|
|
38
|
+
orientation?: "vertical" | "horizontal";
|
|
23
39
|
/** Raised when the selected item(s) have changed */
|
|
24
|
-
|
|
40
|
+
/** The name of the component's form data field */
|
|
41
|
+
name?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Reads options from the network (or anywhere async), receiving
|
|
44
|
+
* `{ searchText }` whenever the bound `searchText` changes. When set and
|
|
45
|
+
* no ListBoxItems are slotted in, the options are rendered automatically
|
|
46
|
+
*/
|
|
47
|
+
load?: Loader;
|
|
48
|
+
/** Called after each successful load with the normalized result */
|
|
49
|
+
onload?: (result: LoadResult) => void;
|
|
50
|
+
/** Extracts the display text for a loaded item (defaults to `label ?? text ?? item`) */
|
|
51
|
+
getItemLabel?: (item: any) => any;
|
|
52
|
+
/** Extracts the value for a loaded item (defaults to `value ?? id`) */
|
|
53
|
+
getItemValue?: (item: any) => any;
|
|
54
|
+
/** Filter text for a `load` function; two-way bindable */
|
|
55
|
+
searchText?: Bindable<string | undefined>;
|
|
56
|
+
onchange?: (value: any | any[]) => void;
|
|
25
57
|
}
|
|
26
58
|
|
|
27
59
|
/**
|
|
@@ -40,28 +72,44 @@ interface ListBoxProps {
|
|
|
40
72
|
*/
|
|
41
73
|
export default function ListBox($props: ListBoxProps | undefined) {
|
|
42
74
|
let defaultId = getId();
|
|
43
|
-
let
|
|
75
|
+
let root: HTMLElement;
|
|
44
76
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
77
|
+
// Wire up the enclosing Form and Field, if any
|
|
78
|
+
const form = createFormField(
|
|
79
|
+
$props?.name,
|
|
80
|
+
$context[FormContextName] as FormContext | undefined,
|
|
81
|
+
$context[FieldContextName] as FieldContext | undefined,
|
|
82
|
+
);
|
|
48
83
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
84
|
+
// Get the current selection type, re-reading $props so changes are picked up
|
|
85
|
+
function getType(): "single" | "multiple" {
|
|
86
|
+
return $props?.type ?? "single";
|
|
87
|
+
}
|
|
53
88
|
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
89
|
+
// This may come from a PopoutContext, or we may need to handle it ourselves
|
|
90
|
+
let searchText: string | undefined;
|
|
91
|
+
|
|
92
|
+
let $state = $watch({
|
|
93
|
+
value: $props?.value ?? (getType() === "single" ? undefined : []),
|
|
94
|
+
searchText: undefined as string | undefined,
|
|
59
95
|
});
|
|
60
96
|
|
|
61
|
-
|
|
97
|
+
$bind($state, $props, "value", "searchText");
|
|
62
98
|
|
|
63
|
-
|
|
64
|
-
|
|
99
|
+
if ($props?.load !== undefined && typeof $props.load !== "function") {
|
|
100
|
+
throw new Error("ListBox: `load` must be a function");
|
|
101
|
+
}
|
|
102
|
+
const hasLoader = typeof $props?.load === "function";
|
|
103
|
+
|
|
104
|
+
// Load options whenever the search text changes; pass the loaded items
|
|
105
|
+
// and getters through the context for the slot fallback to render
|
|
106
|
+
const $load = hasLoader
|
|
107
|
+
? createItemLoader({
|
|
108
|
+
load: $props!.load!,
|
|
109
|
+
getRequest: () => ({ searchText: $state.searchText }),
|
|
110
|
+
onload: (r) => $props?.onload?.(r),
|
|
111
|
+
})
|
|
112
|
+
: undefined;
|
|
65
113
|
|
|
66
114
|
// Maybe get stuff out of a popout context
|
|
67
115
|
let handleButton: HandleButtonPress | undefined = undefined;
|
|
@@ -74,185 +122,204 @@ export default function ListBox($props: ListBoxProps | undefined) {
|
|
|
74
122
|
// called after everything has been shown
|
|
75
123
|
popoutContext.focusFirstElement = focusFirstElement;
|
|
76
124
|
popoutContext.focusLastElement = focusLastElement;
|
|
125
|
+
popoutContext.markElement = markElement;
|
|
126
|
+
popoutContext.selectMarkedElement = selectMarkedElement;
|
|
127
|
+
popoutContext.searchItems = searchItems;
|
|
77
128
|
|
|
78
|
-
// Set the content ID so that
|
|
129
|
+
// Set the content ID and role so that triggers can use them with
|
|
130
|
+
// aria-controls / aria-haspopup
|
|
79
131
|
popoutContext.state.contentId = $props?.id ?? defaultId;
|
|
132
|
+
popoutContext.state.contentRole = "listbox";
|
|
80
133
|
}
|
|
81
134
|
|
|
135
|
+
const group = createItemGroup<ItemState>({
|
|
136
|
+
state: $state,
|
|
137
|
+
type: getType,
|
|
138
|
+
selectedProperty: "selected",
|
|
139
|
+
disabled: () => $props?.disabled,
|
|
140
|
+
onToggle: () => {
|
|
141
|
+
// Clear the keyboard focus marker
|
|
142
|
+
for (let item of group.itemStates) {
|
|
143
|
+
item.active = false;
|
|
144
|
+
}
|
|
145
|
+
form.handleInput();
|
|
146
|
+
// Pass this along to the containing popout if applicable
|
|
147
|
+
if (handleButton) {
|
|
148
|
+
if (getType() === "single") {
|
|
149
|
+
handleButton("confirm", $state.value);
|
|
150
|
+
} else {
|
|
151
|
+
handleButton(undefined, $state.value);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
82
157
|
// Set the context to pass down to items, with functions for each item to call
|
|
83
158
|
let context: ListBoxContext = {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
159
|
+
get type() {
|
|
160
|
+
return getType();
|
|
161
|
+
},
|
|
162
|
+
state: $state,
|
|
163
|
+
registerItem: group.registerItem,
|
|
164
|
+
removeItem: group.removeItem,
|
|
165
|
+
toggleItem: group.toggleItem,
|
|
87
166
|
handleKey,
|
|
167
|
+
setActiveDescendant: popoutContext ? (id) => { popoutContext.state.activeDescendant = id; } : undefined,
|
|
168
|
+
getLoadedItems: $load ? () => $load.items : undefined,
|
|
169
|
+
getItemLabel: $props?.getItemLabel,
|
|
170
|
+
getItemValue: $props?.getItemValue,
|
|
88
171
|
};
|
|
89
172
|
$context[ListBoxContextName] = context;
|
|
90
173
|
|
|
174
|
+
// Dispatch the change event when the value changes
|
|
175
|
+
$handle((first) => {
|
|
176
|
+
const value = $state.value;
|
|
177
|
+
if (!first) $props?.onchange?.(value);
|
|
178
|
+
});
|
|
179
|
+
|
|
91
180
|
function focusFirstElement() {
|
|
92
|
-
if (itemStates.length > 0) {
|
|
93
|
-
itemStates[0].setFocused();
|
|
181
|
+
if (group.itemStates.length > 0) {
|
|
182
|
+
group.itemStates[0].setFocused();
|
|
94
183
|
}
|
|
95
184
|
}
|
|
96
185
|
|
|
97
186
|
function focusLastElement() {
|
|
98
|
-
if (itemStates.length > 0) {
|
|
99
|
-
itemStates.at(-1)!.setFocused();
|
|
187
|
+
if (group.itemStates.length > 0) {
|
|
188
|
+
group.itemStates.at(-1)!.setFocused();
|
|
100
189
|
}
|
|
101
190
|
}
|
|
102
191
|
|
|
103
|
-
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
for (let item of itemStates) {
|
|
111
|
-
item.selected = item.value === value;
|
|
112
|
-
}
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
case "multiple": {
|
|
116
|
-
if (!Array.isArray(value)) {
|
|
117
|
-
value = [value];
|
|
118
|
-
}
|
|
119
|
-
for (let item of itemStates) {
|
|
120
|
-
item.selected = value.indexOf(item.value) !== -1;
|
|
121
|
-
}
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
$run(() => {
|
|
128
|
-
let disabled = $props?.disabled;
|
|
129
|
-
itemStates.forEach((s) => s.parentDisabled = disabled === true);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
// Dispatch the change event when the value changes
|
|
133
|
-
let firstChange = true;
|
|
134
|
-
$run(() => {
|
|
135
|
-
const onchange = $props?.onchange;
|
|
136
|
-
const value = $state.value;
|
|
137
|
-
if (firstChange) {
|
|
138
|
-
firstChange = false;
|
|
139
|
-
} else if (onchange) {
|
|
140
|
-
onchange(value);
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
function registerItem(itemState: ItemState) {
|
|
145
|
-
// If an index wasn't set for the item, set it automatically
|
|
146
|
-
if (itemState.index === -1) {
|
|
147
|
-
itemState.index = nextIndex++;
|
|
148
|
-
}
|
|
192
|
+
function markElement(id: string) {
|
|
193
|
+
// selected stays derived from the group value; active marks the
|
|
194
|
+
// keyboard-focus preview
|
|
195
|
+
group.itemStates.forEach((i) => {
|
|
196
|
+
i.active = i.id === id;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
149
199
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
200
|
+
function selectMarkedElement() {
|
|
201
|
+
const marked = group.itemStates.find((i) => i.active === true);
|
|
202
|
+
if (marked && handleButton) {
|
|
203
|
+
handleButton("confirm", marked.value);
|
|
153
204
|
}
|
|
205
|
+
}
|
|
154
206
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
case "multiple": {
|
|
163
|
-
itemState.selected = $state.value.includes(itemState.value);
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
207
|
+
function searchItems(searchText: string) {
|
|
208
|
+
const normalizedSearchText = searchText.toLocaleLowerCase();
|
|
209
|
+
for (let item of group.itemStates) {
|
|
210
|
+
if (item.text.toLocaleLowerCase().includes(normalizedSearchText)) {
|
|
211
|
+
return item;
|
|
166
212
|
}
|
|
167
213
|
}
|
|
168
|
-
|
|
169
|
-
// Set whether the ListBox itself is disabled
|
|
170
|
-
itemState.parentDisabled = $props?.disabled === true
|
|
171
|
-
|
|
172
|
-
// Add the item's state to the array
|
|
173
|
-
itemStates.splice(itemState.index, 0, itemState);
|
|
174
214
|
}
|
|
175
215
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
itemStates.forEach((item, i) => (item.index = i));
|
|
216
|
+
function focusSelectedElement() {
|
|
217
|
+
// Called when the list box receives focus: focus the selected option,
|
|
218
|
+
// or the first option if none is selected
|
|
219
|
+
const itemStates = group.itemStates;
|
|
220
|
+
const target = itemStates.find((i) => i.selected) ?? itemStates[0];
|
|
221
|
+
target?.setFocused();
|
|
184
222
|
}
|
|
185
223
|
|
|
186
|
-
function
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
// Pass this along to the containing popout if applicable, so
|
|
196
|
-
// that the popout can be closed
|
|
197
|
-
if (handleButton) {
|
|
198
|
-
handleButton("confirm", value)
|
|
199
|
-
}
|
|
200
|
-
break;
|
|
224
|
+
function handleKey(index: number, e: KeyboardEvent) {
|
|
225
|
+
const itemStates = group.itemStates;
|
|
226
|
+
// Finds the nearest focusable item, skipping disabled ones
|
|
227
|
+
const findFocusable = (from: number, step: number): number => {
|
|
228
|
+
let i = from;
|
|
229
|
+
while (i >= 0 && i < itemStates.length && itemStates[i].disabled) {
|
|
230
|
+
i += step;
|
|
201
231
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
newValue.push(item.value);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
$state.value = newValue.sort();
|
|
213
|
-
break;
|
|
232
|
+
return i;
|
|
233
|
+
};
|
|
234
|
+
const clearSearch = () => {
|
|
235
|
+
if (popoutContext) {
|
|
236
|
+
popoutContext.searchText = undefined;
|
|
237
|
+
} else {
|
|
238
|
+
searchText = undefined;
|
|
214
239
|
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function handleKey(index: number, e: KeyboardEvent) {
|
|
240
|
+
};
|
|
219
241
|
switch (e.key) {
|
|
220
|
-
case "Up":
|
|
221
242
|
case "ArrowUp": {
|
|
222
|
-
|
|
243
|
+
const target = findFocusable(index - 1, -1);
|
|
244
|
+
if (target >= 0) {
|
|
223
245
|
e.preventDefault();
|
|
224
|
-
itemStates[
|
|
246
|
+
itemStates[target].setFocused();
|
|
247
|
+
clearSearch();
|
|
225
248
|
}
|
|
226
249
|
break;
|
|
227
250
|
}
|
|
228
|
-
case "Down":
|
|
229
251
|
case "ArrowDown": {
|
|
230
|
-
|
|
252
|
+
const target = findFocusable(index + 1, 1);
|
|
253
|
+
if (target < itemStates.length) {
|
|
231
254
|
e.preventDefault();
|
|
232
|
-
itemStates[
|
|
255
|
+
itemStates[target].setFocused();
|
|
256
|
+
clearSearch();
|
|
233
257
|
}
|
|
234
258
|
break;
|
|
235
259
|
}
|
|
236
260
|
case "Home": {
|
|
237
261
|
if (index > 0) {
|
|
238
262
|
e.preventDefault();
|
|
239
|
-
itemStates[0].setFocused();
|
|
263
|
+
itemStates[findFocusable(0, 1)].setFocused();
|
|
264
|
+
clearSearch();
|
|
240
265
|
}
|
|
241
266
|
break;
|
|
242
267
|
}
|
|
243
268
|
case "End": {
|
|
244
269
|
if (index < itemStates.length - 1) {
|
|
245
270
|
e.preventDefault();
|
|
246
|
-
itemStates[itemStates.length - 1].setFocused();
|
|
271
|
+
itemStates[findFocusable(itemStates.length - 1, -1)].setFocused();
|
|
272
|
+
clearSearch();
|
|
247
273
|
}
|
|
248
274
|
break;
|
|
249
275
|
}
|
|
250
276
|
case "Escape": {
|
|
251
277
|
if (handleButton) {
|
|
252
|
-
handleButton("cancel")
|
|
278
|
+
handleButton("cancel");
|
|
279
|
+
if (popoutContext) {
|
|
280
|
+
popoutContext.searchText = undefined;
|
|
281
|
+
} else {
|
|
282
|
+
searchText = undefined;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
case "Backspace": {
|
|
288
|
+
if (popoutContext?.searchText || searchText) {
|
|
289
|
+
e.preventDefault();
|
|
290
|
+
const shorten = (str: string) => str.substring(0, str.length - 1);
|
|
291
|
+
if (popoutContext) {
|
|
292
|
+
popoutContext.searchText = shorten(popoutContext.searchText!);
|
|
293
|
+
searchText = popoutContext.searchText;
|
|
294
|
+
} else {
|
|
295
|
+
searchText = shorten(searchText!);
|
|
296
|
+
}
|
|
297
|
+
if (searchText.length > 0) {
|
|
298
|
+
const found = searchItems(searchText);
|
|
299
|
+
if (found) {
|
|
300
|
+
found.setFocused();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
253
303
|
}
|
|
254
304
|
break;
|
|
255
305
|
}
|
|
306
|
+
default: {
|
|
307
|
+
// TODO: Handle unicode
|
|
308
|
+
if (e.key.length === 1) {
|
|
309
|
+
e.preventDefault();
|
|
310
|
+
const lengthen = (str: string) => (str ??= "") + e.key;
|
|
311
|
+
if (popoutContext) {
|
|
312
|
+
popoutContext.searchText = lengthen(popoutContext.searchText!);
|
|
313
|
+
searchText = popoutContext.searchText;
|
|
314
|
+
} else {
|
|
315
|
+
searchText = lengthen(searchText!);
|
|
316
|
+
}
|
|
317
|
+
const found = searchItems(searchText);
|
|
318
|
+
if (found) {
|
|
319
|
+
found.setFocused();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
256
323
|
}
|
|
257
324
|
}
|
|
258
325
|
|
|
@@ -262,10 +329,46 @@ export default function ListBox($props: ListBoxProps | undefined) {
|
|
|
262
329
|
class={["torp-list-box", $props?.class]}
|
|
263
330
|
{$props?.style}
|
|
264
331
|
role="listbox"
|
|
332
|
+
tabindex="0"
|
|
333
|
+
onfocus={focusSelectedElement}
|
|
265
334
|
aria-label={$props?.ariaLabel}
|
|
266
|
-
aria-
|
|
335
|
+
aria-labelledby={$props?.ariaLabelledBy}
|
|
336
|
+
aria-multiselectable={getType() === "multiple" ? "true" : undefined}
|
|
337
|
+
aria-disabled={$props?.disabled ? "true" : undefined}
|
|
338
|
+
aria-orientation={$props?.orientation}
|
|
339
|
+
data-valid={form.valid ? "valid" : "invalid"}
|
|
340
|
+
aria-describedby={form.messageId}
|
|
341
|
+
aria-invalid={form.inField && !form.valid ? "true" : undefined}
|
|
342
|
+
onfocusout={(e: FocusEvent) => {
|
|
343
|
+
// Only validate when focus leaves the whole list box
|
|
344
|
+
if (!root.contains(e.relatedTarget as Node | null)) {
|
|
345
|
+
form.handleBlur();
|
|
346
|
+
}
|
|
347
|
+
}}
|
|
348
|
+
&ref={root}
|
|
267
349
|
>
|
|
268
|
-
<slot
|
|
350
|
+
<slot>
|
|
351
|
+
@if (context.getLoadedItems) {
|
|
352
|
+
@// Options loaded from a network loader, rendered automatically
|
|
353
|
+
@try {
|
|
354
|
+
@await {
|
|
355
|
+
<LoadedListBoxItems
|
|
356
|
+
items={context.getLoadedItems!()}
|
|
357
|
+
getItemLabel={context.getItemLabel}
|
|
358
|
+
getItemValue={context.getItemValue}
|
|
359
|
+
/>
|
|
360
|
+
} with {
|
|
361
|
+
<div class="torp-list-box-loading" role="status">Loading…</div>
|
|
362
|
+
}
|
|
363
|
+
} catch (err) {
|
|
364
|
+
<div class="torp-list-box-error" role="alert">
|
|
365
|
+
{err instanceof Error ? err.message : String(err)}
|
|
366
|
+
</div>
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
</slot>
|
|
269
370
|
</div>
|
|
371
|
+
|
|
372
|
+
<FormValues name={form.name} value={$state.value} />
|
|
270
373
|
}
|
|
271
374
|
}
|
|
@@ -1,35 +1,44 @@
|
|
|
1
1
|
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
-
import
|
|
2
|
+
import $handle from "../utils/$handle";
|
|
3
|
+
import getId from "../utils/getId";
|
|
4
|
+
import { type ItemState, type ListBoxContext, ListBoxContextName } from "./ListBoxTypes";
|
|
3
5
|
|
|
4
6
|
interface ListBoxItemProps {
|
|
5
7
|
/** An ID for the root element */
|
|
6
8
|
id?: string;
|
|
7
9
|
/** Classes for the root element */
|
|
8
|
-
class?: ClassValue
|
|
10
|
+
class?: ClassValue;
|
|
9
11
|
/** Styles for the root element */
|
|
10
|
-
style?: StyleValue
|
|
12
|
+
style?: StyleValue;
|
|
11
13
|
/** The index of this item in the ListBox. Set this if you will be inserting, removing or sorting items. If you don't set this, it will be set automatically */
|
|
12
|
-
index?: number
|
|
14
|
+
index?: number;
|
|
15
|
+
/** The text for the item. If not set, this will come from it's text content */
|
|
16
|
+
text?: string;
|
|
13
17
|
/** A value for the item. Set this if you need more control over which item(s) are selected. If you don't set this, the value will be set to the item's initial index */
|
|
14
|
-
value?: string
|
|
18
|
+
value?: string;
|
|
15
19
|
/** If set to true, the user cannot interact with this ListBoxItem */
|
|
16
|
-
disabled?: boolean
|
|
17
|
-
/** Raised when this item
|
|
18
|
-
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/** Raised when this item's selected state has changed */
|
|
22
|
+
onchange?: (selected: boolean) => void;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* An item in an ListBox.
|
|
23
27
|
*/
|
|
24
28
|
export default function ListBoxItem($props: ListBoxItemProps | undefined) {
|
|
29
|
+
let defaultId = getId();
|
|
30
|
+
|
|
25
31
|
let $state: ItemState = $watch({
|
|
32
|
+
id: $props?.id ?? defaultId,
|
|
26
33
|
index: -1,
|
|
27
|
-
|
|
34
|
+
text: $props?.text ?? "",
|
|
35
|
+
value: $props?.value,
|
|
28
36
|
selected: false,
|
|
37
|
+
active: false,
|
|
29
38
|
disabled: $props?.disabled ?? false,
|
|
30
39
|
parentDisabled: false,
|
|
31
|
-
setFocused
|
|
32
|
-
})
|
|
40
|
+
setFocused,
|
|
41
|
+
});
|
|
33
42
|
|
|
34
43
|
let button: HTMLButtonElement;
|
|
35
44
|
|
|
@@ -40,25 +49,19 @@ export default function ListBoxItem($props: ListBoxItemProps | undefined) {
|
|
|
40
49
|
}
|
|
41
50
|
|
|
42
51
|
// Register this item with the parent ListBox, which will handle toggling selected for all items
|
|
43
|
-
context.registerItem($state
|
|
52
|
+
context.registerItem($state);
|
|
44
53
|
|
|
45
54
|
// Remove the item from the parent ListBox when this item is destroyed
|
|
46
55
|
$run(() => {
|
|
47
56
|
return () => {
|
|
48
57
|
context.removeItem($state.index);
|
|
49
|
-
}
|
|
58
|
+
};
|
|
50
59
|
});
|
|
51
60
|
|
|
52
|
-
// Dispatch the
|
|
53
|
-
|
|
54
|
-
$run(() => {
|
|
55
|
-
const ontoggle = $props?.ontoggle;
|
|
61
|
+
// Dispatch the change event when the value of selected changes
|
|
62
|
+
$handle((first) => {
|
|
56
63
|
const selected = $state.selected;
|
|
57
|
-
if (
|
|
58
|
-
firstToggle = false;
|
|
59
|
-
} else if (ontoggle) {
|
|
60
|
-
ontoggle(selected);
|
|
61
|
-
}
|
|
64
|
+
if (!first) $props?.onchange?.(selected);
|
|
62
65
|
});
|
|
63
66
|
|
|
64
67
|
// This function is called by the parent ListBox to focus this item's button
|
|
@@ -68,37 +71,58 @@ export default function ListBoxItem($props: ListBoxItemProps | undefined) {
|
|
|
68
71
|
|
|
69
72
|
function handleClick() {
|
|
70
73
|
// Pass the value to the toggleItem method in the parent ListBox which will handle toggling
|
|
71
|
-
// the value of
|
|
74
|
+
// the value of selected for all items (e.g. to unselect other items if necessary)
|
|
72
75
|
context.toggleItem($state.value);
|
|
73
76
|
}
|
|
74
77
|
|
|
78
|
+
function handleFocus() {
|
|
79
|
+
if (context.setActiveDescendant) {
|
|
80
|
+
context.setActiveDescendant($state.id);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
75
84
|
function handleKey(e: KeyboardEvent) {
|
|
76
|
-
// For testing
|
|
77
85
|
switch (e.key) {
|
|
78
|
-
case "Enter":
|
|
86
|
+
case "Enter": {
|
|
79
87
|
e.preventDefault();
|
|
80
88
|
context.toggleItem($state.value);
|
|
81
89
|
break;
|
|
82
|
-
|
|
90
|
+
}
|
|
91
|
+
default: {
|
|
83
92
|
// Pass the key press up to the parent ListBox which will handle
|
|
84
93
|
// setting the focused button
|
|
85
94
|
context.handleKey($state.index, e);
|
|
86
95
|
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function handleMount(el: HTMLButtonElement) {
|
|
101
|
+
// If the item has no value, set it to the text content; selected is
|
|
102
|
+
// derived from the group value, so it picks this up automatically
|
|
103
|
+
if (!$state.text) {
|
|
104
|
+
$state.text = el.textContent.trim();
|
|
105
|
+
}
|
|
106
|
+
if ($state.value === undefined || $state.value === null) {
|
|
107
|
+
$state.value = $state.text;
|
|
87
108
|
}
|
|
88
109
|
}
|
|
89
110
|
|
|
90
111
|
@render {
|
|
91
112
|
<button
|
|
92
|
-
|
|
113
|
+
type="button"
|
|
114
|
+
{$state.id}
|
|
93
115
|
class={["torp-list-box-item", $props?.class]}
|
|
94
116
|
{$props?.style}
|
|
95
117
|
role="option"
|
|
118
|
+
tabindex="-1"
|
|
96
119
|
aria-selected={$state.selected ? "true" : "false"}
|
|
97
|
-
aria-disabled={$state.disabled ? "true" : undefined}
|
|
98
|
-
data-state={$state.selected ? "active" : undefined}
|
|
99
|
-
data-disabled={$state.disabled ? "true" : undefined}
|
|
120
|
+
aria-disabled={$state.disabled || $state.parentDisabled ? "true" : undefined}
|
|
121
|
+
data-state={$state.selected || $state.active ? "active" : undefined}
|
|
100
122
|
onclick={handleClick}
|
|
101
123
|
onkeydown={handleKey}
|
|
124
|
+
onfocus={handleFocus}
|
|
125
|
+
onmount={handleMount}
|
|
102
126
|
&ref={button}
|
|
103
127
|
>
|
|
104
128
|
<slot />
|
|
@@ -4,9 +4,11 @@ interface ListBoxSeparatorProps {
|
|
|
4
4
|
/** An ID for the root element */
|
|
5
5
|
id?: string;
|
|
6
6
|
/** Classes for the root element */
|
|
7
|
-
class?: ClassValue
|
|
7
|
+
class?: ClassValue;
|
|
8
8
|
/** Styles for the root element */
|
|
9
|
-
style?: StyleValue
|
|
9
|
+
style?: StyleValue;
|
|
10
|
+
/** The orientation of the separator */
|
|
11
|
+
orientation?: "vertical" | "horizontal";
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
/**
|
|
@@ -19,6 +21,7 @@ export default function ListBoxSeparator($props: ListBoxSeparatorProps | undefin
|
|
|
19
21
|
class={["torp-list-box-separator", $props?.class]}
|
|
20
22
|
{$props?.style}
|
|
21
23
|
role="separator"
|
|
24
|
+
aria-orientation={$props?.orientation ?? "horizontal"}
|
|
22
25
|
>
|
|
23
26
|
<slot />
|
|
24
27
|
</div>
|