@torpor/ui 0.3.7 → 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.
Files changed (346) hide show
  1. package/README.md +83 -7
  2. package/dist/Accordion/Accordion.torp +43 -165
  3. package/dist/Accordion/AccordionContent.torp +6 -6
  4. package/dist/Accordion/AccordionHeader.torp +7 -11
  5. package/dist/Accordion/AccordionItem.torp +24 -24
  6. package/dist/Accordion/AccordionTrigger.torp +17 -8
  7. package/dist/Accordion/AccordionTypes.ts +6 -6
  8. package/dist/Accordion/index.d.ts +23 -25
  9. package/dist/Accordion/index.js +6 -22
  10. package/dist/Breadcrumb/Breadcrumb.torp +12 -10
  11. package/dist/Breadcrumb/BreadcrumbItem.torp +6 -6
  12. package/dist/Breadcrumb/BreadcrumbList.torp +21 -0
  13. package/dist/Breadcrumb/BreadcrumbSeparator.torp +4 -4
  14. package/dist/Breadcrumb/index.d.ts +39 -15
  15. package/dist/Breadcrumb/index.js +5 -14
  16. package/dist/Calendar/Calendar.torp +163 -156
  17. package/dist/Calendar/CalendarDay.torp +91 -45
  18. package/dist/Calendar/CalendarDayHeader.torp +36 -0
  19. package/dist/Calendar/CalendarGrid.torp +104 -0
  20. package/dist/Calendar/CalendarGridHeader.torp +43 -0
  21. package/dist/Calendar/CalendarHeader.torp +48 -0
  22. package/dist/Calendar/CalendarHeaderTrigger.torp +54 -0
  23. package/dist/Calendar/CalendarTypes.ts +25 -4
  24. package/dist/Calendar/buildDays.ts +54 -0
  25. package/dist/Calendar/index.d.ts +191 -5
  26. package/dist/Calendar/index.js +8 -10
  27. package/dist/Carousel/Carousel.torp +180 -0
  28. package/dist/Carousel/CarouselIndicators.torp +65 -0
  29. package/dist/Carousel/CarouselNext.torp +43 -0
  30. package/dist/Carousel/CarouselPrevious.torp +44 -0
  31. package/dist/Carousel/CarouselSlide.torp +57 -0
  32. package/dist/Carousel/CarouselTypes.ts +28 -0
  33. package/dist/Carousel/index.d.ts +147 -0
  34. package/dist/Carousel/index.js +6 -0
  35. package/dist/Charts/BarChart.torp +70 -0
  36. package/dist/Charts/Chart.torp +120 -0
  37. package/dist/Charts/ChartBars.torp +78 -0
  38. package/dist/Charts/ChartColumns.torp +66 -0
  39. package/dist/Charts/ChartGrid.torp +54 -0
  40. package/dist/Charts/ChartLines.torp +60 -0
  41. package/dist/Charts/ChartTypes.ts +25 -0
  42. package/dist/Charts/ChartXAxis.torp +83 -0
  43. package/dist/Charts/ChartYAxis.torp +105 -0
  44. package/dist/Charts/ColumnChart.torp +70 -0
  45. package/dist/{Chart → Charts}/GridLines.torp +7 -4
  46. package/dist/Charts/LineChart.torp +73 -0
  47. package/dist/{Chart → Charts}/PieChart.torp +14 -20
  48. package/dist/{Chart → Charts}/ScatterChart.torp +45 -38
  49. package/dist/{Chart → Charts}/SparkLine.torp +16 -19
  50. package/dist/{Chart → Charts}/XAxis.torp +18 -12
  51. package/dist/{Chart → Charts}/YAxis.torp +15 -9
  52. package/dist/Charts/index.d.ts +469 -0
  53. package/dist/Charts/index.js +17 -0
  54. package/dist/ColorPicker/ColorPalette.torp +154 -0
  55. package/dist/ColorPicker/ColorPicker.torp +157 -0
  56. package/dist/ColorPicker/index.d.ts +85 -0
  57. package/dist/ColorPicker/index.js +3 -0
  58. package/dist/ComboBox/ComboBox.torp +205 -0
  59. package/dist/ComboBox/ComboBoxContent.torp +112 -0
  60. package/dist/ComboBox/ComboBoxInput.torp +145 -0
  61. package/dist/ComboBox/ComboBoxTrigger.torp +49 -0
  62. package/dist/ComboBox/ComboBoxTypes.ts +39 -0
  63. package/dist/ComboBox/index.d.ts +152 -0
  64. package/dist/ComboBox/index.js +6 -0
  65. package/dist/CommandPalette/CommandPalette.torp +220 -0
  66. package/dist/CommandPalette/CommandTypes.ts +14 -0
  67. package/dist/CommandPalette/index.d.ts +45 -0
  68. package/dist/CommandPalette/index.js +2 -0
  69. package/dist/Contextual/Contextual.torp +39 -52
  70. package/dist/Contextual/ContextualContent.torp +29 -73
  71. package/dist/Contextual/ContextualHover.torp +112 -0
  72. package/dist/Contextual/ContextualTrigger.torp +31 -42
  73. package/dist/Contextual/ContextualTypes.ts +5 -18
  74. package/dist/Contextual/index.d.ts +44 -27
  75. package/dist/Contextual/index.js +5 -14
  76. package/dist/DataGrid/DataGrid.torp +496 -0
  77. package/dist/DataGrid/DataGridTypes.ts +25 -0
  78. package/dist/DataGrid/index.d.ts +90 -0
  79. package/dist/DataGrid/index.js +3 -0
  80. package/dist/DataGrid/sortRows.ts +32 -0
  81. package/dist/DatePicker/DatePicker.torp +222 -0
  82. package/dist/DatePicker/DatePickerHeader.torp +20 -0
  83. package/dist/DatePicker/index.d.ts +55 -0
  84. package/dist/DatePicker/index.js +2 -0
  85. package/dist/DateRangePicker/DateRangePicker.torp +311 -0
  86. package/dist/DateRangePicker/DateRangePickerDay.torp +137 -0
  87. package/dist/DateRangePicker/DateRangePickerTypes.ts +21 -0
  88. package/dist/DateRangePicker/index.d.ts +76 -0
  89. package/dist/DateRangePicker/index.js +3 -0
  90. package/dist/Dialog/Dialog.torp +33 -30
  91. package/dist/Dialog/DialogBody.torp +5 -9
  92. package/dist/Dialog/DialogButton.torp +14 -11
  93. package/dist/Dialog/DialogFooter.torp +3 -7
  94. package/dist/Dialog/DialogHeader.torp +6 -10
  95. package/dist/Dialog/DialogTypes.ts +2 -2
  96. package/dist/Dialog/index.d.ts +28 -26
  97. package/dist/Dialog/index.js +6 -22
  98. package/dist/Disclosure/Disclosure.torp +18 -18
  99. package/dist/Disclosure/DisclosureContent.torp +5 -6
  100. package/dist/Disclosure/DisclosureHeader.torp +7 -11
  101. package/dist/Disclosure/DisclosureTrigger.torp +4 -5
  102. package/dist/Disclosure/DisclosureTypes.ts +1 -1
  103. package/dist/Disclosure/index.d.ts +14 -16
  104. package/dist/Disclosure/index.js +5 -18
  105. package/dist/Drawer/Drawer.torp +21 -51
  106. package/dist/Drawer/DrawerContent.torp +67 -13
  107. package/dist/Drawer/DrawerOverlay.torp +4 -4
  108. package/dist/Drawer/DrawerTrigger.torp +16 -4
  109. package/dist/Drawer/DrawerTypes.ts +4 -1
  110. package/dist/Drawer/index.d.ts +16 -20
  111. package/dist/Drawer/index.js +5 -18
  112. package/dist/FocusGroup/FocusGroup.torp +70 -0
  113. package/dist/FocusGroup/FocusGroupButton.torp +59 -0
  114. package/dist/FocusGroup/FocusGroupTypes.ts +14 -0
  115. package/dist/FocusGroup/index.d.ts +44 -0
  116. package/dist/FocusGroup/index.js +3 -0
  117. package/dist/Form/CheckBox.torp +28 -20
  118. package/dist/Form/Field.torp +17 -17
  119. package/dist/Form/File.torp +31 -22
  120. package/dist/Form/FileDrop.torp +187 -0
  121. package/dist/Form/Form.torp +24 -22
  122. package/dist/Form/FormTypes.ts +2 -0
  123. package/dist/Form/FormValues.torp +37 -0
  124. package/dist/Form/Hidden.torp +4 -12
  125. package/dist/Form/Input.torp +38 -32
  126. package/dist/Form/Label.torp +3 -3
  127. package/dist/Form/Message.torp +13 -5
  128. package/dist/Form/MessageSummary.torp +39 -0
  129. package/dist/Form/Option.torp +11 -7
  130. package/dist/Form/Select.torp +32 -28
  131. package/dist/Form/TextArea.torp +35 -31
  132. package/dist/Form/Toggle.torp +109 -0
  133. package/dist/Form/index.d.ts +198 -77
  134. package/dist/Form/index.js +16 -46
  135. package/dist/ListBox/ListBox.torp +374 -0
  136. package/dist/ListBox/ListBoxItem.torp +131 -0
  137. package/dist/ListBox/ListBoxSeparator.torp +29 -0
  138. package/dist/ListBox/ListBoxTypes.ts +41 -0
  139. package/dist/ListBox/LoadedListBoxItems.torp +41 -0
  140. package/dist/ListBox/index.d.ts +136 -0
  141. package/dist/ListBox/index.js +4 -0
  142. package/dist/MaskedInput/MaskedInput.torp +143 -0
  143. package/dist/MaskedInput/index.d.ts +52 -0
  144. package/dist/MaskedInput/index.js +2 -0
  145. package/dist/Menu/Menu.torp +90 -70
  146. package/dist/Menu/MenuButton.torp +17 -10
  147. package/dist/Menu/MenuCheck.torp +22 -18
  148. package/dist/Menu/MenuGroup.torp +4 -4
  149. package/dist/Menu/MenuIndicator.torp +5 -13
  150. package/dist/Menu/MenuPopout.torp +20 -50
  151. package/dist/Menu/MenuPopoutContent.torp +15 -66
  152. package/dist/Menu/MenuPopoutTrigger.torp +19 -100
  153. package/dist/Menu/MenuRadio.torp +25 -26
  154. package/dist/Menu/MenuRadioGroup.torp +25 -68
  155. package/dist/Menu/MenuSeparator.torp +3 -2
  156. package/dist/Menu/MenuTypes.ts +12 -21
  157. package/dist/Menu/index.d.ts +45 -51
  158. package/dist/Menu/index.js +12 -46
  159. package/dist/MenuBar/MenuBar.torp +31 -83
  160. package/dist/MenuBar/MenuBarItem.torp +34 -55
  161. package/dist/MenuBar/MenuBarItemContent.torp +15 -101
  162. package/dist/MenuBar/MenuBarItemTrigger.torp +20 -55
  163. package/dist/MenuBar/MenuBarTypes.ts +13 -12
  164. package/dist/MenuBar/index.d.ts +17 -19
  165. package/dist/MenuBar/index.js +5 -18
  166. package/dist/Modal/Modal.torp +28 -48
  167. package/dist/Modal/ModalContent.torp +21 -44
  168. package/dist/Modal/ModalOverlay.torp +4 -4
  169. package/dist/Modal/ModalTrigger.torp +16 -32
  170. package/dist/Modal/ModalTypes.ts +6 -17
  171. package/dist/Modal/index.d.ts +17 -29
  172. package/dist/Modal/index.js +29 -28
  173. package/dist/Modal/index.js.map +1 -1
  174. package/dist/Modal/showPrompt.ts +2 -2
  175. package/dist/NavMenu/NavMenu.torp +22 -104
  176. package/dist/NavMenu/NavMenuButton.torp +10 -8
  177. package/dist/NavMenu/NavMenuElement.torp +6 -7
  178. package/dist/NavMenu/NavMenuGroup.torp +5 -5
  179. package/dist/NavMenu/NavMenuGroupHeader.torp +5 -8
  180. package/dist/NavMenu/NavMenuLink.torp +7 -10
  181. package/dist/NavMenu/NavMenuPopout.torp +16 -61
  182. package/dist/NavMenu/NavMenuPopoutContent.torp +14 -73
  183. package/dist/NavMenu/NavMenuPopoutTrigger.torp +47 -0
  184. package/dist/NavMenu/NavMenuSeparator.torp +3 -6
  185. package/dist/NavMenu/NavMenuTypes.ts +6 -15
  186. package/dist/NavMenu/index.d.ts +55 -55
  187. package/dist/NavMenu/index.js +11 -42
  188. package/dist/Notification/Notification.torp +12 -24
  189. package/dist/Notification/NotificationClose.torp +6 -3
  190. package/dist/Notification/NotificationContainer.torp +3 -7
  191. package/dist/Notification/NotificationContent.torp +3 -7
  192. package/dist/Notification/NotificationTypes.ts +1 -1
  193. package/dist/Notification/index.d.ts +15 -12
  194. package/dist/Notification/index.js +22 -32
  195. package/dist/Notification/index.js.map +1 -1
  196. package/dist/NumberInput/NumberInput.torp +255 -0
  197. package/dist/NumberInput/index.d.ts +44 -0
  198. package/dist/NumberInput/index.js +2 -0
  199. package/dist/Pagination/Pagination.torp +152 -0
  200. package/dist/Pagination/PaginationItem.torp +137 -0
  201. package/dist/Pagination/PaginationTypes.ts +22 -0
  202. package/dist/Pagination/buildPages.ts +61 -0
  203. package/dist/Pagination/index.d.ts +63 -0
  204. package/dist/Pagination/index.js +3 -0
  205. package/dist/Popover/Popover.torp +39 -52
  206. package/dist/Popover/PopoverContent.torp +27 -76
  207. package/dist/Popover/PopoverHover.torp +90 -0
  208. package/dist/Popover/PopoverTrigger.torp +17 -40
  209. package/dist/Popover/PopoverTypes.ts +5 -18
  210. package/dist/Popover/index.d.ts +40 -25
  211. package/dist/Popover/index.js +18 -18
  212. package/dist/Popover/index.js.map +1 -1
  213. package/dist/Progress/Progress.torp +88 -0
  214. package/dist/Progress/index.d.ts +37 -0
  215. package/dist/Progress/index.js +2 -0
  216. package/dist/Rating/Rating.torp +225 -0
  217. package/dist/Rating/index.d.ts +44 -0
  218. package/dist/Rating/index.js +2 -0
  219. package/dist/SegmentedControl/SegmentedControl.torp +233 -0
  220. package/dist/SegmentedControl/SegmentedControlTypes.ts +26 -0
  221. package/dist/SegmentedControl/SegmentedItem.torp +78 -0
  222. package/dist/SegmentedControl/index.d.ts +74 -0
  223. package/dist/SegmentedControl/index.js +3 -0
  224. package/dist/SelectBox/SelectBox.torp +190 -0
  225. package/dist/SelectBox/SelectBoxContent.torp +107 -0
  226. package/dist/SelectBox/SelectBoxTrigger.torp +141 -0
  227. package/dist/SelectBox/SelectBoxTypes.ts +33 -0
  228. package/dist/SelectBox/index.d.ts +112 -0
  229. package/dist/SelectBox/index.js +5 -0
  230. package/dist/Slider/Slider.torp +248 -0
  231. package/dist/Slider/index.d.ts +45 -0
  232. package/dist/Slider/index.js +2 -0
  233. package/dist/Splitter/Splitter.torp +156 -0
  234. package/dist/Splitter/SplitterHandle.torp +161 -0
  235. package/dist/Splitter/SplitterPane.torp +63 -0
  236. package/dist/Splitter/SplitterTypes.ts +31 -0
  237. package/dist/Splitter/index.d.ts +103 -0
  238. package/dist/Splitter/index.js +4 -0
  239. package/dist/Stepper/Stepper.torp +146 -0
  240. package/dist/Stepper/StepperMarker.torp +24 -0
  241. package/dist/Stepper/StepperNext.torp +44 -0
  242. package/dist/Stepper/StepperPrevious.torp +44 -0
  243. package/dist/Stepper/StepperStep.torp +90 -0
  244. package/dist/Stepper/StepperTypes.ts +30 -0
  245. package/dist/Stepper/index.d.ts +149 -0
  246. package/dist/Stepper/index.js +6 -0
  247. package/dist/TabGroup/TabContent.torp +6 -6
  248. package/dist/TabGroup/TabGroup.torp +97 -113
  249. package/dist/TabGroup/TabGroupTypes.ts +3 -3
  250. package/dist/TabGroup/TabHeader.torp +23 -19
  251. package/dist/TabGroup/TabList.torp +8 -21
  252. package/dist/TabGroup/TabTrigger.torp +6 -7
  253. package/dist/TabGroup/index.d.ts +26 -26
  254. package/dist/TabGroup/index.js +6 -22
  255. package/dist/TagInput/TagInput.torp +378 -0
  256. package/dist/TagInput/index.d.ts +48 -0
  257. package/dist/TagInput/index.js +2 -0
  258. package/dist/TimePicker/TimePicker.torp +462 -0
  259. package/dist/TimePicker/index.d.ts +53 -0
  260. package/dist/TimePicker/index.js +2 -0
  261. package/dist/ToolBar/ToolBar.torp +117 -0
  262. package/dist/ToolBar/ToolBarButton.torp +56 -0
  263. package/dist/ToolBar/ToolBarElement.torp +51 -0
  264. package/dist/ToolBar/ToolBarPopout.torp +45 -0
  265. package/dist/ToolBar/ToolBarPopoutContent.torp +34 -0
  266. package/dist/ToolBar/ToolBarPopoutTrigger.torp +47 -0
  267. package/dist/ToolBar/ToolBarSeparator.torp +21 -0
  268. package/dist/ToolBar/ToolBarTypes.ts +28 -0
  269. package/dist/ToolBar/index.d.ts +210 -0
  270. package/dist/ToolBar/index.js +8 -0
  271. package/dist/Tree/Tree.torp +395 -0
  272. package/dist/Tree/TreeItem.torp +176 -0
  273. package/dist/Tree/TreeItemChildren.torp +60 -0
  274. package/dist/Tree/TreeItemContent.torp +46 -0
  275. package/dist/Tree/TreeItemLabel.torp +94 -0
  276. package/dist/Tree/TreeItemTrigger.torp +78 -0
  277. package/dist/Tree/TreeLoadedChildren.torp +122 -0
  278. package/dist/Tree/TreeTypes.ts +63 -0
  279. package/dist/Tree/index.d.ts +262 -0
  280. package/dist/Tree/index.js +7 -0
  281. package/dist/icons/ChevronDoubleLeft.torp +19 -0
  282. package/dist/icons/ChevronDoubleRight.torp +19 -0
  283. package/dist/icons/index.d.ts +61 -1
  284. package/dist/icons/index.js +17 -58
  285. package/dist/loader-DEeG5vFY.js +44 -0
  286. package/dist/loader-DEeG5vFY.js.map +1 -0
  287. package/dist/motion/index.d.ts +12 -8
  288. package/dist/motion/index.d.ts.map +1 -0
  289. package/dist/motion/index.js +72 -88
  290. package/dist/motion/index.js.map +1 -1
  291. package/dist/mount/draggable.ts +63 -0
  292. package/dist/mount/dropTarget.ts +108 -0
  293. package/dist/mount/hoverTrigger.ts +1 -1
  294. package/dist/utils/$handle.ts +23 -0
  295. package/dist/utils/LoadedItems.torp +47 -0
  296. package/dist/utils/PopoutClickTrigger.torp +99 -0
  297. package/dist/utils/PopoutTypes.ts +82 -0
  298. package/dist/utils/SubmenuPopout.torp +89 -0
  299. package/dist/utils/SubmenuPopoutContent.torp +87 -0
  300. package/dist/utils/SubmenuPopoutTrigger.torp +160 -0
  301. package/dist/utils/chartColors.ts +13 -13
  302. package/dist/utils/chartLayout.ts +143 -0
  303. package/dist/utils/chartUtils.ts +1 -1
  304. package/dist/utils/colorUtils.ts +103 -0
  305. package/dist/utils/createItemGroup.ts +152 -0
  306. package/dist/utils/dateUtils.ts +8 -7
  307. package/dist/utils/documentEvents.ts +4 -4
  308. package/dist/utils/dragState.ts +86 -0
  309. package/dist/utils/focusGroup.ts +204 -0
  310. package/dist/utils/focusItem.ts +44 -0
  311. package/dist/utils/formField.ts +70 -0
  312. package/dist/utils/hoverOpen.ts +50 -0
  313. package/dist/utils/hoverReveal.ts +194 -0
  314. package/dist/utils/loader.ts +113 -0
  315. package/dist/utils/maskUtils.ts +98 -0
  316. package/dist/utils/popoutContent.ts +137 -0
  317. package/dist/utils/reorderList.ts +52 -0
  318. package/package.json +116 -25
  319. package/dist/Accordion/index.js.map +0 -1
  320. package/dist/Breadcrumb/index.js.map +0 -1
  321. package/dist/Calendar/index.js.map +0 -1
  322. package/dist/Chart/BarChart.torp +0 -159
  323. package/dist/Chart/LineChart.torp +0 -196
  324. package/dist/Chart/index.d.ts +0 -220
  325. package/dist/Chart/index.js +0 -34
  326. package/dist/Chart/index.js.map +0 -1
  327. package/dist/Contextual/index.js.map +0 -1
  328. package/dist/Dialog/index.js.map +0 -1
  329. package/dist/Disclosure/index.js.map +0 -1
  330. package/dist/Drawer/index.js.map +0 -1
  331. package/dist/Form/index.js.map +0 -1
  332. package/dist/Menu/index.js.map +0 -1
  333. package/dist/MenuBar/index.js.map +0 -1
  334. package/dist/NavMenu/NavMenuPopoutButton.torp +0 -129
  335. package/dist/NavMenu/index.js.map +0 -1
  336. package/dist/TabGroup/index.js.map +0 -1
  337. package/dist/icons/index.js.map +0 -1
  338. package/dist/index.d.ts +0 -19
  339. package/dist/metafile-esm.json +0 -1
  340. package/dist/motion/fade.ts +0 -16
  341. package/dist/motion/grow.ts +0 -23
  342. package/dist/motion/measure.ts +0 -28
  343. package/dist/motion/slide.ts +0 -45
  344. package/dist/mount/index.d.ts +0 -2
  345. package/dist/utils/index.d.ts +0 -2
  346. /package/dist/{Chart → Charts}/DataSeries.ts +0 -0
