plass-ui 1.6.0 → 1.8.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 (373) hide show
  1. package/CHANGELOG.md +494 -0
  2. package/README.md +5 -3
  3. package/dist/components/accordion/PlAccordion.d.ts +19 -1
  4. package/dist/components/accordion/PlAccordion.js +1 -1
  5. package/dist/components/accordion/index.d.ts +1 -1
  6. package/dist/components/alert/PlAlert.js +1 -1
  7. package/dist/components/anchor/PlAnchor.js +1 -1
  8. package/dist/components/animate-appear/PlAnimateAppear.js +1 -1
  9. package/dist/components/animate-counter/PlAnimateCounter.d.ts +5 -2
  10. package/dist/components/animate-counter/PlAnimateCounter.js +1 -1
  11. package/dist/components/animate-float/PlAnimateFloat.js +1 -1
  12. package/dist/components/animate-headline/PlAnimateHeadline.d.ts +10 -1
  13. package/dist/components/animate-headline/PlAnimateHeadline.js +1 -1
  14. package/dist/components/animate-lighting/PlAnimateLighting.js +1 -1
  15. package/dist/components/animate-marquee/PlAnimateMarquee.d.ts +8 -1
  16. package/dist/components/animate-marquee/PlAnimateMarquee.js +1 -1
  17. package/dist/components/animate-scramble/PlAnimateScramble.js +1 -1
  18. package/dist/components/animate-shake/PlAnimateShake.js +1 -1
  19. package/dist/components/animate-split/PlAnimateSplit.js +1 -1
  20. package/dist/components/animate-typing/PlAnimateTyping.js +1 -1
  21. package/dist/components/app-logo/PlAppLogo.d.ts +51 -15
  22. package/dist/components/app-logo/PlAppLogo.js +1 -1
  23. package/dist/components/area-chart/PlAreaChart.d.ts +35 -6
  24. package/dist/components/area-chart/PlAreaChart.js +1 -1
  25. package/dist/components/aspect-ratio/PlAspectRatio.js +1 -1
  26. package/dist/components/avatar/PlAvatar.js +1 -1
  27. package/dist/components/back-top/PlBackTop.d.ts +5 -5
  28. package/dist/components/back-top/PlBackTop.js +1 -1
  29. package/dist/components/badge/PlBadge.js +1 -1
  30. package/dist/components/bar-chart/PlBarChart.d.ts +54 -2
  31. package/dist/components/bar-chart/PlBarChart.js +1 -1
  32. package/dist/components/blockquote/PlBlockquote.d.ts +2 -2
  33. package/dist/components/blockquote/PlBlockquote.js +1 -1
  34. package/dist/components/bottom-navigation/PlBottomNavigation.d.ts +15 -5
  35. package/dist/components/bottom-navigation/PlBottomNavigation.js +1 -1
  36. package/dist/components/breadcrumb/PlBreadcrumb.d.ts +16 -3
  37. package/dist/components/breadcrumb/PlBreadcrumb.js +1 -1
  38. package/dist/components/button/PlButton.d.ts +7 -0
  39. package/dist/components/button/PlButton.js +1 -1
  40. package/dist/components/calendar/PlCalendar.js +1 -1
  41. package/dist/components/card/PlCard.d.ts +9 -5
  42. package/dist/components/card/PlCard.js +1 -1
  43. package/dist/components/carousel/PlCarousel.d.ts +14 -4
  44. package/dist/components/carousel/PlCarousel.js +1 -1
  45. package/dist/components/chat-bubble/PlChatBubble.js +1 -1
  46. package/dist/components/checkbox/PlCheckbox.js +1 -1
  47. package/dist/components/chip/PlChip.d.ts +2 -1
  48. package/dist/components/chip/PlChip.js +1 -1
  49. package/dist/components/code-block/PlCodeBlock.js +1 -1
  50. package/dist/components/collapsible/PlCollapsible.d.ts +11 -0
  51. package/dist/components/collapsible/PlCollapsible.js +1 -1
  52. package/dist/components/color-picker/PlColorPicker.d.ts +3 -1
  53. package/dist/components/color-picker/PlColorPicker.js +1 -1
  54. package/dist/components/combobox/PlCombobox.d.ts +11 -5
  55. package/dist/components/combobox/PlCombobox.js +1 -1
  56. package/dist/components/command-palette/PlCommandPalette.js +1 -1
  57. package/dist/components/confirm/PlConfirmProvider.js +1 -1
  58. package/dist/components/data-table/PlDataTable.d.ts +13 -2
  59. package/dist/components/data-table/PlDataTable.js +1 -1
  60. package/dist/components/date-picker/PlDatePicker.js +1 -1
  61. package/dist/components/date-range-picker/PlDateRangePicker.js +1 -1
  62. package/dist/components/date-time-picker/PlDateTimePicker.js +1 -1
  63. package/dist/components/drawer/PlDrawer.d.ts +27 -2
  64. package/dist/components/drawer/PlDrawer.js +1 -1
  65. package/dist/components/empty/PlEmpty.d.ts +4 -1
  66. package/dist/components/empty/PlEmpty.js +1 -1
  67. package/dist/components/fieldset/PlFieldset.js +1 -1
  68. package/dist/components/file-picker/PlFilePicker.d.ts +32 -1
  69. package/dist/components/file-picker/PlFilePicker.js +1 -1
  70. package/dist/components/file-picker/index.d.ts +1 -1
  71. package/dist/components/floating-action-button/PlFloatingActionButton.d.ts +5 -0
  72. package/dist/components/floating-action-button/PlFloatingActionButton.js +1 -1
  73. package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.d.ts +10 -0
  74. package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +1 -1
  75. package/dist/components/footer/PlFooter.d.ts +3 -1
  76. package/dist/components/footer/PlFooter.js +1 -1
  77. package/dist/components/gallery/PlGallery.js +1 -1
  78. package/dist/components/gauge-chart/PlGaugeChart.d.ts +11 -2
  79. package/dist/components/gauge-chart/PlGaugeChart.js +1 -1
  80. package/dist/components/header/PlHeader.d.ts +4 -2
  81. package/dist/components/header/PlHeader.js +1 -1
  82. package/dist/components/heatmap-chart/PlHeatmapChart.d.ts +1 -1
  83. package/dist/components/heatmap-chart/PlHeatmapChart.js +1 -1
  84. package/dist/components/hover-card/PlHoverCard.js +1 -1
  85. package/dist/components/how-to-steps/PlHowToSteps.js +1 -1
  86. package/dist/components/image/PlImage.js +1 -1
  87. package/dist/components/image/PlImagePreview.d.ts +3 -2
  88. package/dist/components/line-chart/PlLineChart.d.ts +32 -6
  89. package/dist/components/line-chart/PlLineChart.js +1 -1
  90. package/dist/components/list/PlList.d.ts +16 -5
  91. package/dist/components/list/PlList.js +1 -1
  92. package/dist/components/menu/PlMenu.d.ts +19 -7
  93. package/dist/components/menu/PlMenu.js +1 -1
  94. package/dist/components/menubar/PlMenubar.js +1 -1
  95. package/dist/components/meter/PlMeter.js +1 -1
  96. package/dist/components/mockup/PlMockup.d.ts +6 -0
  97. package/dist/components/mockup/PlMockup.js +1 -1
  98. package/dist/components/modal/PlModal.js +1 -1
  99. package/dist/components/navigation-menu/PlNavigationMenu.d.ts +56 -11
  100. package/dist/components/navigation-menu/PlNavigationMenu.js +1 -1
  101. package/dist/components/number-field/PlNumberField.d.ts +7 -5
  102. package/dist/components/number-field/PlNumberField.js +1 -1
  103. package/dist/components/otp-field/PlOtpField.js +1 -1
  104. package/dist/components/overlay/PlOverlay.js +1 -1
  105. package/dist/components/page-layout/PlPageLayout.d.ts +14 -3
  106. package/dist/components/page-layout/PlPageLayout.js +1 -1
  107. package/dist/components/pagination/PlPagination.js +1 -1
  108. package/dist/components/panes/PlPanes.d.ts +4 -1
  109. package/dist/components/panes/PlPanes.js +1 -1
  110. package/dist/components/pie-chart/PlPieChart.d.ts +26 -1
  111. package/dist/components/pie-chart/PlPieChart.js +1 -1
  112. package/dist/components/pill/PlPill.js +1 -1
  113. package/dist/components/popconfirm/PlPopconfirm.d.ts +8 -1
  114. package/dist/components/popconfirm/PlPopconfirm.js +1 -1
  115. package/dist/components/popover/PlPopover.js +1 -1
  116. package/dist/components/progress-box/PlProgressBox.js +1 -1
  117. package/dist/components/progress-circular/PlProgressCircular.d.ts +11 -1
  118. package/dist/components/progress-circular/PlProgressCircular.js +1 -1
  119. package/dist/components/progress-linear/PlProgressLinear.js +1 -1
  120. package/dist/components/radio-group/PlRadioGroup.js +1 -1
  121. package/dist/components/rating/PlRating.js +1 -1
  122. package/dist/components/scatter-chart/PlScatterChart.js +1 -1
  123. package/dist/components/scroll-area/PlScrollArea.js +1 -1
  124. package/dist/components/scroll-zone/PlScrollZone.js +1 -1
  125. package/dist/components/segmented-button/PlSegmentedButton.js +1 -1
  126. package/dist/components/select/PlSelect.d.ts +4 -1
  127. package/dist/components/select/PlSelect.js +1 -1
  128. package/dist/components/sidebar/PlSidebar.d.ts +12 -0
  129. package/dist/components/sidebar/PlSidebar.js +1 -1
  130. package/dist/components/slider/PlSlider.d.ts +2 -1
  131. package/dist/components/slider/PlSlider.js +1 -1
  132. package/dist/components/sparkline/PlSparkline.d.ts +15 -3
  133. package/dist/components/sparkline/PlSparkline.js +1 -1
  134. package/dist/components/stepper/PlStepper.d.ts +11 -0
  135. package/dist/components/stepper/PlStepper.js +1 -1
  136. package/dist/components/switch/PlSwitch.js +1 -1
  137. package/dist/components/table/PlTable.d.ts +11 -1
  138. package/dist/components/table/PlTable.js +1 -1
  139. package/dist/components/tabs/PlTabs.d.ts +18 -1
  140. package/dist/components/tabs/PlTabs.js +1 -1
  141. package/dist/components/text-field/PlTextField.d.ts +6 -8
  142. package/dist/components/text-field/PlTextField.js +1 -1
  143. package/dist/components/text-link/PlTextLink.js +1 -1
  144. package/dist/components/time-picker/PlTimePicker.js +1 -1
  145. package/dist/components/timeline-chart/PlTimelineChart.js +1 -1
  146. package/dist/components/toast/PlToast.js +1 -1
  147. package/dist/components/toggle/PlToggle.js +1 -1
  148. package/dist/components/tooltip/PlTooltip.d.ts +4 -0
  149. package/dist/components/tooltip/PlTooltip.js +1 -1
  150. package/dist/components/tour/PlTour.js +1 -1
  151. package/dist/components/transfer/PlTransfer.d.ts +5 -2
  152. package/dist/components/transfer/PlTransfer.js +1 -1
  153. package/dist/components/tree/PlTree.d.ts +12 -0
  154. package/dist/components/tree/PlTree.js +1 -1
  155. package/dist/components/tree-select/PlTreeSelect.js +1 -1
  156. package/dist/components/typography/PlTypography.d.ts +20 -7
  157. package/dist/components/typography/PlTypography.js +1 -1
  158. package/dist/components/visually-hidden/PlVisuallyHidden.d.ts +12 -3
  159. package/dist/components/visually-hidden/PlVisuallyHidden.js +1 -1
  160. package/dist/components/window-pane/PlWindowPane.d.ts +16 -3
  161. package/dist/components/window-pane/PlWindowPane.js +1 -1
  162. package/dist/css/accordion.css +4 -0
  163. package/dist/css/alert.css +5 -0
  164. package/dist/css/anchor.css +6 -0
  165. package/dist/css/animate-appear.css +3 -0
  166. package/dist/css/animate-blink.css +3 -0
  167. package/dist/css/animate-counter.css +4 -0
  168. package/dist/css/animate-fade.css +3 -0
  169. package/dist/css/animate-float.css +3 -0
  170. package/dist/css/animate-grow.css +3 -0
  171. package/dist/css/animate-headline.css +3 -0
  172. package/dist/css/animate-lighting.css +4 -0
  173. package/dist/css/animate-marquee.css +4 -0
  174. package/dist/css/animate-reveal.css +3 -0
  175. package/dist/css/animate-rotate.css +3 -0
  176. package/dist/css/animate-scramble.css +5 -0
  177. package/dist/css/animate-shake.css +3 -0
  178. package/dist/css/animate-slide.css +3 -0
  179. package/dist/css/animate-split.css +4 -0
  180. package/dist/css/animate-typing.css +4 -0
  181. package/dist/css/animate-zoom.css +3 -0
  182. package/dist/css/app-logo.css +2 -0
  183. package/dist/css/area-chart.css +12 -0
  184. package/dist/css/aspect-ratio.css +2 -0
  185. package/dist/css/avatar.css +2 -0
  186. package/dist/css/back-top.css +11 -0
  187. package/dist/css/badge.css +2 -0
  188. package/dist/css/bar-chart.css +10 -0
  189. package/dist/css/base.css +2 -3
  190. package/dist/css/blockquote.css +2 -0
  191. package/dist/css/bottom-navigation.css +4 -0
  192. package/dist/css/box.css +2 -0
  193. package/dist/css/breadcrumb.css +6 -0
  194. package/dist/css/button-group.css +2 -0
  195. package/dist/css/button.css +7 -0
  196. package/dist/css/calendar.css +17 -0
  197. package/dist/css/card.css +2 -0
  198. package/dist/css/carousel.css +10 -0
  199. package/dist/css/chat-bubble.css +6 -0
  200. package/dist/css/checkbox.css +3 -0
  201. package/dist/css/chip.css +8 -0
  202. package/dist/css/code-block.css +6 -0
  203. package/dist/css/collapsible.css +3 -0
  204. package/dist/css/color-picker.css +17 -0
  205. package/dist/css/combobox.css +10 -0
  206. package/dist/css/command-palette.css +7 -0
  207. package/dist/css/confirm.css +9 -0
  208. package/dist/css/container.css +5 -0
  209. package/dist/css/data-list.css +2 -0
  210. package/dist/css/data-table.css +15 -0
  211. package/dist/css/date-picker.css +16 -0
  212. package/dist/css/date-range-picker.css +16 -0
  213. package/dist/css/date-time-picker.css +16 -0
  214. package/dist/css/divider.css +2 -0
  215. package/dist/css/drawer.css +6 -0
  216. package/dist/css/empty.css +2 -0
  217. package/dist/css/fieldset.css +2 -0
  218. package/dist/css/file-picker.css +8 -0
  219. package/dist/css/flex.css +5 -0
  220. package/dist/css/floating-action-button.css +7 -0
  221. package/dist/css/floating-bottom-navigation.css +5 -0
  222. package/dist/css/footer.css +6 -0
  223. package/dist/css/form.css +2 -0
  224. package/dist/css/gallery.css +15 -0
  225. package/dist/css/gauge-chart.css +11 -0
  226. package/dist/css/grid.css +5 -0
  227. package/dist/css/header.css +6 -0
  228. package/dist/css/heatmap-chart.css +10 -0
  229. package/dist/css/highlight.css +2 -0
  230. package/dist/css/hot-keys.css +3 -0
  231. package/dist/css/hover-card.css +9 -0
  232. package/dist/css/how-to-steps.css +3 -0
  233. package/dist/css/icon-button.css +7 -0
  234. package/dist/css/icon.css +1 -0
  235. package/dist/css/image.css +7 -0
  236. package/dist/css/line-chart.css +12 -0
  237. package/dist/css/list.css +2 -0
  238. package/dist/css/menu.css +5 -0
  239. package/dist/css/menubar.css +5 -0
  240. package/dist/css/meter.css +6 -0
  241. package/dist/css/mockup.css +4 -0
  242. package/dist/css/modal.css +5 -0
  243. package/dist/css/navigation-menu.css +4 -0
  244. package/dist/css/number-field.css +10 -0
  245. package/dist/css/otp-field.css +6 -0
  246. package/dist/css/overlay.css +4 -0
  247. package/dist/css/page-layout.css +7 -0
  248. package/dist/css/pagination.css +8 -0
  249. package/dist/css/panes.css +7 -0
  250. package/dist/css/pie-chart.css +10 -0
  251. package/dist/css/pill.css +4 -0
  252. package/dist/css/popconfirm.css +12 -0
  253. package/dist/css/popover.css +11 -0
  254. package/dist/css/portal.css +1 -0
  255. package/dist/css/progress-box.css +5 -0
  256. package/dist/css/progress-circular.css +5 -0
  257. package/dist/css/progress-linear.css +5 -0
  258. package/dist/css/radio-group.css +3 -0
  259. package/dist/css/rating.css +6 -0
  260. package/dist/css/scatter-chart.css +10 -0
  261. package/dist/css/scroll-area.css +2 -0
  262. package/dist/css/scroll-zone.css +15 -0
  263. package/dist/css/segmented-button.css +5 -0
  264. package/dist/css/select.css +9 -0
  265. package/dist/css/show.css +1 -0
  266. package/dist/css/sidebar.css +16 -0
  267. package/dist/css/skeleton.css +2 -0
  268. package/dist/css/slider.css +3 -0
  269. package/dist/css/sparkline.css +10 -0
  270. package/dist/css/spoiler.css +10 -0
  271. package/dist/css/stack.css +5 -0
  272. package/dist/css/stat.css +2 -0
  273. package/dist/css/stepper.css +8 -0
  274. package/dist/css/switch.css +3 -0
  275. package/dist/css/table.css +3 -0
  276. package/dist/css/tabs.css +7 -0
  277. package/dist/css/text-field.css +8 -0
  278. package/dist/css/text-link.css +6 -0
  279. package/dist/css/time-picker.css +16 -0
  280. package/dist/css/timeline-chart.css +10 -0
  281. package/dist/css/timeline.css +6 -0
  282. package/dist/css/toast.css +5 -0
  283. package/dist/css/toggle.css +5 -0
  284. package/dist/css/toolbar.css +2 -0
  285. package/dist/css/tooltip.css +9 -0
  286. package/dist/css/tour.css +10 -0
  287. package/dist/css/transfer.css +13 -0
  288. package/dist/css/tree-select.css +14 -0
  289. package/dist/css/tree.css +3 -0
  290. package/dist/css/visually-hidden.css +2 -0
  291. package/dist/css/window-pane.css +9 -0
  292. package/dist/internal/animate.d.ts +59 -4
  293. package/dist/internal/animate.js +1 -1
  294. package/dist/internal/bottom-bar.d.ts +29 -0
  295. package/dist/internal/bottom-bar.js +1 -0
  296. package/dist/internal/calendar.js +1 -1
  297. package/dist/internal/chart-frame.d.ts +216 -19
  298. package/dist/internal/chart-frame.js +1 -1
  299. package/dist/internal/chart-line.d.ts +11 -6
  300. package/dist/internal/chart-line.js +1 -1
  301. package/dist/internal/chart.d.ts +149 -1
  302. package/dist/internal/chart.js +1 -1
  303. package/dist/internal/commit-change.d.ts +38 -0
  304. package/dist/internal/commit-change.js +1 -0
  305. package/dist/internal/data-table.d.ts +2 -2
  306. package/dist/internal/data-table.js +1 -1
  307. package/dist/internal/date.d.ts +9 -0
  308. package/dist/internal/date.js +1 -1
  309. package/dist/internal/defaults.d.ts +36 -3
  310. package/dist/internal/defaults.js +1 -1
  311. package/dist/internal/direction.d.ts +8 -2
  312. package/dist/internal/direction.js +1 -1
  313. package/dist/internal/focusable.d.ts +10 -0
  314. package/dist/internal/focusable.js +1 -1
  315. package/dist/internal/form.d.ts +72 -0
  316. package/dist/internal/form.js +1 -1
  317. package/dist/internal/format.d.ts +4 -1
  318. package/dist/internal/format.js +1 -1
  319. package/dist/internal/gallery.d.ts +28 -0
  320. package/dist/internal/gallery.js +1 -1
  321. package/dist/internal/glow.d.ts +39 -3
  322. package/dist/internal/glow.js +1 -1
  323. package/dist/internal/heading.d.ts +11 -0
  324. package/dist/internal/heading.js +1 -0
  325. package/dist/internal/highlight.d.ts +4 -2
  326. package/dist/internal/highlight.js +1 -1
  327. package/dist/internal/icons.d.ts +24 -0
  328. package/dist/internal/icons.js +1 -1
  329. package/dist/internal/labels.d.ts +27 -0
  330. package/dist/internal/labels.js +1 -1
  331. package/dist/internal/layout-box.d.ts +35 -0
  332. package/dist/internal/layout-box.js +1 -0
  333. package/dist/internal/lazy.d.ts +37 -0
  334. package/dist/internal/lazy.js +1 -0
  335. package/dist/internal/loading.d.ts +13 -0
  336. package/dist/internal/loading.js +1 -0
  337. package/dist/internal/media.d.ts +6 -0
  338. package/dist/internal/media.js +1 -1
  339. package/dist/internal/mockup.js +1 -1
  340. package/dist/internal/notch.d.ts +57 -3
  341. package/dist/internal/notch.js +1 -1
  342. package/dist/internal/page-layout.d.ts +24 -13
  343. package/dist/internal/page-layout.js +1 -1
  344. package/dist/internal/picker.d.ts +8 -2
  345. package/dist/internal/picker.js +1 -1
  346. package/dist/internal/progress.d.ts +41 -6
  347. package/dist/internal/progress.js +1 -1
  348. package/dist/internal/search.d.ts +12 -0
  349. package/dist/internal/search.js +1 -1
  350. package/dist/internal/sizer.d.ts +18 -10
  351. package/dist/internal/sizer.js +1 -1
  352. package/dist/internal/steps.d.ts +0 -15
  353. package/dist/internal/steps.js +1 -1
  354. package/dist/internal/styles.d.ts +136 -14
  355. package/dist/internal/styles.js +1 -1
  356. package/dist/internal/table-scroll.d.ts +42 -0
  357. package/dist/internal/table-scroll.js +1 -0
  358. package/dist/internal/table.js +1 -1
  359. package/dist/internal/text.d.ts +8 -5
  360. package/dist/internal/wheel.d.ts +13 -1
  361. package/dist/internal/wheel.js +1 -1
  362. package/dist/internal/window.js +1 -1
  363. package/dist/locales/de.js +1 -1
  364. package/dist/locales/es.js +1 -1
  365. package/dist/locales/fr.js +1 -1
  366. package/dist/locales/ja.js +1 -1
  367. package/dist/locales/ko.js +1 -1
  368. package/dist/locales/zh-Hans.js +1 -1
  369. package/dist/styles.css +1 -1
  370. package/dist/tailwind.css +1163 -81
  371. package/dist/tokens.css +1163 -81
  372. package/dist/types.d.ts +226 -13
  373. package/package.json +18 -17
