@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
@@ -1,23 +1,19 @@
1
1
  import type { ClassValue, StyleValue } from "@torpor/view";
2
- import {
3
- ToolBarContextName,
4
- type ToolBarContext,
5
- type ItemState,
6
- ToolBarPopoutContextName,
7
- type ToolBarPopoutContext
8
- } from "./ToolBarTypes";
2
+ import { type PopoutContext, PopoutContextName } from "../utils/PopoutTypes";
3
+ import { createFocusGroup } from "../utils/focusGroup";
4
+ import { type ItemState, type ToolBarContext, ToolBarContextName } from "./ToolBarTypes";
9
5
 
10
6
  interface ToolBarProps {
11
7
  /** An ID for the root element */
12
8
  id?: string;
13
9
  /** Classes for the root element */
14
- class?: ClassValue,
10
+ class?: ClassValue;
15
11
  /** Styles for the root element */
16
- style?: StyleValue,
12
+ style?: StyleValue;
17
13
  /** An ARIA label for describing the menu to screen readers */
18
- ariaLabel?: string | undefined,
14
+ ariaLabel?: string | undefined;
19
15
  /** The orientation of the menu, which affects keyboard navigation */
20
- orientation?: "horizontal" | "vertical",
16
+ orientation?: "horizontal" | "vertical";
21
17
  }
22
18
 
