@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.
Files changed (342) hide show
  1. package/README.md +83 -7
  2. package/dist/Accordion/Accordion.torp +42 -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 +1 -1
  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 +24 -3
  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 +55 -144
  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/Charts/GridLines.torp +4 -4
  46. package/dist/Charts/LineChart.torp +55 -178
  47. package/dist/Charts/PieChart.torp +14 -20
  48. package/dist/Charts/ScatterChart.torp +45 -38
  49. package/dist/Charts/SparkLine.torp +16 -19
  50. package/dist/Charts/XAxis.torp +11 -11
  51. package/dist/Charts/YAxis.torp +8 -8
  52. package/dist/Charts/index.d.ts +328 -79
  53. package/dist/Charts/index.js +17 -34
  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 +32 -50
  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 +4 -17
  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 +24 -17
  91. package/dist/Dialog/DialogBody.torp +5 -9
  92. package/dist/Dialog/DialogButton.torp +12 -12
  93. package/dist/Dialog/DialogFooter.torp +3 -7
  94. package/dist/Dialog/DialogHeader.torp +6 -10
  95. package/dist/Dialog/index.d.ts +27 -27
  96. package/dist/Dialog/index.js +6 -22
  97. package/dist/Disclosure/Disclosure.torp +18 -18
  98. package/dist/Disclosure/DisclosureContent.torp +5 -6
  99. package/dist/Disclosure/DisclosureHeader.torp +7 -11
  100. package/dist/Disclosure/DisclosureTrigger.torp +4 -5
  101. package/dist/Disclosure/index.d.ts +14 -16
  102. package/dist/Disclosure/index.js +5 -18
  103. package/dist/Drawer/Drawer.torp +19 -49
  104. package/dist/Drawer/DrawerContent.torp +67 -13
  105. package/dist/Drawer/DrawerOverlay.torp +4 -4
  106. package/dist/Drawer/DrawerTrigger.torp +16 -4
  107. package/dist/Drawer/DrawerTypes.ts +3 -0
  108. package/dist/Drawer/index.d.ts +16 -20
  109. package/dist/Drawer/index.js +5 -18
  110. package/dist/FocusGroup/FocusGroup.torp +70 -0
  111. package/dist/FocusGroup/FocusGroupButton.torp +59 -0
  112. package/dist/FocusGroup/FocusGroupTypes.ts +14 -0
  113. package/dist/FocusGroup/index.d.ts +44 -0
  114. package/dist/FocusGroup/index.js +3 -0
  115. package/dist/Form/CheckBox.torp +27 -18
  116. package/dist/Form/Field.torp +17 -17
  117. package/dist/Form/File.torp +31 -22
  118. package/dist/Form/FileDrop.torp +187 -0
  119. package/dist/Form/Form.torp +24 -22
  120. package/dist/Form/FormTypes.ts +2 -0
  121. package/dist/Form/FormValues.torp +37 -0
  122. package/dist/Form/Hidden.torp +4 -12
  123. package/dist/Form/Input.torp +38 -32
  124. package/dist/Form/Label.torp +3 -3
  125. package/dist/Form/Message.torp +13 -5
  126. package/dist/Form/MessageSummary.torp +5 -4
  127. package/dist/Form/Option.torp +11 -7
  128. package/dist/Form/Select.torp +32 -28
  129. package/dist/Form/TextArea.torp +35 -31
  130. package/dist/Form/Toggle.torp +109 -0
  131. package/dist/Form/index.d.ts +178 -79
  132. package/dist/Form/index.js +16 -50
  133. package/dist/ListBox/ListBox.torp +253 -150
  134. package/dist/ListBox/ListBoxItem.torp +54 -30
  135. package/dist/ListBox/ListBoxSeparator.torp +5 -2
  136. package/dist/ListBox/ListBoxTypes.ts +23 -5
  137. package/dist/ListBox/LoadedListBoxItems.torp +41 -0
  138. package/dist/ListBox/index.d.ts +56 -17
  139. package/dist/ListBox/index.js +4 -14
  140. package/dist/MaskedInput/MaskedInput.torp +143 -0
  141. package/dist/MaskedInput/index.d.ts +52 -0
  142. package/dist/MaskedInput/index.js +2 -0
  143. package/dist/Menu/Menu.torp +86 -71
  144. package/dist/Menu/MenuButton.torp +17 -10
  145. package/dist/Menu/MenuCheck.torp +22 -18
  146. package/dist/Menu/MenuGroup.torp +4 -4
  147. package/dist/Menu/MenuIndicator.torp +5 -13
  148. package/dist/Menu/MenuPopout.torp +20 -50
  149. package/dist/Menu/MenuPopoutContent.torp +15 -66
  150. package/dist/Menu/MenuPopoutTrigger.torp +19 -100
  151. package/dist/Menu/MenuRadio.torp +25 -26
  152. package/dist/Menu/MenuRadioGroup.torp +25 -68
  153. package/dist/Menu/MenuSeparator.torp +3 -2
  154. package/dist/Menu/MenuTypes.ts +9 -19
  155. package/dist/Menu/index.d.ts +45 -51
  156. package/dist/Menu/index.js +12 -46
  157. package/dist/MenuBar/MenuBar.torp +31 -83
  158. package/dist/MenuBar/MenuBarItem.torp +33 -51
  159. package/dist/MenuBar/MenuBarItemContent.torp +15 -101
  160. package/dist/MenuBar/MenuBarItemTrigger.torp +20 -55
  161. package/dist/MenuBar/MenuBarTypes.ts +11 -10
  162. package/dist/MenuBar/index.d.ts +17 -19
  163. package/dist/MenuBar/index.js +5 -18
  164. package/dist/Modal/Modal.torp +22 -47
  165. package/dist/Modal/ModalContent.torp +21 -44
  166. package/dist/Modal/ModalOverlay.torp +4 -4
  167. package/dist/Modal/ModalTrigger.torp +16 -32
  168. package/dist/Modal/ModalTypes.ts +5 -16
  169. package/dist/Modal/index.d.ts +17 -29
  170. package/dist/Modal/index.js +29 -28
  171. package/dist/Modal/index.js.map +1 -1
  172. package/dist/Modal/showPrompt.ts +2 -2
  173. package/dist/NavMenu/NavMenu.torp +22 -111
  174. package/dist/NavMenu/NavMenuButton.torp +7 -8
  175. package/dist/NavMenu/NavMenuElement.torp +6 -7
  176. package/dist/NavMenu/NavMenuGroup.torp +5 -5
  177. package/dist/NavMenu/NavMenuGroupHeader.torp +5 -8
  178. package/dist/NavMenu/NavMenuLink.torp +7 -10
  179. package/dist/NavMenu/NavMenuPopout.torp +15 -60
  180. package/dist/NavMenu/NavMenuPopoutContent.torp +14 -73
  181. package/dist/NavMenu/NavMenuPopoutTrigger.torp +17 -99
  182. package/dist/NavMenu/NavMenuSeparator.torp +3 -7
  183. package/dist/NavMenu/NavMenuTypes.ts +4 -14
  184. package/dist/NavMenu/index.d.ts +40 -44
  185. package/dist/NavMenu/index.js +11 -42
  186. package/dist/Notification/Notification.torp +12 -24
  187. package/dist/Notification/NotificationClose.torp +6 -3
  188. package/dist/Notification/NotificationContainer.torp +3 -7
  189. package/dist/Notification/NotificationContent.torp +3 -7
  190. package/dist/Notification/NotificationTypes.ts +1 -1
  191. package/dist/Notification/index.d.ts +15 -12
  192. package/dist/Notification/index.js +22 -32
  193. package/dist/Notification/index.js.map +1 -1
  194. package/dist/NumberInput/NumberInput.torp +255 -0
  195. package/dist/NumberInput/index.d.ts +44 -0
  196. package/dist/NumberInput/index.js +2 -0
  197. package/dist/Pagination/Pagination.torp +41 -34
  198. package/dist/Pagination/PaginationItem.torp +50 -13
  199. package/dist/Pagination/PaginationTypes.ts +3 -6
  200. package/dist/Pagination/buildPages.ts +9 -5
  201. package/dist/Pagination/index.d.ts +19 -9
  202. package/dist/Pagination/index.js +3 -40
  203. package/dist/Popover/Popover.torp +32 -50
  204. package/dist/Popover/PopoverContent.torp +27 -76
  205. package/dist/Popover/PopoverHover.torp +90 -0
  206. package/dist/Popover/PopoverTrigger.torp +17 -40
  207. package/dist/Popover/PopoverTypes.ts +4 -17
  208. package/dist/Popover/index.d.ts +40 -25
  209. package/dist/Popover/index.js +18 -18
  210. package/dist/Popover/index.js.map +1 -1
  211. package/dist/Progress/Progress.torp +88 -0
  212. package/dist/Progress/index.d.ts +37 -0
  213. package/dist/Progress/index.js +2 -0
  214. package/dist/Rating/Rating.torp +225 -0
  215. package/dist/Rating/index.d.ts +44 -0
  216. package/dist/Rating/index.js +2 -0
  217. package/dist/SegmentedControl/SegmentedControl.torp +233 -0
  218. package/dist/SegmentedControl/SegmentedControlTypes.ts +26 -0
  219. package/dist/SegmentedControl/SegmentedItem.torp +78 -0
  220. package/dist/SegmentedControl/index.d.ts +74 -0
  221. package/dist/SegmentedControl/index.js +3 -0
  222. package/dist/SelectBox/SelectBox.torp +107 -53
  223. package/dist/SelectBox/SelectBoxContent.torp +45 -19
  224. package/dist/SelectBox/SelectBoxTrigger.torp +108 -8
  225. package/dist/SelectBox/SelectBoxTypes.ts +26 -11
  226. package/dist/SelectBox/index.d.ts +39 -54
  227. package/dist/SelectBox/index.js +5 -18
  228. package/dist/Slider/Slider.torp +248 -0
  229. package/dist/Slider/index.d.ts +45 -0
  230. package/dist/Slider/index.js +2 -0
  231. package/dist/Splitter/Splitter.torp +156 -0
  232. package/dist/Splitter/SplitterHandle.torp +161 -0
  233. package/dist/Splitter/SplitterPane.torp +63 -0
  234. package/dist/Splitter/SplitterTypes.ts +31 -0
  235. package/dist/Splitter/index.d.ts +103 -0
  236. package/dist/Splitter/index.js +4 -0
  237. package/dist/Stepper/Stepper.torp +146 -0
  238. package/dist/Stepper/StepperMarker.torp +24 -0
  239. package/dist/Stepper/StepperNext.torp +44 -0
  240. package/dist/Stepper/StepperPrevious.torp +44 -0
  241. package/dist/Stepper/StepperStep.torp +90 -0
  242. package/dist/Stepper/StepperTypes.ts +30 -0
  243. package/dist/Stepper/index.d.ts +149 -0
  244. package/dist/Stepper/index.js +6 -0
  245. package/dist/TabGroup/TabContent.torp +6 -6
  246. package/dist/TabGroup/TabGroup.torp +97 -113
  247. package/dist/TabGroup/TabGroupTypes.ts +1 -1
  248. package/dist/TabGroup/TabHeader.torp +23 -19
  249. package/dist/TabGroup/TabList.torp +8 -21
  250. package/dist/TabGroup/TabTrigger.torp +6 -7
  251. package/dist/TabGroup/index.d.ts +26 -26
  252. package/dist/TabGroup/index.js +6 -22
  253. package/dist/TagInput/TagInput.torp +378 -0
  254. package/dist/TagInput/index.d.ts +48 -0
  255. package/dist/TagInput/index.js +2 -0
  256. package/dist/TimePicker/TimePicker.torp +462 -0
  257. package/dist/TimePicker/index.d.ts +53 -0
  258. package/dist/TimePicker/index.js +2 -0
  259. package/dist/ToolBar/ToolBar.torp +29 -110
  260. package/dist/ToolBar/ToolBarButton.torp +7 -8
  261. package/dist/ToolBar/ToolBarElement.torp +7 -11
  262. package/dist/ToolBar/ToolBarPopout.torp +16 -68
  263. package/dist/ToolBar/ToolBarPopoutContent.torp +15 -73
  264. package/dist/ToolBar/ToolBarPopoutTrigger.torp +19 -110
  265. package/dist/ToolBar/ToolBarSeparator.torp +3 -7
  266. package/dist/ToolBar/ToolBarTypes.ts +7 -14
  267. package/dist/ToolBar/index.d.ts +30 -32
  268. package/dist/ToolBar/index.js +8 -30
  269. package/dist/Tree/Tree.torp +395 -0
  270. package/dist/Tree/TreeItem.torp +176 -0
  271. package/dist/Tree/TreeItemChildren.torp +60 -0
  272. package/dist/Tree/TreeItemContent.torp +46 -0
  273. package/dist/Tree/TreeItemLabel.torp +94 -0
  274. package/dist/Tree/TreeItemTrigger.torp +78 -0
  275. package/dist/Tree/TreeLoadedChildren.torp +122 -0
  276. package/dist/Tree/TreeTypes.ts +63 -0
  277. package/dist/Tree/index.d.ts +262 -0
  278. package/dist/Tree/index.js +7 -0
  279. package/dist/icons/ChevronDoubleLeft.torp +19 -0
  280. package/dist/icons/ChevronDoubleRight.torp +19 -0
  281. package/dist/icons/index.d.ts +61 -1
  282. package/dist/icons/index.js +17 -58
  283. package/dist/loader-DEeG5vFY.js +44 -0
  284. package/dist/loader-DEeG5vFY.js.map +1 -0
  285. package/dist/motion/index.d.ts +12 -8
  286. package/dist/motion/index.d.ts.map +1 -0
  287. package/dist/motion/index.js +72 -88
  288. package/dist/motion/index.js.map +1 -1
  289. package/dist/mount/draggable.ts +63 -0
  290. package/dist/mount/dropTarget.ts +108 -0
  291. package/dist/mount/hoverTrigger.ts +1 -1
  292. package/dist/utils/$handle.ts +23 -0
  293. package/dist/utils/LoadedItems.torp +47 -0
  294. package/dist/utils/PopoutClickTrigger.torp +99 -0
  295. package/dist/utils/PopoutTypes.ts +59 -12
  296. package/dist/utils/SubmenuPopout.torp +89 -0
  297. package/dist/utils/SubmenuPopoutContent.torp +87 -0
  298. package/dist/utils/SubmenuPopoutTrigger.torp +160 -0
  299. package/dist/utils/chartColors.ts +13 -13
  300. package/dist/utils/chartLayout.ts +143 -0
  301. package/dist/utils/colorUtils.ts +103 -0
  302. package/dist/utils/createItemGroup.ts +152 -0
  303. package/dist/utils/dateUtils.ts +8 -7
  304. package/dist/utils/documentEvents.ts +4 -4
  305. package/dist/utils/dragState.ts +86 -0
  306. package/dist/utils/focusGroup.ts +204 -0
  307. package/dist/utils/focusItem.ts +44 -0
  308. package/dist/utils/formField.ts +70 -0
  309. package/dist/utils/hoverOpen.ts +50 -0
  310. package/dist/utils/hoverReveal.ts +194 -0
  311. package/dist/utils/loader.ts +113 -0
  312. package/dist/utils/maskUtils.ts +98 -0
  313. package/dist/utils/popoutContent.ts +137 -0
  314. package/dist/utils/reorderList.ts +52 -0
  315. package/package.json +97 -22
  316. package/dist/Accordion/index.js.map +0 -1
  317. package/dist/Breadcrumb/index.js.map +0 -1
  318. package/dist/Calendar/index.js.map +0 -1
  319. package/dist/Charts/index.js.map +0 -1
  320. package/dist/Contextual/index.js.map +0 -1
  321. package/dist/Dialog/index.js.map +0 -1
  322. package/dist/Disclosure/index.js.map +0 -1
  323. package/dist/Drawer/index.js.map +0 -1
  324. package/dist/Form/index.js.map +0 -1
  325. package/dist/ListBox/index.js.map +0 -1
  326. package/dist/Menu/index.js.map +0 -1
  327. package/dist/MenuBar/index.js.map +0 -1
  328. package/dist/NavMenu/index.js.map +0 -1
  329. package/dist/Pagination/index.js.map +0 -1
  330. package/dist/SelectBox/SelectBoxInput.torp +0 -95
  331. package/dist/SelectBox/index.js.map +0 -1
  332. package/dist/TabGroup/index.js.map +0 -1
  333. package/dist/ToolBar/index.js.map +0 -1
  334. package/dist/icons/index.js.map +0 -1
  335. package/dist/index.d.ts +0 -19
  336. package/dist/metafile-esm.json +0 -1
  337. package/dist/motion/fade.ts +0 -16
  338. package/dist/motion/grow.ts +0 -23
  339. package/dist/motion/measure.ts +0 -28
  340. package/dist/motion/slide.ts +0 -45
  341. package/dist/mount/index.d.ts +0 -2
  342. package/dist/utils/index.d.ts +0 -2
