plass-ui 1.4.0 → 1.6.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 (268) hide show
  1. package/CHANGELOG.md +432 -0
  2. package/README.md +45 -23
  3. package/dist/components/accordion/PlAccordion.d.ts +1 -1
  4. package/dist/components/alert/PlAlert.js +1 -1
  5. package/dist/components/anchor/PlAnchor.d.ts +14 -1
  6. package/dist/components/anchor/PlAnchor.js +1 -1
  7. package/dist/components/animate-appear/PlAnimateAppear.js +1 -1
  8. package/dist/components/animate-blink/PlAnimateBlink.js +1 -1
  9. package/dist/components/animate-counter/PlAnimateCounter.js +1 -1
  10. package/dist/components/animate-fade/PlAnimateFade.js +1 -1
  11. package/dist/components/animate-float/PlAnimateFloat.js +1 -1
  12. package/dist/components/animate-grow/PlAnimateGrow.js +1 -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 +16 -4
  16. package/dist/components/animate-marquee/PlAnimateMarquee.js +1 -1
  17. package/dist/components/animate-reveal/PlAnimateReveal.js +1 -1
  18. package/dist/components/animate-rotate/PlAnimateRotate.js +1 -1
  19. package/dist/components/animate-scramble/PlAnimateScramble.js +1 -1
  20. package/dist/components/animate-shake/PlAnimateShake.js +1 -1
  21. package/dist/components/animate-slide/PlAnimateSlide.js +1 -1
  22. package/dist/components/animate-split/PlAnimateSplit.d.ts +7 -4
  23. package/dist/components/animate-split/PlAnimateSplit.js +1 -1
  24. package/dist/components/animate-typing/PlAnimateTyping.d.ts +3 -2
  25. package/dist/components/animate-typing/PlAnimateTyping.js +1 -1
  26. package/dist/components/animate-zoom/PlAnimateZoom.js +1 -1
  27. package/dist/components/app-logo/PlAppLogo.js +1 -1
  28. package/dist/components/area-chart/PlAreaChart.d.ts +1 -1
  29. package/dist/components/area-chart/PlAreaChart.js +1 -1
  30. package/dist/components/aspect-ratio/PlAspectRatio.d.ts +2 -1
  31. package/dist/components/aspect-ratio/PlAspectRatio.js +1 -1
  32. package/dist/components/avatar/PlAvatar.js +1 -1
  33. package/dist/components/back-top/PlBackTop.d.ts +8 -1
  34. package/dist/components/back-top/PlBackTop.js +1 -1
  35. package/dist/components/badge/PlBadge.js +1 -1
  36. package/dist/components/bar-chart/PlBarChart.d.ts +1 -1
  37. package/dist/components/bar-chart/PlBarChart.js +1 -1
  38. package/dist/components/blockquote/PlBlockquote.js +1 -1
  39. package/dist/components/bottom-navigation/PlBottomNavigation.d.ts +3 -0
  40. package/dist/components/breadcrumb/PlBreadcrumb.js +1 -1
  41. package/dist/components/button/PlButton.d.ts +8 -0
  42. package/dist/components/button/PlButton.js +1 -1
  43. package/dist/components/calendar/PlCalendar.js +1 -1
  44. package/dist/components/card/PlCard.js +1 -1
  45. package/dist/components/carousel/PlCarousel.d.ts +1 -1
  46. package/dist/components/carousel/PlCarousel.js +1 -1
  47. package/dist/components/chat-bubble/PlChatBubble.d.ts +4 -1
  48. package/dist/components/chat-bubble/PlChatBubble.js +1 -1
  49. package/dist/components/checkbox/PlCheckbox.js +1 -1
  50. package/dist/components/chip/PlChip.d.ts +6 -2
  51. package/dist/components/chip/PlChip.js +1 -1
  52. package/dist/components/code-block/PlCodeBlock.d.ts +19 -2
  53. package/dist/components/code-block/PlCodeBlock.js +1 -1
  54. package/dist/components/color-picker/PlColorPicker.d.ts +19 -2
  55. package/dist/components/color-picker/PlColorPicker.js +1 -1
  56. package/dist/components/combobox/PlCombobox.d.ts +14 -7
  57. package/dist/components/combobox/PlCombobox.js +1 -1
  58. package/dist/components/command-palette/PlCommandPalette.d.ts +6 -2
  59. package/dist/components/command-palette/PlCommandPalette.js +1 -1
  60. package/dist/components/confirm/PlConfirmProvider.js +1 -1
  61. package/dist/components/container/PlContainer.js +1 -1
  62. package/dist/components/data-table/PlDataTable.d.ts +20 -6
  63. package/dist/components/data-table/PlDataTable.js +1 -1
  64. package/dist/components/date-picker/PlDatePicker.js +1 -1
  65. package/dist/components/date-range-picker/PlDateRangePicker.js +1 -1
  66. package/dist/components/date-time-picker/PlDateTimePicker.js +1 -1
  67. package/dist/components/drawer/PlDrawer.js +1 -1
  68. package/dist/components/empty/PlEmpty.js +1 -1
  69. package/dist/components/file-picker/PlFilePicker.d.ts +22 -3
  70. package/dist/components/file-picker/PlFilePicker.js +1 -1
  71. package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.d.ts +3 -0
  72. package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +1 -1
  73. package/dist/components/form/PlForm.js +1 -1
  74. package/dist/components/gallery/PlGallery.d.ts +40 -2
  75. package/dist/components/gallery/PlGallery.js +1 -1
  76. package/dist/components/gallery/PlGalleryViewer.js +1 -1
  77. package/dist/components/gauge-chart/PlGaugeChart.js +1 -1
  78. package/dist/components/heatmap-chart/PlHeatmapChart.js +1 -1
  79. package/dist/components/highlight/PlHighlight.d.ts +10 -3
  80. package/dist/components/highlight/PlHighlight.js +1 -1
  81. package/dist/components/hot-keys/PlHotKeys.js +1 -1
  82. package/dist/components/hover-card/PlHoverCard.d.ts +5 -3
  83. package/dist/components/hover-card/PlHoverCard.js +1 -1
  84. package/dist/components/how-to-steps/PlHowToSteps.js +1 -1
  85. package/dist/components/image/PlImage.d.ts +195 -8
  86. package/dist/components/image/PlImage.js +1 -1
  87. package/dist/components/image/PlImagePreview.d.ts +58 -0
  88. package/dist/components/image/PlImagePreview.js +1 -0
  89. package/dist/components/image/index.d.ts +1 -1
  90. package/dist/components/list/PlList.js +1 -1
  91. package/dist/components/menu/PlMenu.d.ts +14 -5
  92. package/dist/components/menu/PlMenu.js +1 -1
  93. package/dist/components/meter/PlMeter.js +1 -1
  94. package/dist/components/navigation-menu/PlNavigationMenu.d.ts +7 -1
  95. package/dist/components/navigation-menu/PlNavigationMenu.js +1 -1
  96. package/dist/components/number-field/PlNumberField.d.ts +12 -4
  97. package/dist/components/number-field/PlNumberField.js +1 -1
  98. package/dist/components/otp-field/PlOtpField.d.ts +15 -1
  99. package/dist/components/otp-field/PlOtpField.js +1 -1
  100. package/dist/components/page-layout/PlPageLayout.js +1 -1
  101. package/dist/components/pagination/PlPagination.d.ts +12 -9
  102. package/dist/components/pagination/PlPagination.js +1 -1
  103. package/dist/components/panes/PlPanes.d.ts +5 -0
  104. package/dist/components/panes/PlPanes.js +1 -1
  105. package/dist/components/pie-chart/PlPieChart.js +1 -1
  106. package/dist/components/pill/PlPill.js +1 -1
  107. package/dist/components/popover/PlPopover.d.ts +5 -5
  108. package/dist/components/popover/PlPopover.js +1 -1
  109. package/dist/components/progress-box/PlProgressBox.js +1 -1
  110. package/dist/components/progress-circular/PlProgressCircular.js +1 -1
  111. package/dist/components/progress-linear/PlProgressLinear.js +1 -1
  112. package/dist/components/radio-group/PlRadioGroup.js +1 -1
  113. package/dist/components/rating/PlRating.d.ts +1 -1
  114. package/dist/components/rating/PlRating.js +1 -1
  115. package/dist/components/scatter-chart/PlScatterChart.js +1 -1
  116. package/dist/components/scroll-area/PlScrollArea.js +1 -1
  117. package/dist/components/scroll-zone/PlScrollZone.d.ts +19 -6
  118. package/dist/components/scroll-zone/PlScrollZone.js +1 -1
  119. package/dist/components/segmented-button/PlSegmentedButton.js +1 -1
  120. package/dist/components/select/PlSelect.d.ts +8 -2
  121. package/dist/components/select/PlSelect.js +1 -1
  122. package/dist/components/show/PlShow.d.ts +16 -0
  123. package/dist/components/show/PlShow.js +1 -1
  124. package/dist/components/sidebar/PlSidebar.js +1 -1
  125. package/dist/components/sidebar/PlSidebarTrigger.js +1 -1
  126. package/dist/components/skeleton/PlSkeleton.js +1 -1
  127. package/dist/components/slider/PlSlider.d.ts +13 -1
  128. package/dist/components/slider/PlSlider.js +1 -1
  129. package/dist/components/sparkline/PlSparkline.js +1 -1
  130. package/dist/components/spoiler/PlSpoiler.d.ts +15 -8
  131. package/dist/components/spoiler/PlSpoiler.js +1 -1
  132. package/dist/components/stat/PlStat.d.ts +4 -0
  133. package/dist/components/stat/PlStat.js +1 -1
  134. package/dist/components/stepper/PlStepper.d.ts +1 -1
  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 +5 -5
  138. package/dist/components/tabs/PlTabs.d.ts +26 -1
  139. package/dist/components/tabs/PlTabs.js +1 -1
  140. package/dist/components/text-field/PlTextField.d.ts +15 -5
  141. package/dist/components/text-field/PlTextField.js +1 -1
  142. package/dist/components/text-link/PlTextLink.js +1 -1
  143. package/dist/components/time-picker/PlTimePicker.js +1 -1
  144. package/dist/components/timeline/PlTimeline.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.js +1 -1
  149. package/dist/components/tour/PlTour.js +1 -1
  150. package/dist/components/transfer/PlTransfer.d.ts +10 -1
  151. package/dist/components/transfer/PlTransfer.js +1 -1
  152. package/dist/components/tree/PlTree.js +1 -1
  153. package/dist/components/tree-select/PlTreeSelect.js +1 -1
  154. package/dist/components/typography/PlTypography.js +1 -1
  155. package/dist/components/window-pane/PlWindowPane.d.ts +3 -3
  156. package/dist/components/window-pane/PlWindowPane.js +1 -1
  157. package/dist/css/area-chart.css +1 -0
  158. package/dist/css/back-top.css +2 -0
  159. package/dist/css/bar-chart.css +1 -0
  160. package/dist/css/calendar.css +1 -0
  161. package/dist/css/carousel.css +2 -0
  162. package/dist/css/color-picker.css +1 -0
  163. package/dist/css/combobox.css +1 -0
  164. package/dist/css/command-palette.css +1 -0
  165. package/dist/css/confirm.css +2 -0
  166. package/dist/css/data-table.css +5 -0
  167. package/dist/css/date-picker.css +1 -0
  168. package/dist/css/date-range-picker.css +1 -0
  169. package/dist/css/date-time-picker.css +1 -0
  170. package/dist/css/floating-action-button.css +2 -0
  171. package/dist/css/gallery.css +5 -0
  172. package/dist/css/gauge-chart.css +1 -0
  173. package/dist/css/heatmap-chart.css +1 -0
  174. package/dist/css/icon-button.css +1 -0
  175. package/dist/css/image.css +2 -0
  176. package/dist/css/line-chart.css +1 -0
  177. package/dist/css/menubar.css +1 -0
  178. package/dist/css/pagination.css +1 -0
  179. package/dist/css/pie-chart.css +1 -0
  180. package/dist/css/popconfirm.css +2 -0
  181. package/dist/css/scatter-chart.css +1 -0
  182. package/dist/css/scroll-zone.css +2 -0
  183. package/dist/css/sidebar.css +3 -0
  184. package/dist/css/sparkline.css +1 -0
  185. package/dist/css/spoiler.css +1 -0
  186. package/dist/css/stat.css +1 -0
  187. package/dist/css/time-picker.css +1 -0
  188. package/dist/css/timeline-chart.css +1 -0
  189. package/dist/css/tour.css +1 -0
  190. package/dist/css/transfer.css +4 -0
  191. package/dist/css/tree-select.css +2 -0
  192. package/dist/hooks/usePlElementSize.d.ts +4 -1
  193. package/dist/hooks/usePlElementSize.js +1 -1
  194. package/dist/hooks/usePlHotKeys.d.ts +5 -1
  195. package/dist/hooks/usePlHotKeys.js +1 -1
  196. package/dist/hooks/usePlOnScreen.d.ts +4 -0
  197. package/dist/hooks/usePlOnScreen.js +1 -1
  198. package/dist/internal/animate.d.ts +24 -21
  199. package/dist/internal/animate.js +1 -1
  200. package/dist/internal/calendar.js +1 -1
  201. package/dist/internal/chart-frame.d.ts +3 -14
  202. package/dist/internal/chart-frame.js +1 -1
  203. package/dist/internal/chart-line.js +1 -1
  204. package/dist/internal/chart.d.ts +90 -3
  205. package/dist/internal/chart.js +1 -1
  206. package/dist/internal/color-scheme.js +1 -1
  207. package/dist/internal/data-table.d.ts +5 -4
  208. package/dist/internal/data-table.js +1 -1
  209. package/dist/internal/date.d.ts +10 -0
  210. package/dist/internal/date.js +1 -1
  211. package/dist/internal/defaults.d.ts +14 -1
  212. package/dist/internal/drag.d.ts +16 -0
  213. package/dist/internal/drag.js +1 -1
  214. package/dist/internal/focusable.d.ts +8 -0
  215. package/dist/internal/focusable.js +1 -0
  216. package/dist/internal/form.d.ts +61 -0
  217. package/dist/internal/form.js +1 -0
  218. package/dist/internal/gallery.d.ts +60 -14
  219. package/dist/internal/gallery.js +1 -1
  220. package/dist/internal/glow.d.ts +32 -0
  221. package/dist/internal/glow.js +1 -0
  222. package/dist/internal/highlight.js +1 -1
  223. package/dist/internal/image.d.ts +94 -0
  224. package/dist/internal/image.js +1 -0
  225. package/dist/internal/inert.d.ts +19 -0
  226. package/dist/internal/inert.js +1 -0
  227. package/dist/internal/keys.d.ts +19 -0
  228. package/dist/internal/keys.js +1 -1
  229. package/dist/internal/labels.d.ts +58 -1
  230. package/dist/internal/labels.js +1 -1
  231. package/dist/internal/link.d.ts +17 -0
  232. package/dist/internal/link.js +1 -1
  233. package/dist/internal/notch.d.ts +83 -0
  234. package/dist/internal/notch.js +1 -0
  235. package/dist/internal/page-layout.d.ts +14 -7
  236. package/dist/internal/page-layout.js +1 -1
  237. package/dist/internal/picker.d.ts +51 -8
  238. package/dist/internal/picker.js +1 -1
  239. package/dist/internal/progress.d.ts +16 -8
  240. package/dist/internal/progress.js +1 -1
  241. package/dist/internal/scramble.d.ts +4 -0
  242. package/dist/internal/scramble.js +1 -1
  243. package/dist/internal/scroll-target.d.ts +5 -0
  244. package/dist/internal/scroll-target.js +1 -0
  245. package/dist/internal/steps.js +1 -1
  246. package/dist/internal/styles.d.ts +87 -0
  247. package/dist/internal/styles.js +1 -1
  248. package/dist/internal/text.d.ts +39 -0
  249. package/dist/internal/text.js +1 -0
  250. package/dist/internal/watermark.d.ts +44 -0
  251. package/dist/internal/watermark.js +1 -0
  252. package/dist/internal/wheel.d.ts +52 -0
  253. package/dist/internal/wheel.js +1 -0
  254. package/dist/internal/window.js +1 -1
  255. package/dist/locales/de.js +1 -1
  256. package/dist/locales/es.js +1 -1
  257. package/dist/locales/fr.js +1 -1
  258. package/dist/locales/ja.js +1 -1
  259. package/dist/locales/ko.js +1 -1
  260. package/dist/locales/zh-Hans.js +1 -1
  261. package/dist/provider/PlColorSchemeScript.js +1 -1
  262. package/dist/provider/PlassProvider.d.ts +4 -3
  263. package/dist/provider/PlassProvider.js +1 -1
  264. package/dist/styles.css +1 -1
  265. package/dist/tailwind.css +313 -15
  266. package/dist/tokens.css +313 -15
  267. package/dist/types.d.ts +71 -29
  268. package/package.json +15 -15