23
19
  /**
@@ -39,19 +35,18 @@ interface ToolBarProps {
39
35
  export default function ToolBar($props: ToolBarProps | undefined) {
40
36
  let orientation = $props?.orientation ?? "horizontal";
41
37
 
42
- // A collection containing the state and some functions for each item
43
- let itemStates: ItemState[] = [];
44
- let focusIndex = -1;
38
+ // The focus group owns the item ledger and roving-tabindex bookkeeping
39
+ const group = createFocusGroup<ItemState>();
45
40
 
46
41
  // Check whether this is a menu in a popout
47
- const popoutContext = $context[ToolBarPopoutContextName] as ToolBarPopoutContext;
42
+ const popoutContext = $context[PopoutContextName] as PopoutContext;
48
43
  const inPopout = !!popoutContext;
49
44
  let popoutState = popoutContext?.state;
50
45
 
51
46
  // Set the focusFirstElement method in the PopoverContext(s) so that it can be called after everything has been shown
52
47
  if (popoutContext) {
53
- popoutContext.focusFirstElement = focusFirstElement;
54
- popoutContext.focusLastElement = focusLastElement;
48
+ popoutContext.focusFirstElement = group.focusFirstItem;
49
+ popoutContext.focusLastElement = group.focusLastItem;
55
50
  }
56
51
 
57
52
  // Set the context to pass down to items
@@ -59,126 +54,50 @@ export default function ToolBar($props: ToolBarProps | undefined) {
59
54
  handleItemFocus,
60
55
  handleItemKey,
61
56
  registerItem,
62
- orientation
57
+ handlePopout,
58
+ orientation,
63
59
  };
64
60
  $context[ToolBarContextName] = context;
65
61
 
66
- // If the ToolBar is not in a popout, focus its first item. Otherwise the popout will call focusFirstElement, below
62
+ // If the ToolBar is not in a popout, focus its first item. Otherwise the popout will call focusFirstItem, below
67
63
  function handleFocus() {
68
- if (!popoutContext && itemStates.length) {
69
- itemStates[0].setFocused();
64
+ if (!popoutContext && group.itemStates.length) {
65
+ group.focusFirstItem();
70
66
  }
71
67
  }
72
68
 
73
- function focusFirstElement() {
74
- if (itemStates.length) {
75
- itemStates[0].setFocused();
76
- }
77
- }
78
-
79
- function focusLastElement() {
80
- if (itemStates.length > 0) {
81
- itemStates.at(-1)!.setFocused();
82
- }
83
- }
84
-
85
- function registerItem(setFocused: () => void) {
86
- // Add the item's state to the array and return its index
87
- const newItemState: ItemState = {
88
- setFocused
89
- };
90
- itemStates.push(newItemState);
91
- itemStates = itemStates;
92
- return { index: itemStates.length - 1 };
69
+ function registerItem(item: ItemState) {
70
+ return group.registerItem(item);
93
71
  }
94
72
 
95
73
  function handleItemFocus(index: number) {
96
- focusIndex = index;
74
+ group.handleItemFocus(index);
97
75
  }
98
76
 
99
77
  function handleItemKey(e: KeyboardEvent) {
78
+ const index = group.getFocusIndex();
100
79
  switch (e.key) {
101
- case "Esc":
102
80
  case "Escape": {
103
81
  if (inPopout) {
104
82
  e.preventDefault();
105
- //setPopoutVisible(false);
106
83
  popoutState.visible = false;
107
84
  }
108
85
  break;
109
86
  }
110
- case "Right":
111
- case "ArrowRight": {
112
- if (orientation === "horizontal") {
113
- e.preventDefault();
114
- focusItem("next");
115
- }
116
- break;
117
- }
118
- case "Left":
119
- case "ArrowLeft": {
120
- if (orientation === "horizontal") {
121
- e.preventDefault();
122
- focusItem("previous");
123
- }
124
- break;
125
- }
126
- case "Down":
127
- case "ArrowDown": {
128
- if (orientation === "vertical") {
129
- e.preventDefault();
130
- focusItem("next");
131
- }
132
- break;
133
- }
134
- case "Up":
135
- case "ArrowUp": {
136
- if (orientation === "vertical") {
137
- e.preventDefault();
138
- focusItem("previous");
139
- } else {
140
- // TODO: This should be based on what side the menu shows on
141
- // And on the orientation
142
- if (inPopout) {
143
- e.preventDefault();
144
- popoutState.visible = false;
145
- }
146
- }
147
- break;
148
- }
149
- case "Home": {
150
- e.preventDefault();
151
- focusItem("start");
152
- break;
153
- }
154
- case "End": {
155
- e.preventDefault();
156
- focusItem("end");
87
+ default: {
88
+ group.handleGroupKey(index, e, { vertical: orientation === "vertical" });
157
89
  break;
158
90
  }
159
91
  }
160
92
  }
161
93
 
162
- function focusItem(target: "start" | "previous" | "next" | "end") {
163
- switch (target) {
164
- case "start": {
165
- focusIndex = 0;
166
- break;
167
- }
168
- case "previous": {
169
- focusIndex = Math.max(0, focusIndex - 1);
170
- break;
171
- }
172
- case "next": {
173
- focusIndex = Math.min(itemStates.length - 1, focusIndex + 1);
174
- break;
175
- }
176
- case "end": {
177
- focusIndex = itemStates.length - 1;
178
- break;
94
+ function handlePopout(index: number) {
95
+ // Hide all other popouts
96
+ for (let item of group.itemStates) {
97
+ if (item.index !== index) {
98
+ item.setVisible?.(false);
179
99
  }
180
100
  }
181
- itemStates[focusIndex]?.setFocused();
182
101
  }
183
102
 
184
103
  @render {
@@ -189,7 +108,7 @@ export default function ToolBar($props: ToolBarProps | undefined) {
189
108
  tabindex="0"
190
109
  role="toolbar"
191
110
  aria-label={$props?.ariaLabel}
192
- aria-orientation={orientation}
111
+ aria-orientation={orientation === "vertical" ? "vertical" : undefined}
193
112
  onfocus={handleFocus}
194
113
  >
195
114
  <slot />
@@ -1,19 +1,19 @@
1
1
  import type { ClassValue, StyleValue } from "@torpor/view";
2
- import { ToolBarContextName, type ToolBarContext } from "./ToolBarTypes";
2
+ import { type ToolBarContext, ToolBarContextName } from "./ToolBarTypes";
3
3
 
4
4
  interface ToolBarButtonProps {
5
5
  /** An ID for the root element */
6
6
  id?: string;
7
7
  /** Classes for the root element */
8
- class?: ClassValue,
8
+ class?: ClassValue;
9
9
  /** Styles for the root element */
10
- style?: StyleValue,
10
+ style?: StyleValue;
11
11
  /** Whether this button is disabled */
12
- disabled?: boolean,
12
+ disabled?: boolean;
13
13
  /** Raised when the button is clicked */
14
- onclick?: (e: MouseEvent) => void,
14
+ onclick?: (e: MouseEvent) => void;
15
15
  /** Raised when a key is pressed down */