@@ -16,7 +16,7 @@
16
16
  * makes.
17
17
  */
18
18
  import type * as React from 'react';
19
- import type { PlassChartCategory, PlassChartDatum, PlassChartSeries, PlassChartValueLabels, PlassDensity, PlassSize } from '../types.js';
19
+ import type { PlassChartCategory, PlassChartDatum, PlassChartSeries, PlassChartSort, PlassChartValueLabels, PlassDensity, PlassSize } from '../types.js';
20
20
  /**
21
21
  * How tall a plot is when nobody said, in pixels.
22
22
  *
@@ -130,6 +130,56 @@ export interface ChartValue {
130
130
  export declare function toValue(datum: PlassChartDatum): ChartValue;
131
131
  /** Every series unpacked, in the order it was given. */
132
132
  export declare function toValues(series: readonly PlassChartSeries[]): ChartValue[][];
133
+ /**
134
+ * The categories put in order of size, and the tail of them folded into one.
135
+ *
136
+ * Both are changes to the **data** rather than to the drawing, which is the
137
+ * same rule `zeroNulls` and `stackToFull` follow and for the same reason: the
138
+ * axis, the tooltip, the legend and the table under the chart all read the
139
+ * series they were given, so a category that has been folded away has to be
140
+ * folded away for all of them at once. A painter that reordered the bars would
141
+ * leave the axis naming the old order.
142
+ *
143
+ * ## What "size" means with more than one series
144
+ *
145
+ * The total across every series at that category, and every series' magnitude
146
+ * rather than its signed value — a category whose two series are +50 and −50 is
147
+ * a hundred units of chart, not nothing. `hidden` is not consulted: the order
148
+ * is a property of the data, and a chart whose columns rearranged themselves
149
+ * when a legend entry was clicked is one a reader cannot use.
150
+ *
151
+ * ## The tail
152
+ *
153
+ * `max` keeps the largest that many and sums the rest into one category, which
154
+ * is the answer to a chart of ninety countries: a bar too short to see is a bar
155
+ * that is costing width without saying anything, and eighty of them is a chart
156
+ * of nothing but noise. What is folded is decided by size and never by the
157
+ * order asked for, so `ascending` shows the small ones it kept rather than
158
+ * keeping the small ones. "Other" is always last, wherever the sort would
159
+ * otherwise have put it: it is not a category, it is what is left.
160
+ */
161
+ export declare function rankCategories(series: readonly PlassChartSeries[], categories: readonly PlassChartCategory[] | undefined, options: {
162
+ sort?: PlassChartSort;
163
+ max?: number;
164
+ other: string;
165
+ }): {
166
+ series: readonly PlassChartSeries[];
167
+ categories: readonly PlassChartCategory[] | undefined;
168
+ };
169
+ /**
170
+ * Every gap in every series read as a zero, for `nulls="zero"`.
171
+ *
172
+ * Done to the **data**, before the frame ever sees it, and that is the whole
173
+ * reason it is a function here rather than a branch in the painter. A zero is a
174
+ * value: it has to move the scale, appear in the tooltip, and be in the row a
175
+ * screen reader is handed. Substituted inside the drawing code it would be none
176
+ * of those — the line would touch a baseline the axis did not admit existed,
177
+ * and the table under it would still say the month was missing.
178
+ *
179
+ * A point that carried a label or a colour of its own keeps them, because it is
180
+ * the same point with a number read into it.
181
+ */
182
+ export declare function zeroNulls(series: readonly PlassChartSeries[]): PlassChartSeries[];
133
183
  /**
134
184
  * Which points of a series get a value label, decided once for the whole
135
185
  * series.
@@ -260,6 +310,43 @@ export declare function valueScale(extent: {
260
310
  /** Keeps zero in range. Off for a line chart told an explicit `min`. */
261
311
  includeZero?: boolean;
262
312
  }): ValueScale;
313
+ /**
314
+ * A value axis whose steps are **multiplications** rather than additions.
315
+ *
316
+ * The one scale in the library that changes what a distance on the plot means.
317
+ * On a linear axis the same length is the same number of units wherever it is;
318
+ * here it is the same *ratio* — the gap from 10 to 100 is the gap from 100 to
319
+ * 1,000 — which is the only way a series that runs from 3 to 3,000,000 can be
320
+ * drawn with the small end still legible. It is also the reason a log axis has
321
+ * to be labelled as one: a reader who takes it for linear reads every shape on
322
+ * it wrong, and nothing in the picture says which it is.
323
+ *
324
+ * ## Zero, and everything under it
325
+ *
326
+ * There is no such place. A logarithm has no value at zero and none at all
327
+ * below it, so an axis whose data reaches either cannot simply be stretched to
328
+ * hold them. What happens instead is stated rather than hidden: the axis floors
329
+ * at the smallest **positive** power of ten the data needs, or three decades
330
+ * under the top when the data offers no positive value to floor at, and a zero
331
+ * or a negative is drawn on that floor. It is on the baseline because that is
332
+ * where the axis ends, not because the chart worked out that it belongs there.
333
+ *
334
+ * ## The ticks
335
+ *
336
+ * Powers of ten, because those are the numbers a reader can multiply in their
337
+ * head. Over a short span — two decades or fewer, where whole decades would
338
+ * leave an axis with three labels on it — each decade also gets its 2 and its
339
+ * 5, which is the same 1-2-5 family `niceStep` picks from and for the same
340
+ * reason. Over a long one the decades are thinned by stride instead.
341
+ */
342
+ export declare function logScale(extent: {
343
+ min: number;
344
+ max: number;
345
+ } | null, options?: {
346
+ min?: number;
347
+ max?: number;
348
+ tickCount?: number;
349
+ }): ValueScale;
263
350
  /** The units a time axis is allowed to step in. */
