@torpor/ui 0.4.0 → 1.0.1
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 +85 -0
- package/dist/Charts/ChartYAxis.torp +107 -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 +14 -11
- package/dist/Charts/YAxis.torp +10 -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 +120 -0
- package/dist/ComboBox/ComboBoxInput.torp +161 -0
- package/dist/ComboBox/ComboBoxTrigger.torp +49 -0
- package/dist/ComboBox/ComboBoxTypes.ts +39 -0
- package/dist/ComboBox/index.d.ts +154 -0
- package/dist/ComboBox/index.js +6 -0
- package/dist/CommandPalette/CommandPalette.torp +223 -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 +315 -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 +70 -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 +49 -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 +245 -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 +70 -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
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
+
import type { Loader } from "../utils/loader";
|
|
3
|
+
import getId from "../utils/getId";
|
|
4
|
+
import {
|
|
5
|
+
type ItemState,
|
|
6
|
+
type TreeContext,
|
|
7
|
+
TreeContextName,
|
|
8
|
+
type TreeItemContext,
|
|
9
|
+
TreeItemContextName,
|
|
10
|
+
type TreeLoadRequest,
|
|
11
|
+
} from "./TreeTypes";
|
|
12
|
+
import TreeLoadedChildren from "./TreeLoadedChildren.torp";
|
|
13
|
+
|
|
14
|
+
interface TreeItemProps {
|
|
15
|
+
/** An ID for the root element */
|
|
16
|
+
id?: string;
|
|
17
|
+
/** Classes for the root element */
|
|
18
|
+
class?: ClassValue;
|
|
19
|
+
/** Styles for the root element */
|
|
20
|
+
style?: StyleValue;
|
|
21
|
+
/** A value for the item */
|
|
22
|
+
value?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Declares that the item has children that are not slotted in. When a
|
|
25
|
+
* `load` function is available (this item's, or the tree's) they are
|
|
26
|
+
* loaded from the network when the item is first expanded.
|
|
27
|
+
*/
|
|
28
|
+
hasChildren?: boolean;
|
|
29
|
+
/** If set to true, the user cannot interact with this TreeItem */
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Reads this item's children from the network (or anywhere async),
|
|
33
|
+
* receiving `{ item }` (the item's value). Set alongside `hasChildren`;
|
|
34
|
+
* overrides the tree's `load` function for this item.
|
|
35
|
+
*/
|
|
36
|
+
load?: Loader<any, TreeLoadRequest>;
|
|
37
|
+
/** Raised when this item is expanded or collapsed */
|
|
38
|
+
onexpand?: (expanded: boolean) => void;
|
|
39
|
+
/** Raised when this item is selected or deselected */
|
|
40
|
+
onselect?: (selected: boolean) => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* An item in a Tree, which can contain nested TreeItems via TreeItemChildren.
|
|
45
|
+
*
|
|
46
|
+
* The structure of a TreeItem is:
|
|
47
|
+
*
|
|
48
|
+
* ```
|
|
49
|
+
* <TreeItem>
|
|
50
|
+
* <TreeItemContent>
|
|
51
|
+
* <TreeItemTrigger />
|
|
52
|
+
* <TreeItemLabel />
|
|
53
|
+
* </TreeItemContent>
|
|
54
|
+
* <TreeItemChildren>
|
|
55
|
+
* <TreeItem />
|
|
56
|
+
* </TreeItemChildren>
|
|
57
|
+
* </TreeItem>
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export default function TreeItem($props: TreeItemProps | undefined) {
|
|
61
|
+
let defaultId = getId();
|
|
62
|
+
|
|
63
|
+
const parentContext = $context[TreeItemContextName] as TreeItemContext;
|
|
64
|
+
const level = parentContext ? parentContext.state.level + 1 : 0;
|
|
65
|
+
|
|
66
|
+
let $state: ItemState = $watch({
|
|
67
|
+
id: $props?.id ?? defaultId,
|
|
68
|
+
index: -1,
|
|
69
|
+
value: $props?.value ?? "",
|
|
70
|
+
expanded: false,
|
|
71
|
+
selected: false,
|
|
72
|
+
disabled: $props?.disabled ?? false,
|
|
73
|
+
parentDisabled: false,
|
|
74
|
+
level,
|
|
75
|
+
hasChildren: false,
|
|
76
|
+
setFocused,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const context = $context[TreeContextName] as TreeContext;
|
|
80
|
+
if (!context) {
|
|
81
|
+
throw new Error("TreeItem must be contained within a Tree");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Whether the item declares children that aren't slotted in and can be
|
|
85
|
+
// loaded when expanded. TreeItemChildren sets `slottedChildren` itself.
|
|
86
|
+
const declaredChildren = $props?.hasChildren === true;
|
|
87
|
+
const slottedLoad = typeof $props?.load === "function" ? $props.load : undefined;
|
|
88
|
+
let slottedChildren = false;
|
|
89
|
+
|
|
90
|
+
function updateHasChildren() {
|
|
91
|
+
if (declaredChildren || slottedChildren) {
|
|
92
|
+
if (!$state.hasChildren) $state.hasChildren = true;
|
|
93
|
+
} else if ($state.hasChildren) {
|
|
94
|
+
$state.hasChildren = false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
updateHasChildren();
|
|
98
|
+
|
|
99
|
+
// The loader for this item's children: the item's own or the tree's
|
|
100
|
+
const itemLoader = slottedLoad ?? (declaredChildren ? context.load : undefined);
|
|
101
|
+
if (declaredChildren && !itemLoader) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
"TreeItem: declaring `hasChildren` requires a `load` function on the item or on the tree",
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
context.registerItem($state, $state.level);
|
|
108
|
+
|
|
109
|
+
$run(() => {
|
|
110
|
+
return () => {
|
|
111
|
+
context.removeItem($state.index);
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
$run(() => {
|
|
116
|
+
const onexpand = $props?.onexpand;
|
|
117
|
+
const expanded = $state.expanded;
|
|
118
|
+
if (onexpand) {
|
|
119
|
+
onexpand(expanded);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
$run(() => {
|
|
124
|
+
const onselect = $props?.onselect;
|
|
125
|
+
const selected = $state.selected;
|
|
126
|
+
if (onselect) {
|
|
127
|
+
onselect(selected);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
let focusLabel: (() => void) | undefined;
|
|
132
|
+
|
|
133
|
+
function setFocused() {
|
|
134
|
+
focusLabel?.();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let itemContext: TreeItemContext = {
|
|
138
|
+
state: $state,
|
|
139
|
+
setHasChildren: (hasChildren) => {
|
|
140
|
+
slottedChildren = hasChildren;
|
|
141
|
+
updateHasChildren();
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
$context[TreeItemContextName] = itemContext;
|
|
145
|
+
|
|
146
|
+
@render {
|
|
147
|
+
<div
|
|
148
|
+
{$state.id}
|
|
149
|
+
class={["torp-tree-item", $props?.class]}
|
|
150
|
+
{$props?.style}
|
|
151
|
+
role="treeitem"
|
|
152
|
+
aria-level={$state.level + 1}
|
|
153
|
+
aria-expanded={$state.hasChildren ? ($state.expanded ? "true" : "false") : undefined}
|
|
154
|
+
aria-selected={$state.selected ? "true" : "false"}
|
|
155
|
+
aria-disabled={$state.disabled || $state.parentDisabled ? "true" : undefined}
|
|
156
|
+
data-selected={$state.selected ? "selected" : undefined}
|
|
157
|
+
>
|
|
158
|
+
@// HACK: May be better to do this with CSS?
|
|
159
|
+
@if ($state.level) {
|
|
160
|
+
<div style="display: flex">
|
|
161
|
+
<div class={["torp-tree-item", $props?.class, "spacer"]} />
|
|
162
|
+
<div>
|
|
163
|
+
<slot />
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
} else {
|
|
167
|
+
<div>
|
|
168
|
+
<slot />
|
|
169
|
+
</div>
|
|
170
|
+
}
|
|
171
|
+
@if (declaredChildren && itemLoader) {
|
|
172
|
+
<TreeLoadedChildren itemState={$state} load={itemLoader} />
|
|
173
|
+
}
|
|
174
|
+
</div>
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type TreeItemContext, TreeItemContextName } from "./TreeTypes";
|
|
2
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
3
|
+
|
|
4
|
+
interface TreeItemChildrenProps {
|
|
5
|
+
/** An ID for the root element */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Classes for the root element */
|
|
8
|
+
class?: ClassValue;
|
|
9
|
+
/** Styles for the root element */
|
|
10
|
+
style?: StyleValue;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A container for nested TreeItems. This component must be a direct child of TreeItem.
|
|
15
|
+
*
|
|
16
|
+
* The structure is:
|
|
17
|
+
*
|
|
18
|
+
* ```
|
|
19
|
+
* <TreeItem>
|
|
20
|
+
* <TreeItemContent>...</TreeItemContent>
|
|
21
|
+
* <TreeItemChildren>
|
|
22
|
+
* <TreeItem />
|
|
23
|
+
* </TreeItemChildren>
|
|
24
|
+
* </TreeItem>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export default function TreeItemChildren($props?: TreeItemChildrenProps) {
|
|
28
|
+
const itemContext = $context[TreeItemContextName] as TreeItemContext;
|
|
29
|
+
|
|
30
|
+
if (!itemContext) {
|
|
31
|
+
throw new Error("TreeItemChildren must be contained within a TreeItem");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { setHasChildren, state: $state } = itemContext;
|
|
35
|
+
|
|
36
|
+
$run(() => {
|
|
37
|
+
setHasChildren(true);
|
|
38
|
+
return () => {
|
|
39
|
+
setHasChildren(false);
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// HACK: We need to keep the items in the document so that we can search through them
|
|
44
|
+
@render {
|
|
45
|
+
<div
|
|
46
|
+
{$props?.id}
|
|
47
|
+
class={["torp-tree-item-children", $props?.class, $state.expanded ? undefined : "hidden"]}
|
|
48
|
+
{$props?.style}
|
|
49
|
+
role="group"
|
|
50
|
+
>
|
|
51
|
+
<slot />
|
|
52
|
+
</div>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@style {
|
|
56
|
+
.torp-tree-item-children.hidden {
|
|
57
|
+
display: none;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
+
import { type TreeItemContext, TreeItemContextName } from "./TreeTypes";
|
|
3
|
+
|
|
4
|
+
interface TreeItemContentProps {
|
|
5
|
+
/** An ID for the root element */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Classes for the root element */
|
|
8
|
+
class?: ClassValue;
|
|
9
|
+
/** Styles for the root element */
|
|
10
|
+
style?: StyleValue;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A wrapper for the content of a TreeItem, which should contain TreeItemTrigger and TreeItemLabel.
|
|
15
|
+
*
|
|
16
|
+
* The structure is:
|
|
17
|
+
*
|
|
18
|
+
* ```
|
|
19
|
+
* <TreeItem>
|
|
20
|
+
* <TreeItemContent>
|
|
21
|
+
* <TreeItemTrigger />
|
|
22
|
+
* <TreeItemLabel />
|
|
23
|
+
* </TreeItemContent>
|
|
24
|
+
* </TreeItem>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export default function TreeItemContent($props: TreeItemContentProps | undefined) {
|
|
28
|
+
const itemContext = $context[TreeItemContextName] as TreeItemContext;
|
|
29
|
+
|
|
30
|
+
if (!itemContext) {
|
|
31
|
+
throw new Error("TreeItemLabel must be contained within a TreeItem");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { state: $state } = itemContext;
|
|
35
|
+
|
|
36
|
+
@render {
|
|
37
|
+
<div
|
|
38
|
+
{$props?.id}
|
|
39
|
+
class={["torp-tree-item-content", $props?.class]}
|
|
40
|
+
{$props?.style}
|
|
41
|
+
data-selected={$state.selected ? "selected" : undefined}
|
|
42
|
+
>
|
|
43
|
+
<slot />
|
|
44
|
+
</div>
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type TreeContext,
|
|
3
|
+
TreeContextName,
|
|
4
|
+
type TreeItemContext,
|
|
5
|
+
TreeItemContextName,
|
|
6
|
+
} from "./TreeTypes";
|
|
7
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
8
|
+
|
|
9
|
+
interface TreeItemLabelProps {
|
|
10
|
+
/** An ID for the root element */
|
|
11
|
+
id?: string;
|
|
12
|
+
/** Classes for the root element */
|
|
13
|
+
class?: ClassValue;
|
|
14
|
+
/** Styles for the root element */
|
|
15
|
+
style?: StyleValue;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The interactive label for a TreeItem, which can be clicked or keyboard-navigated to select the item.
|
|
20
|
+
* This component handles keyboard navigation and focus management for the tree.
|
|
21
|
+
*
|
|
22
|
+
* The structure is:
|
|
23
|
+
*
|
|
24
|
+
* ```
|
|
25
|
+
* <TreeItem>
|
|
26
|
+
* <TreeItemContent>
|
|
27
|
+
* <TreeItemTrigger />
|
|
28
|
+
* <TreeItemLabel>Item text</TreeItemLabel>
|
|
29
|
+
* </TreeItemContent>
|
|
30
|
+
* </TreeItem>
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export default function TreeItemLabel($props?: TreeItemLabelProps) {
|
|
34
|
+
const itemContext = $context[TreeItemContextName] as TreeItemContext;
|
|
35
|
+
const treeContext = $context[TreeContextName] as TreeContext;
|
|
36
|
+
|
|
37
|
+
if (!itemContext) {
|
|
38
|
+
throw new Error("TreeItemLabel must be contained within a TreeItem");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!treeContext) {
|
|
42
|
+
throw new Error("TreeItemLabel must be contained within a Tree");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const { state: $state } = itemContext;
|
|
46
|
+
let label: HTMLSpanElement;
|
|
47
|
+
|
|
48
|
+
$run(() => {
|
|
49
|
+
$state.setFocused = () => {
|
|
50
|
+
label.focus();
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
function handleSelectClick(e: MouseEvent) {
|
|
55
|
+
e.stopPropagation();
|
|
56
|
+
if (!$state.disabled && !$state.parentDisabled) {
|
|
57
|
+
treeContext.toggleSelect($state.value);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function handleKey(e: KeyboardEvent) {
|
|
62
|
+
switch (e.key) {
|
|
63
|
+
case "Enter":
|
|
64
|
+
case " ": {
|
|
65
|
+
e.preventDefault();
|
|
66
|
+
e.stopPropagation();
|
|
67
|
+
if (!$state.disabled && !$state.parentDisabled) {
|
|
68
|
+
treeContext.toggleSelect($state.value);
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
default: {
|
|
73
|
+
treeContext.handleKey($state.index, e);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@render {
|
|
80
|
+
<span
|
|
81
|
+
{$props?.id}
|
|
82
|
+
class={["torp-tree-item-label", $props?.class]}
|
|
83
|
+
{$props?.style}
|
|
84
|
+
tabindex="0"
|
|
85
|
+
role="none"
|
|
86
|
+
data-selected={$state.selected ? "selected" : undefined}
|
|
87
|
+
onclick={handleSelectClick}
|
|
88
|
+
onkeydown={handleKey}
|
|
89
|
+
&ref={label}
|
|
90
|
+
>
|
|
91
|
+
<slot />
|
|
92
|
+
</span>
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import ChevronDown from "../icons/ChevronDown.torp";
|
|
2
|
+
import ChevronRight from "../icons/ChevronRight.torp";
|
|
3
|
+
import {
|
|
4
|
+
type TreeContext,
|
|
5
|
+
TreeContextName,
|
|
6
|
+
type TreeItemContext,
|
|
7
|
+
TreeItemContextName,
|
|
8
|
+
} from "./TreeTypes";
|
|
9
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
10
|
+
|
|
11
|
+
interface TreeItemTriggerProps {
|
|
12
|
+
/** An ID for the root element */
|
|
13
|
+
id?: string;
|
|
14
|
+
/** Classes for the root element */
|
|
15
|
+
class?: ClassValue;
|
|
16
|
+
/** Styles for the root element */
|
|
17
|
+
style?: StyleValue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A button for expanding or collapsing a TreeItem that has nested children.
|
|
22
|
+
* When the item has no children, this renders as a spacer for consistent indentation.
|
|
23
|
+
*
|
|
24
|
+
* The structure is:
|
|
25
|
+
*
|
|
26
|
+
* ```
|
|
27
|
+
* <TreeItem>
|
|
28
|
+
* <TreeItemContent>
|
|
29
|
+
* <TreeItemTrigger />
|
|
30
|
+
* <TreeItemLabel />
|
|
31
|
+
* </TreeItemContent>
|
|
32
|
+
* </TreeItem>
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export default function TreeItemTrigger($props?: TreeItemTriggerProps) {
|
|
36
|
+
const itemContext = $context[TreeItemContextName] as TreeItemContext;
|
|
37
|
+
const treeContext = $context[TreeContextName] as TreeContext;
|
|
38
|
+
|
|
39
|
+
if (!itemContext) {
|
|
40
|
+
throw new Error("TreeItemTrigger must be contained within a TreeItem");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!treeContext) {
|
|
44
|
+
throw new Error("TreeItemTrigger must be contained within a Tree");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const { state: $state } = itemContext;
|
|
48
|
+
|
|
49
|
+
function handleClick(e: MouseEvent) {
|
|
50
|
+
e.stopPropagation();
|
|
51
|
+
treeContext.toggleExpand($state.value);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@render {
|
|
55
|
+
@if ($state.hasChildren) {
|
|
56
|
+
<button
|
|
57
|
+
{$props?.id}
|
|
58
|
+
class={["torp-tree-item-trigger", $props?.class]}
|
|
59
|
+
{$props?.style}
|
|
60
|
+
type="button"
|
|
61
|
+
disabled={$state.disabled || $state.parentDisabled}
|
|
62
|
+
aria-hidden="true"
|
|
63
|
+
tabindex="-1"
|
|
64
|
+
onclick={handleClick}
|
|
65
|
+
>
|
|
66
|
+
<slot {$state.expanded}>
|
|
67
|
+
@if ($state.expanded) {
|
|
68
|
+
<ChevronDown />
|
|
69
|
+
} else {
|
|
70
|
+
<ChevronRight />
|
|
71
|
+
}
|
|
72
|
+
</slot>
|
|
73
|
+
</button>
|
|
74
|
+
} else {
|
|
75
|
+
<span {$props?.id} class={["torp-tree-item-trigger", $props?.class, "spacer"]} {$props?.style} />
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { Loader } from "../utils/loader";
|
|
2
|
+
import { createItemLoader } from "../utils/loader";
|
|
3
|
+
import {
|
|
4
|
+
type ItemState,
|
|
5
|
+
type TreeContext,
|
|
6
|
+
TreeContextName,
|
|
7
|
+
type TreeLoadRequest,
|
|
8
|
+
} from "./TreeTypes";
|
|
9
|
+
import TreeItemChildren from "./TreeItemChildren.torp";
|
|
10
|
+
import TreeItem from "./TreeItem.torp";
|
|
11
|
+
import TreeItemContent from "./TreeItemContent.torp";
|
|
12
|
+
import TreeItemLabel from "./TreeItemLabel.torp";
|
|
13
|
+
import TreeItemTrigger from "./TreeItemTrigger.torp";
|
|
14
|
+
|
|
15
|
+
interface TreeLoadedChildrenProps {
|
|
16
|
+
/** The state of the item whose children are loaded */
|
|
17
|
+
itemState: ItemState;
|
|
18
|
+
/** The load function that reads this item's children */
|
|
19
|
+
load: Loader<any, TreeLoadRequest>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** A loaded item, normalized for rendering */
|
|
23
|
+
interface ChildEntry {
|
|
24
|
+
/** The item's value as a string, for the @key directive */
|
|
25
|
+
key: string;
|
|
26
|
+
value: any;
|
|
27
|
+
label: any;
|
|
28
|
+
hasChildren: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function defaultLabel(item: any): string {
|
|
32
|
+
const label = item?.label ?? item?.text ?? item;
|
|
33
|
+
return typeof label === "string" ? label : String(label);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function defaultValue(item: any): any {
|
|
37
|
+
return item?.value ?? item?.id;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Loads the children of a TreeItem that declares `hasChildren` but has no
|
|
42
|
+
* slotted TreeItemChildren, rendering them as nested TreeItems. The load
|
|
43
|
+
* starts when the item is first expanded and is not repeated afterwards;
|
|
44
|
+
* the results stay mounted (hidden while collapsed) so the tree can search
|
|
45
|
+
* through them.
|
|
46
|
+
*
|
|
47
|
+
* This is rendered automatically by TreeItem when there is a `load`
|
|
48
|
+
* function available; it is not part of the public API.
|
|
49
|
+
*/
|
|
50
|
+
export default function TreeLoadedChildren($props: TreeLoadedChildrenProps | undefined) {
|
|
51
|
+
const context = $context[TreeContextName] as TreeContext;
|
|
52
|
+
if (!context) {
|
|
53
|
+
throw new Error("TreeLoadedChildren must be contained within a Tree");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const $itemState = $props!.itemState;
|
|
57
|
+
|
|
58
|
+
const getLabel = context.getItemLabel ?? defaultLabel;
|
|
59
|
+
const getValue = context.getItemValue ?? defaultValue;
|
|
60
|
+
|
|
61
|
+
let $state = $watch({
|
|
62
|
+
started: false,
|
|
63
|
+
get childEntries(): ChildEntry[] {
|
|
64
|
+
return this.items.map(toEntry);
|
|
65
|
+
},
|
|
66
|
+
get items(): any[] {
|
|
67
|
+
return $load.items;
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
function toEntry(item: any): ChildEntry {
|
|
72
|
+
return {
|
|
73
|
+
key: String(getValue(item)),
|
|
74
|
+
value: getValue(item),
|
|
75
|
+
label: getLabel(item),
|
|
76
|
+
hasChildren: item?.hasChildren === true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Nothing is fetched until the item's first expansion; afterwards the
|
|
81
|
+
// loader keeps its result while the item is collapsed again
|
|
82
|
+
const $load = createItemLoader({
|
|
83
|
+
load: $props!.load,
|
|
84
|
+
getRequest: () => ({ item: $itemState.value }),
|
|
85
|
+
onload: (r) => context.onload?.(r, $itemState.value),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
$run(() => {
|
|
89
|
+
if ($itemState.expanded) {
|
|
90
|
+
$state.started = true;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
@render {
|
|
95
|
+
@if ($state.started) {
|
|
96
|
+
<TreeItemChildren>
|
|
97
|
+
@try {
|
|
98
|
+
@await {
|
|
99
|
+
@for (let entry of $state.childEntries) {
|
|
100
|
+
@key = entry.key
|
|
101
|
+
<TreeItem value={entry.value} hasChildren={entry.hasChildren}>
|
|
102
|
+
<TreeItemContent>
|
|
103
|
+
<TreeItemTrigger />
|
|
104
|
+
<TreeItemLabel>{entry.label}</TreeItemLabel>
|
|
105
|
+
</TreeItemContent>
|
|
106
|
+
</TreeItem>
|
|
107
|
+
}
|
|
108
|
+
@if ($state.childEntries.length === 0) {
|
|
109
|
+
<span class="torp-tree-item-empty">No items.</span>
|
|
110
|
+
}
|
|
111
|
+
} with {
|
|
112
|
+
<span class="torp-tree-item-loading">Loading…</span>
|
|
113
|
+
}
|
|
114
|
+
} catch (err) {
|
|
115
|
+
<span class="torp-tree-item-error" role="alert">
|
|
116
|
+
{err instanceof Error ? err.message : String(err)}
|
|
117
|
+
</span>
|
|
118
|
+
}
|
|
119
|
+
</TreeItemChildren>
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { LoadRequest, Loader } from "../utils/loader";
|
|
2
|
+
import type { LoadResult } from "../utils/loader";
|
|
3
|
+
|
|
4
|
+
/** The shape of a request sent to a Tree's `load` function */
|
|
5
|
+
export interface TreeLoadRequest extends LoadRequest {
|
|
6
|
+
/** The value of the item whose children to load */
|
|
7
|
+
item?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const TreeContextName: unique symbol = Symbol.for("torp.Tree");
|
|
11
|
+
|
|
12
|
+
export interface TreeContext {
|
|
13
|
+
type: "single" | "multiple";
|
|
14
|
+
state: TreeState;
|
|
15
|
+
registerItem: (state: ItemState, level: number) => void;
|
|
16
|
+
removeItem: (index: number) => void;
|
|
17
|
+
toggleExpand: (value: string) => void;
|
|
18
|
+
toggleSelect: (value: string) => void;
|
|
19
|
+
handleKey: (index: number, e: KeyboardEvent) => void;
|
|
20
|
+
focusFirstItem: () => void;
|
|
21
|
+
focusLastItem: () => void;
|
|
22
|
+
findItem: (index: number) => ItemState | undefined;
|
|
23
|
+
getNextVisibleItem: (index: number) => ItemState | undefined;
|
|
24
|
+
getPreviousVisibleItem: (index: number) => ItemState | undefined;
|
|
25
|
+
getParentItem: (index: number) => ItemState | undefined;
|
|
26
|
+
getFirstChildItem: (index: number) => ItemState | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Reads the children of an item that declares `hasChildren`, called when
|
|
29
|
+
* the item is first expanded
|
|
30
|
+
*/
|
|
31
|
+
load: Loader<any, TreeLoadRequest> | undefined;
|
|
32
|
+
/** Called after each successful child load with the normalized result */
|
|
33
|
+
onload: ((result: LoadResult, item: string | undefined) => void) | undefined;
|
|
34
|
+
/** Extracts the display text for a loaded item (defaults to `label ?? text ?? item`) */
|
|
35
|
+
getItemLabel: ((item: any) => any) | undefined;
|
|
36
|
+
/** Extracts the value for a loaded item (defaults to `value ?? id`) */
|
|
37
|
+
getItemValue: ((item: any) => any) | undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const TreeItemContextName: unique symbol = Symbol.for("torp.TreeItem");
|
|
41
|
+
|
|
42
|
+
export interface TreeItemContext {
|
|
43
|
+
state: ItemState;
|
|
44
|
+
setHasChildren: (hasChildren: boolean) => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface TreeState {
|
|
48
|
+
expanded?: string | string[];
|
|
49
|
+
value?: string | string[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ItemState {
|
|
53
|
+
id: string;
|
|
54
|
+
index: number;
|
|
55
|
+
value: string;
|
|
56
|
+
expanded: boolean;
|
|
57
|
+
selected: boolean;
|
|
58
|
+
disabled: boolean;
|
|
59
|
+
parentDisabled: boolean;
|
|
60
|
+
level: number;
|
|
61
|
+
hasChildren: boolean;
|
|
62
|
+
setFocused: () => void;
|
|
63
|
+
}
|