16
- onkeydown?: (e: KeyboardEvent) => void,
16
+ onkeydown?: (e: KeyboardEvent) => void;
17
17
  }
18
18
 
19
19
  /**
@@ -31,7 +31,7 @@ export default function ToolBarButton($props: ToolBarButtonProps | undefined) {
31
31
  const { registerItem, handleItemKey, handleItemFocus } = menuContext;
32
32
 
33
33
  // Register this item with the parent ToolBar and store the index
34
- const { index } = registerItem(setFocused);
34
+ const { index } = registerItem({ setFocused, disabled: $props?.disabled });
35
35
 
36
36
  function setFocused() {
37
37
  button.focus();
@@ -45,7 +45,6 @@ export default function ToolBarButton($props: ToolBarButtonProps | undefined) {
45
45
  type="button"
46
46
  {$props?.disabled}
47
47
  aria-disabled={$props?.disabled ? "true" : undefined}
48
- data-disabled={$props?.disabled ? "true" : undefined}
49
48
  {$props?.onclick}
50
49
  onkeydown={handleItemKey}
51
50
  onfocus={() => handleItemFocus(index)}
@@ -1,17 +1,17 @@
1
1
  import type { ClassValue, StyleValue } from "@torpor/view";
2
- import { ToolBarContextName, type ToolBarContext } from "./ToolBarTypes";
2
+ import { type ToolBarContext, ToolBarContextName } from "./ToolBarTypes";
3
3
 
4
4
  interface ToolBarElementProps {
5
5
  /** An ID for the root element */
6
6
  id?: string;
7
7
  /** Classes for the root element */
8
- class?: ClassValue,
8
+ class?: ClassValue;
9
9
  /** Styles for the root element */
10
- style?: StyleValue,
10
+ style?: StyleValue;
11
11
  /** Whether this button is disabled */
12
- disabled?: boolean,
12
+ disabled?: boolean;
13
13
  /** An element that can be focused via keyboard navigation */
14
- element?: HTMLElement,
14
+ element?: HTMLElement;
15
15
  }
16
16
 
17
17
  /**
@@ -27,7 +27,7 @@ export default function ToolBarElement($props: ToolBarElementProps | undefined)
27
27
  const { registerItem, handleItemKey, handleItemFocus } = menuContext;
28
28
 
29
29
  // Register this item with the parent ToolBar and store the index
30
- const { index } = registerItem(setFocused);
30
+ const { index } = registerItem({ setFocused, disabled: $props?.disabled });
31
31
 
32
32
  function setFocused() {
33
33
  if ($props?.element) {
@@ -40,13 +40,9 @@ export default function ToolBarElement($props: ToolBarElementProps | undefined)
40
40
  {$props?.id}
41
41
  class={["torp-tool-bar-div", $props?.class]}
42
42
  {$props?.style}
43
- type="div"
44
- role="menuitem"
43
+ tabindex="0"
45
44
  aria-disabled={$props?.disabled ? "true" : undefined}
46
- data-disabled={$props?.disabled ? "true" : undefined}
47
- onkeydown
48
45
  onkeydown={handleItemKey}
49
- onclick
50
46
  onfocus={() => handleItemFocus(index)}
51
47
  >
52
48
  <slot />
@@ -1,26 +1,23 @@
1
- import type { ClassValue, StyleValue } from "@torpor/view";
2
- import { ToolBarPopoutContextName, type ToolBarPopoutContext } from "./ToolBarTypes";
3
- import { PopoutContextName, type PopoutContext } from "../utils/PopoutTypes";
1
+ import type { Bindable, ClassValue, StyleValue } from "@torpor/view";
2
+ import SubmenuPopout from "../utils/SubmenuPopout.torp";
4
3
 
5
4
  interface ToolBarPopoutProps {
6
5
  /** An ID for the root element */
7
6
  id?: string;
8
7
  /** Classes for the root element */
9
- class?: ClassValue,
8
+ class?: ClassValue;
10
9
  /** Styles for the root element */
11
- style?: StyleValue,
10
+ style?: StyleValue;
12
11
  /** Whether the popout is visible */
13
- visible?: boolean,
14
- /** Raised when the popout is opened or closed */
15
- ontoggle?: (open: boolean) => void,
12
+ visible: Bindable<boolean | undefined>;
16
13
  /** Raised when the popout has opened */