264
351
  export type TimeUnit = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
265
352
  /** A value scale whose numbers are instants, and the unit its ticks step in. */
@@ -390,6 +477,67 @@ export declare function fitCategoryLabels(texts: string[], options: {
390
477
  fontSize: number;
391
478
  ticks: boolean;
392
479
  }): string[];
480
+ /**
481
+ * A caller's tick angle as the axis uses it: degrees, and never past a quarter
482
+ * turn either way.
483
+ *
484
+ * Past 90° a label is upside down, which is not a label. `-45` is the one to
485
+ * reach for — it reads at a glance, where a quarter turn has to be tilted the
486
+ * head for — and the sign is which way the text leans: negative runs it up
487
+ * towards the right, the way every chart that has ever done this draws it.
488
+ */
489
+ export declare function tickAngleOf(angle: number | 'auto' | undefined): number;
490
+ /**
491
+ * The angle `auto` settles on, which is a diagonal or nothing at all.
492
+ *
493
+ * The question it answers is the one a caller would otherwise answer by
494
+ * looking: *would any of these names be cut?* If none of them would, upright is
495
+ * the best an axis can do — it is the one angle that reads without the head
496
+ * moving — and turning them would be spending the plot's height on a problem
497
+ * the chart does not have. As soon as one name is wider than its slot, cutting
498
+ * is the alternative, and a diagonal beats a cut at every width.
499
+ *
500
+ * It is deliberately not a *continuous* answer. An angle worked out to fit the
501
+ * longest name exactly would be a different angle on every chart on a
502
+ * dashboard, and would change under the reader as a window is dragged; -45° is
503
+ * the one every chart that does this has settled on, and holding it still is
504
+ * worth more than the pixels a bespoke angle would save.
505
+ */
506
+ export declare function autoTickAngle(texts: readonly string[], options: {
507
+ slot: number;
508
+ fontSize: number;
509
+ }): number;
510
+ /** How deep a band of labels turned by `angle` is, away from the axis. */
511
+ export declare function tiltedDepth(widest: number, angle: number, fontSize: number): number;
512
+ /**
513
+ * And how far off its own tick it reaches, along the axis.
514
+ *
515
+ * What the two ends of the axis have to keep clear, so the first and the last
516
+ * name are not cut off at the edge of the drawing.
517
+ */
518
+ export declare function tiltedStep(width: number, angle: number, fontSize: number): number;
519
+ /**
520
+ * The least room two turned labels can sit in along the axis without touching.
521
+ *
522
+ * And **not** `tiltedStep`, which is the mistake this is here to avoid. Two
523
+ * labels turned by the same angle are parallel, so what has to clear between
524
+ * them is not their length but the distance *across* them — which is the step
525
+ * along the axis times the sine of the angle. Read the other way round, that is
526
+ * the step one line of text needs, and it is why a turned axis fits so many
527
+ * more labels than an upright one: at a quarter turn the answer is one line of
528
+ * text, whatever the names happen to say.
529
+ */
530
+ export declare function tiltedPitch(angle: number, fontSize: number): number;
531
+ /**
532
+ * How long a turned label may be before it is cut, given the depth the axis is
533
+ * willing to spend on its band.
534
+ *
535
+ * A turned label is not confined to its slot any more, so nothing else stops a
536
+ * forty-character name taking half the drawing. The depth is what is rationed,
537
+ * and this reads the length back out of it. The floor on the sine is what keeps
538
+ * a barely-turned label from being handed a budget of several thousand pixels.
539
+ */
540
+ export declare function tiltedRoom(depth: number, angle: number, fontSize: number): number;
393
541
  /** The plot's box inside the chart, once the axes have taken their bands. */