@@ -0,0 +1,161 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import { type SplitterContext, SplitterContextName } from "./SplitterTypes";
3
+
4
+ interface SplitterHandleProps {
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
+ /** An accessible name for the separator */
12
+ ariaLabel?: string;
13
+ /** If set to true, the user cannot interact with this handle */
14
+ disabled?: boolean;
15
+ }
16
+
17
+ /**
18
+ * The separator in a Splitter that a user can drag, or move with the
19
+ * keyboard, to resize the panes on either side of it.
20
+ *
21
+ * See [the WAI ARIA guidelines for Window Splitters](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/).
22
+ */
23
+ export default function SplitterHandle($props: SplitterHandleProps | undefined) {
24
+ // Get stuff out of the Splitter context
25
+ const context = $context[SplitterContextName] as SplitterContext;
26
+ if (!context) {
27
+ throw new Error("SplitterHandle must be contained within a Splitter");
28
+ }
29
+
30
+ function getDisabled(): boolean {
31
+ return $props?.disabled === true || context.getDisabled();
32
+ }
33
+
34
+ let dragging = false;
35
+
36
+ function removeDragListeners() {
37
+ removeEventListener("mousemove", handleMouseMove);
38
+ removeEventListener("mouseup", handleMouseUp);
39
+ }
40
+
41
+ // Convert a pointer position into a percentage of the container
42
+ function valueFromPointer(e: { clientX: number; clientY: number }): number {
43
+ const container = context.getContainer();
44
+ if (!container) return context.getValue();
45
+ const rect = container.getBoundingClientRect();
46
+ const horizontal = context.getOrientation() === "horizontal";
47
+ const pos = horizontal ? e.clientX - rect.left : e.clientY - rect.top;
48
+ const size = horizontal ? rect.width : rect.height;
49
+ if (!(size > 0)) return context.getValue();
50
+ const ratio = Math.min(1, Math.max(0, pos / size));
51
+ return ratio * 100;
52
+ }
53
+
54
+ function handleMouseDown(e: MouseEvent) {
55
+ if (getDisabled()) return;
56
+ e.preventDefault();
57
+ dragging = true;
58
+ context.setValue(valueFromPointer(e));
59
+ addEventListener("mousemove", handleMouseMove);
60
+ addEventListener("mouseup", handleMouseUp);
61
+ }
62
+
63
+ function handleMouseMove(e: MouseEvent) {
64
+ if (!dragging || getDisabled()) return;
65
+ context.setValue(valueFromPointer(e));
66
+ }
67
+
68
+ function handleMouseUp() {
69
+ if (!dragging) return;
70
+ dragging = false;
71
+ removeDragListeners();
72
+ }
73
+
74
+ // Stop listening if the handle is unmounted mid-drag
75
+ $onmount(() => {
76
+ return () => removeDragListeners();
77
+ });
78
+
79
+ function handleKey(e: KeyboardEvent) {
80
+ if (getDisabled()) return;
81
+ const step = context.getStep();
82
+ const vertical = context.getOrientation() === "vertical";
83
+
84
+ switch (e.key) {
85
+ case "ArrowRight": {
86
+ if (!vertical) {
87
+ e.preventDefault();
88
+ context.setValue(context.getValue() + step);
89
+ }
90
+ break;
91
+ }
92
+ case "ArrowLeft": {
93
+ if (!vertical) {
94
+ e.preventDefault();
95
+ context.setValue(context.getValue() - step);
96
+ }
97
+ break;
98
+ }
99
+ case "ArrowUp": {
100
+ if (vertical) {
101
+ e.preventDefault();
102
+ context.setValue(context.getValue() + step);
103
+ }
104
+ break;
105
+ }
106
+ case "ArrowDown": {
107
+ if (vertical) {
108
+ e.preventDefault();
109
+ context.setValue(context.getValue() - step);
110
+ }
111
+ break;
112
+ }
113
+ case "PageUp": {
114
+ e.preventDefault();
115
+ context.setValue(context.getValue() + step * 10);
116
+ break;
117
+ }
118
+ case "PageDown": {
119
+ e.preventDefault();
120
+ context.setValue(context.getValue() - step * 10);
121
+ break;
122
+ }
123
+ case "Home": {
124
+ e.preventDefault();
125
+ context.setValue(context.getMin());
126
+ break;
127
+ }
128
+ case "End": {
129
+ e.preventDefault();
130
+ context.setValue(context.getMax());
131
+ break;
132
+ }
133
+ }
134
+ }
135
+
136
+ @render {
137
+ <div
138
+ {$props?.id}
139
+ class={["torp-splitter-handle", $props?.class]}
140
+ {$props?.style}
141
+ role="separator"
142
+ tabindex={getDisabled() ? -1 : 0}
143
+ aria-label={$props?.ariaLabel ?? "Resize"}
144
+ aria-orientation={context.getOrientation()}
145
+ aria-valuemin={Math.round(context.getMin())}
146
+ aria-valuemax={Math.round(context.getMax())}
147
+ aria-valuenow={Math.round(context.getValue())}
148
+ aria-disabled={getDisabled() ? "true" : undefined}
149
+ onmousedown={handleMouseDown}
150
+ onkeydown={handleKey}
151
+ />
152
+ }
153
+
154
+ @style {
155
+ /* Headless: behavior only, so the handle can be dragged on touch
156
+ devices. All appearance is up to the consuming theme */
157
+ .torp-splitter-handle {
158
+ touch-action: none;
159
+ }
160
+ }
161
+ }
@@ -0,0 +1,63 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import { type SplitterContext, SplitterContextName } from "./SplitterTypes";
3
+
4
+ interface SplitterPaneProps {
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 pane in a Splitter. When there is more than one pane, the first pane is
15
+ * sized to the splitter's value and the others share what's left.
16
+ */
17
+ export default function SplitterPane($props: SplitterPaneProps | undefined) {
18
+ // Get stuff out of the Splitter context
19
+ const context = $context[SplitterContextName] as SplitterContext;
20
+ if (!context) {
21
+ throw new Error("SplitterPane must be contained within a Splitter");
22
+ }
23
+
24
+ // Register this pane with the parent Splitter
25
+ let $state = context.registerPane();
26
+
27
+ $run(() => {
28
+ return () => {
29
+ context.removePane($state.index);
30
+ };
31
+ });
32
+
33
+ // The primary (first) pane is sized to the value when there are other
34
+ // panes to share the rest of the space with
35
+ function getFlex(): string {
36
+ if ($state.index === 0 && context.count() > 1) {
37
+ return `0 0 ${context.getValue()}%;`;
38
+ }
39
+ return "1 1 0;";
40
+ }
41
+
42
+ @render {
43
+ <div
44
+ {$props?.id}
45
+ class={["torp-splitter-pane", $props?.class]}
46
+ {$props?.style}
47
+ data-orientation={context.getOrientation()}
48
+ style={`flex: ${getFlex()}`}
49
+ >
50
+ <slot />
51
+ </div>
52
+ }
53
+
54
+ @style {
55
+ /* Headless: min sizes only, so the panes can shrink below their
56
+ content. All other appearance is up to the consuming theme */
57
+ .torp-splitter-pane {
58
+ min-height: 0;
59
+ min-width: 0;
60
+ overflow: hidden;
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,31 @@
1
+ export const SplitterContextName: unique symbol = Symbol.for("torp.Splitter");
2
+
3
+ export interface SplitterPaneState {
4
+ /** The index of the pane */
5
+ index: number;
6
+ }
7
+
8
+ export interface SplitterContext {
9
+ /** Called from a pane when it is added */
10
+ registerPane: () => SplitterPaneState;
11
+ /** Called from a pane when it is removed */
12
+ removePane: (index: number) => void;
13
+ /** The orientation of the splitter */
14
+ getOrientation: () => "horizontal" | "vertical";
15
+ /** The clamped percentage of the container taken up by the primary pane */
16
+ getValue: () => number;
17
+ /** The minimum percentage for the primary pane */
18
+ getMin: () => number;
19
+ /** The maximum percentage for the primary pane */
20
+ getMax: () => number;
21
+ /** The amount by which keyboard interaction changes the value */
22
+ getStep: () => number;
23
+ /** Whether the user cannot interact with the splitter */
24
+ getDisabled: () => boolean;
25
+ /** Sets the value, clamped to the min and max */
26
+ setValue: (value: number) => void;
27
+ /** The number of registered panes */
28
+ count: () => number;
29
+ /** The splitter's root element, used to convert pointer positions into values */
30
+ getContainer: () => HTMLElement | undefined;
31
+ }
@@ -0,0 +1,103 @@
1
+ import { type SlotRender } from "@torpor/view";
2
+
3
+
4
+ interface SplitterProps {
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 orientation of the splitter (default horizontal) */
12
+ orientation?: "horizontal" | "vertical";
13
+ /** The percentage of the container taken up by the primary (first) pane */
14
+ value?: Bindable<number>;
15
+ /** The minimum percentage for the primary pane (default 0) */
16
+ min?: number;
17
+ /** The maximum percentage for the primary pane (default 100) */
18
+ max?: number;
19
+ /** The percentage by which keyboard interaction changes the value (default 1) */
20
+ step?: number;
21
+ /** If set to true, the user cannot interact with this splitter */
22
+ disabled?: boolean;
23
+ /** Raised when the value has changed */
24
+ onchange?: (value: number) => void;
25
+ }
26
+
27
+ /**
28
+ * Two resizable panes with a separator between them, which the user can drag
29
+ * or move with the keyboard to resize the panes.
30
+ *
31
+ * See [the WAI ARIA guidelines for Window Splitters](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/).
32
+ *
33
+ * The structure of a Splitter is:
34
+ *
35
+ * ```
36
+ * <Splitter>
37
+ * <SplitterPane>...</SplitterPane>
38
+ * <SplitterHandle ariaLabel="Resize" />
39
+ * <SplitterPane>...</SplitterPane>
40
+ * </Splitter>
41
+ * ```
42
+ */
43
+ declare function Splitter(
44
+ $parent: ParentNode,
45
+ $anchor: Node | null,
46
+ $props: SplitterProps | undefined,
47
+ $context?: Record<PropertyKey, any>,
48
+ $slots?: Record<string, SlotRender>,
49
+ ): void;
50
+
51
+
52
+
53
+ interface SplitterHandleProps {
54
+ /** An ID for the root element */
55
+ id?: string;
56
+ /** Classes for the root element */
57
+ class?: ClassValue;
58
+ /** Styles for the root element */
59
+ style?: StyleValue;
60
+ /** An accessible name for the separator */
61
+ ariaLabel?: string;
62
+ /** If set to true, the user cannot interact with this handle */
63
+ disabled?: boolean;
64
+ }
65
+
66
+ /**
67
+ * The separator in a Splitter that a user can drag, or move with the
68
+ * keyboard, to resize the panes on either side of it.
69
+ *
70
+ * See [the WAI ARIA guidelines for Window Splitters](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/).
71
+ */
72
+ declare function SplitterHandle(
73
+ $parent: ParentNode,
74
+ $anchor: Node | null,
75
+ $props: SplitterHandleProps | undefined,
76
+ $context?: Record<PropertyKey, any>,
77
+ $slots?: Record<string, SlotRender>,
78
+ ): void;
79
+
80
+
81
+
82
+ interface SplitterPaneProps {
83
+ /** An ID for the root element */
84
+ id?: string;
85
+ /** Classes for the root element */
86
+ class?: ClassValue;
87
+ /** Styles for the root element */
88
+ style?: StyleValue;
89
+ }
90
+
91
+ /**
92
+ * A pane in a Splitter. When there is more than one pane, the first pane is
93
+ * sized to the splitter's value and the others share what's left.
94
+ */
95
+ declare function SplitterPane(
96
+ $parent: ParentNode,
97
+ $anchor: Node | null,
98
+ $props: SplitterPaneProps | undefined,
99
+ $context?: Record<PropertyKey, any>,
100
+ $slots?: Record<string, SlotRender>,
101
+ ): void;
102
+
103
+ export { Splitter, SplitterHandle, SplitterPane };
@@ -0,0 +1,4 @@
1
+ import Splitter from "./Splitter.torp";
2
+ import SplitterHandle from "./SplitterHandle.torp";
3
+ import SplitterPane from "./SplitterPane.torp";
4
+ export { Splitter, SplitterHandle, SplitterPane };
@@ -0,0 +1,146 @@
1
+ import type { Bindable, ClassValue, StyleValue } from "@torpor/view";
2
+ import $handle from "../utils/$handle";
3
+ import { type StepperContext, StepperContextName } from "./StepperTypes";
4
+
5
+ interface StepperProps {
6
+ /** An ID for the root element */
7
+ id?: string;
8
+ /** Classes for the root element */
9
+ class?: ClassValue;
10
+ /** Styles for the root element */
11
+ style?: StyleValue;
12
+ /** The index of the current step */
13
+ value?: Bindable<number>;
14
+ /** Whether steps can only be visited in order, with completed ones revisitable (default true) */
15
+ linear?: boolean;
16
+ /** An accessible label for the steps */
17
+ ariaLabel?: string;
18
+ /** Raised when the current step has changed */
19
+ onchange?: (index: number) => void;
20
+ /** Raised when the user moves next from the last step */
21
+ oncomplete?: () => void;
22
+ }
23
+
24
+ /**
25
+ * A sequence of steps in a task, showing progress through them. Steps before
26
+ * the current one are complete, and can be revisited; the user moves between
27
+ * steps with the navigation controls.
28
+ *
29
+ * The structure of a Stepper is:
30
+ *
31
+ * ```
32
+ * <Stepper ariaLabel="Sign up">
33
+ * <StepperStep label="Account" />
34
+ * <StepperStep label="Profile" />
35
+ * <fill name="nav">
36
+ * <StepperPrevious />
37
+ * <StepperNext />
38
+ * </fill>
39
+ * </Stepper>
40
+ * ```
41
+ */
42
+ export default function Stepper($props: StepperProps | undefined) {
43
+ let $state = $watch({
44
+ value: 0,
45
+ steps: [] as StepperStepStateLite[],
46
+ });
47
+
48
+ interface StepperStepStateLite {
49
+ index: number;
50
+ }
51
+
52
+ $bind($state, $props, "value");
53
+
54
+ // Set the context to pass down to steps and navigation controls
55
+ const context: StepperContext = {
56
+ registerStep,
57
+ removeStep,
58
+ getValue,
59
+ setValue,
60
+ next,
61
+ previous,
62
+ canNext,
63
+ canPrevious,
64
+ steps: () => $state.steps,
65
+ count: () => $state.steps.length,
66
+ linear: $props?.linear !== false,
67
+ };
68
+ $context[StepperContextName] = context;
69
+
70
+ // Dispatch the change event when the current step changes
71
+ $handle((first) => {
72
+ const value = getValue();
73
+ if (!first) $props?.onchange?.(value);
74
+ });
75
+
76
+ // The clamped index of the current step
77
+ function getValue(): number {
78
+ const last = Math.max(0, $state.steps.length - 1);
79
+ return Math.min(last, Math.max(0, $state.value));
80
+ }
81
+
82
+ function canNext(): boolean {
83
+ return getValue() < $state.steps.length - 1;
84
+ }
85
+
86
+ function canPrevious(): boolean {
87
+ return getValue() > 0;
88
+ }
89
+
90
+ function setValue(index: number) {
91
+ const last = Math.max(0, $state.steps.length - 1);
92
+ $state.value = Math.min(last, Math.max(0, index));
93
+ }
94
+
95
+ function next() {
96
+ if (canNext()) {
97
+ setValue(getValue() + 1);
98
+ } else {
99
+ $props?.oncomplete?.();
100
+ }
101
+ }
102
+
103
+ function previous() {
104
+ if (canPrevious()) {
105
+ setValue(getValue() - 1);
106
+ }
107
+ }
108
+
109
+ function registerStep(): StepperStepStateLite {
110
+ const state: StepperStepStateLite = $watch({ index: $state.steps.length });
111
+ $state.steps.push(state);
112
+ return state;
113
+ }
114
+
115
+ function removeStep(index: number) {
116
+ if (index >= 0 && index < $state.steps.length) {
117
+ $state.steps.splice(index, 1);
118
+ }
119
+ $state.steps.forEach((step, i) => (step.index = i));
120
+ }
121
+
122
+ @render {
123
+ <div {$props?.id} class={["torp-stepper", $props?.class]} {$props?.style}>
124
+ <ol class="torp-stepper-steps" aria-label={$props?.ariaLabel}>
125
+ <slot />
126
+ </ol>
127
+ <div class="torp-stepper-nav">
128
+ <slot name="nav" />
129
+ </div>
130
+ </div>
131
+ }
132
+
133
+ @style {
134
+ /* Headless: layout only, so the steps and navigation sit in rows. All
135
+ appearance is up to the consuming theme */
136
+ .torp-stepper-steps {
137
+ display: flex;
138
+ list-style: none;
139
+ margin: 0;
140
+ padding: 0;
141
+ }
142
+ .torp-stepper-nav {
143
+ display: flex;
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,24 @@
1
+ import Check from "../icons/Check.torp";
2
+
3
+ interface StepperMarkerProps {
4
+ /** Whether the step this marker belongs to is complete */
5
+ complete: boolean;
6
+ /** The index of the step this marker belongs to */
7
+ index: number;
8
+ }
9
+
10
+ /**
11
+ * The marker for a Stepper step, which shows a check when the step is
12
+ * complete or its number otherwise.
13
+ */
14
+ export default function StepperMarker($props: StepperMarkerProps) {
15
+ @render {
16
+ <span class="torp-stepper-marker" data-state={$props.complete ? "complete" : "incomplete"}>
17
+ @if ($props.complete) {
18
+ <Check />
19
+ } @else {
20
+ <span aria-hidden="true">{$props.index + 1}</span>
21
+ }
22
+ </span>
23
+ }
24
+ }
@@ -0,0 +1,44 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import ChevronRight from "../icons/ChevronRight.torp";
3
+ import { type StepperContext, StepperContextName } from "./StepperTypes";
4
+
5
+ interface StepperNextProps {
6
+ /** An ID for the root element */
7
+ id?: string;
8
+ /** Classes for the root element */
9
+ class?: ClassValue;
10
+ /** Styles for the root element */
11
+ style?: StyleValue;
12
+ /** An ARIA label for the button, for screen readers when the button contains no text */
13
+ ariaLabel?: string;
14
+ /** If set to true, the user cannot interact with this button */
15
+ disabled?: boolean;
16
+ }
17
+
18
+ /**
19
+ * The button in a Stepper that a user can press to move to the next step,
20
+ * which raises the stepper's oncomplete event on the last step.
21
+ */
22
+ export default function StepperNext($props: StepperNextProps | undefined) {
23
+ // Get stuff out of the Stepper context
24
+ const context = $context[StepperContextName] as StepperContext;
25
+ if (!context) {
26
+ throw new Error("StepperNext must be contained within a Stepper");
27
+ }
28
+
29
+ @render {
30
+ <button
31
+ {$props?.id}
32
+ class={["torp-stepper-next", $props?.class]}
33
+ {$props?.style}
34
+ type="button"
35
+ aria-label={$props?.ariaLabel ?? "Next step"}
36
+ disabled={$props?.disabled}
37
+ onclick={() => context.next()}
38
+ >
39
+ <slot>
40
+ <ChevronRight />
41
+ </slot>
42
+ </button>
43
+ }
44
+ }
@@ -0,0 +1,44 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import ChevronLeft from "../icons/ChevronLeft.torp";
3
+ import { type StepperContext, StepperContextName } from "./StepperTypes";
4
+
5
+ interface StepperPreviousProps {
6
+ /** An ID for the root element */
7
+ id?: string;
8
+ /** Classes for the root element */
9
+ class?: ClassValue;
10
+ /** Styles for the root element */
11
+ style?: StyleValue;
12
+ /** An ARIA label for the button, for screen readers when the button contains no text */
13
+ ariaLabel?: string;
14
+ /** If set to true, the user cannot interact with this button */
15
+ disabled?: boolean;
16
+ }
17
+
18
+ /**
19
+ * The button in a Stepper that a user can press to move to the previous
20
+ * step.
21
+ */
22
+ export default function StepperPrevious($props: StepperPreviousProps | undefined) {
23
+ // Get stuff out of the Stepper context
24
+ const context = $context[StepperContextName] as StepperContext;
25
+ if (!context) {
26
+ throw new Error("StepperPrevious must be contained within a Stepper");
27
+ }
28
+
29
+ @render {
30
+ <button
31
+ {$props?.id}
32
+ class={["torp-stepper-previous", $props?.class]}
33
+ {$props?.style}
34
+ type="button"
35
+ aria-label={$props?.ariaLabel ?? "Previous step"}
36
+ disabled={$props?.disabled || !context.canPrevious()}
37
+ onclick={() => context.previous()}
38
+ >
39
+ <slot>
40
+ <ChevronLeft />
41
+ </slot>
42
+ </button>
43
+ }
44
+ }