17
- onopen?: () => void,
14
+ onopen?: () => void;
18
15
  /** Raised when the popout has closed */
19
- onclose?: (result: any) => void,
16
+ onclose?: (result: any) => void;
20
17
  }
21
18
 
22
19
  /**
23
- * A popout that is attached to a menu button and can be used to show a submenu.
20
+ * A popout that is attached to a toolbar button and can be used to show a submenu.
24
21
  *
25
22
  * The structure of a ToolBarPopout is:
26
23
  *
@@ -32,66 +29,17 @@ interface ToolBarPopoutProps {
32
29
  * ```
33
30
  */
34
31
  export default function ToolBarPopout($props: ToolBarPopoutProps | undefined) {
35
- let $state = $watch({
36
- visible: false
37
- });
38
-
39
- // Sync props and state
40
- $run(() => {
41
- $state.visible = $props?.visible ?? false;
42
- });
43
- $run(() => {
44
- if ($props !== undefined) {
45
- $props.visible = $state.visible;
46
- }
47
- });
48
-
49
- let result: any;
50
-
51
- // Set the context to pass down to items
52
- let context: ToolBarPopoutContext = {
53
- state: $state,
54
- };
55
- $context[ToolBarPopoutContextName] = context;
56
-
57
- // Set the context to pass down to items
58
- let popoutContext: PopoutContext = {
59
- handleButton: () => {},
60
- state: $state,
61
- };
62
- $context[PopoutContextName] = popoutContext;
63
-
64
- // Dispatch the toggle event when the popout is opened or closed
65
- let firstToggle = true;
66
- $run(() => {
67
- const ontoggle = $props?.ontoggle;
68
- const onopen = $props?.onopen;
69
- const onclose = $props?.onclose;
70
- const visible = $state.visible;
71
- if (firstToggle) {
72
- firstToggle = false;
73
- } else {
74
- if (ontoggle) ontoggle(visible);
75
- if (visible) {
76
- if (onopen) onopen()
77
- } else {
78
- if (onclose) onclose(result);
79
- }
80
- }
81
- });
82
-
83
- function handleMouseLeave() {
84
- $state.visible = false;
85
- }
86
-
87
32
  @render {
88
- <div
89
- {$props?.id}
33
+ <SubmenuPopout
34
+ id={$props?.id}
90
35
  class={["torp-tool-bar-popout", $props?.class]}
91
- {$props?.style}
92
- onmouseleave={handleMouseLeave}
36
+ style={$props?.style}
37
+ visible={$props?.visible}
38
+ onopen={$props?.onopen}
39
+ onclose={$props?.onclose}
40
+ contentRole="menu"
93
41
  >
94
42
  <slot />
95
- </div>
43
+ </SubmenuPopout>
96
44
  }
97
45
  }
@@ -1,19 +1,17 @@
1
1
  import type { ClassValue, StyleValue } from "@torpor/view";
2
- import getScrollParent from "../utils/getScrollParent";
3
- import setPopoverPosition from "../utils/setPopoverPosition";
4
- import { ToolBarPopoutContextName, type ToolBarPopoutContext } from "./ToolBarTypes";
2
+ import SubmenuPopoutContent from "../utils/SubmenuPopoutContent.torp";
5
3
 
6
4
  interface ToolBarPopoutContentProps {
7
5
  /** An ID for the root element */
8
6
  id?: string;
9
7
  /** Classes for the root element */
10
- class?: ClassValue,
8
+ class?: ClassValue;
11
9
  /** Styles for the root element */
12
- style?: StyleValue,
10
+ style?: StyleValue;
13
11
  /** Where the popout will be shown, relative to the popout button */
14
- side?: "top" | "right" | "bottom" | "left",
12
+ side?: "top" | "right" | "bottom" | "left";
15
13
  /** How the popout will be aligned, relative to the popout button */
16
- alignment?: "start" | "center" | "end",
14
+ alignment?: "start" | "center" | "end";
17
15
  }
18
16
 
19
17
  /**
@@ -21,72 +19,16 @@ interface ToolBarPopoutContentProps {
21
19
  *
22
20
  */