@@ -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
+ }
@@ -0,0 +1,262 @@
1
+ import { type SlotRender } from "@torpor/view";
2
+
3
+
4
+ interface TreeProps {
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
+ /** The value(s) of the expanded TreeItem(s) */
12
+ expanded: Bindable<string | string[] | undefined>;
13
+ /** Whether a single TreeItem or multiple TreeItems can be selected at the same time */
14
+ type?: "single" | "multiple";
15
+ /** The value of the selected TreeItem, or an array of values if the type is "multiple" */
16
+ value: Bindable<string | string[] | undefined>;
17
+ /** If set to true, the user cannot interact with any items in the Tree */
18
+ disabled?: boolean;
19
+ /** The aria-label for the root element */
20
+ ariaLabel?: string | undefined;
21
+ /**
22
+ * Reads the children of an item from the network (or anywhere async) when
23
+ * the item is first expanded. Receives a request with `item` (the parent
24
+ * item's value). Items load automatically when they set the TreeItem
25
+ * `hasChildren` prop; a TreeItem `load` prop overrides this per item.
26
+ */
27
+ load?: Loader<any, TreeLoadRequest>;
28
+ /** Called after each successful child load with the normalized result */
29
+ onload?: (result: LoadResult, item: string | undefined) => void;
30
+ /** Extracts the display text for a loaded item (defaults to `label ?? text ?? item`) */
31
+ getItemLabel?: (item: any) => any;
32
+ /** Extracts the value for a loaded item (defaults to `value ?? id`) */
33
+ getItemValue?: (item: any) => any;
34
+ /** Raised when the expanded item(s) have changed */
35
+ onexpand?: (value: string | string[]) => void;
36
+ /** Raised when the selected item(s) have changed */
37
+ /** The name of the component's form data field */
38
+ name?: string;
39
+ onchange?: (value: string | string[] | undefined) => void;
40
+ }
41
+
42
+ /**
43
+ * A hierarchical list of items that can be expanded and collapsed to reveal nested content,
44
+ * with support for selecting items.
45
+ *
46
+ * See [the WAI ARIA guidelines for Tree Views](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/).
47
+ *
48
+ * The structure of a Tree is:
49
+ *
50
+ * ```
51
+ * <Tree>
52
+ * <TreeItem>
53
+ * <TreeItemContent>
54
+ * <TreeItemTrigger />
55
+ * <TreeItemLabel />
56
+ * </TreeItemContent>
57
+ * <TreeItemChildren>
58
+ * <TreeItem />
59
+ * </TreeItemChildren>
60
+ * </TreeItem>
61
+ * </Tree>
62
+ * ```
63
+ */
64
+ declare function Tree(
65
+ $parent: ParentNode,
66
+ $anchor: Node | null,
67
+ $props: TreeProps | undefined,
68
+ $context?: Record<PropertyKey, any>,
69
+ $slots?: Record<string, SlotRender>,
70
+ ): void;
71
+
72
+
73
+
74
+ interface TreeItemProps {
75
+ /** An ID for the root element */
76
+ id?: string;
77
+ /** Classes for the root element */
78
+ class?: ClassValue;
79
+ /** Styles for the root element */
80
+ style?: StyleValue;
81
+ /** A value for the item */
82
+ value?: string;
83
+ /**
84
+ * Declares that the item has children that are not slotted in. When a
85
+ * `load` function is available (this item's, or the tree's) they are
86
+ * loaded from the network when the item is first expanded.
87
+ */
88
+ hasChildren?: boolean;
89
+ /** If set to true, the user cannot interact with this TreeItem */
90
+ disabled?: boolean;
91
+ /**
92
+ * Reads this item's children from the network (or anywhere async),
93
+ * receiving `{ item }` (the item's value). Set alongside `hasChildren`;
94
+ * overrides the tree's `load` function for this item.
95
+ */
96
+ load?: Loader<any, TreeLoadRequest>;
97
+ /** Raised when this item is expanded or collapsed */
98
+ onexpand?: (expanded: boolean) => void;
99
+ /** Raised when this item is selected or deselected */
100
+ onselect?: (selected: boolean) => void;
101
+ }
102
+
103
+ /**
104
+ * An item in a Tree, which can contain nested TreeItems via TreeItemChildren.
105
+ *
106
+ * The structure of a TreeItem is:
107
+ *
108
+ * ```
109
+ * <TreeItem>
110
+ * <TreeItemContent>
111
+ * <TreeItemTrigger />
112
+ * <TreeItemLabel />
113
+ * </TreeItemContent>
114
+ * <TreeItemChildren>
115
+ * <TreeItem />
116
+ * </TreeItemChildren>
117
+ * </TreeItem>
118
+ * ```
119
+ */
120
+ declare function TreeItem(
121
+ $parent: ParentNode,
122
+ $anchor: Node | null,
123
+ $props: TreeItemProps | undefined,
124
+ $context?: Record<PropertyKey, any>,
125
+ $slots?: Record<string, SlotRender>,
126
+ ): void;
127
+
128
+
129
+
130
+ /**
131
+ * A container for nested TreeItems. This component must be a direct child of TreeItem.
132
+ *
133
+ * The structure is:
134
+ *
135
+ * ```
136
+ * <TreeItem>
137
+ * <TreeItemContent>...</TreeItemContent>
138
+ * <TreeItemChildren>
139
+ * <TreeItem />
140
+ * </TreeItemChildren>
141
+ * </TreeItem>
142
+ * ```
143
+ */
144
+ declare function TreeItemChildren(
145
+ $parent: ParentNode,
146
+ $anchor: Node | null,
147
+ $props?: TreeItemChildrenProps,
148
+ $context?: Record<PropertyKey, any>,
149
+ $slots?: Record<string, SlotRender>,
150
+ ): void;
151
+
152
+
153
+
154
+ interface TreeItemContentProps {
155
+ /** An ID for the root element */
156
+ id?: string;
157
+ /** Classes for the root element */
158
+ class?: ClassValue;
159
+ /** Styles for the root element */
160
+ style?: StyleValue;
161
+ }
162
+
163
+ /**
164
+ * A wrapper for the content of a TreeItem, which should contain TreeItemTrigger and TreeItemLabel.
165
+ *
166
+ * The structure is:
167
+ *
168
+ * ```
169
+ * <TreeItem>
170
+ * <TreeItemContent>
171
+ * <TreeItemTrigger />
172
+ * <TreeItemLabel />
173
+ * </TreeItemContent>
174
+ * </TreeItem>
175
+ * ```
176
+ */
177
+ declare function TreeItemContent(
178
+ $parent: ParentNode,
179
+ $anchor: Node | null,
180
+ $props: TreeItemContentProps | undefined,
181
+ $context?: Record<PropertyKey, any>,
182
+ $slots?: Record<string, SlotRender>,
183
+ ): void;
184
+
185
+
186
+
187
+ /**
188
+ * The interactive label for a TreeItem, which can be clicked or keyboard-navigated to select the item.
189
+ * This component handles keyboard navigation and focus management for the tree.
190
+ *
191
+ * The structure is:
192
+ *
193
+ * ```
194
+ * <TreeItem>
195
+ * <TreeItemContent>
196
+ * <TreeItemTrigger />
197
+ * <TreeItemLabel>Item text</TreeItemLabel>
198
+ * </TreeItemContent>
199
+ * </TreeItem>
200
+ * ```
201
+ */
202
+ declare function TreeItemLabel(
203
+ $parent: ParentNode,
204
+ $anchor: Node | null,
205
+ $props?: TreeItemLabelProps,
206
+ $context?: Record<PropertyKey, any>,
207
+ $slots?: Record<string, SlotRender>,
208
+ ): void;
209
+
210
+
211
+
212
+ /**
213
+ * A button for expanding or collapsing a TreeItem that has nested children.
214
+ * When the item has no children, this renders as a spacer for consistent indentation.
215
+ *
216
+ * The structure is:
217
+ *
218
+ * ```
219
+ * <TreeItem>
220
+ * <TreeItemContent>
221
+ * <TreeItemTrigger />
222
+ * <TreeItemLabel />
223
+ * </TreeItemContent>
224
+ * </TreeItem>
225
+ * ```
226
+ */
227
+ declare function TreeItemTrigger(
228
+ $parent: ParentNode,
229
+ $anchor: Node | null,
230
+ $props?: TreeItemTriggerProps,
231
+ $context?: Record<PropertyKey, any>,
232
+ $slots?: Record<string, SlotRender>,
233
+ ): void;
234
+
235
+
236
+
237
+ interface TreeLoadedChildrenProps {
238
+ /** The state of the item whose children are loaded */
239
+ itemState: ItemState;
240
+ /** The load function that reads this item's children */
241
+ load: Loader<any, TreeLoadRequest>;
242
+ }
243
+
244
+ /**
245
+ * Loads the children of a TreeItem that declares `hasChildren` but has no
246
+ * slotted TreeItemChildren, rendering them as nested TreeItems. The load
247
+ * starts when the item is first expanded and is not repeated afterwards;
248
+ * the results stay mounted (hidden while collapsed) so the tree can search
249
+ * through them.
250
+ *
251
+ * This is rendered automatically by TreeItem when there is a `load`
252
+ * function available; it is not part of the public API.
253
+ */
254
+ declare function TreeLoadedChildren(
255
+ $parent: ParentNode,
256
+ $anchor: Node | null,
257
+ $props: TreeLoadedChildrenProps | undefined,
258
+ $context?: Record<PropertyKey, any>,
259
+ $slots?: Record<string, SlotRender>,
260
+ ): void;
261
+
262
+ export { Tree, TreeItem, TreeItemChildren, TreeItemContent, TreeItemLabel, TreeItemTrigger, TreeLoadedChildren };
@@ -0,0 +1,7 @@
1
+ import Tree from "./Tree.torp";
2
+ import TreeItem from "./TreeItem.torp";
3
+ import TreeItemChildren from "./TreeItemChildren.torp";
4
+ import TreeItemContent from "./TreeItemContent.torp";
5
+ import TreeItemLabel from "./TreeItemLabel.torp";
6
+ import TreeItemTrigger from "./TreeItemTrigger.torp";
7
+ export { Tree, TreeItem, TreeItemChildren, TreeItemContent, TreeItemLabel, TreeItemTrigger };
@@ -0,0 +1,19 @@
1
+ import { type IconProps } from "./IconTypes";
2
+
3
+ export default function ChevronDoubleLeft($props: IconProps | undefined) {
4
+ @render {
5
+ <svg
6
+ {$props?.id}
7
+ class={["torp-icon", $props?.class]}
8
+ {$props?.style}
9
+ viewBox="0 0 100 100"
10
+ stroke-linejoin="round"
11
+ stroke-width="12"
12
+ >
13
+ <g>
14
+ <path fill="none" d="M90,10 L50,50 L90,90"></path>
15
+ <path fill="none" d="M50,10 L10,50 L50,90"></path>
16
+ </g>
17
+ </svg>
18
+ }
19
+ }
@@ -0,0 +1,19 @@
1
+ import { type IconProps } from "./IconTypes";
2
+
3
+ export default function ChevronDoubleRight($props: IconProps | undefined) {
4
+ @render {
5
+ <svg
6
+ {$props?.id}
7
+ class={["torp-icon", $props?.class]}
8
+ {$props?.style}
9
+ viewBox="0 0 100 100"
10
+ stroke-linejoin="round"
11
+ stroke-width="12"
12
+ >
13
+ <g>
14
+ <path d="M10,10 L50,50 L10,90" fill="none" />
15
+ <path d="M50,10 L90,50 L50,90" fill="none" />
16
+ </g>
17
+ </svg>
18
+ }
19
+ }