@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,47 @@
1
+ import { ListBox, ListBoxItem } from "../ListBox/index";
2
+
3
+ interface LoadedItemsProps {
4
+ /** The items to render */
5
+ items: any[];
6
+ /** The selected value(s), bound through to the internal ListBox */
7
+ value: any;
8
+ /** Whether multiple items can be selected */
9
+ multiple?: boolean;
10
+ /** Extracts the display text for an item (defaults to label ?? text ?? item) */
11
+ getItemLabel?: (item: any) => any;
12
+ /** Extracts the value for an item (defaults to value ?? id) */
13
+ getItemValue?: (item: any) => any;
14
+ }
15
+
16
+ function defaultLabel(item: any): string {
17
+ const label = item?.label ?? item?.text ?? item;
18
+ return typeof label === "string" ? label : String(label);
19
+ }
20
+
21
+ function defaultValue(item: any): any {
22
+ return item?.value ?? item?.id;
23
+ }
24
+
25
+ /**
26
+ * The internally rendered list of options for components that load their
27
+ * items from a network loader (ComboBox auto-complete etc). Used as the
28
+ * fallback content when a consumer doesn't slot their own ListBox.
29
+ */
30
+ export default function LoadedItems($props: LoadedItemsProps) {
31
+ const getLabel = $props.getItemLabel ?? defaultLabel;
32
+ const getValue = $props.getItemValue ?? defaultValue;
33
+
34
+ @render {
35
+ <ListBox type={$props.multiple ? "multiple" : "single"} value={$props.value}>
36
+ @for (let item of $props.items) {
37
+ @key = getValue(item)
38
+ <ListBoxItem value={getValue(item)}>
39
+ {getLabel(item)}
40
+ </ListBoxItem>
41
+ }
42
+ </ListBox>
43
+ @if ($props.items.length === 0) {
44
+ <span class="torp-loaded-items-empty">No results.</span>
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,99 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import getId from "./getId";
3
+ import { type PopoutContext } from "./PopoutTypes";
4
+
5
+ interface PopoutClickTriggerProps {
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 element to render: a button, or a div for right-click regions */
13
+ tag?: "button" | "div";
14
+ /** The event that activates the popout */
15
+ event?: "click" | "contextmenu";
16
+ /** The containing popout's context (the family-specific one, not PopoutContext) */
17
+ context: PopoutContext;
18
+ /**
19
+ * Called with the activating event before visibility is toggled, for
20
+ * triggers that track a position (right-click coordinates etc)
21
+ */
22
+ onactivate?: (node: HTMLElement, e: MouseEvent) => void;
23
+ }
24
+
25
+ /**
26
+ * The shared primitive behind PopoverTrigger, ContextualTrigger and
27
+ * ModalTrigger: it publishes the trigger id, renders the standard trigger
28
+ * attributes (aria-haspopup / aria-expanded / aria-controls), anchors the
29
+ * popout to itself and toggles visibility on the configured event.
30
+ *
31
+ * Hover activation deliberately lives in PopoverHover / ContextualHover,
32
+ * whose open/close semantics (intent delay, exit grace) differ enough from
33
+ * a press to warrant their own component.
34
+ */
35
+ export default function PopoutClickTrigger($props?: PopoutClickTriggerProps) {
36
+ let defaultId = getId();
37
+
38
+ const context = $props!.context;
39
+ const $state = context.state;
40
+
41
+ // Set the trigger ID so that it can be used with aria-labelledby
42
+ $state.triggerId = $props?.id ?? defaultId;
43
+
44
+ const tag = $props?.tag ?? "button";
45
+ const event = $props?.event ?? "click";
46
+
47
+ function handleEvent(node: HTMLElement, e: MouseEvent) {
48
+ if (event === "contextmenu") {
49
+ e.preventDefault();
50
+ }
51
+ $props?.onactivate?.(node, e);
52
+ $state.visible = !$state.visible;
53
+ }
54
+
55
+ function handleClick(e: MouseEvent) {
56
+ if (event !== "click") return;
57
+ handleEvent(e.currentTarget as HTMLElement, e);
58
+ }
59
+
60
+ function handleContextMenu(e: MouseEvent) {
61
+ if (event !== "contextmenu") return;
62
+ handleEvent(e.currentTarget as HTMLElement, e);
63
+ }
64
+
65
+ function handleMount(el: HTMLElement) {
66
+ context.anchorElement = el;
67
+ }
68
+
69
+ @render {
70
+ @if (tag === "button") {
71
+ <button
72
+ type="button"
73
+ id={$props?.id ?? defaultId}
74
+ class={["torp-popout-trigger", $props?.class]}
75
+ {$props?.style}
76
+ aria-haspopup={$state.contentRole ?? "true"}
77
+ aria-expanded={$state.visible ? "true" : "false"}
78
+ aria-controls={$state.contentId}
79
+ onclick={handleClick}
80
+ onmount={handleMount}
81
+ >
82
+ <slot />
83
+ </button>
84
+ } else {
85
+ <div
86
+ id={$props?.id ?? defaultId}
87
+ class={["torp-popout-trigger", $props?.class]}
88
+ {$props?.style}
89
+ aria-haspopup={$state.contentRole ?? "true"}
90
+ aria-expanded={$state.visible ? "true" : "false"}
91
+ aria-controls={$state.contentId}
92
+ oncontextmenu={handleContextMenu}
93
+ onmount={handleMount}
94
+ >
95
+ <slot />
96
+ </div>
97
+ }
98
+ }
99
+ }
@@ -0,0 +1,82 @@
1
+ export const PopoutContextName: unique symbol = Symbol.for("torp.Popout");
2
+
3
+ // TODO: Use this type in more places
4
+ export type HandleButtonPress = (type: "confirm" | "cancel" | undefined, value?: any) => void;
5
+
6
+ /**
7
+ * The shared focus API for popout-style contexts: content can focus its
8
+ * first/last item after being shown.
9
+ *
10
+ * HACK: Deferring the focus call is necessary because if we focus the first
11
+ * element e.g. in a Dialog's onMount, it will scroll the page to the focused
12
+ * element and mess up our careful positioning. We need to be able to manually
13
+ * set the order to
14
+ * 1. set visible (so we have an element with content)
15
+ * 2. set position (so the element is in the right place)
16
+ * 3. set focus (for accessibility)
17
+ * There may be a more elegant way to accomplish this!
18
+ */
19
+ export interface FocusApi {
20
+ focusFirstElement?: () => void;
21
+ focusLastElement?: () => void;
22
+ }
23
+
24
+ /** The shared context for popout components */
25
+ export interface PopoutContext extends FocusApi {
26
+ handleButton: HandleButtonPress;
27
+ // HACK: We need to be able to let children (i.e. Dialogs) override the click outside functionality
28
+ // There may be a more elegant way to accomplish this too
29
+ handleClickOutside?: (e: MouseEvent | KeyboardEvent) => void;
30
+ state: PopoutState;
31
+ //modal: boolean;
32
+ anchorElement?: HTMLElement;
33
+
34
+ /**
35
+ * Called from menu content when an arrow key should move to an adjacent item
36
+ * in a containing MenuBar, opening its menu. Only set by MenuBarItem.
37
+ */
38
+ navigateMenuBar?: (target: "previous" | "next") => void;
39
+
40
+ markElement?: (id: string) => void;
41
+ selectMarkedElement?: () => void;
42
+ searchText?: string;
43
+ searchItems?: (searchText: string) => { id: string; setFocused: () => void } | undefined;
44
+ }
45
+
46
+ export interface PopoutState {
47
+ visible: boolean;
48
+ contentId?: string;
49
+ triggerId?: string;
50
+ /**
51
+ * The role of this popout's content ("menu", "listbox", "tree", "grid" or
52
+ * "dialog"), set by the content component so that triggers can use it for
53
+ * their aria-haspopup attribute.
54
+ */
55
+ contentRole?: string;
56
+ /** Whether the popout is modal (e.g. it has an overlay) */
57
+ modal?: boolean;
58
+ /** The ID of the active descendant element, for aria-activedescendant */
59
+ activeDescendant?: string;
60
+ }
61
+
62
+ /**
63
+ * The state that a submenu trigger registers with its containing group
64
+ * (Menu, MenuBar, ToolBar or NavMenu). Passed to `registerItem`; the group
65
+ * assigns `index`, and the trigger assigns `text` from its label on mount.
66
+ */
67
+ export interface SubmenuItemState {
68
+ /** Assigned by the group on registration */
69
+ index?: number;
70
+ /** The item's label, set from its text content on mount; used for type-ahead */
71
+ text?: string;
72
+ setFocused: () => void;
73
+ /** Shows or hides the item's submenu */
74
+ setVisible?: (visible: boolean) => void;
75
+ /** Whether the item is disabled; disabled items are skipped by keyboard navigation */
76
+ disabled?: boolean;
77
+ }
78
+
79
+ export interface Point {
80
+ x: number;
81
+ y: number;
82
+ }
@@ -0,0 +1,89 @@
1
+ import type { Bindable, ClassValue, StyleValue } from "@torpor/view";
2
+ import $handle from "./$handle";
3
+ import { type PopoutContext, type PopoutState, PopoutContextName } from "./PopoutTypes";
4
+
5
+ interface SubmenuPopoutProps {
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
+ /** Whether the popout is visible */
13
+ visible: Bindable<boolean | undefined>;
14
+ /** Raised when the popout has opened */
15
+ onopen?: () => void;
16
+ /** Raised when the popout has closed */
17
+ onclose?: (result: any) => void;
18
+ /** The popout's state, supplied when the containing component needs access to it */
19
+ state?: PopoutState;
20
+ /** Extra values published through the popout context, e.g. handleButton */
21
+ context?: Partial<PopoutContext>;
22
+ /** Whether the popout closes when the pointer leaves it (default true) */
23
+ closeOnMouseLeave?: boolean;
24
+ /** The role of the popout's content, published so that triggers can use it for aria-haspopup */
25
+ contentRole?: string;
26
+ }
27
+
28
+ /**
29
+ * The shared primitive behind MenuPopout, MenuBarItem, ToolBarPopout and
30
+ * NavMenuPopout: it owns the popout's state, publishes the popout context for
31
+ * its trigger and content, and raises open/close events. The component
32
+ * wrappers supply their group's behaviour through props.
33
+ *
34
+ * The structure of a submenu popout is:
35
+ *
36
+ * ```
37
+ * <XPopout>
38
+ * <XPopoutTrigger /> (optional)
39
+ * <XPopoutContent />
40
+ * </XPopout>
41
+ * ```
42
+ */
43
+ export default function SubmenuPopout($props: SubmenuPopoutProps | undefined) {
44
+ let $state: PopoutState = $props?.state ?? $watch({
45
+ visible: false,
46
+ contentId: undefined,
47
+ triggerId: undefined,
48
+ contentRole: $props?.contentRole,
49
+ });
50
+
51
+ $bind($state, $props, "visible");
52
+
53
+ let result: any;
54
+
55
+ // Set the context to pass down to the trigger and content
56
+ let context: PopoutContext = {
57
+ handleButton: () => {},
58
+ ...$props?.context,
59
+ state: $state,
60
+ };
61
+ $context[PopoutContextName] = context;
62
+
63
+ $handle((first) => {
64
+ const visible = $state.visible;
65
+ if (first) return;
66
+ if (visible) {
67
+ $props?.onopen?.();
68
+ } else {
69
+ $props?.onclose?.(result);
70
+ }
71
+ });
72
+
73
+ function handleMouseLeave() {
74
+ if ($props?.closeOnMouseLeave !== false) {
75
+ $state.visible = false;
76
+ }
77
+ }
78
+
79
+ @render {
80
+ <div
81
+ {$props?.id}
82
+ class={$props?.class}
83
+ {$props?.style}
84
+ onmouseleave={handleMouseLeave}
85
+ >
86
+ <slot />
87
+ </div>
88
+ }
89
+ }
@@ -0,0 +1,87 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import getId from "./getId";
3
+ import { createPopoutContent } from "./popoutContent";
4
+ import { type PopoutContext, PopoutContextName } from "./PopoutTypes";
5
+
6
+ interface SubmenuPopoutContentProps {
7
+ /** An ID for the root element */
8
+ id?: string;
9
+ /** Classes for the root element */
10
+ class?: ClassValue;
11
+ /** Styles for the root element */
12
+ style?: StyleValue;
13
+ /** Where the popout will be shown, relative to the popout button */
14
+ side?: "top" | "right" | "bottom" | "left";
15
+ /** How the popout will be aligned, relative to the popout button */
16
+ alignment?: "start" | "center" | "end";
17
+ /** Whether pressing Escape closes the popout (default true) */
18
+ closeOnEscape?: boolean;
19
+ /** Only close on Escape when the focus is inside the content */
20
+ escapeOnlyWhenFocused?: boolean;
21
+ /** The ARIA role of the content element, e.g. "menu" */
22
+ role?: string;
23
+ /**
24
+ * The role of the popout's content, published so that triggers can use it
25
+ * for aria-haspopup
26
+ */
27
+ contentRole?: string;
28
+ }
29
+
30
+ /**
31
+ * The shared primitive behind MenuPopoutContent, MenuBarItemContent,
32
+ * ToolBarPopoutContent and NavMenuPopoutContent: it positions the content
33
+ * against the trigger, handles outside clicks, Escape and focus, and renders
34
+ * the content when the popout is visible.
35
+ */
36
+ export default function SubmenuPopoutContent($props: SubmenuPopoutContentProps | undefined) {
37
+ const defaultId = getId();
38
+
39
+ // Get stuff out of the PopoutContext
40
+ const popoutContext = $context[PopoutContextName] as PopoutContext;
41
+ if (!popoutContext) {
42
+ throw new Error("SubmenuPopoutContent must be contained within a SubmenuPopout");
43
+ }
44
+ let $state = popoutContext.state;
45
+
46
+ // Set the content ID so that triggers can use it with aria-controls
47
+ $state.contentId = $props?.id ?? defaultId;
48
+
49
+ // Set the content role so that triggers can use it with aria-haspopup
50
+ $state.contentRole = $props?.contentRole ?? $state.contentRole;
51
+
52
+ const popout = createPopoutContent({
53
+ getAnchor: () => popoutContext.anchorElement,
54
+ getContent: () => div,
55
+ close: () => ($state.visible = false),
56
+ side: $props?.side ?? "bottom",
57
+ alignment: $props?.alignment ?? "start",
58
+ closeOnEscape: $props?.closeOnEscape ?? true,
59
+ escapeOnlyWhenFocused: $props?.escapeOnlyWhenFocused,
60
+ focusFirstElement: () => popoutContext.focusFirstElement?.(),
61
+ refocusAnchorOnHide: true,
62
+ });
63
+
64
+ let div: HTMLDivElement;
65
+
66
+ $run(() => {
67
+ if (!$state.visible) {
68
+ popout.hide();
69
+ }
70
+ });
71
+
72
+ @render {
73
+ @if ($state.visible) {
74
+ <div
75
+ id={$props?.id ?? defaultId}
76
+ class={$props?.class}
77
+ {$props?.style}
78
+ role={$props?.role}
79
+ aria-labelledby={$props?.role ? $state.triggerId : undefined}
80
+ &ref={div}
81
+ onmount={(_el) => popout.show()}
82
+ >
83
+ <slot />
84
+ </div>
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,160 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import getId from "./getId";
3
+ import { createHoverOpen } from "./hoverOpen";
4
+ import {
5
+ type PopoutContext,
6
+ PopoutContextName,
7
+ type SubmenuItemState,
8
+ } from "./PopoutTypes";
9
+
10
+ interface SubmenuPopoutTriggerProps {
11
+ /** An ID for the root element */
12
+ id?: string;
13
+ /** Classes for the root element */
14
+ class?: ClassValue;
15
+ /** Styles for the root element */
16
+ style?: StyleValue;
17
+ /** The delay before showing the popout on hover, in milliseconds (default 500; 0 opens immediately) */
18
+ hoverDelay?: number;
19
+ /** Whether this button is disabled */
20
+ disabled?: boolean;
21
+ /** The ARIA role of the trigger */
22
+ role?: string;
23
+ /** The element's tabindex, if it should not take focus via tabbing */
24
+ tabindex?: string;
25
+ /** The key that opens the popout */
26
+ openKey?: string;
27
+ /** The containing group's registration function */
28
+ registerItem: (item: SubmenuItemState) => { index: number };
29
+ /** Called with the registration index, for wrappers that need it elsewhere */
30
+ onRegister?: (index: number) => void;
31
+ /** The containing group's key handler, called for keys other than openKey */
32
+ handleItemKey: (e: KeyboardEvent) => void;
33
+ /** The containing group's focus handler */
34
+ handleItemFocus: (index: number) => void;
35
+ /**
36
+ * Replaces how the popout is shown/hidden, which by default writes the
37
+ * popout's visible state; also registered with the group
38
+ */
39
+ setVisible?: (visible: boolean) => void;
40
+ /**
41
+ * Called with the registration index when the trigger is activated by
42
+ * clicking or with openKey, before the popout is shown
43
+ */
44
+ onActivate?: (index: number) => void;
45
+ /** Replaces the default toggle behaviour when the trigger is clicked */
46
+ onclick?: () => void;
47
+ }
48
+
49
+ /**
50
+ * The shared primitive behind MenuPopoutTrigger, MenuBarItemTrigger,
51
+ * ToolBarPopoutTrigger and NavMenuPopoutTrigger: it registers itself with the
52
+ * containing group, opens the popout on hover, on click or with the group's
53
+ * open key, and renders the standard trigger attributes.
54
+ */
55
+ export default function SubmenuPopoutTrigger($props: SubmenuPopoutTriggerProps | undefined) {
56
+ let defaultId = getId();
57
+
58
+ let button: HTMLButtonElement;
59
+
60
+ // Get stuff out of the PopoutContext
61
+ const popoutContext = $context[PopoutContextName] as PopoutContext;
62
+ if (!popoutContext) {
63
+ throw new Error("SubmenuPopoutTrigger must be contained within a SubmenuPopout");
64
+ }
65
+ const { state: $state } = popoutContext;
66
+
67
+ // Set the trigger ID so that it can be used with aria-labelledby
68
+ $state.triggerId = $props?.id ?? defaultId;
69
+
70
+ function setVisible(visible: boolean) {
71
+ if ($props?.setVisible) {
72
+ $props.setVisible(visible);
73
+ } else {
74
+ $state.visible = visible;
75
+ }
76
+ }
77
+
78
+ // Register this item with the containing group and store the index
79
+ const item: SubmenuItemState = { setFocused, setVisible, disabled: $props?.disabled };
80
+ const { index } = $props!.registerItem(item);
81
+ $props?.onRegister?.(index);
82
+
83
+ function setFocused() {
84
+ button.focus();
85
+ }
86
+
87
+ // Store the anchor element, and the item's label for type-ahead
88
+ function handleMount(el: HTMLButtonElement) {
89
+ popoutContext.anchorElement = el;
90
+ item.text = el.textContent.trim();
91
+ }
92
+
93
+ function activate() {
94
+ $props?.onActivate?.(index);
95
+ }
96
+
97
+ function handleClick() {
98
+ if ($props?.onclick) {
99
+ $props.onclick();
100
+ return;
101
+ }
102
+ activate();
103
+ setVisible(!$state.visible);
104
+ }
105
+
106
+ function handleKey(e: KeyboardEvent) {
107
+ if (e.key === $props?.openKey) {
108
+ // TODO: This should be based on what side the menu shows on
109
+ e.preventDefault();
110
+ activate();
111
+ setVisible(true);
112
+ } else {
113
+ $props!.handleItemKey(e);
114
+ }
115
+ }
116
+
117
+ const hoverDelay = $props?.hoverDelay ?? 500;
118
+ const hoverOpen = createHoverOpen(
119
+ () => setVisible(true),
120
+ () => $props?.disabled ?? false,
121
+ hoverDelay,
122
+ );
123
+
124
+ function handleMouseEnter() {
125
+ // Open immediately when there is no hover delay, as menubar items do
126
+ if (hoverDelay <= 0) {
127
+ if (!$props?.disabled) {
128
+ setVisible(true);
129
+ }
130
+ } else {
131
+ hoverOpen.handleMouseEnter();
132
+ }
133
+ }
134
+
135
+ @render {
136
+ <button
137
+ id={$props?.id ?? defaultId}
138
+ class={$props?.class}
139
+ {$props?.style}
140
+ type="button"
141
+ {$props?.disabled}
142
+ role={$props?.role}
143
+ tabindex={$props?.tabindex}
144
+ aria-haspopup={$state.contentRole ?? "true"}
145
+ aria-expanded={$state.visible ? "true" : "false"}
146
+ aria-controls={$state.contentId}
147
+ aria-disabled={$props?.disabled ? "true" : undefined}
148
+ onkeydown={handleKey}
149
+ onclick={handleClick}
150
+ onfocus={() => $props!.handleItemFocus(index)}
151
+ onmouseenter={handleMouseEnter}
152
+ onmouseleave={hoverOpen.handleMouseLeave}
153
+ onmousemove={hoverOpen.handleMouseMove}
154
+ &ref={button}
155
+ onmount={handleMount}
156
+ >
157
+ <slot />
158
+ </button>
159
+ }
160
+ }
@@ -2,16 +2,16 @@
2
2
  * Colors that can be used in charts, from http://colorbrewer2.org/
3
3
  */
4
4
  export const chartColors = [
5
- "#A6CEE3",
6
- "#B2DF8A",
7
- "#FB9A99",
8
- "#FDBF6F",
9
- "#CAB2D6",
10
- "#FFFF99",
11
- "#1F78B4",
12
- "#33A02C",
13
- "#E31A1C",
14
- "#FF7F00",
15
- "#6A3D9A",
16
- "#B15928"
17
- ];
5
+ "#A6CEE3",
6
+ "#B2DF8A",
7
+ "#FB9A99",
8
+ "#FDBF6F",
9
+ "#CAB2D6",
10
+ "#FFFF99",
11
+ "#1F78B4",
12
+ "#33A02C",
13
+ "#E31A1C",
14
+ "#FF7F00",
15
+ "#6A3D9A",
16
+ "#B15928",
17
+ ] as const;