@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,248 @@
1
+ import type { Bindable, ClassValue, StyleValue } from "@torpor/view";
2
+ import $handle from "../utils/$handle";
3
+ import {
4
+ type FieldContext,
5
+ FieldContextName,
6
+ type FormContext,
7
+ FormContextName,
8
+ } from "../Form/FormTypes";
9
+ import FormValues from "../Form/FormValues.torp";
10
+ import createFormField from "../utils/formField";
11
+
12
+ interface SliderProps {
13
+ /** An ID for the root element */
14
+ id?: string;
15
+ /** Classes for the root element */
16
+ class?: ClassValue;
17
+ /** Styles for the root element */
18
+ style?: StyleValue;
19
+ /** The minimum allowed value */
20
+ min?: number;
21
+ /** The maximum allowed value */
22
+ max?: number;
23
+ /** The amount by which the value is increased or decreased */
24
+ step?: number;
25
+ /** The current value of the slider */
26
+ value?: Bindable<number>;
27
+ /** The orientation of the slider */
28
+ orientation?: "horizontal" | "vertical";
29
+ /** If set to true, the user cannot interact with this slider */
30
+ disabled?: boolean;
31
+ /** An accessible name for the slider */
32
+ ariaLabel?: string;
33
+ /** The name of the component's form data field */
34
+ name?: string;
35
+ /** Raised when the value has changed */
36
+ onchange?: (value: number) => void;
37
+ }
38
+
39
+ /**
40
+ * An input where the user selects a value from within a given range, by
41
+ * dragging a thumb along a track or by using the keyboard.
42
+ *
43
+ * See [the WAI ARIA guidelines for Sliders](https://www.w3.org/WAI/ARIA/apg/patterns/slider/).
44
+ */
45
+ export default function Slider($props: SliderProps | undefined) {
46
+ let track: HTMLElement;
47
+ let thumb: HTMLElement;
48
+
49
+ // Wire up the enclosing Form and Field, if any
50
+ const form = createFormField(
51
+ $props?.name,
52
+ $context[FormContextName] as FormContext | undefined,
53
+ $context[FieldContextName] as FieldContext | undefined,
54
+ );
55
+
56
+ function getMin(): number {
57
+ return $props?.min ?? 0;
58
+ }
59
+ function getMax(): number {
60
+ return $props?.max ?? 100;
61
+ }
62
+ function getStep(): number {
63
+ const step = $props?.step ?? 1;
64
+ return step > 0 ? step : 1;
65
+ }
66
+ function getOrientation(): "horizontal" | "vertical" {
67
+ return $props?.orientation === "vertical" ? "vertical" : "horizontal";
68
+ }
69
+ function getDisabled(): boolean {
70
+ return $props?.disabled === true;
71
+ }
72
+
73
+ let $state = $watch({
74
+ value: 0,
75
+ });
76
+
77
+ $bind($state, $props, "value");
78
+
79
+ // Dispatch the change event when the value changes
80
+ $handle((first) => {
81
+ const value = $state.value;
82
+ if (!first) $props?.onchange?.(value);
83
+ });
84
+
85
+ function clamp(value: number): number {
86
+ return Math.min(getMax(), Math.max(getMin(), value));
87
+ }
88
+
89
+ // Snap a raw position-derived value to the nearest step multiple
90
+ function snap(value: number): number {
91
+ const min = getMin();
92
+ const snapped = min + Math.round((value - min) / getStep()) * getStep();
93
+ return snapped === -0 ? 0 : snapped;
94
+ }
95
+
96
+ // The clamped value that is displayed and reported to assistive tech
97
+ function getValue(): number {
98
+ return clamp($state.value);
99
+ }
100
+
101
+ // The percentage of the range that the value represents (0..100)
102
+ function getPct(): number {
103
+ const min = getMin();
104
+ const max = getMax();
105
+ if (max <= min) return 0;
106
+ return ((getValue() - min) / (max - min)) * 100;
107
+ }
108
+
109
+ function setValue(value: number) {
110
+ const next = clamp(snap(value));
111
+ if (next !== $state.value) {
112
+ $state.value = next;
113
+ form.handleInput();
114
+ return true;
115
+ }
116
+ return false;
117
+ }
118
+
119
+ // Convert a pointer position into a value along the track
120
+ function valueFromPointer(e: { clientX: number; clientY: number }): number {
121
+ const rect = track.getBoundingClientRect();
122
+ const horizontal = getOrientation() === "horizontal";
123
+ const pos = horizontal ? e.clientX - rect.left : e.clientY - rect.top;
124
+ const size = horizontal ? rect.width : rect.height;
125
+ if (!(size > 0)) {
126
+ return getValue();
127
+ }
128
+ const ratio = Math.min(1, Math.max(0, pos / size));
129
+ return getMin() + ratio * (getMax() - getMin());
130
+ }
131
+
132
+ let dragging = false;
133
+
134
+ function removeDragListeners() {
135
+ removeEventListener("mousemove", handleMouseMove);
136
+ removeEventListener("mouseup", handleMouseUp);
137
+ }
138
+
139
+ function handleMouseDown(e: MouseEvent) {
140
+ if (getDisabled()) return;
141
+ e.preventDefault();
142
+ dragging = true;
143
+ setValue(valueFromPointer(e));
144
+ thumb.focus();
145
+ addEventListener("mousemove", handleMouseMove);
146
+ addEventListener("mouseup", handleMouseUp);
147
+ }
148
+
149
+ function handleMouseMove(e: MouseEvent) {
150
+ if (!dragging || getDisabled()) return;
151
+ setValue(valueFromPointer(e));
152
+ }
153
+
154
+ function handleMouseUp() {
155
+ if (!dragging) return;
156
+ dragging = false;
157
+ removeDragListeners();
158
+ }
159
+
160
+ // Stop listening if the slider is unmounted mid-drag
161
+ $onmount(() => {
162
+ return () => removeDragListeners();
163
+ });
164
+
165
+ function handleKey(e: KeyboardEvent) {
166
+ if (getDisabled()) return;
167
+
168
+ switch (e.key) {
169
+ case "ArrowRight":
170
+ case "ArrowUp": {
171
+ e.preventDefault();
172
+ setValue($state.value + getStep());
173
+ break;
174
+ }
175
+ case "ArrowLeft":
176
+ case "ArrowDown": {
177
+ e.preventDefault();
178
+ setValue($state.value - getStep());
179
+ break;
180
+ }
181
+ case "PageUp": {
182
+ e.preventDefault();
183
+ setValue($state.value + getStep() * 10);
184
+ break;
185
+ }
186
+ case "PageDown": {
187
+ e.preventDefault();
188
+ setValue($state.value - getStep() * 10);
189
+ break;
190
+ }
191
+ case "Home": {
192
+ e.preventDefault();
193
+ setValue(getMin());
194
+ break;
195
+ }
196
+ case "End": {
197
+ e.preventDefault();
198
+ setValue(getMax());
199
+ break;
200
+ }
201
+ }
202
+ }
203
+
204
+ @render {
205
+ <div
206
+ {$props?.id}
207
+ class={["torp-slider", getDisabled() ? "torp-slider-disabled" : undefined, $props?.class]}
208
+ {$props?.style}
209
+ onmousedown={handleMouseDown}
210
+ &ref={track}
211
+ >
212
+ <div class="torp-slider-fill" style={`${getOrientation() === "vertical" ? "height" : "width"}: ${getPct()}%;`} />
213
+ <div
214
+ class="torp-slider-thumb"
215
+ style={`${getOrientation() === "vertical" ? "top" : "left"}: ${getPct()}%;`}
216
+ role="slider"
217
+ tabindex={getDisabled() ? -1 : 0}
218
+ aria-orientation={getOrientation()}
219
+ aria-valuemin={getMin()}
220
+ aria-valuemax={getMax()}
221
+ aria-valuenow={getValue()}
222
+ aria-label={$props?.ariaLabel}
223
+ aria-disabled={getDisabled() ? "true" : undefined}
224
+ data-valid={form.valid ? "valid" : "invalid"}
225
+ aria-describedby={form.messageId}
226
+ aria-invalid={form.inField && !form.valid ? "true" : undefined}
227
+ onblur={form.handleBlur}
228
+ onkeydown={handleKey}
229
+ &ref={thumb}
230
+ />
231
+ </div>
232
+
233
+ <FormValues name={form.name} value={getValue()} />
234
+ }
235
+
236
+ @style {
237
+ /* Headless: positioning only, so the thumb sits at the value along
238
+ the track. All appearance is up to the consuming theme */
239
+ .torp-slider {
240
+ position: relative;
241
+ touch-action: none;
242
+ }
243
+ .torp-slider-thumb {
244
+ position: absolute;
245
+ transform: translateX(-50%);
246
+ }
247
+ }
248
+ }
@@ -0,0 +1,45 @@
1
+ import { type SlotRender } from "@torpor/view";
2
+
3
+
4
+ interface SliderProps {
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 minimum allowed value */
12
+ min?: number;
13
+ /** The maximum allowed value */
14
+ max?: number;
15
+ /** The amount by which the value is increased or decreased */
16
+ step?: number;
17
+ /** The current value of the slider */
18
+ value?: Bindable<number>;
19
+ /** The orientation of the slider */
20
+ orientation?: "horizontal" | "vertical";
21
+ /** If set to true, the user cannot interact with this slider */
22
+ disabled?: boolean;
23
+ /** An accessible name for the slider */
24
+ ariaLabel?: string;
25
+ /** The name of the component's form data field */
26
+ name?: string;
27
+ /** Raised when the value has changed */
28
+ onchange?: (value: number) => void;
29
+ }
30
+
31
+ /**
32
+ * An input where the user selects a value from within a given range, by
33
+ * dragging a thumb along a track or by using the keyboard.
34
+ *
35
+ * See [the WAI ARIA guidelines for Sliders](https://www.w3.org/WAI/ARIA/apg/patterns/slider/).
36
+ */
37
+ declare function Slider(
38
+ $parent: ParentNode,
39
+ $anchor: Node | null,
40
+ $props: SliderProps | undefined,
41
+ $context?: Record<PropertyKey, any>,
42
+ $slots?: Record<string, SlotRender>,
43
+ ): void;
44
+
45
+ export { Slider };
@@ -0,0 +1,2 @@
1
+ import Slider from "./Slider.torp";
2
+ export { Slider };
@@ -0,0 +1,156 @@
1
+ import type { Bindable, ClassValue, StyleValue } from "@torpor/view";
2
+ import $handle from "../utils/$handle";
3
+ import { type SplitterContext, SplitterContextName } from "./SplitterTypes";
4
+
5
+ interface SplitterProps {
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 orientation of the splitter (default horizontal) */
13
+ orientation?: "horizontal" | "vertical";
14
+ /** The percentage of the container taken up by the primary (first) pane */
15
+ value?: Bindable<number>;
16
+ /** The minimum percentage for the primary pane (default 0) */
17
+ min?: number;
18
+ /** The maximum percentage for the primary pane (default 100) */
19
+ max?: number;
20
+ /** The percentage by which keyboard interaction changes the value (default 1) */
21
+ step?: number;
22
+ /** If set to true, the user cannot interact with this splitter */
23
+ disabled?: boolean;
24
+ /** Raised when the value has changed */
25
+ onchange?: (value: number) => void;
26
+ }
27
+
28
+ /**
29
+ * Two resizable panes with a separator between them, which the user can drag
30
+ * or move with the keyboard to resize the panes.
31
+ *
32
+ * See [the WAI ARIA guidelines for Window Splitters](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/).
33
+ *
34
+ * The structure of a Splitter is:
35
+ *
36
+ * ```
37
+ * <Splitter>
38
+ * <SplitterPane>...</SplitterPane>
39
+ * <SplitterHandle ariaLabel="Resize" />
40
+ * <SplitterPane>...</SplitterPane>
41
+ * </Splitter>
42
+ * ```
43
+ */
44
+ export default function Splitter($props: SplitterProps | undefined) {
45
+ let container: HTMLElement;
46
+
47
+ let $state = $watch({
48
+ value: 50,
49
+ panes: [] as SplitterPaneStateLite[],
50
+ });
51
+
52
+ interface SplitterPaneStateLite {
53
+ index: number;
54
+ }
55
+
56
+ $bind($state, $props, "value");
57
+
58
+ // Keep the stored value clamped, so that out-of-range initial values or
59
+ // min/max changes don't later surface as user changes
60
+ $run(() => {
61
+ const clamped = getValue();
62
+ if (clamped !== $state.value) {
63
+ $state.value = clamped;
64
+ }
65
+ });
66
+
67
+ // Set the context to pass down to panes and handles
68
+ const context: SplitterContext = {
69
+ registerPane,
70
+ removePane,
71
+ getOrientation,
72
+ getValue,
73
+ getMin,
74
+ getMax,
75
+ getStep,
76
+ getDisabled,
77
+ setValue,
78
+ count: () => $state.panes.length,
79
+ getContainer: () => container,
80
+ };
81
+ $context[SplitterContextName] = context;
82
+
83
+ // Dispatch the change event when the value changes
84
+ $handle((first) => {
85
+ const value = getValue();
86
+ if (!first) $props?.onchange?.(value);
87
+ });
88
+
89
+ function getOrientation(): "horizontal" | "vertical" {
90
+ return $props?.orientation === "vertical" ? "vertical" : "horizontal";
91
+ }
92
+
93
+ function getMin(): number {
94
+ return clampPercent($props?.min ?? 0);
95
+ }
96
+
97
+ function getMax(): number {
98
+ return clampPercent($props?.max ?? 100);
99
+ }
100
+
101
+ function clampPercent(value: number): number {
102
+ return Math.min(100, Math.max(0, value));
103
+ }
104
+
105
+ function getStep(): number {
106
+ const step = $props?.step ?? 1;
107
+ return step > 0 ? step : 1;
108
+ }
109
+
110
+ function getDisabled(): boolean {
111
+ return $props?.disabled === true;
112
+ }
113
+
114
+ // The clamped value that is applied to the primary pane
115
+ function getValue(): number {
116
+ return Math.min(getMax(), Math.max(getMin(), $state.value));
117
+ }
118
+
119
+ function setValue(value: number) {
120
+ $state.value = Math.min(getMax(), Math.max(getMin(), value));
121
+ }
122
+
123
+ function registerPane(): SplitterPaneStateLite {
124
+ const state: SplitterPaneStateLite = $watch({ index: $state.panes.length });
125
+ $state.panes.push(state);
126
+ return state;
127
+ }
128
+
129
+ function removePane(index: number) {
130
+ if (index >= 0 && index < $state.panes.length) {
131
+ $state.panes.splice(index, 1);
132
+ }
133
+ $state.panes.forEach((pane, i) => (pane.index = i));
134
+ }
135
+
136
+ @render {
137
+ <div
138
+ {$props?.id}
139
+ class={["torp-splitter", $props?.class]}
140
+ {$props?.style}
141
+ data-orientation={getOrientation()}
142
+ style={`flex-direction: ${getOrientation()};`}
143
+ &ref={container}
144
+ >
145
+ <slot />
146
+ </div>
147
+ }
148
+
149
+ @style {
150
+ /* Headless: layout only, so the panes split the container. All other
151
+ appearance is up to the consuming theme */
152
+ .torp-splitter {
153
+ display: flex;
154
+ }
155
+ }
156
+ }
@@ -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
+ }