@torpor/ui 0.4.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +85 -0
  43. package/dist/Charts/ChartYAxis.torp +107 -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 +14 -11
  51. package/dist/Charts/YAxis.torp +10 -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 +120 -0
  60. package/dist/ComboBox/ComboBoxInput.torp +161 -0
  61. package/dist/ComboBox/ComboBoxTrigger.torp +49 -0
  62. package/dist/ComboBox/ComboBoxTypes.ts +39 -0
  63. package/dist/ComboBox/index.d.ts +154 -0
  64. package/dist/ComboBox/index.js +6 -0
  65. package/dist/CommandPalette/CommandPalette.torp +223 -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 +315 -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 +70 -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 +49 -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 +245 -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 +70 -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,180 @@
1
+ import type { Bindable, ClassValue, StyleValue } from "@torpor/view";
2
+ import $handle from "../utils/$handle";
3
+ import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
4
+
5
+ interface CarouselProps {
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 active slide */
13
+ value?: Bindable<number>;
14
+ /** Whether the next and previous controls wrap around at the ends (default true) */
15
+ wrap?: boolean;
16
+ /** An accessible label for the carousel region */
17
+ ariaLabel?: string;
18
+ /** Raised when the active slide has changed */
19
+ onchange?: (index: number) => void;
20
+ }
21
+
22
+ /**
23
+ * A carousel that displays a sequence of slides, which the user can move
24
+ * between with previous and next controls, slide indicators, or the keyboard.
25
+ *
26
+ * See [the WAI ARIA guidelines for Carousels](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/).
27
+ *
28
+ * The structure of a Carousel is:
29
+ *
30
+ * ```
31
+ * <Carousel ariaLabel="Featured">
32
+ * <CarouselPrevious />
33
+ * <CarouselSlide>...</CarouselSlide>
34
+ * <CarouselSlide>...</CarouselSlide>
35
+ * <CarouselNext />
36
+ * <CarouselIndicators />
37
+ * </Carousel>
38
+ * ```
39
+ */
40
+ export default function Carousel($props: CarouselProps | undefined) {
41
+ let $state = $watch({
42
+ value: 0,
43
+ slides: [] as SlideStateLite[],
44
+ });
45
+
46
+ interface SlideStateLite {
47
+ index: number;
48
+ }
49
+
50
+ $bind($state, $props, "value");
51
+
52
+ // Set the context to pass down to slides and controls
53
+ const context: CarouselContext = {
54
+ registerSlide,
55
+ removeSlide,
56
+ goToSlide,
57
+ nextSlide,
58
+ previousSlide,
59
+ isActive,
60
+ canNext,
61
+ canPrevious,
62
+ slides: () => $state.slides,
63
+ count: () => $state.slides.length,
64
+ };
65
+ $context[CarouselContextName] = context;
66
+
67
+ // Dispatch the change event when the active slide changes
68
+ $handle((first) => {
69
+ const value = getValue();
70
+ if (!first) $props?.onchange?.(value);
71
+ });
72
+
73
+ function getWrap(): boolean {
74
+ return $props?.wrap !== false;
75
+ }
76
+
77
+ // The clamped index that is displayed and reported to assistive tech
78
+ function getValue(): number {
79
+ const last = Math.max(0, $state.slides.length - 1);
80
+ return Math.min(last, Math.max(0, $state.value));
81
+ }
82
+
83
+ function isActive(index: number): boolean {
84
+ return getValue() === index;
85
+ }
86
+
87
+ function canNext(): boolean {
88
+ if ($state.slides.length < 2) return false;
89
+ return getWrap() || getValue() < $state.slides.length - 1;
90
+ }
91
+
92
+ function canPrevious(): boolean {
93
+ if ($state.slides.length < 2) return false;
94
+ return getWrap() || getValue() > 0;
95
+ }
96
+
97
+ function goToSlide(index: number) {
98
+ const last = Math.max(0, $state.slides.length - 1);
99
+ $state.value = Math.min(last, Math.max(0, index));
100
+ }
101
+
102
+ function nextSlide() {
103
+ const count = $state.slides.length;
104
+ if (count < 2) return;
105
+ if (getWrap()) {
106
+ goToSlide((getValue() + 1) % count);
107
+ } else {
108
+ goToSlide(getValue() + 1);
109
+ }
110
+ }
111
+
112
+ function previousSlide() {
113
+ const count = $state.slides.length;
114
+ if (count < 2) return;
115
+ if (getWrap()) {
116
+ goToSlide((getValue() - 1 + count) % count);
117
+ } else {
118
+ goToSlide(getValue() - 1);
119
+ }
120
+ }
121
+
122
+ function registerSlide(): SlideStateLite {
123
+ const state: SlideStateLite = $watch({ index: $state.slides.length });
124
+ $state.slides.push(state);
125
+ return state;
126
+ }
127
+
128
+ function removeSlide(index: number) {
129
+ if (index >= 0 && index < $state.slides.length) {
130
+ $state.slides.splice(index, 1);
131
+ }
132
+ $state.slides.forEach((slide, i) => (slide.index = i));
133
+ }
134
+
135
+ // The keyboard interface is the previous / next controls; arrow keys also
136
+ // work when focus is on the region or a slide, but never when it is on an
137
+ // interactive element inside the carousel
138
+ function handleKey(e: KeyboardEvent) {
139
+ const target = e.target as HTMLElement;
140
+ if (target.closest("button, a, input, select, textarea, [contenteditable]")) {
141
+ return;
142
+ }
143
+ switch (e.key) {
144
+ case "ArrowRight": {
145
+ e.preventDefault();
146
+ nextSlide();
147
+ break;
148
+ }
149
+ case "ArrowLeft": {
150
+ e.preventDefault();
151
+ previousSlide();
152
+ break;
153
+ }
154
+ case "Home": {
155
+ e.preventDefault();
156
+ goToSlide(0);
157
+ break;
158
+ }
159
+ case "End": {
160
+ e.preventDefault();
161
+ goToSlide($state.slides.length - 1);
162
+ break;
163
+ }
164
+ }
165
+ }
166
+
167
+ @render {
168
+ <div
169
+ {$props?.id}
170
+ class={["torp-carousel", $props?.class]}
171
+ {$props?.style}
172
+ role="region"
173
+ aria-roledescription="carousel"
174
+ aria-label={$props?.ariaLabel ?? "Carousel"}
175
+ onkeydown={handleKey}
176
+ >
177
+ <slot />
178
+ </div>
179
+ }
180
+ }
@@ -0,0 +1,65 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
3
+
4
+ interface CarouselIndicatorsProps {
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 series of buttons in a Carousel, one per slide, that a user can press to
15
+ * move directly to that slide.
16
+ */
17
+ export default function CarouselIndicators($props: CarouselIndicatorsProps | undefined) {
18
+ // Get stuff out of the Carousel context
19
+ const context = $context[CarouselContextName] as CarouselContext;
20
+ if (!context) {
21
+ throw new Error("CarouselIndicators must be contained within a Carousel");
22
+ }
23
+
24
+ let $state = $watch({
25
+ get slides() {
26
+ return context.slides();
27
+ },
28
+ });
29
+
30
+ function indicatorLabel(index: number): string {
31
+ return `Go to slide ${index + 1}`;
32
+ }
33
+
34
+ @render {
35
+ <div
36
+ {$props?.id}
37
+ class={["torp-carousel-indicators", $props?.class]}
38
+ {$props?.style}
39
+ >
40
+ @for (let slide of $state.slides) {
41
+ @key = slide.index
42
+ <button
43
+ type="button"
44
+ class="torp-carousel-indicator"
45
+ aria-label={indicatorLabel(slide.index)}
46
+ aria-current={context.isActive(slide.index) ? "true" : undefined}
47
+ data-state={context.isActive(slide.index) ? "active" : "inactive"}
48
+ onclick={() => context.goToSlide(slide.index)}
49
+ >
50
+ <slot item={{ index: slide.index, active: context.isActive(slide.index) }}>
51
+ <span aria-hidden="true" />
52
+ </slot>
53
+ </button>
54
+ }
55
+ </div>
56
+ }
57
+
58
+ @style {
59
+ /* Headless: layout only, so the indicators sit in a row. All appearance
60
+ is up to the consuming theme */
61
+ .torp-carousel-indicators {
62
+ display: flex;
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,43 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import ChevronRight from "../icons/ChevronRight.torp";
3
+ import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
4
+
5
+ interface CarouselNextProps {
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 Carousel that a user can press to move to the next slide.
20
+ */
21
+ export default function CarouselNext($props: CarouselNextProps | undefined) {
22
+ // Get stuff out of the Carousel context
23
+ const context = $context[CarouselContextName] as CarouselContext;
24
+ if (!context) {
25
+ throw new Error("CarouselNext must be contained within a Carousel");
26
+ }
27
+
28
+ @render {
29
+ <button
30
+ {$props?.id}
31
+ class={["torp-carousel-next", $props?.class]}
32
+ {$props?.style}
33
+ type="button"
34
+ aria-label={$props?.ariaLabel ?? "Next slide"}
35
+ disabled={$props?.disabled || !context.canNext()}
36
+ onclick={() => context.nextSlide()}
37
+ >
38
+ <slot>
39
+ <ChevronRight />
40
+ </slot>
41
+ </button>
42
+ }
43
+ }
@@ -0,0 +1,44 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import ChevronLeft from "../icons/ChevronLeft.torp";
3
+ import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
4
+
5
+ interface CarouselPreviousProps {
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 Carousel that a user can press to move to the previous
20
+ * slide.
21
+ */
22
+ export default function CarouselPrevious($props: CarouselPreviousProps | undefined) {
23
+ // Get stuff out of the Carousel context
24
+ const context = $context[CarouselContextName] as CarouselContext;
25
+ if (!context) {
26
+ throw new Error("CarouselPrevious must be contained within a Carousel");
27
+ }
28
+
29
+ @render {
30
+ <button
31
+ {$props?.id}
32
+ class={["torp-carousel-previous", $props?.class]}
33
+ {$props?.style}
34
+ type="button"
35
+ aria-label={$props?.ariaLabel ?? "Previous slide"}
36
+ disabled={$props?.disabled || !context.canPrevious()}
37
+ onclick={() => context.previousSlide()}
38
+ >
39
+ <slot>
40
+ <ChevronLeft />
41
+ </slot>
42
+ </button>
43
+ }
44
+ }
@@ -0,0 +1,57 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
3
+
4
+ interface CarouselSlideProps {
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 label for the slide; defaults to "n of m" */
12
+ ariaLabel?: string;
13
+ }
14
+
15
+ /**
16
+ * A slide in a Carousel, only one of which is visible at a time.
17
+ */
18
+ export default function CarouselSlide($props: CarouselSlideProps | undefined) {
19
+ // Get stuff out of the Carousel context
20
+ const context = $context[CarouselContextName] as CarouselContext;
21
+ if (!context) {
22
+ throw new Error("CarouselSlide must be contained within a Carousel");
23
+ }
24
+
25
+ // Register this slide with the parent Carousel
26
+ let $state = context.registerSlide();
27
+
28
+ $run(() => {
29
+ return () => {
30
+ context.removeSlide($state.index);
31
+ };
32
+ });
33
+
34
+ @render {
35
+ <div
36
+ {$props?.id}
37
+ class={["torp-carousel-slide", $props?.class]}
38
+ {$props?.style}
39
+ role="group"
40
+ aria-roledescription="slide"
41
+ aria-label={$props?.ariaLabel ?? `${$state.index + 1} of ${context.count()}`}
42
+ data-state={context.isActive($state.index) ? "active" : "inactive"}
43
+ >
44
+ @if (context.isActive($state.index)) {
45
+ <slot />
46
+ }
47
+ </div>
48
+ }
49
+
50
+ @style {
51
+ /* Headless: inactive slides are hidden from display and the accessibility
52
+ tree. All other appearance is up to the consuming theme */
53
+ .torp-carousel-slide[data-state="inactive"] {
54
+ display: none;
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,28 @@
1
+ export const CarouselContextName: unique symbol = Symbol.for("torp.Carousel");
2
+
3
+ export interface SlideState {
4
+ /** The index of the slide */
5
+ index: number;
6
+ }
7
+
8
+ export interface CarouselContext {
9
+ /** Called from a slide when it is added */
10
+ registerSlide: () => SlideState;
11
+ /** Called from a slide when it is removed */
12
+ removeSlide: (index: number) => void;
13
+ /** Moves to the slide at the given index */
14
+ goToSlide: (index: number) => void;
15
+ /** Moves to the next slide */
16
+ nextSlide: () => void;
17
+ /** Moves to the previous slide */
18
+ previousSlide: () => void;
19
+ /** Whether the slide at the given index is the active one */
20
+ isActive: (index: number) => boolean;
21
+ /** Whether the next / previous controls can move from the current slide */
22
+ canNext: () => boolean;
23
+ canPrevious: () => boolean;
24
+ /** The reactive list of registered slides */
25
+ slides: () => SlideState[];
26
+ /** The number of registered slides */
27
+ count: () => number;
28
+ }
@@ -0,0 +1,147 @@
1
+ import { type SlotRender } from "@torpor/view";
2
+
3
+
4
+ interface CarouselProps {
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 index of the active slide */
12
+ value?: Bindable<number>;
13
+ /** Whether the next and previous controls wrap around at the ends (default true) */
14
+ wrap?: boolean;
15
+ /** An accessible label for the carousel region */
16
+ ariaLabel?: string;
17
+ /** Raised when the active slide has changed */
18
+ onchange?: (index: number) => void;
19
+ }
20
+
21
+ /**
22
+ * A carousel that displays a sequence of slides, which the user can move
23
+ * between with previous and next controls, slide indicators, or the keyboard.
24
+ *
25
+ * See [the WAI ARIA guidelines for Carousels](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/).
26
+ *
27
+ * The structure of a Carousel is:
28
+ *
29
+ * ```
30
+ * <Carousel ariaLabel="Featured">
31
+ * <CarouselPrevious />
32
+ * <CarouselSlide>...</CarouselSlide>
33
+ * <CarouselSlide>...</CarouselSlide>
34
+ * <CarouselNext />
35
+ * <CarouselIndicators />
36
+ * </Carousel>
37
+ * ```
38
+ */
39
+ declare function Carousel(
40
+ $parent: ParentNode,
41
+ $anchor: Node | null,
42
+ $props: CarouselProps | undefined,
43
+ $context?: Record<PropertyKey, any>,
44
+ $slots?: Record<string, SlotRender>,
45
+ ): void;
46
+
47
+
48
+
49
+ interface CarouselIndicatorsProps {
50
+ /** An ID for the root element */
51
+ id?: string;
52
+ /** Classes for the root element */
53
+ class?: ClassValue;
54
+ /** Styles for the root element */
55
+ style?: StyleValue;
56
+ }
57
+
58
+ /**
59
+ * A series of buttons in a Carousel, one per slide, that a user can press to
60
+ * move directly to that slide.
61
+ */
62
+ declare function CarouselIndicators(
63
+ $parent: ParentNode,
64
+ $anchor: Node | null,
65
+ $props: CarouselIndicatorsProps | undefined,
66
+ $context?: Record<PropertyKey, any>,
67
+ $slots?: Record<string, SlotRender>,
68
+ ): void;
69
+
70
+
71
+
72
+ interface CarouselNextProps {
73
+ /** An ID for the root element */
74
+ id?: string;
75
+ /** Classes for the root element */
76
+ class?: ClassValue;
77
+ /** Styles for the root element */
78
+ style?: StyleValue;
79
+ /** An ARIA label for the button, for screen readers when the button contains no text */
80
+ ariaLabel?: string;
81
+ /** If set to true, the user cannot interact with this button */
82
+ disabled?: boolean;
83
+ }
84
+
85
+ /**
86
+ * The button in a Carousel that a user can press to move to the next slide.
87
+ */
88
+ declare function CarouselNext(
89
+ $parent: ParentNode,
90
+ $anchor: Node | null,
91
+ $props: CarouselNextProps | undefined,
92
+ $context?: Record<PropertyKey, any>,
93
+ $slots?: Record<string, SlotRender>,
94
+ ): void;
95
+
96
+
97
+
98
+ interface CarouselPreviousProps {
99
+ /** An ID for the root element */
100
+ id?: string;
101
+ /** Classes for the root element */
102
+ class?: ClassValue;
103
+ /** Styles for the root element */
104
+ style?: StyleValue;
105
+ /** An ARIA label for the button, for screen readers when the button contains no text */
106
+ ariaLabel?: string;
107
+ /** If set to true, the user cannot interact with this button */
108
+ disabled?: boolean;
109
+ }
110
+
111
+ /**
112
+ * The button in a Carousel that a user can press to move to the previous
113
+ * slide.
114
+ */
115
+ declare function CarouselPrevious(
116
+ $parent: ParentNode,
117
+ $anchor: Node | null,
118
+ $props: CarouselPreviousProps | undefined,
119
+ $context?: Record<PropertyKey, any>,
120
+ $slots?: Record<string, SlotRender>,
121
+ ): void;
122
+
123
+
124
+
125
+ interface CarouselSlideProps {
126
+ /** An ID for the root element */
127
+ id?: string;
128
+ /** Classes for the root element */
129
+ class?: ClassValue;
130
+ /** Styles for the root element */
131
+ style?: StyleValue;
132
+ /** An accessible label for the slide; defaults to "n of m" */
133
+ ariaLabel?: string;
134
+ }
135
+
136
+ /**
137
+ * A slide in a Carousel, only one of which is visible at a time.
138
+ */
139
+ declare function CarouselSlide(
140
+ $parent: ParentNode,
141
+ $anchor: Node | null,
142
+ $props: CarouselSlideProps | undefined,
143
+ $context?: Record<PropertyKey, any>,
144
+ $slots?: Record<string, SlotRender>,
145
+ ): void;
146
+
147
+ export { Carousel, CarouselIndicators, CarouselNext, CarouselPrevious, CarouselSlide };
@@ -0,0 +1,6 @@
1
+ import Carousel from "./Carousel.torp";
2
+ import CarouselIndicators from "./CarouselIndicators.torp";
3
+ import CarouselNext from "./CarouselNext.torp";
4
+ import CarouselPrevious from "./CarouselPrevious.torp";
5
+ import CarouselSlide from "./CarouselSlide.torp";
6
+ export { Carousel, CarouselIndicators, CarouselNext, CarouselPrevious, CarouselSlide };