package/README.md CHANGED
@@ -4,23 +4,27 @@
4
4
 
5
5
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/jooy2/plass-ui/blob/main/LICENSE) [![npm latest package](https://img.shields.io/npm/v/plass-ui/latest.svg)](https://www.npmjs.com/package/plass-ui) [![npm downloads](https://img.shields.io/npm/dm/plass-ui.svg)](https://www.npmjs.com/package/plass-ui)
6
6
 
7
- ### 📘 [**plass.cdget.com**](https://plass.cdget.com)
7
+ ### [**plass.cdget.com**](https://plass.cdget.com)
8
8
 
9
- Live previews and full props for every component pick **React** in the sidebar. This README is just the quick start.
9
+ Live previews and full props for every component. Pick **React** in the sidebar. This README is just the quick start.
10
+
11
+ ![Plass UI components arranged around the Plass mark: a search field, a settings card, radio buttons and checkboxes, buttons and chips, a segmented button and pagination, a success alert, a slider, a progress bar and a meter, an avatar stack, a badge and a rating](https://plass.cdget.com/showcase.png)
10
12
 
11
13
  ---
12
14
 
13
- > **Plass is one design language, shipped as two libraries.** Every surface answers a single question — is this pressed, or does it hold something? A thing you press is **tinted glass**: a gradient that _turns_ through its colour family rather than darkening, a shadow thrown in that same colour, and a bloom of light that follows your pointer across it. A thing that holds something is **clear glass**: translucent, deeply blurred, edged with a white hairline, never dyed. Nothing is bevelled, nothing is embossed and nothing moves when you press it — depth is carried by light, colour and blur.
15
+ > **Plass is one design language, shipped as two libraries.** 127 components made of tinted glass and gradients, in React and in Flutter, under the same names and the same numbers. React adds three more for problems only the DOM has.
16
+ >
17
+ > Every surface answers one question: is this pressed, or does it hold something? A thing you press is a tinted pane, filled with a gradient that turns through its colour family and lit by a bloom that follows your pointer. A thing that holds something is clear glass: translucent, deeply blurred, never dyed. Nothing is bevelled or embossed, and depth is carried by light, colour and blur.
14
18
 
15
- This is the React half. The [Flutter package](https://pub.dev/packages/plass_ui) is the other one, and the two hold the same components under the same names, the same prop vocabulary and the same numbers. They version independently, so this package's number and the pub.dev one's will not always agree.
19
+ This is the React half. The [Flutter package](https://pub.dev/packages/plass_ui) is the other one, and the two hold the same 127 components under the same names, the same prop vocabulary and the same numbers. They version independently, so this package's number and the pub.dev one's will not always agree.
16
20
 
17
21
  - **Finished the moment it is installed.** The gradients, the shadows, the blur, the focus ring and the press response are already decided and already agree with each other. One CSS import and the first screen looks like something.
18
- - **Five props, not fifty.** `size`, `color`, `variant`, `density` and `elevation` mean the same thing on every component an `md` control is 40px, `primary` is the same family so the tenth one costs nothing to learn after the first.
22
+ - **Five props, not fifty.** `size`, `color`, `variant`, `density` and `elevation` mean the same thing on every component (an `md` control is 40px, `primary` is the same family), so the tenth one costs nothing to learn after the first.
19
23
  - **Readable because it was measured.** Every gradient stop clears 4.5:1 against its own label, the lightest corner included. A colour choice here is not a contrast bug waiting for an audit.
20
24
  - **Accessible without the checklist.** Real roles, labels, focus management and keyboard support, not `div`s with click handlers.
21
25
  - **Dark mode you do not write.** Follows `prefers-color-scheme`, and can be forced either way on any subtree. No second palette, no colours redeclared.
22
26
  - **Types in the box.** TypeScript declarations ship with the package, so your editor knows the prop names and the values they take before you do.
23
- - **Nothing you did not ask for.** ESM only, tree-shakeable, a single runtime dependency, and an entry point per component for a build that cannot shake a barrel.
27
+ - **Nothing you did not ask for.** ESM only, tree-shakeable, two runtime dependencies (`@base-ui/react` and `highlight.js`), and an entry point per component for a build that cannot shake a barrel.
24
28
 
25
29
  ## Install
26
30
 
@@ -28,7 +32,7 @@ This is the React half. The [Flutter package](https://pub.dev/packages/plass_ui)
28
32
  npm install plass-ui
29
33
  ```
30
34
 
31
- `react` and `react-dom` are peer dependencies React 18 or 19. Node.js 20.19 or later.
35
+ `react` and `react-dom` are peer dependencies, React 18 or 19. Node.js 20.19 or later.
32
36
 
33
37
  ### Setup
34
38
 
@@ -38,7 +42,7 @@ Add one line to your app's CSS entry point:
38
42
  @import 'plass-ui/styles.css';
39
43
  ```
40
44
 
41
- `plass-ui/styles.css` is finished CSS the design tokens, the compiled rules for every utility class the components use, and a small reset whose every rule is specificity 0 so your own styles always win. [Tailwind CSS](https://tailwindcss.com) v4 builds this package; it does not have to be installed in yours.
45
+ `plass-ui/styles.css` is finished CSS, the design tokens, the compiled rules for every utility class the components use, and a small reset whose every rule is specificity 0 so your own styles always win. [Tailwind CSS](https://tailwindcss.com) v4 builds this package; it does not have to be installed in yours.
42
46
 
43
47
  If your project already runs Tailwind v4, import the token sheet instead:
44
48
 
@@ -47,7 +51,7 @@ If your project already runs Tailwind v4, import the token sheet instead:
47
51
  @import 'plass-ui/tailwind.css';
48
52
  ```
49
53
 
50
- `plass-ui/tailwind.css` registers all 74 components with Tailwind, because Tailwind scans files rather than imports nothing in a build connects `import { PlButton }` to the classes `PlSelect.js` spells out. A project that uses a handful of components can register the handful instead:
54
+ `plass-ui/tailwind.css` registers all 130 components with Tailwind, because Tailwind scans files rather than imports, nothing in a build connects `import { PlButton }` to the classes `PlSelect.js` spells out. A project that uses a handful of components can register the handful instead:
51
55
 
52
56
  ```css
53
57
  @import 'tailwindcss';
@@ -56,11 +60,11 @@ If your project already runs Tailwind v4, import the token sheet instead:
56
60
  @import 'plass-ui/css/text-field.css';
57
61
  ```
58
62
 
59
- Still one Tailwind pass, so the utilities keep Tailwind's own order and about 5 kB gzipped smaller for a small set of components. There is one manifest per component, named after its folder in `dist/components`.
63
+ Still one Tailwind pass, so the utilities keep Tailwind's own order, and about 5 kB gzipped smaller for a small set of components. There is one manifest per component, named after its folder in `dist/components`.
60
64
 
61
65
  ### The page under the components
62
66
 
63
- Plass draws controls and sheets. It does not paint your `<body>` but a sheet of glass over a flat white page has nothing to be in front of, and every translucent surface in the library will read as opaque. Two tokens exist for exactly this:
67
+ Plass draws controls and sheets. It does not paint your `<body>`, but a sheet of glass over a flat white page has nothing to be in front of, and every translucent surface in the library will read as opaque. Two tokens exist for exactly this:
64
68
 
65
69
  ```css
66
70
  body {
@@ -92,7 +96,7 @@ export default function SignIn() {
92
96
 
93
97
  ### One entry point per component
94
98
 
95
- Every component also has an entry point of its own, for a build that cannot tree-shake a barrel or for a server render, where the barrel loads all 74 components and their dependencies before the first one is used:
99
+ Every component also has an entry point of its own, for a build that cannot tree-shake a barrel, or for a server render, where the barrel loads all 130 components and their dependencies before the first one is used:
96
100
 
97
101
  ```tsx
98
102
  import { PlButton } from 'plass-ui/button';
@@ -102,47 +106,65 @@ Same component, same types. The barrel is the one to reach for by default; this
102
106
 
103
107
  ### Next.js and server components
104
108
 
105
- Nearly every component carries `'use client'`, so a Server Component can import one directly and there is nothing to configure no `transpilePackages`, no `next.config` entry, no provider. What the directive cannot do is carry a function across the server boundary: a file that passes `onClick`, `onValueChange` or `render` needs its own `'use client'`, which is React's rule for every client component rather than this library's. Outside a server-component graph the directive is inert.
109
+ Nearly every component carries `'use client'`, so a Server Component can import one directly and there is nothing to configure, no `transpilePackages`, no `next.config` entry, no provider. What the directive cannot do is carry a function across the server boundary: a file that passes `onClick`, `onValueChange` or `render` needs its own `'use client'`, which is React's rule for every client component rather than this library's. Outside a server-component graph the directive is inert.
106
110
 
107
111
  `PlTable` is the exception and has no directive, because that rule would otherwise have cost it its own API: every column is a `render` callback, and a table belongs on a page that fetches its own rows. A Server Component renders it whole; a client module that imports it gets a client component, as it does for anything else it imports.
108
112
 
109
113
  ### Dark mode
110
114
 
111
- Follows `prefers-color-scheme` with no configuration. To force it either way, put `.dark` / `.light` or `[data-theme='dark']` / `[data-theme='light']` on any ancestor, `<html>` included.
115
+ Follows `prefers-color-scheme` with no configuration. To force it either way, put `.dark` / `.light` (or `[data-theme='dark']` / `[data-theme='light']`) on any ancestor, `<html>` included.
112
116
 
113
117
  One thing does **not** change with the theme, and it is deliberate: the colour of a key. What changes is the sheet it rests on.
114
118
 
115
119
  ## Components
116
120
 
117
- Every component is exported under a `Pl` prefix `Button`, `Card` and `Table` are the most-taken identifiers in the ecosystem, and a consumer should not have to alias ours on import.
121
+ Every component is exported under a `Pl` prefix. `Button`, `Card` and `Table` are the most-taken identifiers in the ecosystem, and a consumer should not have to alias ours on import.
122
+
123
+ 130 of them. The [Flutter package](https://pub.dev/packages/plass_ui) holds 127 of these under the same names: `PlFlex`, `PlPortal` and `PlVisuallyHidden` answer problems only the DOM has, and `PlContextMenu` is a second trigger onto `PlMenu`'s surface. Every component has a page of its own with live previews and the full props table.
124
+
125
+ ### Charts
126
+
127
+ `PlAreaChart` · `PlBarChart` · `PlGaugeChart` · `PlHeatmapChart` · `PlLineChart` · `PlPieChart` · `PlScatterChart` · `PlSparkline` · `PlTimelineChart`
118
128
 
119
129
  ### Display
120
130
 
121
- `PlAvatar` · `PlBadge` · `PlBlockquote` · `PlBreadcrumb` · `PlChip` · `PlDivider` · `PlHighlight` · `PlHotKeys` · `PlIcon` · `PlList` · `PlTable` · `PlTextLink` · `PlTimeline` · `PlTypography`
131
+ `PlAppLogo` · `PlAvatar` · `PlBadge` · `PlBlockquote` · `PlBreadcrumb` · `PlChip` · `PlCodeBlock` · `PlDataList` · `PlDataTable` · `PlDivider` · `PlGallery` · `PlHighlight` · `PlHotKeys` · `PlIcon` · `PlImage` · `PlList` · `PlMockup` · `PlStat` · `PlTable` · `PlTextLink` · `PlTimeline` · `PlTree` · `PlTypography` · `PlVisuallyHidden`
122
132
 
123
133
  ### Feedback
124
134
 
125
- `PlAlert` · `PlDrawer` · `PlModal` · `PlOverlay` · `PlPopover` · `PlProgressBox` · `PlProgressCircular` · `PlProgressLinear` · `PlSkeleton` · `PlToast` · `PlTooltip`
135
+ `PlAlert` · `PlConfirmProvider` · `PlDrawer` · `PlEmpty` · `PlMeter` · `PlModal` · `PlOverlay` · `PlPopconfirm` · `PlPopover` · `PlProgressBox` · `PlProgressCircular` · `PlProgressLinear` · `PlSkeleton` · `PlToast` · `PlTooltip` · `PlTour`
126
136
 
127
137
  ### Inputs
128
138
 
129
- `PlButton` · `PlButtonGroup` · `PlCheckbox` · `PlCombobox` · `PlDatePicker` · `PlDateRangePicker` · `PlDateTimePicker` · `PlFilePicker` · `PlIconButton` · `PlNumberField` · `PlOtpField` · `PlPagination` · `PlRadioGroup` · `PlRating` · `PlSegmentedButton` · `PlSelect` · `PlSlider` · `PlSwitch` · `PlTextField` · `PlTimePicker`
139
+ `PlButton` · `PlButtonGroup` · `PlCalendar` · `PlCheckbox` · `PlColorPicker` · `PlCombobox` · `PlDatePicker` · `PlDateRangePicker` · `PlDateTimePicker` · `PlFieldset` · `PlFilePicker` · `PlFloatingActionButton` · `PlForm` · `PlIconButton` · `PlNumberField` · `PlOtpField` · `PlPagination` · `PlRadioGroup` · `PlRating` · `PlSegmentedButton` · `PlSelect` · `PlSlider` · `PlSwitch` · `PlTextField` · `PlTimePicker` · `PlToggle` · `PlToggleGroup` · `PlTransfer` · `PlTreeSelect`
130
140
 
131
141
  ### Layout
132
142
 
133
- `PlAspectRatio` · `PlContainer` · `PlGrid` · `PlPanes` · `PlScrollZone`
143
+ `PlAspectRatio` · `PlContainer` · `PlFlex` · `PlFooter` · `PlGrid` · `PlHeader` · `PlPageLayout` · `PlPanes` · `PlPortal` · `PlScrollArea` · `PlScrollZone` · `PlShow` · `PlSidebar` · `PlStack`
134
144
 
135
145
  ### Navigation
136
146
 
137
- `PlBottomNavigation` · `PlContextMenu` · `PlFloatingBottomNavigation` · `PlMenu`
147
+ `PlAnchor` · `PlBackTop` · `PlBottomNavigation` · `PlCommandPalette` · `PlContextMenu` · `PlFloatingBottomNavigation` · `PlMenu` · `PlMenubar` · `PlNavigationMenu` · `PlStepper`
138
148
 
139
149
  ### Surfaces
140
150
 
141
- `PlAccordion` · `PlBox` · `PlCard` · `PlCarousel` · `PlChatBubble` · `PlCollapsible` · `PlPill` · `PlSpoiler` · `PlTabs` · `PlToolbar`
151
+ `PlAccordion` · `PlBox` · `PlCard` · `PlCarousel` · `PlChatBubble` · `PlCollapsible` · `PlHoverCard` · `PlHowToSteps` · `PlPill` · `PlSpoiler` · `PlTabs` · `PlToolbar` · `PlWindowPane`
142
152
 
143
153
  ### Transitions
144
154
 
145
- `PlAnimateAppear` · `PlAnimateBlink` · `PlAnimateFade` · `PlAnimateGrow` · `PlAnimateHeadline` · `PlAnimateLighting` · `PlAnimateMarquee` · `PlAnimateRotate` · `PlAnimateSlide` · `PlAnimateTyping` · `PlAnimateZoom`
155
+ `PlAnimateAppear` · `PlAnimateBlink` · `PlAnimateCounter` · `PlAnimateFade` · `PlAnimateFloat` · `PlAnimateGrow` · `PlAnimateHeadline` · `PlAnimateLighting` · `PlAnimateMarquee` · `PlAnimateReveal` · `PlAnimateRotate` · `PlAnimateScramble` · `PlAnimateShake` · `PlAnimateSlide` · `PlAnimateSplit` · `PlAnimateTyping` · `PlAnimateZoom`
156
+
157
+ ### Hooks
158
+
159
+ React-only, and the machinery the library already ran on rather than anything new. Import them from the barrel or from `plass-ui/hooks`.
160
+
161
+ `usePlBreakpoint` · `usePlBreakpointValue` · `usePlColorScheme` · `usePlDisclosure` · `usePlElementSize` · `usePlHotKeys` · `usePlMediaQuery` · `usePlOnScreen` · `usePlReducedMotion`
162
+
163
+ `usePlassDefaults`, `usePlToast` and `usePlConfirm` live with the part they belong to instead, and come from `plass-ui/provider`, `plass-ui/toast` and `plass-ui/confirm`.
164
+
165
+ ## Changelog
166
+
167
+ [CHANGELOG.md](https://github.com/jooy2/plass-ui/blob/main/packages/react/CHANGELOG.md) is this package's history, and [plass.cdget.com/changelog](https://plass.cdget.com/changelog) is the same list beside the Flutter package's. The two version independently, so a release on one side is not a release on the other.
146
168
 
147
169
  ## Development
148
170
 
@@ -157,7 +179,7 @@ npm run lint # ESLint
157
179
  npm run size # what the package costs, packed and installed
158
180
  ```
159
181
 
160
- The documentation site lives at the repository root, in [`docs/`](https://github.com/jooy2/plass-ui/tree/main/docs), and renders these components from `src/` through a Vite alias so `cd docs && npm run dev` is the develop-and-eyeball loop and there is no separate demo app. [CONTRIBUTING.md](https://github.com/jooy2/plass-ui/blob/main/CONTRIBUTING.md) has the rest.
182
+ The documentation site lives at the repository root, in [`docs/`](https://github.com/jooy2/plass-ui/tree/main/docs), and renders these components from `src/` through a Vite alias, so `cd docs && npm run dev` is the develop-and-eyeball loop and there is no separate demo app. [CONTRIBUTING.md](https://github.com/jooy2/plass-ui/blob/main/CONTRIBUTING.md) has the rest.
161
183
 
162
184
  ## License
163
185
 
@@ -60,7 +60,7 @@ export interface PlAccordionItemProps extends Omit<React.ComponentPropsWithoutRe
60
60
  /** Content before the title — an icon, a status dot, a count. */
61
61
  startIcon?: React.ReactNode;
62
62
  /**
63
- * A control pinned to the end of the header, before the chevron.
63
+ * A control pinned to the end of the header, after the chevron.
64
64
  *
65
65
  * Deliberately outside the trigger: a header that both folds and holds a
66
66
  * switch has two things to press, and one of them cannot be nested inside the
@@ -1 +1 @@
1
- "use client";import{jsx as s,jsxs as e}from"react/jsx-runtime";import*as l from"react";import{useDefaults as t}from"../../internal/defaults.js";import{useLabels as a}from"../../internal/labels.js";import{CloseIcon as i,severityIcon as r}from"../../internal/icons.js";import{controlSlots as o,focusRingClasses as n,glassClasses as c,hasContent as d,iconClasses as m,radiusClasses as f,sheetBodyClasses as p,sheetHeaderGapClasses as u,sheetPaddingXClasses as h,sheetPaddingYClasses as v,sheetSectionGapClasses as x,sheetTitleClasses as g,transitionClasses as b}from"../../internal/styles.js";const y={solid:/* @__PURE__ */["text-(--p-on-solid) [background-image:var(--p-fill)]","[box-shadow:var(--p-elev),var(--p-lift)]"].join(" "),glass:/* @__PURE__ */[c,"border text-(--plass-fg) bg-(--plass-glass)","[border-color:var(--p-line)]","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),ghost:"text-(--plass-fg) bg-(--p-soft)"},j={solid:"",glass:"text-(--p-accent)",ghost:"text-(--p-accent)"},N={solid:"",glass:"text-(--plass-muted-fg)",ghost:"text-(--plass-muted-fg)"},w={primary:"status",secondary:"status",info:"status",success:"status",warning:"alert",danger:"alert"};export const PlAlert=/* @__PURE__ */l.forwardRef(function PlAlert({variant:l="glass",size:c,color:k,density:$,elevation:z=0,title:A,icon:C,action:P,onClose:_,closeLabel:B,className:L,style:R,children:q,...D},E){const F=t(),G=a(),H=B??G.dismiss,I=c??F.size??"md",J=k??F.color??"info",K=$??F.density??"default",M=void 0===C?r(J):C,O=j[l],Q=d(A);return e("div",{ref:E,role:w[J],className:["flex w-full items-start",h[K][I],v[K][I],f[I],x[I],p[I],b,y[l],m,L??""].filter(Boolean).join(" "),style:{...o(J,z,l),...R},...D,children:[d(M)?s("span",{className:`flex h-[1lh] shrink-0 items-center ${O}`,children:M}):null,e("div",{className:`flex min-w-0 flex-1 flex-col ${u[I]}`,children:[Q?s("div",{className:`plass-title font-semibold ${g[I]} ${O}`,children:A}):null,d(q)?s("div",{className:Q?N[l]:void 0,children:q}):null]}),d(P)?s("div",{className:"flex h-[1lh] shrink-0 items-center",children:P}):null,_?s("span",{className:"flex h-[1lh] shrink-0 items-center",children:s("button",{type:"button","aria-label":H,onClick:_,className:["inline-flex size-[1.15em] cursor-pointer items-center justify-center rounded-full","opacity-70 [transition:opacity_var(--plass-duration)_var(--plass-ease)]","hover:opacity-100 focus-visible:opacity-100",n].join(" "),children:s(i,{})})}):null]})});
1
+ "use client";import{jsx as s,jsxs as e}from"react/jsx-runtime";import*as l from"react";import{useDefaults as t}from"../../internal/defaults.js";import{useLabels as a}from"../../internal/labels.js";import{CloseIcon as i,severityIcon as r}from"../../internal/icons.js";import{controlSlots as o,focusRingClasses as n,forcedFieldEdgeClasses as c,glassClasses as d,hasContent as m,iconClasses as f,radiusClasses as p,sheetBodyClasses as u,sheetHeaderGapClasses as h,sheetPaddingXClasses as v,sheetPaddingYClasses as x,sheetSectionGapClasses as g,sheetTitleClasses as b,transitionClasses as y}from"../../internal/styles.js";const j={solid:/* @__PURE__ */["text-(--p-on-solid) [background-image:var(--p-fill)]","[box-shadow:var(--p-elev),var(--p-lift)]",c].join(" "),glass:/* @__PURE__ */[d,"border text-(--plass-fg) bg-(--plass-glass)","[border-color:var(--p-line)]","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),ghost:"text-(--plass-fg) bg-(--p-soft)"},N={solid:"",glass:"text-(--p-accent)",ghost:"text-(--p-accent)"},w={solid:"",glass:"text-(--plass-muted-fg)",ghost:"text-(--plass-muted-fg)"},k={primary:"status",secondary:"status",info:"status",success:"status",warning:"alert",danger:"alert"};export const PlAlert=/* @__PURE__ */l.forwardRef(function PlAlert({variant:l="glass",size:c,color:d,density:$,elevation:z=0,title:A,icon:C,action:P,onClose:_,closeLabel:B,className:L,style:R,children:q,...D},E){const F=t(),G=a(),H=B??G.dismiss,I=c??F.size??"md",J=d??F.color??"info",K=$??F.density??"default",M=void 0===C?r(J):C,O=N[l],Q=m(A);return e("div",{ref:E,role:k[J],className:["flex w-full items-start",v[K][I],x[K][I],p[I],g[I],u[I],y,j[l],f,L??""].filter(Boolean).join(" "),style:{...o(J,z,l),...R},...D,children:[m(M)?s("span",{className:`flex h-[1lh] shrink-0 items-center ${O}`,children:M}):null,e("div",{className:`flex min-w-0 flex-1 flex-col ${h[I]}`,children:[Q?s("div",{className:`plass-title font-semibold ${b[I]} ${O}`,children:A}):null,m(q)?s("div",{className:Q?w[l]:void 0,children:q}):null]}),m(P)?s("div",{className:"flex h-[1lh] shrink-0 items-center",children:P}):null,_?s("span",{className:"flex h-[1lh] shrink-0 items-center",children:s("button",{type:"button","aria-label":H,onClick:_,className:["inline-flex size-[1.15em] cursor-pointer items-center justify-center rounded-full","opacity-70 [transition:opacity_var(--plass-duration)_var(--plass-ease)]","hover:opacity-100 focus-visible:opacity-100",n].join(" "),children:s(i,{})})}):null]})});
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import type { PlassColor, PlassSize } from '../../types.js';
3
+ import type { PlBackTopTarget } from '../back-top/PlBackTop.js';
3
4
  /** One heading in the list. */
4
5
  export interface PlAnchorItem {
5
6
  /**
@@ -27,7 +28,7 @@ export interface PlAnchorProps extends Omit<React.ComponentPropsWithoutRef<'nav'
27
28
  */
28
29
  active?: string;
29
30
  /**
30
- * How far below the top of the window the reading line sits, in pixels.
31
+ * How far below the top of `target` the reading line sits, in pixels.
31
32
  *
32
33
  * The height of whatever is pinned over the page. Without it a heading goes
33
34
  * on counting as the *next* one after it has already slid out of sight behind
@@ -36,6 +37,14 @@ export interface PlAnchorProps extends Omit<React.ComponentPropsWithoutRef<'nav'
36
37
  * @default 0
37
38
  */
38
39
  offset?: number;
40
+ /**
41
+ * What scrolls the headings. The window by default; a ref or an element for
42
+ * an app shell whose `<main>` scrolls on its own.
43
+ *
44
+ * The window of such a shell never moves, so a list following it would light
45
+ * nothing however far the reader went.
46
+ */
47
+ target?: PlBackTopTarget;
39
48
  /** Called with the item that was clicked, before the browser moves. */
40
49
  onSelect?: (item: PlAnchorItem, event: React.MouseEvent<HTMLAnchorElement>) => void;
41
50
  /** A heading for the list itself. Drawn above it. */
@@ -68,5 +77,9 @@ export interface PlAnchorProps extends Omit<React.ComponentPropsWithoutRef<'nav'
68
77
  * is the height of whatever is pinned over the page — without it a heading goes
69
78
  * on counting as the next one after it has slid out of sight behind the bar,
70
79
  * and the list stays a section behind.
80
+ *
81
+ * `target` is what is scrolled, the window unless it says otherwise. An app
82
+ * shell whose `<main>` scrolls on its own never moves the window, and the line
83
+ * is measured from the top of that element instead.
71
84
  */
72
85
  export declare const PlAnchor: React.ForwardRefExoticComponent<PlAnchorProps & React.RefAttributes<HTMLElement>>;
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{useDefaults as n}from"../../internal/defaults.js";import{useLabels as s}from"../../internal/labels.js";import{controlTextLeadingClasses as o,cx as l,focusRingClasses as a,surfaceSlots as i,transitionClasses as c}from"../../internal/styles.js";export const PlAnchor=/* @__PURE__ */t.forwardRef(function PlAnchor({items:m,active:d,offset:f=0,onSelect:p,label:u,navLabel:h,size:g,color:v,className:w,style:x,...b},y){const E=n(),j=s(),N=h??j.onThisPage,A=g??E.size??"sm",L=v??E.color??"primary",[z,H]=t.useState(void 0),P=void 0!==d;t.useEffect(()=>{if(P)return;let e=0;const measure=()=>{e=0,H(function readingAt(e,r){if(0===e.length)return;const t=document.documentElement.scrollHeight;if(t>window.innerHeight+1&&window.innerHeight+window.scrollY>=t-2)return e[e.length-1].href;let n;for(const t of e){const e=document.getElementById(t.href.replace(/^#/,""));e&&e.getBoundingClientRect().top-r<=1&&(n=t.href)}return n}(m,f))},onScroll=()=>{e||=requestAnimationFrame(measure)};return measure(),window.addEventListener("scroll",onScroll,{passive:!0}),window.addEventListener("resize",onScroll,{passive:!0}),()=>{e&&cancelAnimationFrame(e),window.removeEventListener("scroll",onScroll),window.removeEventListener("resize",onScroll)}},[P,m,f]);const S=P?d:z;return r("nav",{ref:y,"aria-label":N,className:l("flex flex-col gap-2",o[A],w),style:{...i(L,0),...x},...b,children:[u?e("span",{className:"font-semibold text-(--plass-fg)",children:u}):null,e("ul",{className:"m-0 flex list-none flex-col gap-0.5 p-0",children:m.map(r=>{const t=r.href===S;return e("li",{className:"min-w-0",children:e("a",{href:r.href,"aria-current":t?"location":void 0,onClick:e=>p?.(r,e),className:l("block truncate rounded-(--plass-radius-xs) px-2 py-1","border-s-2",c,a,t?"[border-color:var(--p-accent)] bg-(--p-soft) font-medium text-(--p-accent)":"border-transparent text-(--plass-muted-fg) hover:bg-(--plass-glass-hover) hover:text-(--plass-fg)"),style:{paddingInlineStart:`calc(0.5rem + ${r.depth??0} * 0.75rem)`},children:r.label})},r.href)})})]})});
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{useDefaults as n}from"../../internal/defaults.js";import{resolveScrollTarget as s}from"../../internal/scroll-target.js";import{useLabels as o}from"../../internal/labels.js";import{controlTextLeadingClasses as l,cx as a,focusRingClasses as i,surfaceSlots as c,transitionClasses as m}from"../../internal/styles.js";export const PlAnchor=/* @__PURE__ */r.forwardRef(function PlAnchor({items:f,active:d,offset:p=0,target:u,onSelect:h,label:g,navLabel:v,size:x,color:b,className:w,style:j,...y},E){const N=n(),A=o(),L=v??A.onThisPage,z=x??N.size??"sm",H=b??N.color??"primary",[B,C]=r.useState(void 0),P=void 0!==d;r.useEffect(()=>{if(P)return;const e=s(u);if(!e)return;let t=0;const measure=()=>{t=0,C(function readingAt(e,t,r){if(0===e.length)return;const n=r instanceof Window,s=n?document.documentElement.scrollHeight:r.scrollHeight,o=n?window.innerHeight:r.clientHeight,l=n?window.scrollY:r.scrollTop;if(s>o+1&&o+l>=s-2)return e[e.length-1].href;const a=n?0:r.getBoundingClientRect().top+r.clientTop;let i;for(const r of e){const e=document.getElementById(r.href.replace(/^#/,""));e&&e.getBoundingClientRect().top-a-t<=1&&(i=r.href)}return i}(f,p,e))},onScroll=()=>{t||=requestAnimationFrame(measure)};return measure(),e.addEventListener("scroll",onScroll,{passive:!0}),window.addEventListener("resize",onScroll,{passive:!0}),()=>{t&&cancelAnimationFrame(t),e.removeEventListener("scroll",onScroll),window.removeEventListener("resize",onScroll)}},[P,f,p,u]);const R=P?d:B;return t("nav",{ref:E,"aria-label":L,className:a("flex flex-col gap-2",l[z],w),style:{...c(H,0),...j},...y,children:[g?e("span",{className:"font-semibold text-(--plass-fg)",children:g}):null,e("ul",{className:"m-0 flex list-none flex-col gap-0.5 p-0",children:f.map(t=>{const r=t.href===R;return e("li",{className:"min-w-0",children:e("a",{href:t.href,"aria-current":r?"location":void 0,onClick:e=>h?.(t,e),className:a("block truncate rounded-(--plass-radius-xs) px-2 py-1","border-s-2",m,i,r?"[border-color:var(--p-accent)] bg-(--p-soft) font-medium text-(--p-accent)":"border-transparent text-(--plass-muted-fg) hover:bg-(--plass-glass-hover) hover:text-(--plass-fg)"),style:{paddingInlineStart:`calc(0.5rem + ${t.depth??0} * 0.75rem)`},children:t.label})},t.href)})})]})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as a}from"@base-ui/react/use-render";import{animBaseClass as t,animateChildren as r,animationClasses as n,animationSlots as s,isInfinite as i,slideOffsets as o,staggerSlots as d,useAnimationRun as p}from"../../internal/animate.js";export const PlAnimateAppear=/* @__PURE__ */e.forwardRef(function PlAnimateAppear({duration:e=380,delay:l=0,easing:m,repeat:c=1,alternate:u,paused:f,trigger:g="mount",play:y,once:h=!0,threshold:x=.2,stagger:A=70,durationStep:b=0,from:v="bottom",distance:N="0.75rem",fade:P=!0,reverse:S=!1,render:$,className:j,style:w,children:R,...k},q){const z=p({trigger:g,play:y,once:h,threshold:x,paused:f,infinite:i(c)}),{x:B,y:C}=o(v,N),D=r(R,`${t} ${n.slide}`,(a,t)=>s(d({duration:e,delay:l,easing:m,repeat:c,alternate:u,x:B,y:C,opacity:P?0:1},{index:a,count:t,stagger:A,durationStep:b,reverse:S})));return a({render:$,ref:[q,z.ref],props:{...k,className:j,style:{"--p-anim-state":z.state,...w},...z.handlers,"data-plass-animation":"appear","data-state":z.state,children:D}})});
1
+ "use client";import*as e from"react";import{mergeProps as a}from"@base-ui/react/merge-props";import{useRender as r}from"@base-ui/react/use-render";import{animBaseClass as t,animateChildren as n,animationClasses as s,animationSlots as i,isInfinite as o,slideOffsets as p,staggerSlots as d,useAnimationRun as l}from"../../internal/animate.js";export const PlAnimateAppear=/* @__PURE__ */e.forwardRef(function PlAnimateAppear({duration:e=380,delay:m=0,easing:c,repeat:u=1,alternate:f,paused:g,trigger:y="mount",play:h,once:x=!0,threshold:A=.2,stagger:b=70,durationStep:v=0,from:N="bottom",distance:P="0.75rem",fade:S=!0,reverse:$=!1,render:j,className:w,style:R,children:k,...q},z){const B=l({trigger:y,play:h,once:x,threshold:A,paused:g,infinite:o(u)}),{x:C,y:D}=p(N,P),E=n(k,`${t} ${s.slide}`,(a,r)=>i(d({duration:e,delay:m,easing:c,repeat:u,alternate:f,x:C,y:D,opacity:S?0:1},{index:a,count:r,stagger:b,durationStep:v,reverse:$})));return r({render:j,ref:[z,B.ref],props:{...a(q,B.handlers),className:w,style:{"--p-anim-state":B.state,...R},"data-plass-animation":"appear","data-state":B.state,children:E}})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,useAnimateElement as n}from"../../internal/animate.js";import{cx as a}from"../../internal/styles.js";export const PlAnimateBlink=/* @__PURE__ */e.forwardRef(function PlAnimateBlink({duration:e=1e3,delay:i=0,easing:s,repeat:l="infinite",alternate:o,paused:d,trigger:m="mount",play:p,once:c=!0,threshold:f=.2,timeline:g,range:u,stagger:y=0,durationStep:h=0,reverse:k=!1,min:N=0,render:b,className:j,style:v,children:A,...B},P){const S=n({effect:"blink",duration:e,delay:i,easing:s,repeat:l,alternate:o,opacity:N,trigger:m,play:p,once:c,threshold:f,paused:d,infinite:t(l),timeline:g,range:u,stagger:y,durationStep:h,reverse:k,children:A});return r({render:b,ref:[P,S.ref],props:{...B,className:a(S.className,j),style:{...S.style,...v},...S.props,children:S.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{useRender as t}from"@base-ui/react/use-render";import{isInfinite as n,useAnimateElement as a}from"../../internal/animate.js";import{cx as i}from"../../internal/styles.js";export const PlAnimateBlink=/* @__PURE__ */e.forwardRef(function PlAnimateBlink({duration:e=1e3,delay:s=0,easing:l,repeat:o="infinite",alternate:m,paused:p,trigger:c="mount",play:d,once:f=!0,threshold:g=.2,timeline:u,range:y,stagger:h=0,durationStep:b=0,reverse:k=!1,min:N=0,render:j,className:v,style:A,children:B,...P},S){const w=a({effect:"blink",duration:e,delay:s,easing:l,repeat:o,alternate:m,opacity:N,trigger:c,play:d,once:f,threshold:g,paused:p,infinite:n(o),timeline:u,range:y,stagger:h,durationStep:b,reverse:k,children:B});return t({render:j,ref:[S,w.ref],props:{...r(P,w.props),className:i(w.className,v),style:{...w.style,...A},children:w.children}})});
@@ -1 +1 @@
1
- "use client";import{jsx as e,Fragment as r,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{useRender as n}from"@base-ui/react/use-render";import{useAnimationRun as s}from"../../internal/animate.js";import{useDefaults as i}from"../../internal/defaults.js";import{usePrefersReducedMotion as o}from"../../internal/media.js";import{cx as m,srOnlyClasses as l}from"../../internal/styles.js";function easeOut(e){return 1-(1-e)**3}export const PlAnimateCounter=/* @__PURE__ */a.forwardRef(function PlAnimateCounter({value:u,from:c=0,duration:d=1200,delay:f=0,format:p,easing:h=easeOut,trigger:j="visible",play:g,once:A=!0,threshold:F=.2,paused:x,render:b,className:v,...y},N){const q=i(),M=o(),w=s({trigger:j,play:g,once:A,threshold:F,paused:x,infinite:!1,nonce:u}),C=a.useMemo(()=>new Intl.NumberFormat(q.locale,p),[q.locale,p]),[O,P]=a.useState(()=>M?u:c);a.useEffect(()=>{if(M)return void P(u);if(!w.started)return void P(c);if(x)return;let e=0,r=0;const step=t=>{r||=t;const a=Math.min(1,(t-r-f)/Math.max(1,d));a<0?e=requestAnimationFrame(step):(P(c+(u-c)*h(a)),a<1&&(e=requestAnimationFrame(step)))};return e=requestAnimationFrame(step),()=>cancelAnimationFrame(e)},[w.started,M,x,u,c,d,f,h]);const E=C.format(u);return n({render:b??e("span",{}),ref:[N,w.ref],props:{className:m("tabular-nums",v),...w.handlers,"data-plass-animation":"counter","data-state":w.state,children:t(r,{children:[e("span",{className:l,children:E}),e("span",{"aria-hidden":"true",children:C.format(O)})]}),...y}})});
1
+ "use client";import{jsx as e,Fragment as r,jsxs as t}from"react/jsx-runtime";import*as n from"react";import{mergeProps as a}from"@base-ui/react/merge-props";import{useRender as s}from"@base-ui/react/use-render";import{useAnimationRun as i}from"../../internal/animate.js";import{useDefaults as o}from"../../internal/defaults.js";import{usePrefersReducedMotion as u}from"../../internal/media.js";import{cx as m,srOnlyCopyClasses as c}from"../../internal/styles.js";function easeOut(e){return 1-(1-e)**3}export const PlAnimateCounter=/* @__PURE__ */n.forwardRef(function PlAnimateCounter({value:l,from:f=0,duration:d=1200,delay:p=0,format:h,easing:g=easeOut,trigger:j="visible",play:y,once:A=!0,threshold:F=.2,paused:b,render:x,className:N,...v},R){const q=o(),E=u(),O=i({trigger:j,play:y,once:A,threshold:F,paused:b,infinite:!1,nonce:l}),k=`${q.locale??""}\0${JSON.stringify(h??null)}`,w=n.useRef(null);null!==w.current&&w.current.key===k||(w.current={key:k,formatter:new Intl.NumberFormat(q.locale,h)});const C=w.current.formatter,[M,P]=n.useState(()=>E?l:f),S=n.useRef(0),$=n.useRef(g);n.useEffect(()=>{$.current=g}),n.useEffect(()=>{S.current=0},[O.runs,l,f]),n.useEffect(()=>{if(E)return void P(l);if(!O.started)return S.current=0,void P(f);if(b)return;const e=Math.max(1,d);let r,t=0;const step=n=>{r??=n-S.current,S.current=n-r;const a=Math.min(1,(S.current-p)/e);a<0?t=requestAnimationFrame(step):(P(f+(l-f)*$.current(a)),a<1&&(t=requestAnimationFrame(step)))};return t=requestAnimationFrame(step),()=>cancelAnimationFrame(t)},[O.started,O.runs,E,b,l,f,d,p]);const I=C.format(l);return s({render:x??e("span",{}),ref:[R,O.ref],props:{className:m("tabular-nums",N),"data-plass-animation":"counter","data-state":O.state,children:t(r,{children:[e("span",{className:c,children:I}),e("span",{"aria-hidden":"true",children:C.format(M)})]}),...a(v,O.handlers)}})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,useAnimateElement as a}from"../../internal/animate.js";import{cx as n}from"../../internal/styles.js";export const PlAnimateFade=/* @__PURE__ */e.forwardRef(function PlAnimateFade({duration:e=300,delay:i=0,easing:s,repeat:o=1,alternate:l,paused:d,trigger:m="mount",play:p,once:c=!0,threshold:f=.2,timeline:g,range:u,stagger:y=0,durationStep:h=0,reverse:N=!1,mode:j="in",from:v=0,render:A,className:F,style:P,children:S,...b},w){const x=a({effect:"fade",duration:e,delay:i,easing:s,repeat:o,alternate:l,mode:j,opacity:v,trigger:m,play:p,once:c,threshold:f,paused:d,infinite:t(o),timeline:g,range:u,stagger:y,durationStep:h,reverse:N,children:S});return r({render:A,ref:[w,x.ref],props:{...b,className:n(x.className,F),style:{...x.style,...P},...x.props,children:x.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{useRender as t}from"@base-ui/react/use-render";import{isInfinite as a,useAnimateElement as n}from"../../internal/animate.js";import{cx as i}from"../../internal/styles.js";export const PlAnimateFade=/* @__PURE__ */e.forwardRef(function PlAnimateFade({duration:e=300,delay:s=0,easing:o,repeat:l=1,alternate:d,paused:m,trigger:p="mount",play:c,once:f=!0,threshold:g=.2,timeline:u,range:y,stagger:h=0,durationStep:N=0,reverse:b=!1,mode:j="in",from:v=0,render:A,className:F,style:P,children:S,...w},x){const R=n({effect:"fade",duration:e,delay:s,easing:o,repeat:l,alternate:d,mode:j,opacity:v,trigger:p,play:c,once:f,threshold:g,paused:m,infinite:a(l),timeline:u,range:y,stagger:h,durationStep:N,reverse:b,children:S});return t({render:A,ref:[x,R.ref],props:{...r(w,R.props),className:i(R.className,F),style:{...R.style,...P},children:R.children}})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as a}from"@base-ui/react/use-render";import{animBaseClass as t,lengthValue as r,useAnimateElement as n}from"../../internal/animate.js";import{cx as i}from"../../internal/styles.js";export const PlAnimateFloat=/* @__PURE__ */e.forwardRef(function PlAnimateFloat({duration:e=3e3,delay:l=0,easing:s="ease-in-out",repeat:o="infinite",alternate:c,paused:d,trigger:m="mount",play:p,once:f=!0,threshold:u=.2,distance:y=8,orientation:h="vertical",render:g,className:N,style:j,children:v,...x},A){const F=r(y),P="vertical"===h,b=n({effect:null,duration:e,delay:l,easing:s,repeat:o,alternate:c,x:P?"0":F,y:P?`-${F}`:"0",trigger:m,play:p,once:f,threshold:u,paused:d,infinite:!0,children:v});return a({render:g,ref:[A,b.ref],props:{...x,className:i(t,"plass-anim-float",b.className,N),style:{...b.style,...j},...b.props,"data-plass-animation":"float",children:b.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as a}from"@base-ui/react/merge-props";import{useRender as r}from"@base-ui/react/use-render";import{animBaseClass as t,lengthValue as n,useAnimateElement as i}from"../../internal/animate.js";import{cx as l}from"../../internal/styles.js";export const PlAnimateFloat=/* @__PURE__ */e.forwardRef(function PlAnimateFloat({duration:e=3e3,delay:s=0,easing:o="ease-in-out",repeat:c="infinite",alternate:p,paused:m,trigger:d="mount",play:f,once:u=!0,threshold:y=.2,distance:h=8,orientation:g="vertical",render:b,className:x,style:N,children:j,...v},A){const F=n(h),P="vertical"===g,w=i({effect:null,duration:e,delay:s,easing:o,repeat:c,alternate:p,x:P?"0":F,y:P?"number"==typeof h?-h+"px":`calc(-1 * ${F})`:"0",trigger:d,play:f,once:u,threshold:y,paused:m,infinite:!0,children:j});return r({render:b,ref:[A,w.ref],props:{...a(v,w.props),className:l(t,"plass-anim-float",w.className,x),style:{...w.style,...N},"data-plass-animation":"float",children:w.children}})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,useAnimateElement as a}from"../../internal/animate.js";import{cx as n}from"../../internal/styles.js";export const PlAnimateGrow=/* @__PURE__ */e.forwardRef(function PlAnimateGrow({duration:e=320,delay:i=0,easing:o,repeat:s=1,alternate:l,paused:d,trigger:m="mount",play:c,once:p=!0,threshold:g=.2,timeline:f,range:u,stagger:y=0,durationStep:h=0,reverse:w=!1,mode:N="in",from:j=.8,origin:v="center",fade:A=!0,render:G,className:P,style:S,children:b,...x},R){const k=a({effect:"grow",duration:e,delay:i,easing:o,repeat:s,alternate:l,mode:N,scale:j,opacity:A?0:1,trigger:m,play:c,once:p,threshold:g,paused:d,infinite:t(s),timeline:f,range:u,origin:v,stagger:y,durationStep:h,reverse:w,children:b});return r({render:G,ref:[R,k.ref],props:{...x,className:n(k.className,P),style:{...k.style,...S},...k.props,children:k.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{useRender as t}from"@base-ui/react/use-render";import{isInfinite as a,useAnimateElement as n}from"../../internal/animate.js";import{cx as i}from"../../internal/styles.js";export const PlAnimateGrow=/* @__PURE__ */e.forwardRef(function PlAnimateGrow({duration:e=320,delay:o=0,easing:s,repeat:l=1,alternate:m,paused:d,trigger:p="mount",play:c,once:g=!0,threshold:f=.2,timeline:u,range:y,stagger:h=0,durationStep:w=0,reverse:N=!1,mode:b="in",from:j=.8,origin:v="center",fade:A=!0,render:G,className:P,style:S,children:x,...R},k){const q=n({effect:"grow",duration:e,delay:o,easing:s,repeat:l,alternate:m,mode:b,scale:j,opacity:A?0:1,trigger:p,play:c,once:g,threshold:f,paused:d,infinite:a(l),timeline:u,range:y,origin:v,stagger:h,durationStep:w,reverse:N,children:x});return t({render:G,ref:[k,q.ref],props:{...r(R,q.props),className:i(q.className,P),style:{...q.style,...S},children:q.children}})});
@@ -1 +1 @@
1
- "use client";import{jsx as e}from"react/jsx-runtime";import*as t from"react";import{isInfinite as n,lengthValue as a,useAnimationRun as r}from"../../internal/animate.js";import{usePrefersReducedMotion as i}from"../../internal/media.js";import{cx as s}from"../../internal/styles.js";export const PlAnimateHeadline=/* @__PURE__ */t.forwardRef(function PlAnimateHeadline({duration:l=460,delay:o=0,easing:u,repeat:m="infinite",paused:c,trigger:d="mount",play:f,once:p=!0,threshold:h=.2,interval:g=2600,index:v,defaultIndex:y=0,onIndexChange:x,loop:j=!0,rise:E="100%",className:N,style:T,children:A,...C},R){const k=r({trigger:d,play:f,once:p,threshold:h,paused:c,infinite:n(m)}),H=i(),I=t.Children.toArray(A),M=I.length,[P,S]=t.useState(y),b=Math.min(v??P,Math.max(M-1,0)),[w,V]=t.useState(null),$=t.useRef(b);t.useEffect(()=>{$.current!==b&&(V($.current),$.current=b)},[b]),t.useEffect(()=>{if(null===w)return;const e=setTimeout(()=>V(null),l);return()=>clearTimeout(e)},[w,l]);const q=t.useCallback(()=>{const e=b+1;if(e>=M){if(!j)return;return void 0===v&&S(0),void x?.(0)}void 0===v&&S(e),x?.(e)},[b,M,j,v,x]),z=t.useRef(!1);return t.useEffect(()=>{if(void 0!==v||M<2||"running"!==k.state)return;if(!j&&b===M-1)return;const e=setTimeout(()=>{z.current=!0,q()},g+(z.current?0:o));return()=>clearTimeout(e)},[v,M,k.state,g,o,q,j,b]),e("div",{ref:e=>{k.ref(e),"function"==typeof R?R(e):R&&(R.current=e)},className:s("plass-headline",N),style:{"--p-anim-duration":`${l}ms`,"--p-anim-rise":a(E),...u?{"--p-anim-ease":u}:{},"--p-anim-state":k.state,...T},"data-plass-animation":"headline","data-state":k.state,...k.handlers,...C,children:I.map((n,a)=>{const r=a===b?"active":a!==w||H?void 0:"leaving";if(!t.isValidElement(n))return e("span",{className:"plass-headline-item","data-state":r,children:n},a);const i=n.props;return t.cloneElement(n,{key:a,className:s("plass-headline-item",i.className),"data-state":r})})})});
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import*as t from"react";import{mergeProps as n}from"@base-ui/react/merge-props";import{isInfinite as a,lengthValue as r,useAnimationRun as s}from"../../internal/animate.js";import{usePrefersReducedMotion as i}from"../../internal/media.js";import{cx as l}from"../../internal/styles.js";export const PlAnimateHeadline=/* @__PURE__ */t.forwardRef(function PlAnimateHeadline({duration:o=460,delay:u=0,easing:c,repeat:m="infinite",paused:d,trigger:f="mount",play:p,once:h=!0,threshold:g=.2,interval:v=2600,index:y,defaultIndex:x=0,onIndexChange:E,loop:j=!0,rise:N="100%",className:R,style:T,children:A,...C},b){const k=s({trigger:f,play:p,once:h,threshold:g,paused:d,infinite:a(m)}),H=i(),I=t.Children.toArray(A),M=I.length,[P,S]=t.useState(x),w=Math.min(y??P,Math.max(M-1,0)),[V,$]=t.useState(null),q=t.useRef(w);t.useEffect(()=>{q.current!==w&&($(q.current),q.current=w)},[w]),t.useEffect(()=>{if(null===V)return;const e=setTimeout(()=>$(null),o);return()=>clearTimeout(e)},[V,o]);const z=t.useCallback(()=>{const e=w+1;if(e>=M){if(!j)return;return void 0===y&&S(0),void E?.(0)}void 0===y&&S(e),E?.(e)},[w,M,j,y,E]),B=t.useRef(z);t.useEffect(()=>{B.current=z});const D=t.useRef(!1);return t.useEffect(()=>{if(void 0!==y||M<2||"running"!==k.state)return;if(!j&&w===M-1)return;const e=setTimeout(()=>{D.current=!0,B.current()},v+(D.current?0:u));return()=>clearTimeout(e)},[y,M,k.state,v,u,j,w]),e("div",{ref:e=>{k.ref(e),"function"==typeof b?b(e):b&&(b.current=e)},className:l("plass-headline",R),style:{"--p-anim-duration":`${o}ms`,"--p-anim-rise":r(N),...c?{"--p-anim-ease":c}:{},"--p-anim-state":k.state,...T},"data-plass-animation":"headline","data-state":k.state,...n(C,k.handlers),children:I.map((n,a)=>{const r=a===w?"active":a!==V||H?void 0:"leaving";if(!t.isValidElement(n))return e("span",{className:"plass-headline-item","data-state":r,children:n},a);const s=n.props;return t.cloneElement(n,{key:a,className:l("plass-headline-item",s.className),"data-state":r})})})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useDefaults as r}from"../../internal/defaults.js";import{useRender as a}from"@base-ui/react/use-render";import{isInfinite as i,useAnimateElement as t}from"../../internal/animate.js";import{cx as n,radiusClasses as l}from"../../internal/styles.js";export const PlAnimateLighting=/* @__PURE__ */e.forwardRef(function PlAnimateLighting({duration:e=3e3,delay:o=0,easing:s,repeat:p="infinite",alternate:m,paused:d,trigger:g="mount",play:c,once:f=!0,threshold:u=.2,color:h,glow:y,size:w,spread:$=3,arc:b=50,blur:j=5,reverse:v=!1,render:x,className:z,style:A,children:L,...N},P){const R=r(),k=h??R.color??"primary",q=w??R.size??"md",B=t({effect:null,duration:e,delay:o,easing:s,repeat:p,alternate:m,mode:v?"out":"in",trigger:g,play:c,once:f,threshold:u,paused:d,infinite:i(p)});return a({render:x,ref:[P,B.ref],props:{...N,className:n("plass-anim-lighting",l[q],z),style:{...B.style,"--p-anim-glow-from":y??`var(--plass-${k}-solid)`,"--p-anim-glow-to":y??`var(--plass-${k}-solid-to)`,"--p-anim-glow-width":`${$}px`,"--p-anim-glow-arc":`${b}deg`,"--p-anim-glow-blur":`${j}px`,...A},...B.props,"data-plass-animation":"lighting",children:L}})});
1
+ "use client";import*as e from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{useDefaults as a}from"../../internal/defaults.js";import{useRender as i}from"@base-ui/react/use-render";import{isInfinite as t,useAnimateElement as n}from"../../internal/animate.js";import{cx as o,radiusClasses as l}from"../../internal/styles.js";export const PlAnimateLighting=/* @__PURE__ */e.forwardRef(function PlAnimateLighting({duration:e=3e3,delay:s=0,easing:p,repeat:m="infinite",alternate:d,paused:g,trigger:c="mount",play:f,once:u=!0,threshold:h=.2,color:y,glow:w,size:$,spread:b=3,arc:j=50,blur:v=5,reverse:x=!1,render:z,className:A,style:L,children:N,...P},R){const k=a(),q=y??k.color??"primary",B=$??k.size??"md",C=n({effect:null,duration:e,delay:s,easing:p,repeat:m,alternate:d,mode:x?"out":"in",trigger:c,play:f,once:u,threshold:h,paused:g,infinite:t(m)});return i({render:z,ref:[R,C.ref],props:{...r(P,C.props),className:o("plass-anim-lighting",l[B],A),style:{...C.style,"--p-anim-glow-from":w??`var(--plass-${q}-solid)`,"--p-anim-glow-to":w??`var(--plass-${q}-solid-to)`,"--p-anim-glow-width":`${b}px`,"--p-anim-glow-arc":`${j}deg`,"--p-anim-glow-blur":`${v}px`,...L},"data-plass-animation":"lighting",children:N}})});
@@ -15,6 +15,9 @@ export interface PlAnimateMarqueeProps extends PlassAnimateProps, React.Componen
15
15
  * How fast the content travels, in pixels per second. A speed rather than a
16
16
  * duration, so a strip of four logos and a strip of forty move at the same
17
17
  * pace instead of the long one becoming a blur.
18
+ *
19
+ * `0` or less holds the strip where it is, as `paused` does. `duration`
20
+ * overrides this.
18
21
  * @default 60
19
22
  */
20
23
  speed?: number;
@@ -27,7 +30,8 @@ export interface PlAnimateMarqueeProps extends PlassAnimateProps, React.Componen
27
30
  /**
28
31
  * How many copies of the content are laid end to end. Two is enough for
29
32
  * anything at least as wide as its container; raise it when the content is
30
- * short enough to leave a hole behind itself.
33
+ * short enough to leave a hole behind itself. Only the first is drawn under
34
+ * `prefers-reduced-motion`.
31
35
  * @default 2
32
36
  */
33
37
  copies?: number;
@@ -58,8 +62,16 @@ export interface PlAnimateMarqueeProps extends PlassAnimateProps, React.Componen
58
62
  * pointer cannot be clicked reliably, and a link inside a marquee that never
59
63
  * stops is a link nobody can follow.
60
64
  *
61
- * Only the first copy is read out. The rest carry `aria-hidden`, or a screen
62
- * reader would announce everything on the strip as many times as it was laid
63
- * down.
65
+ * Under `prefers-reduced-motion` the strip stops, and what was past the edge of
66
+ * the box would be out of sight for good. So the stylesheet draws only the
67
+ * first copy and lets the box scroll along it instead of clipping it, and the
68
+ * box is a tab stop while there is anything to scroll, for a reader with no
69
+ * pointer to scroll it with.
70
+ *
71
+ * Only the first copy is read out or reached with Tab. The rest carry
72
+ * `aria-hidden`, or a screen reader would announce everything on the strip as
73
+ * many times as it was laid down, and `inert`, because `aria-hidden` does not
74
+ * stop the focus: a strip of ten links would otherwise be thirty Tab stops,
75
+ * twenty of them with no name.
64
76
  */
65
77
  export declare const PlAnimateMarquee: React.ForwardRefExoticComponent<PlAnimateMarqueeProps & React.RefAttributes<HTMLDivElement>>;
@@ -1 +1 @@
1
- "use client";import{jsx as e}from"react/jsx-runtime";import*as t from"react";import{isInfinite as a,lengthValue as r,repeatValue as n,directionValue as s,useAnimationRun as i}from"../../internal/animate.js";import{cx as o}from"../../internal/styles.js";export const PlAnimateMarquee=/* @__PURE__ */t.forwardRef(function PlAnimateMarquee({duration:l,delay:u=0,easing:m,repeat:p="infinite",alternate:c,paused:d,trigger:f="mount",play:h,once:v=!0,threshold:y=.2,orientation:g="horizontal",reverse:q=!1,speed:R=60,gap:b="2rem",copies:j=2,pauseOnHover:x=!0,className:M,style:w,children:z,...A},N){const O=i({trigger:f,play:h,once:v,threshold:y,paused:d,infinite:a(p)}),G=t.useRef(null),H=t.useRef(null),[P,S]=t.useState(0),$="vertical"===g;t.useEffect(()=>{const e=G.current,t=H.current;if(!e||!t)return;const measure=()=>{const a=getComputedStyle(e),r=parseFloat($?a.rowGap:a.columnGap)||0,n=$?t.offsetHeight:t.offsetWidth;S(n+r)};if(measure(),"undefined"==typeof ResizeObserver)return;const a=new ResizeObserver(measure);return a.observe(t),a.observe(e),()=>a.disconnect()},[$,z]);const k=l??(P>0?P/R*1e3:12e3);return e("div",{ref:e=>{G.current=e,O.ref(e),"function"==typeof N?N(e):N&&(N.current=e)},className:o("plass-marquee",$&&"plass-marquee-vertical",M),style:{"--p-anim-gap":r(b),...m?{"--p-anim-ease":m}:{},"--p-anim-duration":`${Math.round(k)}ms`,"--p-anim-delay":`${u}ms`,"--p-anim-repeat":n(p),"--p-anim-direction":s(q?"out":"in",c),"--p-anim-state":O.state,...w},"data-plass-animation":"marquee","data-state":O.state,"data-pause-on-hover":x?"":void 0,...O.handlers,...A,children:Array.from({length:Math.max(1,j)},(t,a)=>(t=>e("div",{ref:0===t?H:void 0,className:"plass-marquee-track","aria-hidden":0===t?void 0:"true",children:z},t))(a))})});
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import*as t from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{isInfinite as a,lengthValue as n,repeatValue as i,directionValue as s,useAnimationRun as o}from"../../internal/animate.js";import{inertProps as l}from"../../internal/inert.js";import{usePrefersReducedMotion as m}from"../../internal/media.js";import{cx as p}from"../../internal/styles.js";export const PlAnimateMarquee=/* @__PURE__ */t.forwardRef(function PlAnimateMarquee({duration:u,delay:c=0,easing:d,repeat:f="infinite",alternate:h,paused:v,trigger:g="mount",play:y,once:b=!0,threshold:j=.2,orientation:q="horizontal",reverse:x=!1,speed:R=60,gap:H="2rem",copies:M=2,pauseOnHover:w=!0,className:z,style:A,children:N,...O},S){const W=void 0===u&&R<=0,G=o({trigger:g,play:y,once:b,threshold:j,paused:v||W,infinite:a(f)}),P=t.useRef(null),$=t.useRef(null),[k,C]=t.useState(0),[E,F]=t.useState(!1),I="vertical"===q,B=m();t.useEffect(()=>{const e=P.current,t=$.current;if(!e||!t)return;const measure=()=>{const r=getComputedStyle(e),a=parseFloat(I?r.rowGap:r.columnGap)||0,n=I?t.offsetHeight:t.offsetWidth;C(n+a),F(I?e.scrollHeight>e.clientHeight:e.scrollWidth>e.clientWidth)};if(measure(),"undefined"==typeof ResizeObserver)return;const r=new ResizeObserver(measure);return r.observe(t),r.observe(e),()=>r.disconnect()},[I,B]);const D=u??(k>0&&!W?k/R*1e3:12e3);return e("div",{ref:e=>{P.current=e,G.ref(e),"function"==typeof S?S(e):S&&(S.current=e)},className:p("plass-marquee",I&&"plass-marquee-vertical",z),style:{"--p-anim-gap":n(H),...d?{"--p-anim-ease":d}:{},"--p-anim-duration":`${Math.round(D)}ms`,"--p-anim-delay":`${c}ms`,"--p-anim-repeat":i(f),"--p-anim-direction":s(x?"out":"in",h),"--p-anim-state":G.state,...A},"data-plass-animation":"marquee","data-state":G.state,"data-pause-on-hover":w?"":void 0,tabIndex:B&&E?0:void 0,...r(O,G.handlers),children:Array.from({length:Math.max(1,M)},(t,r)=>(t=>e("div",{ref:0===t?$:void 0,className:"plass-marquee-track","aria-hidden":0===t?void 0:"true",...l(0!==t),children:N},t))(r))})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,revealClip as a,useAnimateElement as n}from"../../internal/animate.js";import{cx as i}from"../../internal/styles.js";export const PlAnimateReveal=/* @__PURE__ */e.forwardRef(function PlAnimateReveal({duration:e=520,delay:l=0,easing:s,repeat:o=1,alternate:d,paused:m,trigger:p="mount",play:c,once:f=!0,threshold:g=.2,timeline:u,range:y,stagger:h=0,durationStep:v=0,reverse:N=!1,mode:R="in",from:j="left",fade:A=!1,render:P,className:S,style:b,children:w,...x},k){const q=n({effect:"reveal",duration:e,delay:l,easing:s,repeat:o,alternate:d,mode:R,clip:a(j),opacity:A?0:1,trigger:p,play:c,once:f,threshold:g,paused:m,infinite:t(o),timeline:u,range:y,stagger:h,durationStep:v,reverse:N,children:w});return r({render:P,ref:[k,q.ref],props:{...x,className:i(q.className,S),style:{...q.style,...b},...q.props,children:q.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{useRender as t}from"@base-ui/react/use-render";import{isInfinite as a,revealClip as n,useAnimateElement as i}from"../../internal/animate.js";import{cx as s}from"../../internal/styles.js";export const PlAnimateReveal=/* @__PURE__ */e.forwardRef(function PlAnimateReveal({duration:e=520,delay:l=0,easing:o,repeat:m=1,alternate:p,paused:d,trigger:c="mount",play:f,once:g=!0,threshold:u=.2,timeline:y,range:h,stagger:v=0,durationStep:N=0,reverse:R=!1,mode:b="in",from:j="left",fade:A=!1,render:P,className:S,style:w,children:x,...k},q){const z=i({effect:"reveal",duration:e,delay:l,easing:o,repeat:m,alternate:p,mode:b,clip:n(j),opacity:A?0:1,trigger:c,play:f,once:g,threshold:u,paused:d,infinite:a(m),timeline:y,range:h,stagger:v,durationStep:N,reverse:R,children:x});return t({render:P,ref:[q,z.ref],props:{...r(k,z.props),className:s(z.className,S),style:{...z.style,...w},children:z.children}})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,useAnimateElement as a}from"../../internal/animate.js";import{cx as n}from"../../internal/styles.js";export const PlAnimateRotate=/* @__PURE__ */e.forwardRef(function PlAnimateRotate({duration:e=440,delay:i=0,easing:o,repeat:s=1,alternate:l,paused:d,trigger:m="mount",play:c,once:g=!0,threshold:p=.2,timeline:f,range:u,stagger:y=0,durationStep:h=0,reverse:N=!1,mode:R="in",from:j=-180,to:v=0,origin:A="center",fade:P=!0,render:S,className:$,style:b,children:w,...x},T){const k=a({effect:"rotate",duration:e,delay:i,easing:o,repeat:s,alternate:l,mode:R,angle:`${j}deg`,angleTo:`${v}deg`,opacity:P?0:1,trigger:m,play:c,once:g,threshold:p,paused:d,infinite:t(s),timeline:f,range:u,origin:A,stagger:y,durationStep:h,reverse:N,children:w});return r({render:S,ref:[T,k.ref],props:{...x,className:n(k.className,$),style:{...k.style,...b},...k.props,children:k.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{useRender as t}from"@base-ui/react/use-render";import{isInfinite as a,useAnimateElement as n}from"../../internal/animate.js";import{cx as i}from"../../internal/styles.js";export const PlAnimateRotate=/* @__PURE__ */e.forwardRef(function PlAnimateRotate({duration:e=440,delay:o=0,easing:s,repeat:l=1,alternate:d,paused:m,trigger:p="mount",play:c,once:g=!0,threshold:f=.2,timeline:u,range:y,stagger:h=0,durationStep:N=0,reverse:R=!1,mode:b="in",from:j=-180,to:v=0,origin:A="center",fade:P=!0,render:S,className:$,style:w,children:x,...T},k){const q=n({effect:"rotate",duration:e,delay:o,easing:s,repeat:l,alternate:d,mode:b,angle:`${j}deg`,angleTo:`${v}deg`,opacity:P?0:1,trigger:p,play:c,once:g,threshold:f,paused:m,infinite:a(l),timeline:u,range:y,origin:A,stagger:h,durationStep:N,reverse:R,children:x});return t({render:S,ref:[k,q.ref],props:{...r(T,q.props),className:i(q.className,$),style:{...q.style,...w},children:q.children}})});
@@ -1 +1 @@
1
- "use client";import{jsx as e,Fragment as r,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{useRender as n}from"@base-ui/react/use-render";import{useAnimationRun as s}from"../../internal/animate.js";import{usePrefersReducedMotion as i}from"../../internal/media.js";import{poolOf as m,scrambleAt as o}from"../../internal/scramble.js";import{cx as c,srOnlyClasses as l}from"../../internal/styles.js";export const PlAnimateScramble=/* @__PURE__ */t.forwardRef(function PlAnimateScramble({children:d,characters:f,duration:p=1200,delay:u=0,tick:h=45,trigger:x="visible",play:j,once:M=!0,threshold:b=.2,paused:g,render:A,className:y,...F},v){const N=i(),S=s({trigger:x,play:j,once:M,threshold:b,paused:g,infinite:!1,nonce:d}),q=t.useMemo(()=>f??m(d),[f,d]),[w,P]=t.useState(()=>d);return t.useEffect(()=>{if(N)return void P(d);if(!S.started)return void P(o(d,q,0,0));if(g)return;const e=performance.now();let r=0,a=0,t=-1;const step=n=>{const s=n-e-u,i=Math.min(1,s/Math.max(1,p)),m=Math.floor(Math.max(0,s)/Math.max(1,h));m!==t&&(t=m,a+=1,P(o(d,q,Math.max(0,i),a))),i<1?r=requestAnimationFrame(step):P(d)};return r=requestAnimationFrame(step),()=>cancelAnimationFrame(r)},[S.started,N,g,d,q,p,u,h]),n({render:A??e("span",{}),ref:[v,S.ref],props:{className:c(y),...S.handlers,"data-plass-animation":"scramble","data-state":S.state,children:a(r,{children:[e("span",{className:l,children:d}),e("span",{"aria-hidden":"true",children:w})]}),...F}})});
1
+ "use client";import{jsx as e,Fragment as r,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{mergeProps as n}from"@base-ui/react/merge-props";import{useRender as s}from"@base-ui/react/use-render";import{useAnimationRun as i}from"../../internal/animate.js";import{usePrefersReducedMotion as m}from"../../internal/media.js";import{poolOf as o,scrambleAt as c}from"../../internal/scramble.js";import{cx as l,srOnlyCopyClasses as u}from"../../internal/styles.js";export const PlAnimateScramble=/* @__PURE__ */a.forwardRef(function PlAnimateScramble({children:d,characters:f,duration:p=1200,delay:h=0,tick:x=45,trigger:b="visible",play:j,once:M=!0,threshold:g=.2,paused:A,render:y,className:F,...v},N){const S=m(),q=i({trigger:b,play:j,once:M,threshold:g,paused:A,infinite:!1,nonce:d}),E=a.useMemo(()=>f??o(d),[f,d]),[P,R]=a.useState(()=>d),k=a.useRef(0);return a.useEffect(()=>{k.current=0},[q.runs,d]),a.useEffect(()=>{if(S)return void R(d);if(!q.started)return k.current=0,void R(c(d,E,0,0));if(A)return;const e=Math.max(1,p);let r,t=0,a=0,n=-1;const step=s=>{r??=s-k.current,k.current=s-r;const i=k.current-h,m=Math.min(1,i/e),o=Math.floor(Math.max(0,i)/Math.max(1,x));o!==n&&(n=o,a+=1,R(c(d,E,Math.max(0,m),a))),m<1?t=requestAnimationFrame(step):R(d)};return t=requestAnimationFrame(step),()=>cancelAnimationFrame(t)},[q.started,q.runs,S,A,d,E,p,h,x]),s({render:y??e("span",{}),ref:[N,q.ref],props:{className:l(F),"data-plass-animation":"scramble","data-state":q.state,children:t(r,{children:[e("span",{className:u,children:d}),e("span",{"aria-hidden":"true",children:P})]}),...n(v,q.handlers)}})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as a}from"@base-ui/react/use-render";import{animBaseClass as r,lengthValue as n,useAnimateElement as t}from"../../internal/animate.js";import{cx as s}from"../../internal/styles.js";export const PlAnimateShake=/* @__PURE__ */e.forwardRef(function PlAnimateShake({duration:e=400,delay:l=0,easing:i,repeat:o=1,alternate:c,paused:d,trigger:p="manual",play:m=!1,once:f=!0,threshold:h=.2,replay:u,distance:y=6,render:g,className:k,style:N,children:j,...x},A){const P=t({effect:null,duration:e,delay:l,easing:i,repeat:o,alternate:c,x:n(y),trigger:p,play:m,once:f,threshold:h,paused:d,infinite:!1,nonce:u,children:j});return a({render:g,ref:[A,P.ref],props:{...x,className:s(r,"plass-anim-shake",P.className,k),style:{...P.style,...N},...P.props,"data-plass-animation":"shake",children:P.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as a}from"@base-ui/react/merge-props";import{useRender as r}from"@base-ui/react/use-render";import{animBaseClass as t,lengthValue as n,useAnimateElement as s}from"../../internal/animate.js";import{cx as i}from"../../internal/styles.js";export const PlAnimateShake=/* @__PURE__ */e.forwardRef(function PlAnimateShake({duration:e=400,delay:l=0,easing:o,repeat:p=1,alternate:m,paused:c,trigger:d="manual",play:f=!1,once:h=!0,threshold:u=.2,replay:y,distance:g=6,render:k,className:N,style:b,children:j,...x},A){const P=s({effect:null,duration:e,delay:l,easing:o,repeat:p,alternate:m,x:n(g),trigger:d,play:f,once:h,threshold:u,paused:c,infinite:!1,nonce:y,children:j});return r({render:k,ref:[A,P.ref],props:{...a(x,P.props),className:i(t,"plass-anim-shake",P.className,N),style:{...P.style,...b},"data-plass-animation":"shake",children:P.children}})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,slideOffsets as a,useAnimateElement as n}from"../../internal/animate.js";import{cx as i}from"../../internal/styles.js";export const PlAnimateSlide=/* @__PURE__ */e.forwardRef(function PlAnimateSlide({duration:e=360,delay:s=0,easing:o,repeat:l=1,alternate:d,paused:m,trigger:c="mount",play:p,once:f=!0,threshold:g=.2,timeline:u,range:y,stagger:h=0,durationStep:S=0,reverse:x=!1,mode:N="in",from:b="bottom",distance:j="100%",fade:v=!0,render:A,className:P,style:w,children:R,...k},q){const{x:z,y:B}=a(b,j),C=n({effect:"slide",duration:e,delay:s,easing:o,repeat:l,alternate:d,mode:N,x:z,y:B,opacity:v?0:1,trigger:c,play:p,once:f,threshold:g,paused:m,infinite:t(l),timeline:u,range:y,stagger:h,durationStep:S,reverse:x,children:R});return r({render:A,ref:[q,C.ref],props:{...k,className:i(C.className,P),style:{...C.style,...w},...C.props,children:C.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{useRender as t}from"@base-ui/react/use-render";import{isInfinite as a,slideOffsets as i,useAnimateElement as n}from"../../internal/animate.js";import{cx as s}from"../../internal/styles.js";export const PlAnimateSlide=/* @__PURE__ */e.forwardRef(function PlAnimateSlide({duration:e=360,delay:o=0,easing:l,repeat:d=1,alternate:m,paused:p,trigger:c="mount",play:f,once:g=!0,threshold:u=.2,timeline:y,range:h,stagger:S=0,durationStep:b=0,reverse:x=!1,mode:N="in",from:j="bottom",distance:v="100%",fade:A=!0,render:P,className:w,style:R,children:k,...q},z){const{x:B,y:C}=i(j,v),D=n({effect:"slide",duration:e,delay:o,easing:l,repeat:d,alternate:m,mode:N,x:B,y:C,opacity:A?0:1,trigger:c,play:f,once:g,threshold:u,paused:p,infinite:a(d),timeline:y,range:h,stagger:S,durationStep:b,reverse:x,children:k});return t({render:P,ref:[z,D.ref],props:{...r(q,D.props),className:s(D.className,w),style:{...D.style,...R},children:D.children}})});
@@ -18,7 +18,9 @@ export interface PlAnimateSplitProps extends PlassAnimateProps, PlassAnimateStag
18
18
  */
19
19
  by?: PlAnimateSplitBy;
20
20
  /**
21
- * Which of the entrances each part plays.
21
+ * Which of the entrances each part plays. A part starts where the component
22
+ * of that name starts when it is given nothing, so a `slide` part rises from
23
+ * its own height below and a `zoom` part grows from 0.4.
22
24
  * @default 'fade'
23
25
  */
24
26
  effect?: PlassAnimation;
@@ -42,9 +44,10 @@ export interface PlAnimateSplitProps extends PlassAnimateProps, PlassAnimateStag
42
44
  *
43
45
  * **`by="character"` is not safe in every script**, and that is the one thing
44
46
  * to know before reaching for it. A character span breaks the shaping between
45
- * letters, so Arabic stops joining, Devanagari conjuncts come apart, and an
46
- * emoji built out of several code points is cut into its pieces. `word` has
47
- * none of those problems, is the default, and is what a headline wants anyway.
47
+ * letters, so Arabic stops joining. A character is a grapheme, what a reader
48
+ * counts as one, so an emoji, a flag or a Devanagari conjunct stays in one
49
+ * part. `word` keeps the shaping, is the default, and is what a headline wants
50
+ * anyway.
48
51
  *
49
52
  * **A screen reader is told the line, once.** The parts are hidden from the
50
53
  * accessibility tree and the whole line sits beside them in a clipped span,
@@ -1 +1 @@
1
- "use client";import{jsx as e,Fragment as r,jsxs as t}from"react/jsx-runtime";import*as a from"react";import{useRender as n}from"@base-ui/react/use-render";import{animBaseClass as i,animationClasses as s,animationSlots as l,isInfinite as o,staggerSlots as m,useAnimationRun as d}from"../../internal/animate.js";import{cx as p,srOnlyClasses as c}from"../../internal/styles.js";export const PlAnimateSplit=/* @__PURE__ */a.forwardRef(function PlAnimateSplit({children:f,by:u="word",effect:h="fade",mode:g="in",duration:y=400,delay:j=0,easing:x,repeat:w=1,alternate:N,paused:S,trigger:b="mount",play:v,once:A=!0,threshold:$=.2,timeline:F,range:P,stagger:k=40,durationStep:M=0,reverse:O=!1,render:R,className:q,style:z,...B},C){const D=a.useMemo(()=>function partsOf(e,r){return"character"===r?Array.from(e):e.split(/(\s+)/).filter(e=>""!==e)}(f,u),[f,u]),E=d({trigger:"view"===F?"mount":b,play:v,once:A,threshold:$,paused:S,infinite:o(w)}),G={duration:y,delay:j,easing:x,repeat:w,alternate:N,mode:g,timeline:F,range:P},H=D.filter(e=>""!==e.trim()).length,I=`${i} ${s[h]}`;let J=-1;return n({render:R??e("span",{}),ref:[C,E.ref],props:{...B,className:p(q),style:z,...E.handlers,"data-plass-animation":h,"data-state":E.state,children:t(r,{children:[e("span",{className:c,children:f}),e("span",{"aria-hidden":"true",children:D.map((r,t)=>""===r.trim()?e(a.Fragment,{children:r},t):(J+=1,e("span",{className:`${I} inline-block whitespace-pre`,style:{...l(m(G,{index:J,count:H,stagger:k,durationStep:M,reverse:O})),"--p-anim-state":E.state},children:r},t)))})]})}})});
1
+ "use client";import{jsx as e,Fragment as t,jsxs as r}from"react/jsx-runtime";import*as a from"react";import{mergeProps as n}from"@base-ui/react/merge-props";import{useRender as i}from"@base-ui/react/use-render";import{animBaseClass as s,animationClasses as o,animationSlots as c,isInfinite as p,revealClip as l,slideOffsets as m,staggerSlots as d,useAnimationRun as u}from"../../internal/animate.js";import{cx as f,srOnlyCopyClasses as g}from"../../internal/styles.js";import{graphemesOf as h}from"../../internal/text.js";const y=/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Bopomofo}\p{Script=Thai}\p{Script=Lao}\p{Script=Khmer}\p{Script=Myanmar}]/u;function effectStart(e){switch(e){case"slide":return{opacity:0,...m("bottom","100%")};case"grow":return{opacity:0,scale:.8};case"zoom":return{opacity:0,scale:.4};case"rotate":return{opacity:0,angle:"-180deg",angleTo:"0deg"};case"reveal":return{opacity:1,clip:l("left")};default:return{opacity:0}}}export const PlAnimateSplit=/* @__PURE__ */a.forwardRef(function PlAnimateSplit({children:l,by:m="word",effect:S="fade",mode:w="in",duration:b=400,delay:j=0,easing:x,repeat:N=1,alternate:v,paused:k,trigger:$="mount",play:A,once:F=!0,threshold:H=.2,timeline:K,range:M,stagger:P=40,durationStep:T=0,reverse:z=!1,render:B,className:L,style:O,...R},q){const C=a.useMemo(()=>function piecesOf(e,t){const r=[];for(const a of e.split(/(\s+)/)){if(""===a)continue;if("word"===t||""===a.trim()){r.push([a]);continue}let e=[];for(const t of h(a))0===e.length||y.test(t)?(e=[t],r.push(e)):e.push(t)}return r}(l,m),[l,m]),D=u({trigger:"view"===K?"mount":$,play:A,once:F,threshold:H,paused:k,infinite:p(N)}),E={...effectStart(S),duration:b,delay:j,easing:x,repeat:N,alternate:v,mode:w,timeline:K,range:M},G=C.reduce((e,t)=>""===t[0].trim()?e:e+t.length,0),I=`${s} ${o[S]}`;let J=-1;const renderPart=(t,r)=>(J+=1,e("span",{className:`${I} inline-block whitespace-normal`,style:{...c(d(E,{index:J,count:G,stagger:P,durationStep:T,reverse:z})),"--p-anim-state":D.state},children:t},r));return i({render:B??e("span",{}),ref:[q,D.ref],props:{...n(R,D.handlers),className:f(L),style:O,"data-plass-animation":S,"data-state":D.state,children:r(t,{children:[e("span",{className:g,children:l}),e("span",{"aria-hidden":"true",children:C.map((t,r)=>""===t[0].trim()?e(a.Fragment,{children:t[0]},r):1===t.length?renderPart(t[0],r):e("span",{className:"inline-block",children:t.map((e,t)=>renderPart(e,t))},r))})]})}})});
@@ -42,8 +42,9 @@ export interface PlAnimateTypingProps extends Omit<PlassAnimateProps, 'alternate
42
42
  * for a screen reader, which reads it once and is not made to sit through the
43
43
  * performance — and what animates is a visible copy that is `aria-hidden`. So
44
44
  * the effect costs a reader who cannot see it nothing, and costs a reader who
45
- * can nothing either: the box is not laid out from the characters that have
46
- * arrived, so the text around it does not reflow on every frame.
45
+ * can nothing either: the characters still to come are laid out after the
46
+ * caret without being drawn, so the box holds the whole string from the first
47
+ * frame and nothing around it moves as the text arrives.
47
48
  *
48
49
  * `repeat`, `hold` and `erase` are what make it a loop: type, hold, delete,
49
50
  * type again. Without `erase` a repeat clears in one frame, which is right for
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{isInfinite as n,useAnimationRun as a}from"../../internal/animate.js";import{usePrefersReducedMotion as i}from"../../internal/media.js";import{srOnlyClasses as s}from"../../internal/styles.js";function textOf(e){return"string"==typeof e||"number"==typeof e?String(e):Array.isArray(e)?e.map(textOf).join(""):""}export const PlAnimateTyping=/* @__PURE__ */r.forwardRef(function PlAnimateTyping({text:o,speed:u=24,hold:m=1400,erase:l=!1,eraseSpeed:c,caret:f=!0,caretChar:p="|",duration:d,delay:h=0,repeat:g=1,paused:y,trigger:x="mount",play:T,once:j=!0,threshold:v=.2,className:N,style:S,children:w,...A},M){const O=a({trigger:x,play:T,once:j,threshold:v,paused:y,infinite:n(g)}),I=i(),E=o??textOf(w),P=r.useMemo(()=>function graphemesOf(e,t){return"undefined"!=typeof Intl&&"Segmenter"in Intl?[...new Intl.Segmenter(t,{granularity:"grapheme"}).segment(e)].map(e=>e.segment):[...e]}(E),[E]),R=P.length,[b,C]=r.useState(0),k=r.useRef(0),q=d&&R>0?d/R:1e3/Math.max(u,1),z=1e3/Math.max(c??2*u,1);return r.useEffect(()=>{k.current=0},[R]),r.useEffect(()=>{if(I||0===R)return void C(R);if(!O.started)return k.current=0,void C(0);if(y)return;let e,t=!1,r=k.current,n=1,a=!1;const i="infinite"===g?1/0:Math.max(1,g);if(r>=R&&1===i)return;const step=()=>{if(!t){if(a)return r-=1,k.current=r,C(r),r<=0&&(a=!1,n+=1),void(e=setTimeout(step,a?z:q));if(r+=1,k.current=r,C(r),r<R)e=setTimeout(step,q);else if(!(n>=i)){if(l)return a=!0,void(e=setTimeout(step,m));n+=1,e=setTimeout(()=>{t||(r=0,k.current=0,C(0),e=setTimeout(step,q))},m)}}};return C(r),e=setTimeout(step,0===r?h:q),()=>{t=!0,clearTimeout(e)}},[O.started,y,I,R,q,z,h,m,l,g]),t("div",{ref:e=>{O.ref(e),"function"==typeof M?M(e):M&&(M.current=e)},className:N,style:S,"data-plass-animation":"typing","data-state":O.state,...O.handlers,...A,children:[e("span",{className:s,children:E}),t("span",{"aria-hidden":"true",className:"whitespace-pre-wrap",children:[P.slice(0,b).join(""),f?e("span",{className:"plass-caret",children:p}):null]})]})});
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{mergeProps as a}from"@base-ui/react/merge-props";import{isInfinite as s,useAnimationRun as i}from"../../internal/animate.js";import{usePrefersReducedMotion as n}from"../../internal/media.js";import{srOnlyCopyClasses as l}from"../../internal/styles.js";import{graphemesOf as o,textOf as c}from"../../internal/text.js";export const PlAnimateTyping=/* @__PURE__ */r.forwardRef(function PlAnimateTyping({text:m,speed:u=24,hold:p=1400,erase:d=!1,eraseSpeed:f,caret:h=!0,caretChar:y="|",duration:g,delay:j=0,repeat:x=1,paused:T,trigger:v="mount",play:N,once:b=!0,threshold:M=.2,className:w,style:A,children:E,...P},R){const S=i({trigger:v,play:N,once:b,threshold:M,paused:T,infinite:s(x)}),k=n(),C=m??c(E),q=r.useMemo(()=>o(C),[C]),z=q.length,[B,D]=r.useState(0),F=r.useRef(0),G=g&&z>0?g/z:1e3/Math.max(u,1),H=1e3/Math.max(f??2*u,1);return r.useEffect(()=>{F.current=0},[C,S.runs]),r.useEffect(()=>{if(k||0===z)return void D(z);if(!S.started)return F.current=0,void D(0);if(T)return;let e,t=!1,r=F.current,a=1,s=!1;const i="infinite"===x?1/0:Math.max(1,x);if(r>=z&&1===i)return;const step=()=>{if(!t){if(s)return r-=1,F.current=r,D(r),r<=0&&(s=!1,a+=1),void(e=setTimeout(step,s?H:G));if(r+=1,F.current=r,D(r),r<z)e=setTimeout(step,G);else if(!(a>=i)){if(d)return s=!0,void(e=setTimeout(step,p));a+=1,e=setTimeout(()=>{t||(r=0,F.current=0,D(0),e=setTimeout(step,G))},p)}}};return D(r),e=setTimeout(step,0===r?j:G),()=>{t=!0,clearTimeout(e)}},[S.started,S.runs,C,T,k,z,G,H,j,p,d,x]),t("div",{ref:e=>{S.ref(e),"function"==typeof R?R(e):R&&(R.current=e)},className:w,style:A,"data-plass-animation":"typing","data-state":S.state,...a(P,S.handlers),children:[e("span",{className:l,children:C}),t("span",{"aria-hidden":"true",className:"relative whitespace-pre-wrap",children:[q.slice(0,B).join(""),h?e("span",{className:"plass-caret absolute",children:y}):null,e("span",{"data-sample":q.slice(B).join(""),className:"invisible before:content-[attr(data-sample)]",children:h?e("span",{className:"inline-block",children:y}):null})]})]})});
@@ -1 +1 @@
1
- "use client";import*as e from"react";import{useRender as r}from"@base-ui/react/use-render";import{isInfinite as t,useAnimateElement as a}from"../../internal/animate.js";import{cx as n}from"../../internal/styles.js";export const PlAnimateZoom=/* @__PURE__ */e.forwardRef(function PlAnimateZoom({duration:e=320,delay:i=0,easing:o,repeat:s=1,alternate:l,paused:m,trigger:d="mount",play:c,once:p=!0,threshold:f=.2,timeline:g,range:u,stagger:y=0,durationStep:h=0,reverse:N=!1,mode:j="in",from:v=.4,fade:A=!0,render:P,className:S,style:Z,children:b,...w},x){const z=a({effect:"zoom",duration:e,delay:i,easing:o,repeat:s,alternate:l,mode:j,scale:v,opacity:A?0:1,trigger:d,play:c,once:p,threshold:f,paused:m,infinite:t(s),timeline:g,range:u,origin:"center",stagger:y,durationStep:h,reverse:N,children:b});return r({render:P,ref:[x,z.ref],props:{...w,className:n(z.className,S),style:{...z.style,...Z},...z.props,children:z.children}})});
1
+ "use client";import*as e from"react";import{mergeProps as r}from"@base-ui/react/merge-props";import{useRender as t}from"@base-ui/react/use-render";import{isInfinite as a,useAnimateElement as n}from"../../internal/animate.js";import{cx as o}from"../../internal/styles.js";export const PlAnimateZoom=/* @__PURE__ */e.forwardRef(function PlAnimateZoom({duration:e=320,delay:i=0,easing:s,repeat:l=1,alternate:m,paused:d,trigger:p="mount",play:c,once:f=!0,threshold:g=.2,timeline:u,range:y,stagger:h=0,durationStep:N=0,reverse:b=!1,mode:j="in",from:v=.4,fade:A=!0,render:P,className:S,style:Z,children:w,...x},z){const R=n({effect:"zoom",duration:e,delay:i,easing:s,repeat:l,alternate:m,mode:j,scale:v,opacity:A?0:1,trigger:p,play:c,once:f,threshold:g,paused:d,infinite:a(l),timeline:u,range:y,origin:"center",stagger:h,durationStep:N,reverse:b,children:w});return t({render:P,ref:[z,R.ref],props:{...r(x,R.props),className:o(R.className,S),style:{...R.style,...Z},children:R.children}})});