23
21
  export default function ToolBarPopoutContent($props: ToolBarPopoutContentProps | undefined) {
24
- let div: HTMLDivElement;
25
- let shown = false;
26
-
27
- // Get stuff out of the ToolBarPopoutContext
28
- const context = $context[ToolBarPopoutContextName] as ToolBarPopoutContext;
29
- if (!context) {
30
- throw new Error("ToolBarPopoutContent must be contained within a ToolBarPopout");
31
- }
32
- let $state = context.state;
33
-
34
- $run(() => {
35
- if (!$state.visible) {
36
- hide();
37
- }
38
- });
39
-
40
- function show() {
41
- shown = true;
42
-
43
- // Set the position and listen for window resize and scroll to reset the position
44
- setPosition();
45
- const anchorElement = context.anchorElement!
46
- const scrollParent = getScrollParent(anchorElement)
47
- scrollParent.addEventListener("resize", setPosition);
48
- scrollParent.addEventListener("scroll", setPosition);
49
- if (context.focusFirstElement) {
50
- context.focusFirstElement();
51
- }
52
- }
53
-
54
- function hide() {
55
- if (!shown) return;
56
-
57
- // Stop listening for window resize and focus the anchor element per WAI guidelines
58
- const anchorElement = context.anchorElement!
59
- const scrollParent = getScrollParent(anchorElement)
60
- scrollParent.removeEventListener("resize", setPosition);
61
- scrollParent.removeEventListener("scroll", setPosition);
62
- if (anchorElement.focus) {
63
- anchorElement.focus();
64
- }
65
- }
66
-
67
- function setPosition() {
68
- if (!context.anchorElement) {
69
- throw new Error("ToolBarPopoutContent must have an anchor element");
70
- }
71
-
72
- if (div) {
73
- let side = $props?.side ?? "bottom";
74
- let alignment = $props?.alignment ?? "start";
75
- setPopoverPosition(context.anchorElement, div, side, alignment);
76
- }
77
- }
78
-
79
22
  @render {
80
- @if ($state.visible) {
81
- <div
82
- {$props?.id}
83
- class={["torp-tool-bar-popout-content", $props?.class]}
84
- {$props?.style}
85
- &ref={div}
86
- onmount={show}
87
- >
88
- <slot />
89
- </div>
90
- }
23
+ <SubmenuPopoutContent
24
+ id={$props?.id}
25
+ class={["torp-tool-bar-popout-content", $props?.class]}
26
+ style={$props?.style}
27
+ side={$props?.side}
28
+ alignment={$props?.alignment}
29
+ role="menu"
30
+ >
31
+ <slot />
32
+ </SubmenuPopoutContent>
91
33
  }
92
34
  }
@@ -1,22 +1,18 @@
1
1
  import type { ClassValue, StyleValue } from "@torpor/view";
2
- import {
3
- ToolBarContextName,
4
- ToolBarPopoutContextName,
5
- type ToolBarContext,
6
- type ToolBarPopoutContext,
7
- } from "./ToolBarTypes";
2
+ import SubmenuPopoutTrigger from "../utils/SubmenuPopoutTrigger.torp";
3
+ import { type ToolBarContext, ToolBarContextName } from "./ToolBarTypes";
8
4
 
9
5
  interface ToolBarPopoutTriggerProps {
10
6
  /** An ID for the root element */
11
7
  id?: string;
12
8
  /** Classes for the root element */
13
- class?: ClassValue,
9
+ class?: ClassValue;
14
10
  /** Styles for the root element */
15
- style?: StyleValue,
11
+ style?: StyleValue;
16
12
  /** The delay before showing the popout, in milliseconds */
17
- hoverDelay?: number,
13
+ hoverDelay?: number;
18
14
  /** Whether this button is disabled */
19
- disabled?: boolean,
15
+ disabled?: boolean;
20
16
  }
21
17
 
22
18
  /**
@@ -24,115 +20,28 @@ interface ToolBarPopoutTriggerProps {
24
20
  *
25
21
  */