394
542
  export interface PlotBox {
395
543
  left: number;
@@ -1 +1 @@
1
- import{dateFormatter as t,numberFormatter as e}from"./format.js";export const plotHeights={xs:120,sm:160,md:220,lg:280,xl:360};export const sparklineHeights={xs:16,sm:20,md:28,lg:40,xl:56};export const lineWidths={xs:1.5,sm:1.75,md:2,lg:2.25,xl:2.5};export const lineDash="6 4";export const markerRadii={xs:3,sm:3.5,md:4,lg:4.5,xl:5};export const chartFontSizes={xs:10,sm:11,md:12,lg:13,xl:14};export const barMaxThickness={xs:14,sm:18,md:24,lg:30,xl:36};export const barBandRatio={default:.62,compact:.82};export const markGap=2;export const barRadius=4;export const chartPalette=["var(--plass-chart-1)","var(--plass-chart-2)","var(--plass-chart-3)","var(--plass-chart-4)","var(--plass-chart-5)","var(--plass-chart-6)","var(--plass-chart-7)","var(--plass-chart-8)"];const n=new Set(["primary","secondary","success","warning","danger","info"]);export function resolveColor(t){return n.has(t)?`var(--plass-${t}-accent)`:t}export function seriesColor(t,e,n=chartPalette){return resolveColor(t?.color?t.color:n[e%n.length]??chartPalette[0])}export function dimmedByHover(t,e,n){return null!==t&&t!==e&&!0===n[t]}export function toValue(t){return null==t?{value:null}:"number"==typeof t?{value:Number.isFinite(t)?t:null}:(t=>"object"==typeof t&&null!==t)(t)?{value:null!==t.y&&Number.isFinite(t.y)?t.y:null,x:t.x,z:t.z,color:t.color?resolveColor(t.color):void 0,label:t.label}:{value:null}}export function toValues(t){return t.map(t=>t.data.map(toValue))}export function labelledPoints(t,e){if("none"===e)return()=>!1;if("all"===e)return()=>!0;if("last"===e){let e=-1;for(let n=t.length-1;n>=0;n--)if(null!==t[n].value){e=n;break}return t=>t===e}let n=1/0,r=-1/0;for(const e of t)null!==e.value&&(n=Math.min(n,e.value),r=Math.max(r,e.value));return e=>{const o=t[e].value;return null!==o&&(o===n||o===r)}}export function stackToFull(t,e){const n=toValues(t),r=[];for(const t of n)t.forEach((t,e)=>{r[e]=(r[e]??0)+Math.abs(t.value??0)});return t.map((t,o)=>({...t,data:n[o].map((t,n)=>{if(null===t.value)return null;const o=r[n];return{x:t.x,y:0===o?0:t.value/o*100,color:t.color,label:t.label??e(t.value)}})}))}export function toNumber(t){return t instanceof Date?Number.isFinite(t.getTime())?t.getTime():null:"number"==typeof t&&Number.isFinite(t)?t:null}export function pointX(t,e,n){return toNumber(t.x??n?.[e]??e)}export function categoriesAreDates(t,e){return(e?.some(t=>t instanceof Date)??!1)||t.some(t=>t.some(t=>t.x instanceof Date))}export function categoryExtent(t,e){let n=1/0,r=-1/0,o=!1;return t.forEach(t=>{t.forEach((t,a)=>{if(null===t.value)return;const i=pointX(t,a,e);null!==i&&(o=!0,n=Math.min(n,i),r=Math.max(r,i))})}),o?{min:n,max:r}:null}export function bubbleRadius(t,e,n,r){return e>0&&Number.isFinite(t)&&!(t<=0)?Math.max(r,Math.sqrt(Math.min(t,e)/e)*n):0===t?0:r}export function categoryCount(t){return t.reduce((t,e)=>Math.max(t,e.data.length),0)}export function categoryAt(t,e,n){if(e&&t<e.length)return e[t];for(const e of n){const n=e[t]?.x;if(void 0!==n)return n}return t}export function extentOf(t,e){let n=1/0,r=-1/0,o=!1;if(e){const e=t.reduce((t,e)=>Math.max(t,e.length),0);for(let a=0;a<e;a++){let e=0,i=0;for(const n of t){const t=n[a]?.value;null!=t&&(o=!0,t>=0?e+=t:i+=t)}n=Math.min(n,i),r=Math.max(r,e)}}else for(const e of t)for(const{value:t}of e)null!==t&&(o=!0,n=Math.min(n,t),r=Math.max(r,t));return o?{min:n,max:r}:null}function niceStep(t){const e=10**Math.floor(Math.log10(t)),n=t/e;return n<=1?e:n<=2?2*e:n<=5?5*e:10*e}export function valueScale(t,e={}){const{tickCount:n=5,includeZero:r=!0}=e;let o=e.min??(t?t.min:0),a=e.max??(t?t.max:1);if(r&&void 0===e.min&&(o=Math.min(o,0)),r&&void 0===e.max&&(a=Math.max(a,0)),a===o){const t=Math.abs(a)>0?.5*Math.abs(a):1,n=void 0===e.min,r=void 0===e.max;!n&&r||(o-=t),!r&&n||(a+=t)}const i=void 0!==e.min&&void 0!==e.max?function dividingStep(t,e){const n=10**Math.floor(Math.log10(t/Math.max(1,e)));let r=niceStep(t/Math.max(1,e)),o=1/0;for(const a of[.1,1,10])for(const i of[1,2,2.5,5]){const u=i*a*n,s=t/u,c=Math.round(s);if(c<1||Math.abs(s-c)>1e-9)continue;const l=Math.abs(c-e);l<o&&(o=l,r=u)}return r}(a-o,n):niceStep((a-o)/Math.max(1,n)),u=void 0!==e.min?o:Math.floor(o/i)*i,s=void 0!==e.max?a:Math.ceil(a/i)*i,c=s-u||1,l=[];for(let t=u;t<=s+1e-9*i;t+=i)l.push(Number(t.toFixed(12)));return{min:u,max:s,ticks:l,fraction:t=>(t-u)/c}}const r=1e3,o=6e4,a=36e5,i=24*a,u=[{unit:"second",count:1,size:r},{unit:"second",count:5,size:5e3},{unit:"second",count:15,size:15e3},{unit:"second",count:30,size:3e4},{unit:"minute",count:1,size:o},{unit:"minute",count:5,size:3e5},{unit:"minute",count:15,size:9e5},{unit:"minute",count:30,size:18e5},{unit:"hour",count:1,size:a},{unit:"hour",count:3,size:3*a},{unit:"hour",count:6,size:6*a},{unit:"hour",count:12,size:12*a},{unit:"day",count:1,size:i},{unit:"day",count:2,size:2*i},{unit:"week",count:1,size:7*i},{unit:"week",count:2,size:14*i},{unit:"month",count:1,size:30*i},{unit:"quarter",count:1,size:91*i},{unit:"month",count:6,size:182*i},{unit:"year",count:1,size:365*i}];function floorTime(t,e){const n=new Date(t);if("year"===e)return new Date(n.getFullYear(),0,1).getTime();if("quarter"===e)return new Date(n.getFullYear(),3*Math.floor(n.getMonth()/3),1).getTime();if("month"===e)return new Date(n.getFullYear(),n.getMonth(),1).getTime();if("week"===e){const t=new Date(n.getFullYear(),n.getMonth(),n.getDate());return t.setDate(t.getDate()-t.getDay()),t.getTime()}return"day"===e?new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime():"hour"===e?new Date(n.getFullYear(),n.getMonth(),n.getDate(),n.getHours()).getTime():"minute"===e?Math.floor(t/o)*o:Math.floor(t/r)*r}function addTime(t,e,n){const a=new Date(t);if("year"===e)a.setFullYear(a.getFullYear()+n);else if("quarter"===e)a.setMonth(a.getMonth()+3*n);else if("month"===e)a.setMonth(a.getMonth()+n);else if("week"===e)a.setDate(a.getDate()+7*n);else if("day"===e)a.setDate(a.getDate()+n);else{if("hour"!==e)return t+n*("minute"===e?o:r);a.setHours(a.getHours()+n)}return a.getTime()}const s={second:"minute",minute:"hour",hour:"day",day:"month",week:"week",month:"year",quarter:"year",year:"year"};export function timeScale(t,e={}){const{tickCount:n=6}=e;let r=e.min??t?.min??Date.parse("2000-01-01T00:00:00"),o=e.max??t?.max??r+i;o<=r&&(r-=i/2,o+=i/2);const a=o-r;let c=u[0],l=1/0;for(const t of u){const e=Math.abs(a/t.size-n);e<l&&(l=e,c=t)}const h=c.unit,m="year"===h?Math.max(1,Math.round(niceStep(a/n/(365*i)))):c.count;let f=e.min??function alignTime(t,e,n){let r=floorTime(t,s[e]);if("year"===e&&n>1){const t=new Date(r).getFullYear();r=new Date(t-(t%n+n)%n,0,1).getTime()}for(let o=0;o<500;o++){const o=addTime(r,e,n);if(o>t)return r;r=o}return r}(r,h,m);const $=[];let x=f;for(let t=0;t<500&&($.push(x),!(x>o));t++)x=addTime(x,h,m);let p=e.max??$[$.length-1];p<=f&&(f-=i/2,p+=i/2);const M=p-f;return{min:f,max:p,ticks:$.filter(t=>t>=f&&t<=p),unit:h,step:m,fraction:t=>(t-f)/M}}function timeParts(t,e,n=!1){if("second"===t||"minute"===t||"hour"===t){const r="second"===t?{hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}:{hour:"2-digit",minute:"2-digit",hourCycle:"h23"};if(!n)return r;const o={month:"short",day:"numeric",...r};return e?{...o,year:"numeric"}:o}if("year"===t)return{year:"numeric"};const r="month"===t||"quarter"===t?{month:"short"}:{month:"short",day:"numeric"};return e?{...r,year:"numeric"}:r}export function timeNeedsDate(t,e){return!("second"!==e&&"minute"!==e&&"hour"!==e||t.length<2||floorTime(t[0],"day")===floorTime(t[t.length-1]-1,"day"))}export function formatTimeValue(e,n,r,o=!1){return t(r,timeParts(n,!0,o)).format(new Date(e))}export function formatTimeTicks(e,n,r){const o=new Set(e.map(t=>new Date(t).getFullYear())).size>1,a=timeNeedsDate(e,n);return e.map((e,i)=>t(r,timeParts(n,o||0===i,a)).format(new Date(e)))}export function tickStride(t,e,n){if(t<=1||e<=0)return 1;const r=Math.max(1,Math.floor(e/Math.max(1,n)));return Math.max(1,Math.ceil(t/r))}export function showsTick(t,e,n,r){return t%n===0||r&&t===e-1}export function fitsLast(t,e,n,r){const o=(t-1)%e;return o>0&&o*n>=r+8}export function textWidth(t,e){let n=0;for(const e of t)n+=/[ᄀ-ᇿ⺀-꓏가-퟿豈-﫿︰-﹏]/.test(e)?1:.6;return n*e}export function truncate(t,e,n){if(e<=0||textWidth(t,n)<=e)return t;const r=e-textWidth("…",n);let o="",a=0;for(const e of t){const t=a+textWidth(e,n);if(t>r)break;a=t,o+=e}return o.length>0?`${o.trimEnd()}…`:"…"}export function fitCategoryLabels(t,e){const{horizontal:n,slot:r,fontSize:o,ticks:a}=e;return a||!n&&r-6<2.4*o?t:t.map(t=>truncate(t,n?150:r-6,o))}export function bandScale(t,e,n){const r=t>0?e/t:e;return{step:r,band:r*n,centre:t=>r*(t+.5)}}export function linePath(t,e){const n=[];let r=[];const flush=()=>{if(0!==r.length){if(1===r.length)n.push(`M${r[0].x} ${r[0].y}h0`);else if("step"===e){n.push(`M${r[0].x} ${r[0].y}`);for(let t=1;t<r.length;t++){const e=(r[t-1].x+r[t].x)/2;n.push(`H${e}V${r[t].y}H${r[t].x}`)}}else if("smooth"===e)n.push(`M${r[0].x} ${r[0].y}`),n.push(function monotonePath(t){const e=t.length,n=[];for(let r=0;r<e-1;r++){const e=t[r+1].x-t[r].x;n.push(0===e?0:(t[r+1].y-t[r].y)/e)}const r=[n[0]??0];for(let t=1;t<e-1;t++){const e=n[t-1],o=n[t];r.push(e*o<=0?0:2*e*o/(e+o))}r.push(n[e-2]??0);const o=[];for(let n=0;n<e-1;n++){const e=(t[n+1].x-t[n].x)/3;o.push(`C${t[n].x+e} ${t[n].y+r[n]*e} ${t[n+1].x-e} ${t[n+1].y-r[n+1]*e} ${t[n+1].x} ${t[n+1].y}`)}return o.join("")}(r));else{n.push(`M${r[0].x} ${r[0].y}`);for(let t=1;t<r.length;t++)n.push(`L${r[t].x} ${r[t].y}`)}r=[]}};for(const e of t)null===e?flush():r.push(e);return flush(),n.join("")}export function areaPath(t,e,n){const r=[];let o=0;const flush=a=>{const i=t.slice(o,a).filter(Boolean);if(0===i.length)return;const u="number"==typeof e?i.map(t=>({x:t.x,y:e})).reverse():e.slice(o,a).filter(Boolean).reverse();if(0===u.length)return;const s=linePath(i,n),c=linePath(u,n).replace(/^M/,"L");r.push(`${s}${c}Z`)};for(let e=0;e<t.length;e++)null===t[e]&&(flush(e),o=e+1);return flush(t.length),r.join("")}export function barPath(t,e,n,r,o,a){const i=Math.max(0,Math.min(o,n/2,r/2));if(0===i||n<=0||r<=0)return`M${t} ${e}h${n}v${r}h${-n}Z`;const arc=(t,e)=>`a${i} ${i} 0 0 1 ${t} ${e}`;return"up"===a?`M${t} ${e+r}V${e+i}${arc(i,-i)}H${t+n-i}${arc(i,i)}V${e+r}Z`:"down"===a?`M${t} ${e}H${t+n}V${e+r-i}${arc(-i,i)}H${t+i}${arc(-i,-i)}Z`:"right"===a?`M${t} ${e}H${t+n-i}${arc(i,i)}V${e+r-i}${arc(-i,i)}H${t}Z`:`M${t+n} ${e+r}H${t+i}${arc(-i,-i)}V${e+i}${arc(i,-i)}H${t+n}Z`}export const markShapes=["circle","square","triangle","diamond","cross"];const c={circle:1,square:.8862,triangle:1.5551,diamond:1.2533,cross:1.189};export function markPath(t,e,n,r){const o=Math.max(0,r)*c[t];if(0===o)return"";if("circle"===t)return`M${e-o} ${n}a${o} ${o} 0 1 0 ${2*o} 0a${o} ${o} 0 1 0 ${2*-o} 0Z`;if("square"===t)return`M${e-o} ${n-o}h${2*o}v${2*o}h${2*-o}Z`;if("diamond"===t)return`M${e} ${n-o}L${e+o} ${n}L${e} ${n+o}L${e-o} ${n}Z`;if("triangle"===t)return`M${[0,120,240].map(t=>{const r=(t-90)*Math.PI/180;return`${e+o*Math.cos(r)} ${n+o*Math.sin(r)}`}).join("L")}Z`;const a=o/3;return`M${e-a} ${n-o}h${2*a}v${o-a}h${o-a}v${2*a}h${-(o-a)}v${o-a}h${2*-a}v${-(o-a)}h${-(o-a)}v${2*-a}h${o-a}Z`}export function ringPath(t,e,n,r,o){const point=r=>{const o=(r-90)*Math.PI/180;return`${t+n*Math.cos(o)} ${e+n*Math.sin(o)}`};if(Math.abs(o-r)>=360){const t=r+180;return`M${point(r)}A${n} ${n} 0 1 1 ${point(t)}A${n} ${n} 0 1 1 ${point(r)}`}const a=Math.abs(o-r)>180?1:0;return`M${point(r)}A${n} ${n} 0 ${a} 1 ${point(o)}`}export function arcPath(t,e,n,r,o,a){const point=(n,r)=>{const o=(r-90)*Math.PI/180;return`${t+n*Math.cos(o)} ${e+n*Math.sin(o)}`};if(Math.abs(a-o)>=360){const t=o+180;return r>0?`M${point(n,o)}A${n} ${n} 0 1 1 ${point(n,t)}A${n} ${n} 0 1 1 ${point(n,o)}ZM${point(r,o)}A${r} ${r} 0 1 0 ${point(r,t)}A${r} ${r} 0 1 0 ${point(r,o)}Z`:`M${point(n,o)}A${n} ${n} 0 1 1 ${point(n,t)}A${n} ${n} 0 1 1 ${point(n,o)}Z`}const i=Math.abs(a-o)>180?1:0;return r<=0?`M${t} ${e}L${point(n,o)}A${n} ${n} 0 ${i} 1 ${point(n,a)}Z`:`M${point(n,o)}A${n} ${n} 0 ${i} 1 ${point(n,a)}L${point(r,a)}A${r} ${r} 0 ${i} 0 ${point(r,o)}Z`}export const rampSteps=5;export function rampStep(t,e,n,r,o=0){if("diverging"===r){const r=Math.max(Math.abs(n-o),Math.abs(o-e));if(!(r>0))return 2;const a=(t-o)/r;return Math.min(4,Math.max(0,2+Math.round(2*a)))}const a=n-e;return a>0?Math.min(4,Math.max(0,Math.floor((t-e)/a*5))):4}export function rampFill(t,e){return`var(--plass-chart-${"diverging"===e?"div":"seq"}-${t+1})`}export function rampInk(t,e){return`var(--plass-chart-${"diverging"===e?"div":"seq"}-on-${t+1})`}export function squarify(t,e,n){const r=t.reduce((t,e)=>t+Math.max(0,e),0);if(!(r>0)||e<=0||n<=0)return[];const o=e*n/r,a=t.map((t,e)=>({index:e,area:Math.max(0,t)*o})).filter(t=>t.area>0).sort((t,e)=>e.area-t.area),i=[];let u=0,s=0,c=e,l=n,h=[];const worst=t=>{const e=Math.min(c,l),n=t.reduce((t,e)=>t+e.area,0);if(!(n>0&&e>0))return 1/0;const r=t[0].area,o=t[t.length-1].area;return Math.max(e*e*r/(n*n),n*n/(e*e*o))},place=()=>{const t=h.reduce((t,e)=>t+e.area,0),e=Math.min(c,l),n=e>0?t/e:0,r=c>=l;let o=0;for(const t of h){const e=n>0?t.area/n:0;i.push(r?{index:t.index,x:u,y:s+o,width:n,height:e}:{index:t.index,x:u+o,y:s,width:e,height:n}),o+=e}r?(u+=n,c-=n):(s+=n,l-=n),h=[]};for(const t of a)0===h.length||worst([...h,t])<=worst(h)||place(),h.push(t);return h.length>0&&place(),i}const l={month:"short",day:"numeric"},h={notation:"compact",maximumFractionDigits:1},m={maximumFractionDigits:2};export function formatCategory(e,n){return e instanceof Date?t(n,l).format(e):String(e)}export function compactNumber(t,n){return Math.abs(t)>=1e4?e(n,h).format(t):e(n,m).format(t)}export function writeChartValue(t,n,r){return n?e(r,n).format(t):compactNumber(t,r)}
1
+ import{dateFormatter as t,numberFormatter as e}from"./format.js";export const plotHeights={xs:120,sm:160,md:220,lg:280,xl:360};export const sparklineHeights={xs:16,sm:20,md:28,lg:40,xl:56};export const lineWidths={xs:1.5,sm:1.75,md:2,lg:2.25,xl:2.5};export const lineDash="6 4";export const markerRadii={xs:3,sm:3.5,md:4,lg:4.5,xl:5};export const chartFontSizes={xs:10,sm:11,md:12,lg:13,xl:14};export const barMaxThickness={xs:14,sm:18,md:24,lg:30,xl:36};export const barBandRatio={default:.62,compact:.82};export const markGap=2;export const barRadius=4;export const chartPalette=["var(--plass-chart-1)","var(--plass-chart-2)","var(--plass-chart-3)","var(--plass-chart-4)","var(--plass-chart-5)","var(--plass-chart-6)","var(--plass-chart-7)","var(--plass-chart-8)"];const n=new Set(["primary","secondary","success","warning","danger","info"]);export function resolveColor(t){return n.has(t)?`var(--plass-${t}-accent)`:t}export function seriesColor(t,e,n=chartPalette){return resolveColor(t?.color?t.color:n[e%n.length]??chartPalette[0])}export function dimmedByHover(t,e,n){return null!==t&&t!==e&&!0===n[t]}export function toValue(t){return null==t?{value:null}:"number"==typeof t?{value:Number.isFinite(t)?t:null}:(t=>"object"==typeof t&&null!==t)(t)?{value:null!==t.y&&Number.isFinite(t.y)?t.y:null,x:t.x,z:t.z,color:t.color?resolveColor(t.color):void 0,label:t.label}:{value:null}}export function toValues(t){return t.map(t=>t.data.map(toValue))}export function rankCategories(t,e,n){const{sort:o="none",max:r,other:a}=n,i=categoryCount(t),u=void 0!==r&&r>0&&i>r;if(!u&&("none"===o||0===i))return{series:t,categories:e};const s=toValues(t),size=t=>s.reduce((e,n)=>e+Math.abs(n[t]?.value??0),0),c=Array.from({length:i},(t,e)=>e),l=u?[...c].sort((t,e)=>size(e)-size(t)).slice(0,r).sort((t,e)=>t-e):c,h=u?c.filter(t=>!l.includes(t)):[],m="none"===o?l:[...l].sort((t,e)=>"ascending"===o?size(t)-size(e):size(e)-size(t));return{series:t.map((t,e)=>{const n=s[e],o=m.map(e=>t.data[e]??null);if(h.length>0){const t=h.filter(t=>null!==n[t]?.value),e=t.reduce((t,e)=>t+(n[e]?.value??0),0);o.push(0===t.length?{y:null,x:a}:{y:e,x:a})}return{...t,data:o}}),categories:e?[...m.map(t=>e[t]??t),...h.length>0?[a]:[]]:void 0}}export function zeroNulls(t){return t.map(t=>({...t,data:t.data.map(t=>null==t?0:"number"==typeof t?Number.isFinite(t)?t:0:null!==t.y&&void 0!==t.y&&Number.isFinite(t.y)?t:{...t,y:0})}))}export function labelledPoints(t,e){if("none"===e)return()=>!1;if("all"===e)return()=>!0;if("last"===e){let e=-1;for(let n=t.length-1;n>=0;n--)if(null!==t[n].value){e=n;break}return t=>t===e}let n=1/0,o=-1/0;for(const e of t)null!==e.value&&(n=Math.min(n,e.value),o=Math.max(o,e.value));return e=>{const r=t[e].value;return null!==r&&(r===n||r===o)}}export function stackToFull(t,e){const n=toValues(t),o=[];for(const t of n)t.forEach((t,e)=>{o[e]=(o[e]??0)+Math.abs(t.value??0)});return t.map((t,r)=>({...t,data:n[r].map((t,n)=>{if(null===t.value)return null;const r=o[n];return{x:t.x,y:0===r?0:t.value/r*100,color:t.color,label:t.label??e(t.value)}})}))}export function toNumber(t){return t instanceof Date?Number.isFinite(t.getTime())?t.getTime():null:"number"==typeof t&&Number.isFinite(t)?t:null}export function pointX(t,e,n){return toNumber(t.x??n?.[e]??e)}export function categoriesAreDates(t,e){return(e?.some(t=>t instanceof Date)??!1)||t.some(t=>t.some(t=>t.x instanceof Date))}export function categoryExtent(t,e){let n=1/0,o=-1/0,r=!1;return t.forEach(t=>{t.forEach((t,a)=>{if(null===t.value)return;const i=pointX(t,a,e);null!==i&&(r=!0,n=Math.min(n,i),o=Math.max(o,i))})}),r?{min:n,max:o}:null}export function bubbleRadius(t,e,n,o){return e>0&&Number.isFinite(t)&&!(t<=0)?Math.max(o,Math.sqrt(Math.min(t,e)/e)*n):0===t?0:o}export function categoryCount(t){return t.reduce((t,e)=>Math.max(t,e.data.length),0)}export function categoryAt(t,e,n){if(e&&t<e.length)return e[t];for(const e of n){const n=e[t]?.x;if(void 0!==n)return n}return t}export function extentOf(t,e){let n=1/0,o=-1/0,r=!1;if(e){const e=t.reduce((t,e)=>Math.max(t,e.length),0);for(let a=0;a<e;a++){let e=0,i=0;for(const n of t){const t=n[a]?.value;null!=t&&(r=!0,t>=0?e+=t:i+=t)}n=Math.min(n,i),o=Math.max(o,e)}}else for(const e of t)for(const{value:t}of e)null!==t&&(r=!0,n=Math.min(n,t),o=Math.max(o,t));return r?{min:n,max:o}:null}function niceStep(t){const e=10**Math.floor(Math.log10(t)),n=t/e;return n<=1?e:n<=2?2*e:n<=5?5*e:10*e}export function valueScale(t,e={}){const{tickCount:n=5,includeZero:o=!0}=e;let r=e.min??(t?t.min:0),a=e.max??(t?t.max:1);if(o&&void 0===e.min&&(r=Math.min(r,0)),o&&void 0===e.max&&(a=Math.max(a,0)),a===r){const t=Math.abs(a)>0?.5*Math.abs(a):1,n=void 0===e.min,o=void 0===e.max;!n&&o||(r-=t),!o&&n||(a+=t)}const i=void 0!==e.min&&void 0!==e.max?function dividingStep(t,e){const n=10**Math.floor(Math.log10(t/Math.max(1,e)));let o=niceStep(t/Math.max(1,e)),r=1/0;for(const a of[.1,1,10])for(const i of[1,2,2.5,5]){const u=i*a*n,s=t/u,c=Math.round(s);if(c<1||Math.abs(s-c)>1e-9)continue;const l=Math.abs(c-e);l<r&&(r=l,o=u)}return o}(a-r,n):niceStep((a-r)/Math.max(1,n)),u=void 0!==e.min?r:Math.floor(r/i)*i,s=void 0!==e.max?a:Math.ceil(a/i)*i,c=s-u||1,l=[];for(let t=u;t<=s+1e-9*i;t+=i)l.push(Number(t.toFixed(12)));return{min:u,max:s,ticks:l,fraction:t=>(t-u)/c}}export function logScale(t,e={}){const{tickCount:n=5}=e,o=Math.max(e.max??(t?t.max:1),1e-12),r=e.min??(t?t.min:o/1e3),a=r>0?r:o/1e3,i=Math.floor(Math.log10(a)),u=Math.ceil(Math.log10(o)),s=10**i,c=10**Math.max(u,i+1),l=Math.log10(c)-Math.log10(s),h=[];if(l<=2){for(let t=i;t<=Math.log10(c)+1e-9;t+=1)for(const e of[1,2,5]){const n=e*10**t;n>=s-1e-12&&n<=c+1e-12&&h.push(Number(n.toPrecision(12)))}h[h.length-1]!==c&&h.push(c)}else{const t=Math.max(1,Math.round(l/Math.max(1,n-1)));for(let e=i;e<=Math.log10(c)+1e-9;e+=t)h.push(Number((10**e).toPrecision(12)));h[h.length-1]!==c&&h.push(c)}return{min:s,max:c,ticks:h,fraction:t=>(Math.log10(Math.min(c,Math.max(s,t)))-Math.log10(s))/(l||1)}}const o=1e3,r=6e4,a=36e5,i=24*a,u=[{unit:"second",count:1,size:o},{unit:"second",count:5,size:5e3},{unit:"second",count:15,size:15e3},{unit:"second",count:30,size:3e4},{unit:"minute",count:1,size:r},{unit:"minute",count:5,size:3e5},{unit:"minute",count:15,size:9e5},{unit:"minute",count:30,size:18e5},{unit:"hour",count:1,size:a},{unit:"hour",count:3,size:3*a},{unit:"hour",count:6,size:6*a},{unit:"hour",count:12,size:12*a},{unit:"day",count:1,size:i},{unit:"day",count:2,size:2*i},{unit:"week",count:1,size:7*i},{unit:"week",count:2,size:14*i},{unit:"month",count:1,size:30*i},{unit:"quarter",count:1,size:91*i},{unit:"month",count:6,size:182*i},{unit:"year",count:1,size:365*i}];function floorTime(t,e){const n=new Date(t);if("year"===e)return new Date(n.getFullYear(),0,1).getTime();if("quarter"===e)return new Date(n.getFullYear(),3*Math.floor(n.getMonth()/3),1).getTime();if("month"===e)return new Date(n.getFullYear(),n.getMonth(),1).getTime();if("week"===e){const t=new Date(n.getFullYear(),n.getMonth(),n.getDate());return t.setDate(t.getDate()-t.getDay()),t.getTime()}return"day"===e?new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime():"hour"===e?new Date(n.getFullYear(),n.getMonth(),n.getDate(),n.getHours()).getTime():"minute"===e?Math.floor(t/r)*r:Math.floor(t/o)*o}function addTime(t,e,n){const a=new Date(t);if("year"===e)a.setFullYear(a.getFullYear()+n);else if("quarter"===e)a.setMonth(a.getMonth()+3*n);else if("month"===e)a.setMonth(a.getMonth()+n);else if("week"===e)a.setDate(a.getDate()+7*n);else if("day"===e)a.setDate(a.getDate()+n);else{if("hour"!==e)return t+n*("minute"===e?r:o);a.setHours(a.getHours()+n)}return a.getTime()}const s={second:"minute",minute:"hour",hour:"day",day:"month",week:"week",month:"year",quarter:"year",year:"year"};export function timeScale(t,e={}){const{tickCount:n=6}=e;let o=e.min??t?.min??Date.parse("2000-01-01T00:00:00"),r=e.max??t?.max??o+i;r<=o&&(o-=i/2,r+=i/2);const a=r-o;let c=u[0],l=1/0;for(const t of u){const e=Math.abs(a/t.size-n);e<l&&(l=e,c=t)}const h=c.unit,m="year"===h?Math.max(1,Math.round(niceStep(a/n/(365*i)))):c.count;let f=e.min??function alignTime(t,e,n){let o=floorTime(t,s[e]);if("year"===e&&n>1){const t=new Date(o).getFullYear();o=new Date(t-(t%n+n)%n,0,1).getTime()}for(let r=0;r<500;r++){const r=addTime(o,e,n);if(r>t)return o;o=r}return o}(o,h,m);const x=[];let $=f;for(let t=0;t<500&&(x.push($),!($>r));t++)$=addTime($,h,m);let M=e.max??x[x.length-1];M<=f&&(f-=i/2,M+=i/2);const p=M-f;return{min:f,max:M,ticks:x.filter(t=>t>=f&&t<=M),unit:h,step:m,fraction:t=>(t-f)/p}}function timeParts(t,e,n=!1){if("second"===t||"minute"===t||"hour"===t){const o="second"===t?{hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}:{hour:"2-digit",minute:"2-digit",hourCycle:"h23"};if(!n)return o;const r={month:"short",day:"numeric",...o};return e?{...r,year:"numeric"}:r}if("year"===t)return{year:"numeric"};const o="month"===t||"quarter"===t?{month:"short"}:{month:"short",day:"numeric"};return e?{...o,year:"numeric"}:o}export function timeNeedsDate(t,e){return!("second"!==e&&"minute"!==e&&"hour"!==e||t.length<2||floorTime(t[0],"day")===floorTime(t[t.length-1]-1,"day"))}export function formatTimeValue(e,n,o,r=!1){return t(o,timeParts(n,!0,r)).format(new Date(e))}export function formatTimeTicks(e,n,o){const r=new Set(e.map(t=>new Date(t).getFullYear())).size>1,a=timeNeedsDate(e,n);return e.map((e,i)=>t(o,timeParts(n,r||0===i,a)).format(new Date(e)))}export function tickStride(t,e,n){if(t<=1||e<=0)return 1;const o=Math.max(1,Math.floor(e/Math.max(1,n)));return Math.max(1,Math.ceil(t/o))}export function showsTick(t,e,n,o){return t%n===0||o&&t===e-1}export function fitsLast(t,e,n,o){const r=(t-1)%e;return r>0&&r*n>=o+8}export function textWidth(t,e){let n=0;for(const e of t)n+=/[ᄀ-ᇿ⺀-꓏가-퟿豈-﫿︰-﹏]/.test(e)?1:.6;return n*e}export function truncate(t,e,n){if(e<=0||textWidth(t,n)<=e)return t;const o=e-textWidth("…",n);let r="",a=0;for(const e of t){const t=a+textWidth(e,n);if(t>o)break;a=t,r+=e}return r.length>0?`${r.trimEnd()}…`:"…"}export function fitCategoryLabels(t,e){const{horizontal:n,slot:o,fontSize:r,ticks:a}=e;return a||!n&&o-6<2.4*r?t:t.map(t=>truncate(t,n?150:o-6,r))}export function tickAngleOf(t){return void 0!==t&&"auto"!==t&&Number.isFinite(t)?Math.max(-90,Math.min(90,t)):0}export function autoTickAngle(t,e){const n=e.slot-6;return t.some(t=>textWidth(t,e.fontSize)>n)?-45:0}export function tiltedDepth(t,e,n){const o=Math.abs(e)*Math.PI/180;return Math.abs(Math.sin(o))*t+Math.abs(Math.cos(o))*n}export function tiltedStep(t,e,n){const o=Math.abs(e)*Math.PI/180;return Math.abs(Math.cos(o))*t+Math.abs(Math.sin(o))*n}export function tiltedPitch(t,e){const n=Math.abs(t)*Math.PI/180;return 1.35*e/Math.max(Math.abs(Math.sin(n)),.09)}export function tiltedRoom(t,e,n){const o=Math.abs(e)*Math.PI/180;return Math.max(3*n,(t-Math.abs(Math.cos(o))*n)/Math.max(Math.abs(Math.sin(o)),.09))}export function bandScale(t,e,n){const o=t>0?e/t:e;return{step:o,band:o*n,centre:t=>o*(t+.5)}}export function linePath(t,e){const n=[];let o=[];const flush=()=>{if(0!==o.length){if(1===o.length)n.push(`M${o[0].x} ${o[0].y}h0`);else if("step"===e){n.push(`M${o[0].x} ${o[0].y}`);for(let t=1;t<o.length;t++){const e=(o[t-1].x+o[t].x)/2;n.push(`H${e}V${o[t].y}H${o[t].x}`)}}else if("smooth"===e)n.push(`M${o[0].x} ${o[0].y}`),n.push(function monotonePath(t){const e=t.length,n=[];for(let o=0;o<e-1;o++){const e=t[o+1].x-t[o].x;n.push(0===e?0:(t[o+1].y-t[o].y)/e)}const o=[n[0]??0];for(let t=1;t<e-1;t++){const e=n[t-1],r=n[t];o.push(e*r<=0?0:2*e*r/(e+r))}o.push(n[e-2]??0);const r=[];for(let n=0;n<e-1;n++){const e=(t[n+1].x-t[n].x)/3;r.push(`C${t[n].x+e} ${t[n].y+o[n]*e} ${t[n+1].x-e} ${t[n+1].y-o[n+1]*e} ${t[n+1].x} ${t[n+1].y}`)}return r.join("")}(o));else{n.push(`M${o[0].x} ${o[0].y}`);for(let t=1;t<o.length;t++)n.push(`L${o[t].x} ${o[t].y}`)}o=[]}};for(const e of t)null===e?flush():o.push(e);return flush(),n.join("")}export function areaPath(t,e,n){const o=[];let r=0;const flush=a=>{const i=t.slice(r,a).filter(Boolean);if(0===i.length)return;const u="number"==typeof e?i.map(t=>({x:t.x,y:e})).reverse():e.slice(r,a).filter(Boolean).reverse();if(0===u.length)return;const s=linePath(i,n),c=linePath(u,n).replace(/^M/,"L");o.push(`${s}${c}Z`)};for(let e=0;e<t.length;e++)null===t[e]&&(flush(e),r=e+1);return flush(t.length),o.join("")}export function barPath(t,e,n,o,r,a){const i=Math.max(0,Math.min(r,n/2,o/2));if(0===i||n<=0||o<=0)return`M${t} ${e}h${n}v${o}h${-n}Z`;const arc=(t,e)=>`a${i} ${i} 0 0 1 ${t} ${e}`;return"up"===a?`M${t} ${e+o}V${e+i}${arc(i,-i)}H${t+n-i}${arc(i,i)}V${e+o}Z`:"down"===a?`M${t} ${e}H${t+n}V${e+o-i}${arc(-i,i)}H${t+i}${arc(-i,-i)}Z`:"right"===a?`M${t} ${e}H${t+n-i}${arc(i,i)}V${e+o-i}${arc(-i,i)}H${t}Z`:`M${t+n} ${e+o}H${t+i}${arc(-i,-i)}V${e+i}${arc(i,-i)}H${t+n}Z`}export const markShapes=["circle","square","triangle","diamond","cross"];const c={circle:1,square:.8862,triangle:1.5551,diamond:1.2533,cross:1.189};export function markPath(t,e,n,o){const r=Math.max(0,o)*c[t];if(0===r)return"";if("circle"===t)return`M${e-r} ${n}a${r} ${r} 0 1 0 ${2*r} 0a${r} ${r} 0 1 0 ${2*-r} 0Z`;if("square"===t)return`M${e-r} ${n-r}h${2*r}v${2*r}h${2*-r}Z`;if("diamond"===t)return`M${e} ${n-r}L${e+r} ${n}L${e} ${n+r}L${e-r} ${n}Z`;if("triangle"===t)return`M${[0,120,240].map(t=>{const o=(t-90)*Math.PI/180;return`${e+r*Math.cos(o)} ${n+r*Math.sin(o)}`}).join("L")}Z`;const a=r/3;return`M${e-a} ${n-r}h${2*a}v${r-a}h${r-a}v${2*a}h${-(r-a)}v${r-a}h${2*-a}v${-(r-a)}h${-(r-a)}v${2*-a}h${r-a}Z`}export function ringPath(t,e,n,o,r){const point=o=>{const r=(o-90)*Math.PI/180;return`${t+n*Math.cos(r)} ${e+n*Math.sin(r)}`};if(Math.abs(r-o)>=360){const t=o+180;return`M${point(o)}A${n} ${n} 0 1 1 ${point(t)}A${n} ${n} 0 1 1 ${point(o)}`}const a=Math.abs(r-o)>180?1:0;return`M${point(o)}A${n} ${n} 0 ${a} 1 ${point(r)}`}export function arcPath(t,e,n,o,r,a){const point=(n,o)=>{const r=(o-90)*Math.PI/180;return`${t+n*Math.cos(r)} ${e+n*Math.sin(r)}`};if(Math.abs(a-r)>=360){const t=r+180;return o>0?`M${point(n,r)}A${n} ${n} 0 1 1 ${point(n,t)}A${n} ${n} 0 1 1 ${point(n,r)}ZM${point(o,r)}A${o} ${o} 0 1 0 ${point(o,t)}A${o} ${o} 0 1 0 ${point(o,r)}Z`:`M${point(n,r)}A${n} ${n} 0 1 1 ${point(n,t)}A${n} ${n} 0 1 1 ${point(n,r)}Z`}const i=Math.abs(a-r)>180?1:0;return o<=0?`M${t} ${e}L${point(n,r)}A${n} ${n} 0 ${i} 1 ${point(n,a)}Z`:`M${point(n,r)}A${n} ${n} 0 ${i} 1 ${point(n,a)}L${point(o,a)}A${o} ${o} 0 ${i} 0 ${point(o,r)}Z`}export const rampSteps=5;export function rampStep(t,e,n,o,r=0){if("diverging"===o){const o=Math.max(Math.abs(n-r),Math.abs(r-e));if(!(o>0))return 2;const a=(t-r)/o;return Math.min(4,Math.max(0,2+Math.round(2*a)))}const a=n-e;return a>0?Math.min(4,Math.max(0,Math.floor((t-e)/a*5))):4}export function rampFill(t,e){return`var(--plass-chart-${"diverging"===e?"div":"seq"}-${t+1})`}export function rampInk(t,e){return`var(--plass-chart-${"diverging"===e?"div":"seq"}-on-${t+1})`}export function squarify(t,e,n){const o=t.reduce((t,e)=>t+Math.max(0,e),0);if(!(o>0)||e<=0||n<=0)return[];const r=e*n/o,a=t.map((t,e)=>({index:e,area:Math.max(0,t)*r})).filter(t=>t.area>0).sort((t,e)=>e.area-t.area),i=[];let u=0,s=0,c=e,l=n,h=[];const worst=t=>{const e=Math.min(c,l),n=t.reduce((t,e)=>t+e.area,0);if(!(n>0&&e>0))return 1/0;const o=t[0].area,r=t[t.length-1].area;return Math.max(e*e*o/(n*n),n*n/(e*e*r))},place=()=>{const t=h.reduce((t,e)=>t+e.area,0),e=Math.min(c,l),n=e>0?t/e:0,o=c>=l;let r=0;for(const t of h){const e=n>0?t.area/n:0;i.push(o?{index:t.index,x:u,y:s+r,width:n,height:e}:{index:t.index,x:u+r,y:s,width:e,height:n}),r+=e}o?(u+=n,c-=n):(s+=n,l-=n),h=[]};for(const t of a)0===h.length||worst([...h,t])<=worst(h)||place(),h.push(t);return h.length>0&&place(),i}const l={month:"short",day:"numeric"},h={notation:"compact",maximumFractionDigits:1},m={maximumFractionDigits:2};export function formatCategory(e,n){return e instanceof Date?t(n,l).format(e):String(e)}export function compactNumber(t,n){return Math.abs(t)>=1e4?e(n,h).format(t):e(n,m).format(t)}export function writeChartValue(t,n,o){return n?e(o,n).format(t):compactNumber(t,o)}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * When a component that measures its own children has to measure them again.
3
+ *
4
+ * A component handed its children as `children` is handed a new reference on
5
+ * every render a parent does, whether anything in them changed or not, so a
6
+ * layout effect that lists `children` reads the layout back on every one of
7
+ * those renders. `PlSegmentedButton` and `PlFloatingBottomNavigation` both did,
8
+ * and a screen with several of them recalculated the layout between each one's
9
+ * reads and the next one's writes.
10
+ *
11
+ * This runs on every commit as well, but it reads only the DOM tree, never the
12
+ * layout, and calls back only when the commit changed something the children
13
+ * can have moved with:
14
+ *
15
+ * - one of `deps`, which are the props the component sizes its children by;
16
+ * - the markup under the element: a child added, removed or moved, text
17
+ * edited, a `class`, a `style` or a `dir` changed. A `MutationObserver`
18
+ * records those, and its records are taken in the layout effect, before the
19
+ * browser delivers them, so they are exactly the ones the commit being
20
+ * checked made. A parent rendering again with the same `style` writes
21
+ * nothing, since React sets only the declarations whose values changed, and
22
+ * the `style` of the element the callback writes its own answer to, such as
23
+ * a sliding tile, is the answer landing rather than anything that moved;
24
+ * - the nearest `dir` above the element, since a document turned over in the
25
+ * same commit moves every child without touching the markup under it.
26
+ *
27
+ * A change made outside a commit of the component, such as a child that updates
28
+ * itself or a font that loads, is left to the component's `ResizeObserver`,
29
+ * which answers it when it changes a size, as it did before.
30
+ */
31
+ import * as React from 'react';
32
+ /**
33
+ * Calls `onChange` before the browser paints, on the first commit and on every
34
+ * later one that changed `deps`, the markup under `ref`, or the direction it
35
+ * runs in. `output` is the element `onChange` writes to, whose own `style` does
36
+ * not count.
37
+ */
38
+ export declare function useCommitChange(ref: React.RefObject<HTMLElement | null>, deps: readonly unknown[], onChange: () => void, output?: React.RefObject<HTMLElement | null>): void;
@@ -0,0 +1 @@
1
+ "use client";import*as e from"react";export function useCommitChange(t,r,n,u){const c=e.useRef(null),s=e.useRef(null);e.useLayoutEffect(()=>{const e=t.current;if(!e||"undefined"==typeof MutationObserver)return;const r=new MutationObserver(()=>{});return r.observe(e,{subtree:!0,childList:!0,characterData:!0,attributeFilter:["class","style","dir"]}),c.current=r,()=>{r.disconnect(),c.current=null}},[t]),e.useLayoutEffect(()=>{const e=t.current;if(!e)return;const i=u?.current,o=(c.current?.takeRecords()??[]).some(e=>!("style"===e.attributeName&&e.target===i)),a=[...r,e.closest("[dir]")?.getAttribute("dir")],l=s.current;!o&&null!==l&&a.length===l.length&&a.every((e,t)=>Object.is(e,l[t]))||(s.current=a,n())})}
@@ -34,9 +34,9 @@ export interface PlassSort {
34
34
  * **Strings compare with `localeCompare`.** `'a' < 'B'` is false by code point,
35
35
  * which puts every capitalised word above every lower-case one and sorts `Ösi`
36
36
  * after `Zoe`. A list of names a reader cannot scan is a list that was sorted
37
- * for the machine.
37
+ * for the machine. `locale` is the collation, and left out it is the runtime's.
38
38
  */
39
- export declare function compareValues(a: unknown, b: unknown, direction?: 1 | -1): number;
39
+ export declare function compareValues(a: unknown, b: unknown, direction?: 1 | -1, locale?: Intl.LocalesArgument): number;
40
40
  /**
41
41
  * What pressing a column heading does next.
42
42
  *
@@ -1 +1 @@
1
- export function compareValues(e,n,t=1){const o=null==e||""===e,r=null==n||""===n;return o||r?o&&r?0:o?1:-1:function compareKnown(e,n){return"number"==typeof e&&"number"==typeof n?e-n:"boolean"==typeof e&&"boolean"==typeof n?Number(e)-Number(n):e instanceof Date&&n instanceof Date?e.getTime()-n.getTime():String(e).localeCompare(String(n))}(e,n)*t}export function nextSort(e,n){return null===e||e.key!==n?{key:n,direction:"asc"}:"asc"===e.direction?{key:n,direction:"desc"}:null}export function keysBetween(e,n,t){const o=e.indexOf(n),r=e.indexOf(t);return-1===o||-1===r?[]:o<=r?e.slice(o,r+1):e.slice(r,o+1)}export function pageBounds(e,n,t){const o=Math.max(1,Math.ceil(e/t)),r=(Math.min(Math.max(1,Math.trunc(n)),o)-1)*t;return[r,Math.min(r+t,e)]}
1
+ export function compareValues(e,n,t=1,o){const r=null==e||""===e,i=null==n||""===n;return r||i?r&&i?0:r?1:-1:function compareKnown(e,n,t){return"number"==typeof e&&"number"==typeof n?e-n:"boolean"==typeof e&&"boolean"==typeof n?Number(e)-Number(n):e instanceof Date&&n instanceof Date?e.getTime()-n.getTime():String(e).localeCompare(String(n),t)}(e,n,o)*t}export function nextSort(e,n){return null===e||e.key!==n?{key:n,direction:"asc"}:"asc"===e.direction?{key:n,direction:"desc"}:null}export function keysBetween(e,n,t){const o=e.indexOf(n),r=e.indexOf(t);return-1===o||-1===r?[]:o<=r?e.slice(o,r+1):e.slice(r,o+1)}export function pageBounds(e,n,t){const o=Math.max(1,Math.ceil(e/t)),r=(Math.min(Math.max(1,Math.trunc(n)),o)-1)*t;return[r,Math.min(r+t,e)]}
@@ -54,6 +54,15 @@ export declare function startOfYear(date: Date): Date;
54
54
  export declare function daysInMonth(year: number, month: number): number;
55
55
  /** Today, at midnight. The one place the pickers read the clock for a *date*. */
56
56
  export declare function today(): Date;
57
+ /**
58
+ * Today as the clock reads in `timeZone`, at local midnight — the day it is
59
+ * there, as the local date everything else here works on. Left out, it is
60
+ * {@link today}.
61
+ *
62
+ * A server render reads the clock in UTC rather than in whatever zone the
63
+ * machine is set to, so the browser hydrating it can ask for the same day.
64
+ */
65
+ export declare function todayIn(timeZone: string | undefined): Date;
57
66
  export declare function addDays(date: Date, amount: number): Date;
58
67
  /**
59
68
  * Months, with the day of the month clamped rather than allowed to overflow.
@@ -1 +1 @@
1
- import{dateFormatter as t}from"./format.js";export const YEAR_PAGE_SIZE=12;export function makeDate(t,e,n){const r=new Date(0);return r.setFullYear(t,e,n),r.setHours(0,0,0,0),r}export function isValidDate(t){return t instanceof Date&&!Number.isNaN(t.getTime())}export function startOfDay(t){const e=new Date(t.getTime());return e.setHours(0,0,0,0),e}export function startOfMonth(t){return makeDate(t.getFullYear(),t.getMonth(),1)}export function startOfYear(t){return makeDate(t.getFullYear(),0,1)}export function daysInMonth(t,e){return makeDate(t,e+1,0).getDate()}export function today(){return startOfDay(new Date)}export function addDays(t,e){const n=new Date(t.getTime());return n.setDate(n.getDate()+e),n}export function addMonths(t,e){const n=new Date(t.getTime()),r=makeDate(t.getFullYear(),t.getMonth()+e,1);return n.setFullYear(r.getFullYear(),r.getMonth(),Math.min(t.getDate(),daysInMonth(r.getFullYear(),r.getMonth()))),n}export function addYears(t,e){return addMonths(t,12*e)}export function compareDay(t,e){return startOfDay(t).getTime()-startOfDay(e).getTime()}export function isSameDay(t,e){return isValidDate(t)&&isValidDate(e)&&0===compareDay(t,e)}export function isSameMonth(t,e){return isValidDate(t)&&isValidDate(e)&&t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()}export function clampDate(t,e,n){return isValidDate(e)&&t.getTime()<e.getTime()?new Date(e.getTime()):isValidDate(n)&&t.getTime()>n.getTime()?new Date(n.getTime()):t}export function isDayOutside(t,e,n){return!!(isValidDate(e)&&compareDay(t,e)<0)||isValidDate(n)&&compareDay(t,n)>0}export function isMonthOutside(t,e,n){const r=t.getFullYear(),o=t.getMonth();return isDayOutside(makeDate(r,o,daysInMonth(r,o)),e,null)||isDayOutside(makeDate(r,o,1),null,n)}export function isYearOutside(t,e,n){const r=t.getFullYear();return isValidDate(e)&&r<e.getFullYear()||isValidDate(n)&&r>n.getFullYear()}export function secondsOfDay(t){return 3600*t.getHours()+60*t.getMinutes()+t.getSeconds()}export function timeUnitSpan(t,e){const n=secondsOfDay(e);if("hour"===t){const t=3600*Math.floor(n/3600);return[t,t+3599]}if("minute"===t){const t=60*Math.floor(n/60);return[t,t+59]}if("second"===t)return[n,n];const r=e.getHours()<12?0:43200;return[r,r+43200-1]}export function withTime(t,e){const n=new Date(t.getTime());return n.setHours(e.hours??n.getHours(),e.minutes??n.getMinutes(),e.seconds??n.getSeconds(),0),n}export function clampMoment(t,e,n,r){const o=r?1e3:6e4,floor=t=>withTime(t,{seconds:r?t.getSeconds():0});if(isValidDate(e)&&t.getTime()<e.getTime()){const t=floor(e),r=t.getTime()<e.getTime()?new Date(t.getTime()+o):t;return isValidDate(n)&&r.getTime()>n.getTime()?new Date(e.getTime()):r}if(isValidDate(n)&&t.getTime()>n.getTime()){const t=floor(n);return isValidDate(e)&&t.getTime()<e.getTime()?new Date(n.getTime()):t}return t}export function mergeDateAndTime(t,e){return withTime(startOfDay(t),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()})}export function calendarWeeks(t,e){const n=startOfMonth(t),r=(n.getDay()-e+7)%7,o=addDays(n,-r);return Array.from({length:6},(t,e)=>Array.from({length:7},(t,n)=>addDays(o,7*e+n)))}export function yearPageStart(t){return t-(t%12+12)%12}export function formatDate(e,n,r){return isValidDate(e)?t(n,r).format(e):""}const e=/* @__PURE__ */[...Array.from({length:24},(t,e)=>new Date(2027,e%12,21+e%7,e,58,58)),new Date(2027,0,22,12,58,58)];export function displaySamples(n,r){const o=t(n,r);return[...new Set(e.map(t=>o.format(t)))]}export function withPlaceholder(t,e){return"string"==typeof e&&""!==e?[...t,e]:t}export function toISODate(t){const pad=t=>String(t).padStart(2,"0");return`${String(t.getFullYear()).padStart(4,"0")}-${pad(t.getMonth()+1)}-${pad(t.getDate())}`}export function toISOMonth(t){return`${String(t.getFullYear()).padStart(4,"0")}-${String(t.getMonth()+1).padStart(2,"0")}`}export function toISOYear(t){return String(t.getFullYear()).padStart(4,"0")}export function toISOTime(t,e=!1){const pad=t=>String(t).padStart(2,"0"),n=`${pad(t.getHours())}:${pad(t.getMinutes())}`;return e?`${n}:${pad(t.getSeconds())}`:n}export function toISODateTime(t,e=!1){return`${toISODate(t)}T${toISOTime(t,e)}`}const n=/* @__PURE__ */makeDate(2021,7,1);export function weekdayLabels(e,r,o="short"){const a=t(e,{weekday:o});return Array.from({length:7},(t,e)=>a.format(addDays(n,(r+e)%7)))}export function monthLabels(e,n="short"){const r=t(e,{month:n});return Array.from({length:12},(t,e)=>r.format(makeDate(2021,e,1)))}export function isMonthBeforeYear(e){const r=t(e,{year:"numeric",month:"long"}).formatToParts(n);return r.findIndex(t=>"month"===t.type)<r.findIndex(t=>"year"===t.type)}export function isHour12(e){const n=t(e,{hour:"numeric"}).resolvedOptions();return n.hourCycle?"h11"===n.hourCycle||"h12"===n.hourCycle:!0===n.hour12}export function meridiemLabels(e){const r=t(e,{hour:"numeric",hour12:!0}),read=t=>{const e=r.formatToParts(withTime(n,{hours:t})).find(t=>"dayPeriod"===t.type);return e?.value??(t<12?"AM":"PM")};return[read(9),read(21)]}export function localeWeekStart(t){try{const e=t??(new Intl.DateTimeFormat).resolvedOptions().locale,n=new Intl.Locale(e),r="function"==typeof n.getWeekInfo?n.getWeekInfo():n.weekInfo;if("number"==typeof r?.firstDay)return r.firstDay%7}catch{}return 0}
1
+ import{dateFormatter as t}from"./format.js";export const YEAR_PAGE_SIZE=12;export function makeDate(t,e,n){const r=new Date(0);return r.setFullYear(t,e,n),r.setHours(0,0,0,0),r}export function isValidDate(t){return t instanceof Date&&!Number.isNaN(t.getTime())}export function startOfDay(t){const e=new Date(t.getTime());return e.setHours(0,0,0,0),e}export function startOfMonth(t){return makeDate(t.getFullYear(),t.getMonth(),1)}export function startOfYear(t){return makeDate(t.getFullYear(),0,1)}export function daysInMonth(t,e){return makeDate(t,e+1,0).getDate()}export function today(){return startOfDay(new Date)}const e={year:"numeric",month:"numeric",day:"numeric"};export function todayIn(n){if(void 0===n)return today();const r=t("en-US",{...e,timeZone:n}).formatToParts(new Date),part=t=>Number(r.find(e=>e.type===t)?.value);return makeDate(part("year"),part("month")-1,part("day"))}export function addDays(t,e){const n=new Date(t.getTime());return n.setDate(n.getDate()+e),n}export function addMonths(t,e){const n=new Date(t.getTime()),r=makeDate(t.getFullYear(),t.getMonth()+e,1);return n.setFullYear(r.getFullYear(),r.getMonth(),Math.min(t.getDate(),daysInMonth(r.getFullYear(),r.getMonth()))),n}export function addYears(t,e){return addMonths(t,12*e)}export function compareDay(t,e){return startOfDay(t).getTime()-startOfDay(e).getTime()}export function isSameDay(t,e){return isValidDate(t)&&isValidDate(e)&&0===compareDay(t,e)}export function isSameMonth(t,e){return isValidDate(t)&&isValidDate(e)&&t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()}export function clampDate(t,e,n){return isValidDate(e)&&t.getTime()<e.getTime()?new Date(e.getTime()):isValidDate(n)&&t.getTime()>n.getTime()?new Date(n.getTime()):t}export function isDayOutside(t,e,n){return!!(isValidDate(e)&&compareDay(t,e)<0)||isValidDate(n)&&compareDay(t,n)>0}export function isMonthOutside(t,e,n){const r=t.getFullYear(),o=t.getMonth();return isDayOutside(makeDate(r,o,daysInMonth(r,o)),e,null)||isDayOutside(makeDate(r,o,1),null,n)}export function isYearOutside(t,e,n){const r=t.getFullYear();return isValidDate(e)&&r<e.getFullYear()||isValidDate(n)&&r>n.getFullYear()}export function secondsOfDay(t){return 3600*t.getHours()+60*t.getMinutes()+t.getSeconds()}export function timeUnitSpan(t,e){const n=secondsOfDay(e);if("hour"===t){const t=3600*Math.floor(n/3600);return[t,t+3599]}if("minute"===t){const t=60*Math.floor(n/60);return[t,t+59]}if("second"===t)return[n,n];const r=e.getHours()<12?0:43200;return[r,r+43200-1]}export function withTime(t,e){const n=new Date(t.getTime());return n.setHours(e.hours??n.getHours(),e.minutes??n.getMinutes(),e.seconds??n.getSeconds(),0),n}export function clampMoment(t,e,n,r){const o=r?1e3:6e4,floor=t=>withTime(t,{seconds:r?t.getSeconds():0});if(isValidDate(e)&&t.getTime()<e.getTime()){const t=floor(e),r=t.getTime()<e.getTime()?new Date(t.getTime()+o):t;return isValidDate(n)&&r.getTime()>n.getTime()?new Date(e.getTime()):r}if(isValidDate(n)&&t.getTime()>n.getTime()){const t=floor(n);return isValidDate(e)&&t.getTime()<e.getTime()?new Date(n.getTime()):t}return t}export function mergeDateAndTime(t,e){return withTime(startOfDay(t),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()})}export function calendarWeeks(t,e){const n=startOfMonth(t),r=(n.getDay()-e+7)%7,o=addDays(n,-r);return Array.from({length:6},(t,e)=>Array.from({length:7},(t,n)=>addDays(o,7*e+n)))}export function yearPageStart(t){return t-(t%12+12)%12}export function formatDate(e,n,r){return isValidDate(e)?t(n,r).format(e):""}const n=/* @__PURE__ */[...Array.from({length:24},(t,e)=>new Date(2027,e%12,21+e%7,e,58,58)),new Date(2027,0,22,12,58,58)];export function displaySamples(e,r){const o=t(e,r);return[...new Set(n.map(t=>o.format(t)))]}export function withPlaceholder(t,e){return"string"==typeof e&&""!==e?[...t,e]:t}export function toISODate(t){const pad=t=>String(t).padStart(2,"0");return`${String(t.getFullYear()).padStart(4,"0")}-${pad(t.getMonth()+1)}-${pad(t.getDate())}`}export function toISOMonth(t){return`${String(t.getFullYear()).padStart(4,"0")}-${String(t.getMonth()+1).padStart(2,"0")}`}export function toISOYear(t){return String(t.getFullYear()).padStart(4,"0")}export function toISOTime(t,e=!1){const pad=t=>String(t).padStart(2,"0"),n=`${pad(t.getHours())}:${pad(t.getMinutes())}`;return e?`${n}:${pad(t.getSeconds())}`:n}export function toISODateTime(t,e=!1){return`${toISODate(t)}T${toISOTime(t,e)}`}function weekdayOrigin(){return makeDate(2021,7,1)}export function weekdayLabels(e,n,r="short"){const o=t(e,{weekday:r}),a=weekdayOrigin();return Array.from({length:7},(t,e)=>o.format(addDays(a,(n+e)%7)))}export function monthLabels(e,n="short"){const r=t(e,{month:n});return Array.from({length:12},(t,e)=>r.format(makeDate(2021,e,1)))}export function isMonthBeforeYear(e){const n=t(e,{year:"numeric",month:"long"}).formatToParts(weekdayOrigin());return n.findIndex(t=>"month"===t.type)<n.findIndex(t=>"year"===t.type)}export function isHour12(e){const n=t(e,{hour:"numeric"}).resolvedOptions();return n.hourCycle?"h11"===n.hourCycle||"h12"===n.hourCycle:!0===n.hour12}export function meridiemLabels(e){const n=t(e,{hour:"numeric",hour12:!0}),r=weekdayOrigin(),read=t=>{const e=n.formatToParts(withTime(r,{hours:t})).find(t=>"dayPeriod"===t.type);return e?.value??(t<12?"AM":"PM")};return[read(9),read(21)]}const r=new Map;export function localeWeekStart(t){let e=r.get(t);return void 0===e&&(e=function readWeekStart(t){try{const e=t??(new Intl.DateTimeFormat).resolvedOptions().locale,n=new Intl.Locale(e),r="function"==typeof n.getWeekInfo?n.getWeekInfo():n.weekInfo;if("number"==typeof r?.firstDay)return r.firstDay%7}catch{}return 0}(t),r.set(t,e)),e}
@@ -41,8 +41,8 @@ export interface PlassDefaults {
41
41
  /** How tightly they pack their content. */
42
42
  density?: PlassDensity;
43
43
  /**
44
- * Where a labelled control puts its label — above the box, or in the box's
45
- * top edge.
44
+ * Where a labelled control puts its label — above the box, in the box's top
45
+ * edge, or inside the box until it is focused or filled.
46
46
  *
47
47
  * Here for the same reason `density` is: a product whose forms notch their
48
48
  * labels notches all of them, and the decision is the application's rather
@@ -53,7 +53,14 @@ export interface PlassDefaults {
53
53
  * to cut, so its label stays above the row whatever this says.
54
54
  */
55
55
  labelPlacement?: PlassFieldLabelPlacement;
56
- /** The BCP 47 tag the date and time components format and read against. */
56
+ /**
57
+ * The BCP 47 tag the date and time components format and read against.
58
+ *
59
+ * Left out, it is the browser's own, which a server cannot ask for: a server
60
+ * render and its hydration write `en-US`, and the components switch once
61
+ * hydration is done. A server-rendered page that names it paints the reader's
62
+ * format from the start.
63
+ */
57
64
  locale?: string;
58
65
  /** Which day their weeks start on, as `Date` counts them — Sunday is `0`. */
59
66
  weekStartsOn?: PlassWeekday;
@@ -85,3 +92,29 @@ export declare const DefaultsContext: React.Context<PlassDefaults>;
85
92
  * compact application.
86
93
  */
87
94
  export declare function useDefaults(): PlassDefaults;
95
+ /** What a server render and its hydration format in when nobody named a locale. */
96
+ declare const hydrationLocale = "en-US";
97
+ /**
98
+ * The locale to format in, given the one a component was told.
99
+ *
100
+ * `given` comes back as it is. Left out, it is `undefined` — the runtime's own
101
+ * locale — except in a server render and its hydration, where it is `en-US`.
102
+ * For the few components that do not read the provider's locale; the rest call
103
+ * {@link useLocale}.
104
+ */
105
+ export declare function useRuntimeLocale<T extends Intl.LocalesArgument>(given: T): T | typeof hydrationLocale;
106
+ /**
107
+ * The locale a component formats in: its own `locale` prop, then the nearest
108
+ * provider's, then the runtime's, which a server render and its hydration pin
109
+ * to `en-US`. See {@link useRuntimeLocale}.
110
+ */
111
+ export declare function useLocale<T extends Intl.LocalesArgument = string | undefined>(own?: T): T | string | undefined;
112
+ /** What a server render and its hydration read the clock in. */
113
+ declare const hydrationTimeZone = "UTC";
114
+ /**
115
+ * The zone to read the clock in: `undefined` — the runtime's own — except in a
116
+ * server render and its hydration, where it is `UTC`. `todayIn` in
117
+ * `internal/date.ts` turns it into a day.
118
+ */
119
+ export declare function useRuntimeTimeZone(): typeof hydrationTimeZone | undefined;
120
+ export {};
@@ -1 +1 @@
1
- "use client";import*as t from"react";const e=/* @__PURE__ */Object.freeze({});export const DefaultsContext=/* @__PURE__ */t.createContext(e);export function useDefaults(){return t.useContext(DefaultsContext)}
1
+ "use client";import*as e from"react";const n=/* @__PURE__ */Object.freeze({});export const DefaultsContext=/* @__PURE__ */e.createContext(n);export function useDefaults(){return e.useContext(DefaultsContext)}function subscribeToNothing(){return unsubscribeFromNothing}function unsubscribeFromNothing(){}export function useRuntimeLocale(n){return e.useSyncExternalStore(subscribeToNothing,()=>n,()=>n??"en-US")}export function useLocale(n){const t=e.useContext(DefaultsContext).locale;return useRuntimeLocale(n??t)}function runtimeTimeZone(){}function pinnedTimeZone(){return"UTC"}export function useRuntimeTimeZone(){return e.useSyncExternalStore(subscribeToNothing,runtimeTimeZone,pinnedTimeZone)}
@@ -1,4 +1,10 @@
1
1
  /** The two directions a document can run in. */
2
2
  export type PlassDirection = 'ltr' | 'rtl';
3
- /** Which way the document runs, re-rendering when it turns over. */
4
- export declare function useDocumentDirection(): PlassDirection;
3
+ /**
4
+ * Which way the document runs, re-rendering when it turns over.
5
+ *
6
+ * `active: false` answers `ltr` without reading the document or listening to
7
+ * it, for a component that needs the direction only in one of its states and
8
+ * should cost nothing in the others.
9
+ */
10
+ export declare function useDocumentDirection(active?: boolean): PlassDirection;
@@ -1 +1 @@
1
- "use client";import*as e from"react";function read(){return"undefined"==typeof document?"ltr":"rtl"===getComputedStyle(document.documentElement).direction?"rtl":"ltr"}let t=null,n=null;const r=new Set;function snapshot(){return null===t&&(t=read()),t}function onServer(){return"ltr"}function subscribe(e){return r.add(e),n||"undefined"==typeof document||(n=new MutationObserver(()=>{const e=read();e!==t&&(t=e,r.forEach(e=>e()))}),n.observe(document.documentElement,{attributes:!0,attributeFilter:["dir","class","style"]})),()=>{r.delete(e),0===r.size&&(n?.disconnect(),n=null,t=null)}}export function useDocumentDirection(){return e.useSyncExternalStore(subscribe,snapshot,onServer)}
1
+ "use client";import*as e from"react";function read(){return"undefined"==typeof document?"ltr":"rtl"===getComputedStyle(document.documentElement).direction?"rtl":"ltr"}let t=null,n=null;const r=new Set;function snapshot(){return null===t&&(t=read()),t}function onServer(){return"ltr"}function subscribe(e){return r.add(e),n||"undefined"==typeof document||(n=new MutationObserver(()=>{const e=read();e!==t&&(t=e,r.forEach(e=>e()))}),n.observe(document.documentElement,{attributes:!0,attributeFilter:["dir","class","style"]})),()=>{r.delete(e),0===r.size&&(n?.disconnect(),n=null,t=null)}}function idle(){return()=>{}}export function useDocumentDirection(t=!0){return e.useSyncExternalStore(t?subscribe:idle,t?snapshot:onServer,onServer)}
@@ -6,3 +6,13 @@
6
6
  * it to the top of the document.
7
7
  */
8
8
  export declare function focusablesIn(root: ParentNode): HTMLElement[];
9
+ /**
10
+ * Whether a press on `target`, inside a field's `shell`, is one the browser
11
+ * should be left to answer: a press on the field's own `control`, where it
12
+ * places the caret or starts a selection, or on something in the shell that
13
+ * takes a press of its own, a button or a link in an adornment.
14
+ *
15
+ * Anything else in the shell, its padding or a drawn adornment, is part of the
16
+ * field, and a press there keeps the focus in the control.
17
+ */
18
+ export declare function ownsPress(target: EventTarget | null, shell: Element, control: Element | null): boolean;
@@ -1 +1 @@
1
- export function focusablesIn(e){return Array.from(e.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter(e=>!e.closest("[inert]"))}
1
+ export function focusablesIn(t){return Array.from(t.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter(t=>!t.closest("[inert]"))}export function ownsPress(t,e,n){if(!(t instanceof Element))return!0;if(null!==n&&n.contains(t))return!0;const o=t.closest('a[href], button, input, select, textarea, [tabindex], [role="button"]');return null!==o&&o!==e&&e.contains(o)}
@@ -24,6 +24,78 @@ export declare const FormReportContext: React.Context<FormReport | null>;
24
24
  * for as long as `enabled` holds. Outside a `PlForm` it does nothing.
25
25
  */
26
26
  export declare function useFormReport(name: string | undefined, read: () => unknown, enabled?: boolean): void;
27
+ /**
28
+ * Whether a `PlFieldset` around the caller is disabled, the nearest one or any
29
+ * further out.
30
+ *
31
+ * Base UI hands a disabled fieldset to every `Field` inside it through a
32
+ * context of its own, and the browser disables a native control inside a
33
+ * `<fieldset disabled>`. Neither reaches the look, which a shell draws from its
34
+ * own `disabled`, nor a control that is neither in a `Field` nor native, such
35
+ * as a slider's track or a segmented button's segments. `PlFieldset` hands the
36
+ * answer Base UI gives its fields down through this as well, and a control
37
+ * counts it in wherever it reads its own `disabled`.
38
+ */
39
+ export declare const FieldsetDisabledContext: React.Context<boolean>;
40
+ /**
41
+ * Whether a surface around the caller is already drawn at a disabled control's
42
+ * fade, the half opacity and the drained colour of `disabledClasses`.
43
+ *
44
+ * A control disabled together with that surface draws the look of a disabled
45
+ * control without the fade, which would draw it at a quarter. A disabled
46
+ * `multiple` `PlCombobox` hands it to its chips, and a `PlChip` disabled
47
+ * anywhere else still fades on its own. The Flutter build hands the same answer
48
+ * down through `PlassFadedScope`.
49
+ */
50
+ export declare const FadedContext: React.Context<boolean>;
51
+ /**
52
+ * A control's `disabled`, with a disabled `PlFieldset` around it counted in, so
53
+ * a control in one draws itself exactly as it would with `disabled` of its own.
54
+ */
55
+ export declare function useDisabled(disabled: boolean | undefined): boolean;
56
+ /** The two attributes a caller names a control with. */
57
+ export interface ControlNaming {
58
+ 'aria-label'?: string;
59
+ 'aria-labelledby'?: string;
60
+ }
61
+ /**
62
+ * A caller's `aria-label` and `aria-labelledby`, for the control a field's
63
+ * other props are carried past.
64
+ *
65
+ * A labelled field spreads what it does not know onto the stack around it, and
66
+ * a `<div>` with no role is named by neither: a select in a toolbar, with no
67
+ * room for a `label`, had no way to name its trigger.
68
+ *
69
+ * Base UI merges a caller's props over its own, and its own `aria-labelledby`
70
+ * points at the visible label, which would outrank an `aria-label`. So an
71
+ * `aria-label` given without an `aria-labelledby` comes with that key holding
72
+ * `undefined`, which takes Base UI's away and leaves the `aria-label` as the
73
+ * name in the label's place, as an `aria-label` outranks a `<label>` on a
74
+ * native control. A caller's `aria-labelledby` outranks both. With neither,
75
+ * neither key is there, and the label goes on naming the control.
76
+ *
77
+ * A meter and the three progress indicators take them on their root for the
78
+ * same reason: Base UI's `Meter.Root` and `Progress.Root` point their own
79
+ * `aria-labelledby` at the visible label.
80
+ */
81
+ export declare function controlNaming(label: string | undefined, labelledBy: string | undefined): ControlNaming;
82
+ /**
83
+ * The `aria-labelledby` that names a control by a caller's `aria-label`, and
84
+ * the hidden words it points at, for a Base UI part `controlNaming` cannot
85
+ * reach.
86
+ *
87
+ * A checkbox, a switch, a radio, and the group around a slider's thumbs or a
88
+ * code's slots read `aria-labelledby` themselves and fall back to the visible
89
+ * label for anything but a reference of the caller's, `undefined` included. So
90
+ * an `aria-label` given without an `aria-labelledby` is written into a hidden
91
+ * node as well, and the part is pointed at that, which leaves the `aria-label`
92
+ * as the name in the label's place. A caller's `aria-labelledby` comes back as
93
+ * it was, and with neither there is no reference and no node.
94
+ */
95
+ export declare function useLabelReference(label: string | undefined, labelledBy: string | undefined): {
96
+ labelledBy: string | undefined;
97
+ node: React.ReactNode;
98
+ };
27
99
  /**
28
100
  * Whether `element` is inside a disabled `<fieldset>`, re-rendering when a
29
101
  * fieldset around it turns `disabled` on or off.
@@ -1 +1 @@
1
- import{jsx as e,Fragment as t,jsxs as r}from"react/jsx-runtime";import*as n from"react";import{Field as o}from"@base-ui/react/field";export const FormReportContext=/* @__PURE__ */n.createContext(null);export function useFormReport(e,t,r=!0){const o=n.useContext(FormReportContext),s=n.useRef(t);n.useEffect(()=>{s.current=t}),n.useEffect(()=>{if(!o||!e||!r)return;const entry=()=>s.current();return o.set(e,entry),()=>{o.get(e)===entry&&o.delete(e)}},[o,e,r])}function fieldsetsAround(e){const t=[];for(let r=e.parentElement?.closest("fieldset");r;r=r.parentElement?.closest("fieldset"))t.push(r);return t}export function useFieldsetDisabled(e){const t=n.useCallback(t=>{if(!e)return()=>{};const r=new MutationObserver(t);return fieldsetsAround(e).forEach(e=>r.observe(e,{attributes:!0,attributeFilter:["disabled"]})),()=>r.disconnect()},[e]);return n.useSyncExternalStore(t,()=>null!==e&&fieldsetsAround(e).some(t=>t.disabled&&!t.querySelector(":scope > legend")?.contains(e)),()=>!1)}export function leaveFormControl(e){e?.dispatchEvent(new FocusEvent("focusout",{bubbles:!0}))}export const FormControl=/* @__PURE__ */n.forwardRef(function FormControl({name:n,value:s,required:u,disabled:i,standIn:a},l){const c=Array.isArray(s),d=c?s.length>0&&s.every(e=>""!==e):""!==s;return useFormReport(n,()=>[...s],c&&!i),r(t,{children:[e(o.Control,{ref:l,name:n,value:c?d?s.join("\n"):"":s,required:u,disabled:i,tabIndex:-1,"aria-hidden":"true",autoComplete:"off",className:"pointer-events-none absolute size-px overflow-hidden opacity-0 [clip-path:inset(50%)]",onFocus:()=>a()?.focus(),render:c?t=>e("input",{...t,name:void 0}):void 0}),c&&n?s.map((t,r)=>e("input",{type:"hidden",name:n,value:t,disabled:i},r)):null]})});
1
+ import{jsx as e,Fragment as t,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{Field as r}from"@base-ui/react/field";export const FormReportContext=/* @__PURE__ */o.createContext(null);export function useFormReport(e,t,n=!0){const r=o.useContext(FormReportContext),s=o.useRef(t);o.useEffect(()=>{s.current=t}),o.useEffect(()=>{if(!r||!e||!n)return;const entry=()=>s.current();return r.set(e,entry),()=>{r.get(e)===entry&&r.delete(e)}},[r,e,n])}export const FieldsetDisabledContext=/* @__PURE__ */o.createContext(!1);export const FadedContext=/* @__PURE__ */o.createContext(!1);export function useDisabled(e){return o.useContext(FieldsetDisabledContext)||!0===e}export function controlNaming(e,t){return{...void 0===e?null:{"aria-label":e},...void 0!==t||e?{"aria-labelledby":t}:null}}export function useLabelReference(t,n){const r=o.useId();return void 0===n&&t?{labelledBy:r,node:e("span",{id:r,hidden:!0,children:t})}:{labelledBy:n,node:null}}function fieldsetsAround(e){const t=[];for(let n=e.parentElement?.closest("fieldset");n;n=n.parentElement?.closest("fieldset"))t.push(n);return t}export function useFieldsetDisabled(e){const t=o.useCallback(t=>{if(!e)return()=>{};const n=new MutationObserver(t);return fieldsetsAround(e).forEach(e=>n.observe(e,{attributes:!0,attributeFilter:["disabled"]})),()=>n.disconnect()},[e]);return o.useSyncExternalStore(t,()=>null!==e&&fieldsetsAround(e).some(t=>t.disabled&&!t.querySelector(":scope > legend")?.contains(e)),()=>!1)}export function leaveFormControl(e){e?.dispatchEvent(new FocusEvent("focusout",{bubbles:!0}))}export const FormControl=/* @__PURE__ */o.forwardRef(function FormControl({name:o,value:s,required:l,disabled:i,standIn:a},u){const d=Array.isArray(s),c=d?s.length>0&&s.every(e=>""!==e):""!==s;return useFormReport(o,()=>[...s],d&&!i),n(t,{children:[e(r.Control,{ref:u,name:o,value:d?c?s.join("\n"):"":s,required:l,disabled:i,tabIndex:-1,"aria-hidden":"true",autoComplete:"off",className:"pointer-events-none absolute size-px overflow-hidden opacity-0 [clip-path:inset(50%)]",onFocus:()=>a()?.focus(),render:d?t=>e("input",{...t,name:void 0}):void 0}),d&&o?s.map((t,n)=>e("input",{type:"hidden",name:o,value:t,disabled:i},n)):null]})});
@@ -20,7 +20,10 @@
20
20
  * object on every render, which is the ordinary way that prop gets written, and
21
21
  * keying on identity would miss every time and cache nothing but garbage.
22
22
  */
23
- /** A memoised `Intl.DateTimeFormat`. */
23
+ /**
24
+ * A memoised `Intl.DateTimeFormat`, built again when the runtime's time zone
25
+ * has changed since it was.
26
+ */
24
27
  export declare function dateFormatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat;
25
28
  /** A memoised `Intl.NumberFormat`. */
26
29
  export declare function numberFormatter(locale: string | undefined, options?: Intl.NumberFormatOptions): Intl.NumberFormat;
@@ -1 +1 @@
1
- function cacheKey(t,e){return`${t??""}\0${e?JSON.stringify(e):""}`}const t=new Map;export function dateFormatter(e,n){const r=cacheKey(e,n);let c=t.get(r);return c||(c=new Intl.DateTimeFormat(e,n),t.set(r,c)),c}const e=new Map;export function numberFormatter(t,n){const r=cacheKey(t,n);let c=e.get(r);return c||(c=new Intl.NumberFormat(t,n),e.set(r,c)),c}
1
+ function cacheKey(e,t){return`${e??""}\0${t?JSON.stringify(t):""}`}const e=new Map,t=/* @__PURE__ */new Date(16094592e5),n=/* @__PURE__ */new Date(16250976e5);let r=Number.NaN,o=Number.NaN;export function dateFormatter(a,c){(function zoneHasMoved(){const e=t.getTimezoneOffset(),a=n.getTimezoneOffset();return(e!==r||a!==o)&&(r=e,o=a,!0)})()&&e.clear();const u=cacheKey(a,c);let m=e.get(u);return m||(m=new Intl.DateTimeFormat(a,c),e.set(u,m)),m}const a=new Map;export function numberFormatter(e,t){const n=cacheKey(e,t);let r=a.get(n);return r||(r=new Intl.NumberFormat(e,t),a.set(n,r)),r}
@@ -1,3 +1,4 @@
1
+ import type { PlassResponsive } from '../types.js';
1
2
  /**
2
3
  * A tile's proportion as the number the layouts do arithmetic on.
3
4
  *
@@ -78,3 +79,30 @@ export declare function masonryRows(ratios: readonly number[], columns: number,
78
79
  tracks: PlassMasonryTrack[];
79
80
  tiles: PlassMasonryTile[];
80
81
  };
82
+ /**
83
+ * A column count as a gallery uses it: a whole number of lanes, and at least
84
+ * one. The column slot and the masonry deal both read it through here, so the
85
+ * columns the stylesheet draws are the columns the tiles were dealt into.
86
+ */
87
+ export declare function laneCount(value: number): number;
88
+ /**
89
+ * A masonry dealt at every rung of the breakpoint ladder, as the slots the
90
+ * stylesheet switches between.
91
+ *
92
+ * Which lane a tile lands in depends on the heights of the tiles before it, so
93
+ * a stylesheet cannot work it out — but it can choose between answers worked
94
+ * out ahead of time. The deal is made once per lane count the columns name,
95
+ * and the rung it starts at is written as slots: the list's rows as
96
+ * `--p-lane-rows-{rung}`, and each tile's place and the number of rows it spans
97
+ * as `--p-lane-area-{rung}` and `--p-lane-span-{rung}`. A rung that changes
98
+ * nothing is left out, and the stylesheet carries the rung below up through it,
99
+ * so a server's markup is laid out right at every width before any script has
100
+ * run, and a resize redraws without React hearing about it.
101
+ *
102
+ * `track` writes one row track as CSS, because the gap and the caption rows
103
+ * are lengths only the gallery knows.
104
+ */
105
+ export declare function masonrySlots(ratios: readonly number[], columns: PlassResponsive<number>, captions: boolean, track: (track: PlassMasonryTrack) => string): {
106
+ list: Record<string, string>;
107
+ tiles: Array<Record<string, string>>;
108
+ };