@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,143 @@
1
+ import { $watch } from "@torpor/view";
2
+ import type DataSeries from "../Charts/DataSeries";
3
+ import {
4
+ calculateChartBottom,
5
+ calculateChartLeft,
6
+ calculateItemWidth,
7
+ calculateMaxValue,
8
+ calculateStepLabels,
9
+ calculateStepValue,
10
+ calculateValueHeight,
11
+ } from "./chartUtils";
12
+
13
+ export interface ChartLayoutOptions {
14
+ /** The named series to lay out */
15
+ series: () => DataSeries[];
16
+ /** Fixed height, if any (default 200 or the container's client height) */
17
+ height?: () => number | undefined;
18
+ /** Fixed width, if any (default 400 or the container's client width) */
19
+ width?: () => number | undefined;
20
+ /** Label under the x axis */
21
+ xLabel?: () => string | undefined;
22
+ /** Label beside the y axis */
23
+ yLabel?: () => string | undefined;
24
+ /** The value at the top of the chart, instead of the series' maximum */
25
+ maxValue?: () => number | undefined;
26
+ /** The number of steps between 0 and the maximum value (default 2) */
27
+ stepCount?: () => number | undefined;
28
+ /** The size of each step, instead of being calculated */
29
+ stepValue?: () => number | undefined;
30
+ /** The container element, used to measure responsive widths */
31
+ getContainer?: () => HTMLElement | undefined;
32
+ }
33
+
34
+ /**
35
+ * The shared layout scaffold behind the cartesian charts (Bar, Column,
36
+ * Line): measures the chart's text so labels can be sized, and calculates
37
+ * the plot geometry -- maximum value, step sizes, slot widths and the
38
+ * left/bottom margins -- reactively from the series and axis props.
39
+ *
40
+ * Charts render only their own marks; call `measure` from `$onmount` with the
41
+ * hidden `<text>` element they render for that purpose.
42
+ *
43
+ * ```
44
+ * let $layout = createChartLayout({
45
+ * series: () => $props.series,
46
+ * getContainer: () => container,
47
+ * });
48
+ * $onmount(() => setTimeout(() => measure($layout, measurer), 1));
49
+ * ```
50
+ */
51
+ export interface ChartLayout {
52
+ /** The width of the chart's text, measured from the measurer element */
53
+ textWidth: number;
54
+ /** The height of the chart's text (1.5x the measurer's box) */
55
+ textHeight: number;
56
+ /** The series names, rendered along the x axis */
57
+ readonly labels: string[];
58
+ readonly calculatedHeight: number;
59
+ readonly calculatedWidth: number;
60
+ /** The largest value across all series, unless overridden */
61
+ readonly maxValue: number;
62
+ /** The size of one y axis step */
63
+ readonly stepValue: number;
64
+ /** The labels for each step, 0 through max */
65
+ readonly stepLabels: number[];
66
+ /** The width of one category slot */
67
+ readonly itemWidth: number;
68
+ /** The pixel height of one unit of value */
69
+ readonly valueHeight: number;
70
+ /** The bottom edge of the plot area */
71
+ readonly chartBottom: number;
72
+ /** The left edge of the plot area */
73
+ readonly chartLeft: number;
74
+ setTextSize(width: number, height: number): void;
75
+ }
76
+
77
+ export function createChartLayout(options: ChartLayoutOptions): ChartLayout {
78
+ const defaultHeight = 200;
79
+ const defaultWidth = 400;
80
+ const getStepCount = () => options.stepCount?.() ?? 2;
81
+
82
+ return $watch({
83
+ textWidth: 0,
84
+ textHeight: 0,
85
+
86
+ get labels() {
87
+ return options.series().map((s) => s.name);
88
+ },
89
+ get calculatedHeight() {
90
+ return options.height?.() || defaultHeight;
91
+ },
92
+ get calculatedWidth() {
93
+ return options.width?.() || options.getContainer?.()?.clientWidth || defaultWidth;
94
+ },
95
+ get maxValue() {
96
+ return options.maxValue?.() || calculateMaxValue(options.series());
97
+ },
98
+ get stepValue() {
99
+ return options.stepValue?.() || calculateStepValue(this.maxValue, options.stepCount?.());
100
+ },
101
+ get stepLabels() {
102
+ return calculateStepLabels(getStepCount(), this.stepValue);
103
+ },
104
+ get itemWidth() {
105
+ return calculateItemWidth(this.calculatedWidth, this.chartLeft, this.labels);
106
+ },
107
+ get valueHeight() {
108
+ return calculateValueHeight(
109
+ this.chartBottom,
110
+ this.textHeight,
111
+ this.stepValue,
112
+ getStepCount(),
113
+ );
114
+ },
115
+ get chartBottom() {
116
+ return calculateChartBottom(options.xLabel?.() ?? "", this.calculatedHeight, this.textHeight);
117
+ },
118
+ get chartLeft() {
119
+ return calculateChartLeft(
120
+ this.stepLabels,
121
+ options.yLabel?.() ?? "",
122
+ this.textHeight,
123
+ this.textWidth,
124
+ );
125
+ },
126
+
127
+ setTextSize(width: number, height: number) {
128
+ this.textWidth = width;
129
+ this.textHeight = height * 1.5;
130
+ },
131
+ });
132
+ }
133
+
134
+ /**
135
+ * Reads the size of a hidden measurer `<text>` element into the layout
136
+ * state and removes it. Call once the element is in the document (from
137
+ * `$onmount`, deferred a tick).
138
+ */
139
+ export function measureChartText(layout: ChartLayout, measurer: SVGTextElement): void {
140
+ const bbox = measurer.getBBox();
141
+ layout.setTextSize(bbox.width, bbox.height);
142
+ measurer.remove();
143
+ }
@@ -1,4 +1,4 @@
1
- import type DataSeries from "../Chart/DataSeries";
1
+ import type DataSeries from "../Charts/DataSeries";
2
2
 