26
22
  export default function ToolBarPopoutTrigger($props: ToolBarPopoutTriggerProps | undefined) {
27
- let defaultHoverDelay = 500;
28
-
29
- let button: HTMLButtonElement;
30
- let interval: NodeJS.Timeout | undefined;
31
-
32
23
  // Get stuff out of the ToolBarContext
33
24
  const toolBarContext = $context[ToolBarContextName] as ToolBarContext;
34
25
  if (!toolBarContext) {
35
26
  throw new Error("ToolBarPopoutTrigger must be contained within a ToolBar");
36
27
  }
37
- const { registerItem, handleItemKey, handleItemFocus } = toolBarContext;
38
-
39
- // Get stuff out of the ToolBarPopoutContext
40
- const popoutContext = $context[ToolBarPopoutContextName] as ToolBarPopoutContext;
41
- if (!popoutContext) {
42
- throw new Error("ToolBarPopoutTrigger must be contained within a ToolBarPopout");
43
- }
44
- let $state = popoutContext.state;
45
-
46
- // Register this item with the parent ToolBar and store the index
47
- const { index } = registerItem(setFocused);
48
-
49
- // TODO: $mount should be run AFTER the button has been set
50
- //$mount(() => {
51
- // // Set the anchor element to the button when it exists
52
- // popoutContext.anchorElement = button;
53
- //});
54
-
55
- function setFocused() {
56
- button.focus();
57
- }
58
-
59
- function handleClick() {
60
- $state.visible = true;
61
- }
62
-
63
- function handlePopoutKey(e: KeyboardEvent) {
64
- switch (e.key) {
65
- case "Right":
66
- case "ArrowRight":
67
- if (toolBarContext.orientation === "vertical") {
68
- // TODO: This should be based on what side the menu shows on
69
- e.preventDefault();
70
- $state.visible = true;
71
- }
72
- break;
73
- case "Down":
74
- case "ArrowDown":
75
- if (toolBarContext.orientation === "horizontal") {
76
- e.preventDefault();
77
- $state.visible = true;
78
- }
79
- break;
80
- default:
81
- handleItemKey(e);
82
- }
83
- }
84
-
85
- function handleMouseEnter() {
86
- if ($props?.disabled) return;
87
-
88
- // Handle the hover after a delay
89
- if (!interval) {
90
- interval = setTimeout(() => $state.visible = true, $props?.hoverDelay ?? defaultHoverDelay);
91
- }
92
- }
93
-
94
- function handleMouseLeave() {
95
- if ($props?.disabled) return;
96
-
97
- // Prevent short hovers or touches from firing the event
98
- if (interval) {
99
- clearTimeout(interval);
100
- interval = undefined;
101
- }
102
- }
103
-
104
- function handleMouseMove() {
105
- if ($props?.disabled) return;
106
-
107
- // Reset the interval on mouse move
108
- if (interval) {
109
- clearTimeout(interval);
110
- interval = setTimeout(() => $state.visible = true, $props?.hoverDelay ?? defaultHoverDelay);
111
- }
112
- }
28
+ const { registerItem, handleItemKey, handleItemFocus, handlePopout, orientation } =
29
+ toolBarContext;
113
30
 
114
31
  @render {
115
- <button
116
- {$props?.id}
32
+ <SubmenuPopoutTrigger
33
+ id={$props?.id}
117
34
  class={["torp-tool-bar-popout-trigger", $props?.class]}
118
- {$props?.style}
119
- type="button"
120
- {$props?.disabled}
121
- role="menuitem"
122
- aria-haspopup="true"
123
- aria-expanded={$state.visible.toString()}
124
- aria-disabled={$props?.disabled ? "true" : undefined}
125
- data-disabled={$props?.disabled ? "true" : undefined}
126
- onkeydown={handlePopoutKey}
127
- onclick={handleClick}
128
- onfocus={() => handleItemFocus(index)}
129
- onmouseenter={handleMouseEnter}
130
- onmouseleave={handleMouseLeave}
131
- onmousemove={handleMouseMove}
132
- &ref={button}
133
- onmount={(el) => popoutContext.anchorElement = el }
35
+ style={$props?.style}
36
+ hoverDelay={$props?.hoverDelay}
37
+ disabled={$props?.disabled}
38
+ openKey={orientation === "vertical" ? "ArrowRight" : "ArrowDown"}
39
+ registerItem={registerItem}
40
+ handleItemKey={handleItemKey}
41
+ handleItemFocus={handleItemFocus}
42
+ onActivate={handlePopout}
134
43
  >
135
44
  <slot />
136
- </button>
45
+ </SubmenuPopoutTrigger>
137
46
  }
138
47
  }