3
3
  export function calculateMaxValue(series: DataSeries[]): number {
4
4
  // HACK: Yeah, nested reduces
@@ -0,0 +1,103 @@
1
+ /** Converts between color representations used by the picker components */
2
+
3
+ export interface Rgb {
4
+ r: number;
5
+ g: number;
6
+ b: number;
7
+ }
8
+
9
+ /** Parses "#rgb", "#rrggbb" or "rrggbb"; returns undefined when invalid */
10
+ export function parseHex(text: string | undefined | null): string | undefined {
11
+ if (!text) return undefined;
12
+ let value = text.trim().replace(/^#/, "");
13
+ if (value.length === 3) {
14
+ value = value
15
+ .split("")
16
+ .map((c) => c + c)
17
+ .join("");
18
+ }
19
+ if (!/^[0-9a-fA-F]{6}$/.test(value)) return undefined;
20
+ return "#" + value.toLowerCase();
21
+ }
22
+
23
+ export function hexToRgb(hex: string): Rgb {
24
+ const value = parseHex(hex) ?? "#000000";
25
+ return {
26
+ r: parseInt(value.slice(1, 3), 16),
27
+ g: parseInt(value.slice(3, 5), 16),
28
+ b: parseInt(value.slice(5, 7), 16),
29
+ };
30
+ }
31
+
32
+ function toHexPart(n: number): string {
33
+ const clamped = Math.min(255, Math.max(0, Math.round(n)));
34
+ return clamped.toString(16).padStart(2, "0");
35
+ }
36
+
37
+ export function rgbToHex({ r, g, b }: Rgb): string {
38
+ return `#${toHexPart(r)}${toHexPart(g)}${toHexPart(b)}`;
39
+ }
40
+
41
+ /** Blends two colors; amount 0 returns a, 1 returns b */
42
+ export function mix(a: string, b: string, amount: number): string {
43
+ const ca = hexToRgb(a);
44
+ const cb = hexToRgb(b);
45
+ const t = Math.min(1, Math.max(0, amount));
46
+ return rgbToHex({
47
+ r: ca.r + (cb.r - ca.r) * t,
48
+ g: ca.g + (cb.g - ca.g) * t,
49
+ b: ca.b + (cb.b - ca.b) * t,
50
+ });
51
+ }
52
+
53
+ /** Perceptual lightness in [0..1], for choosing readable text on swatches */
54
+ export function luminance(hex: string): number {
55
+ const { r, g, b } = hexToRgb(hex);
56
+ return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
57
+ }
58
+
59
+ /** A default palette, roughly ordered light to dark */
60
+ export const defaultPalette: string[] = [
61
+ "#FFFFFF",
62
+ "#F5F5F5",
63
+ "#D9D9D9",
64
+ "#BFBFBF",
65
+ "#8C8C8C",
66
+ "#595959",
67
+ "#404040",
68
+ "#262626",
69
+ "#0F0F0F",
70
+ "#000000",
71
+ "#FFE4E1",
72
+ "#FFC0CB",
73
+ "#FF7F7F",
74
+ "#FF4040",
75
+ "#E60000",
76
+ "#A61C00",
77
+ "#FFEDCC",
78
+ "#FFD59E",
79
+ "#FFAA33",
80
+ "#E67E00",
81
+ "#B35900",
82
+ "#FFF9C4",
83
+ "#FFF176",
84
+ "#FFEB3B",
85
+ "#FBC02D",
86
+ "#F9A825",
87
+ "#827717",
88
+ "#E8F5E9",
89
+ "#A5D6A7",
90
+ "#66BB6A",
91
+ "#2E7D32",
92
+ "#1B5E20",
93
+ "#0D47A1",
94
+ "#1565C0",
95
+ "#1E88E5",
96
+ "#42A5F5",
97
+ "#90CAF9",
98
+ "#E1BEE7",
99
+ "#CE93D8",
100
+ "#AB47BC",
101
+ "#8E24AA",
102
+ "#4A148C",
103
+ ];
@@ -0,0 +1,152 @@
1
+ import { $cache, $run } from "@torpor/view";
2
+
3
+ export interface ItemGroupItem {
4
+ index: number;
5
+ value: any;
6
+ parentDisabled?: boolean;
7
+ }
8
+
9
+ export interface ItemGroup<T extends ItemGroupItem> {
10
+ itemStates: T[];
11
+ registerItem: (item: T) => void;
12
+ removeItem: (itemIndex: number) => void;
13
+ toggleItem: (value: any) => void;
14
+ }
15
+
16
+ /**
17
+ * Creates a managed collection of selectable items for group-style components
18
+ * (Accordion, ListBox, TabGroup, Tree, etc.).
19
+ *
20
+ * Handles item registration, removal, and toggle logic. Each item's selection
21
+ * state is derived: registration installs a `$cache` getter over
22
+ * `selectedProperty` that computes from the group value, so selection can
23
+ * never drift out of sync with it — eliminating the boilerplate that was
24
+ * duplicated across ~5 components.
25
+ *
26
+ * The returned `itemStates` array is the source of truth; components should
27
+ * store it in their context for child items to access.
28
+ *
29
+ * NOTE: Items must be registered before their selection property is first
30
+ * read, so the derived getter can take the property over.
31
+ */
32
+ export function createItemGroup<T extends ItemGroupItem>(options: {
33
+ /** The reactive state containing the group value */
34
+ state: { value: any };
35
+ /** Selection type, or a getter for it if it can change */
36
+ type: "single" | "multiple" | (() => "single" | "multiple");
37
+ /** The boolean property on items that reflects selection state */
38
+ selectedProperty: keyof T;
39
+ /** Getter for parent disabled state */
40
+ disabled?: () => boolean | undefined;
41
+ /** Allow deselecting in single-select mode (default: true) */
42
+ allowDeselect?: boolean;
43
+ /** Called for each item after index assignment but before selection check */
44
+ onRegister?: (item: T) => void;
45
+ /** Callback after a toggle, for side effects like closing a popout */
46
+ onToggle?: (value: any) => void;
47
+ }): ItemGroup<T> {
48
+ const { state, selectedProperty } = options;
49
+ const getType = typeof options.type === "function" ? options.type : () => options.type;
50
+ const allowDeselect = options.allowDeselect ?? true;
51
+ const itemStates: T[] = [];
52
+ let nextIndex = 0;
53
+
54
+ // Propagate disabled state from parent
55
+ if (options.disabled) {
56
+ const disabledGetter = options.disabled;
57
+ $run(() => {
58
+ const disabled = disabledGetter() === true;
59
+ for (let item of itemStates) {
60
+ item.parentDisabled = disabled;
61
+ }
62
+ });
63
+ }
64
+
65
+ function isItemSelected(item: T, value: any): boolean {
66
+ if (value === undefined || value === null) return false;
67
+ if (getType() === "multiple") {
68
+ const values = Array.isArray(value) ? value : [value];
69
+ return values.some((v) => sameValue(v, item.value));
70
+ }
71
+ return sameValue(item.value, value);
72
+ }
73
+
74
+ function registerItem(item: T) {
75
+ if (item.index === -1 || item.index === undefined) {
76
+ item.index = nextIndex++;
77
+ }
78
+ if (options.onRegister) {
79
+ options.onRegister(item);
80
+ }
81
+ // Make the selection property derived: a cached getter computed from the
82
+ // group value, so it always reflects (and only reflects) that value
83
+ Object.defineProperty(item, selectedProperty, {
84
+ get() {
85
+ return $cache(() => isItemSelected(item, state.value));
86
+ },
87
+ enumerable: true,
88
+ configurable: true,
89
+ });
90
+ if (options.disabled) {
91
+ item.parentDisabled = options.disabled() === true;
92
+ }
93
+ itemStates.splice(item.index, 0, item);
94
+ }
95
+
96
+ function removeItem(itemIndex: number) {
97
+ const index = itemStates.findIndex((item) => item.index === itemIndex);
98
+ if (index !== -1) {
99
+ itemStates.splice(index, 1);
100
+ }
101
+ itemStates.forEach((item, i) => (item.index = i));
102
+ }
103
+
104
+ function toggleItem(value: any) {
105
+ switch (getType()) {
106
+ case "single": {
107
+ const item = itemStates.find((i) => sameValue(i.value, value));
108
+ if (allowDeselect) {
109
+ if (item) {
110
+ state.value = (item as any)[selectedProperty] ? undefined : item.value;
111
+ }
112
+ } else {
113
+ // Store the item's own value, so the group value keeps its
114
+ // canonical type
115
+ state.value = item ? item.value : value;
116
+ }
117
+ break;
118
+ }
119
+ case "multiple": {
120
+ const newValue: any[] = [];
121
+ for (let item of itemStates) {
122
+ const toggled = sameValue(item.value, value);
123
+ if (
124
+ (toggled && !(item as any)[selectedProperty]) ||
125
+ (!toggled && (item as any)[selectedProperty])
126
+ ) {
127
+ newValue.push(item.value);
128
+ }
129
+ }
130
+ state.value = newValue.sort((a, b) => a - b);
131
+ break;
132
+ }
133
+ }
134
+ if (options.onToggle) {
135
+ options.onToggle(value);
136
+ }
137
+ }
138
+
139
+ return { itemStates, registerItem, removeItem, toggleItem };
140
+ }
141
+
142
+ /**
143
+ * Compares an item value with a group/toggle value. Primitives are compared
144
+ * as strings — DOM values are always strings, while callers may pass e.g.
145
+ * numbers — and everything else by strict equality.
146
+ */
147
+ function sameValue(a: any, b: any): boolean {
148
+ if (a === b) return true;
149
+ if (a === null || b === null || a === undefined || b === undefined) return false;
150
+ if (typeof a === "object" || typeof b === "object") return false;
151
+ return String(a) === String(b);
152
+ }
@@ -25,7 +25,7 @@ const dayNames: string[] = [
25
25
  "Saturday",
26
26
  "Sunday",
27
27
  ];
28
- const shortDayNames: string[] = dayNames.map((n) => n.substring(0, 3).toLowerCase());
28
+ const shortDayNames: string[] = dayNames.map((n) => n.substring(0, 2));
29
29
 
30
30
  export { monthNames, shortMonthNames, dayNames, shortDayNames };
31
31
 
@@ -229,16 +229,17 @@ function formatMonth(date: Date, m: string): string {
229
229
  } else if (m.length === 3) {
230
230
  return monthNames[date.getMonth()].substring(0, 3);
231
231
  } else if (m.length == 2) {
232
- let text = date.getMonth().toString();
233
- return text.length < 2 ? "0" + text : text;
232
+ // getMonth is zero-based
233
+ return String(date.getMonth() + 1).padStart(2, "0");
234
234
  } else {
235
235
  return date.getMonth().toString();
236
236
  }
237
237
  }
238
238
 
239
239
  function formatYear(date: Date, y: string): string {
240
- return date
241
- .getFullYear()
242
- .toString()
243
- .substring(4 - y.length, y.length);
240
+ const year = date.getFullYear().toString();
241
+ if (y.length >= 4) {
242
+ return year;
243
+ }
244
+ return year.substring(4 - y.length);
244
245
  }
@@ -1,17 +1,17 @@
1
1
  export function addDocumentEvent<K extends keyof DocumentEventMap>(
2
2
  type: K,
3
- listener: (this: Document, ev: DocumentEventMap[K]) => any
3
+ listener: (this: Document, ev: DocumentEventMap[K]) => any,
4
4
  ): void {
5
- if (typeof document !== 'undefined') {
5
+ if (typeof document !== "undefined") {
6
6
  document.addEventListener(type, listener);
7
7
  }
8
8
  }
9
9
 
10
10
  export function removeDocumentEvent<K extends keyof DocumentEventMap>(
11
11
  type: K,
12
- listener: (this: Document, ev: DocumentEventMap[K]) => any
12
+ listener: (this: Document, ev: DocumentEventMap[K]) => any,
13
13
  ): void {
14
- if (typeof document !== 'undefined') {
14
+ if (typeof document !== "undefined") {
15
15
  document.removeEventListener(type, listener);
16
16
  }
17
17
  }
@@ -0,0 +1,86 @@
1
+ import { $watch } from "@torpor/view";
2
+
3
+ /**
4
+ * Shared state for HTML5 drag & drop. A source element starts a drag with
5
+ * `beginDrag`; drop targets consult `dragState.current` during dragover and
6
+ * drop. Because the dataTransfer API restricts what can be read outside
7
+ * drop, the store is the reliable channel -- the dataTransfer only carries
8
+ * the drag's id, which doubles as an integrity check and makes drags
9
+ * interoperable across windows when the type is allowed through.
10
+ *
11
+ * Drags don't nest, so a single module-level state is enough.
12
+ */
13
+
14
+ export interface DragInfo {
15
+ /** Generated identifier for this drag, mirrored into the dataTransfer */
16
+ id: string;
17
+ /** High-level kind ("list-item", "tree-item", "file"...), for filtering */
18
+ kind: string;
19
+ /** Arbitrary payload attached by the drag source */
20
+ data: any;
21
+ }
22
+
23
+ export interface DragState {
24
+ /** The active drag, if any */
25
+ current: DragInfo | undefined;
26
+ }
27
+
28
+ export const dragState: DragState = $watch({
29
+ current: undefined as DragInfo | undefined,
30
+ });
31
+
32
+ let nextId = 0;
33
+
34
+ /** Starts tracking a drag and returns its id */
35
+ export function beginDrag(kind: string, data: any): DragInfo {
36
+ const info: DragInfo = {
37
+ id: String(nextId++),
38
+ kind,
39
+ data,
40
+ };
41
+ dragState.current = info;
42
+ return info;
43
+ }
44
+
45
+ /** Clears the tracked drag */
46
+ export function endDrag(): void {
47
+ dragState.current = undefined;
48
+ }
49
+
50
+ const TYPE_PREFIX = "application/x-torpor-drag/";
51
+
52
+ /** Encodes a drag id into a dataTransfer-compatible mime type */
53
+ export function encodeDragType(id: string): string {
54
+ return TYPE_PREFIX + id;
55
+ }
56
+
57
+ /**
58
+ * Writes the drag's id into the event's dataTransfer. No-op when the event
59
+ * carries no transfer (some synthetic tests construct bare events).
60
+ */
61
+ export function writeDragType(e: DragEvent, id: string): void {
62
+ e.dataTransfer?.setData(encodeDragType(id), id);
63
+ }
64
+
65
+ /**
66
+ * Resolves which drag an incoming event refers to. Prefers the id encoded
67
+ * in the dataTransfer (verified against the live drag); falls back to the
68
+ * tracked drag itself for dragover events, whose transfers are locked.
69
+ */
70
+ export function resolveDrag(e: DragEvent): DragInfo | undefined {
71
+ const current = dragState.current;
72
+ if (!current) return undefined;
73
+
74
+ try {
75
+ const types: readonly string[] = e.dataTransfer?.types ?? [];
76
+ for (let type of types) {
77
+ if (type.startsWith(TYPE_PREFIX)) {
78
+ return type === encodeDragType(current.id) ? current : undefined;
79
+ }
80
+ }
81
+ } catch {
82
+ // Reading types can throw for foreign-origin drags; treat those as
83
+ // unmatched and fall back to the tracked drag below
84
+ }
85
+ return current;
86
+ }