@funstack/ui 0.1.0-alpha.1 → 0.1.0-alpha.3

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 (288) hide show
  1. package/dist/accordion/accordion-context.mjs.map +1 -1
  2. package/dist/accordion/accordion-item.mjs +18 -4
  3. package/dist/accordion/accordion-item.mjs.map +1 -1
  4. package/dist/accordion/accordion-panel.mjs +2 -3
  5. package/dist/accordion/accordion-panel.mjs.map +1 -1
  6. package/dist/accordion/accordion-root.d.mts.map +1 -1
  7. package/dist/accordion/accordion-root.mjs +32 -14
  8. package/dist/accordion/accordion-root.mjs.map +1 -1
  9. package/dist/accordion/accordion-trigger.mjs +4 -5
  10. package/dist/accordion/accordion-trigger.mjs.map +1 -1
  11. package/dist/checkbox/checkbox.d.mts +5 -3
  12. package/dist/checkbox/checkbox.d.mts.map +1 -1
  13. package/dist/checkbox/checkbox.mjs +25 -9
  14. package/dist/checkbox/checkbox.mjs.map +1 -1
  15. package/dist/checkbox-group/checkbox-group-context.mjs.map +1 -1
  16. package/dist/checkbox-group/checkbox-group-item.d.mts +2 -1
  17. package/dist/checkbox-group/checkbox-group-item.d.mts.map +1 -1
  18. package/dist/checkbox-group/checkbox-group-item.mjs +3 -1
  19. package/dist/checkbox-group/checkbox-group-item.mjs.map +1 -1
  20. package/dist/checkbox-group/checkbox-group-root.d.mts +5 -2
  21. package/dist/checkbox-group/checkbox-group-root.d.mts.map +1 -1
  22. package/dist/checkbox-group/checkbox-group-root.mjs +24 -5
  23. package/dist/checkbox-group/checkbox-group-root.mjs.map +1 -1
  24. package/dist/combobox/combobox-clear.d.mts +34 -0
  25. package/dist/combobox/combobox-clear.d.mts.map +1 -0
  26. package/dist/combobox/combobox-clear.mjs +58 -0
  27. package/dist/combobox/combobox-clear.mjs.map +1 -0
  28. package/dist/combobox/combobox-context.mjs +23 -0
  29. package/dist/combobox/combobox-context.mjs.map +1 -0
  30. package/dist/combobox/combobox-group.d.mts +72 -0
  31. package/dist/combobox/combobox-group.d.mts.map +1 -0
  32. package/dist/combobox/combobox-group.mjs +104 -0
  33. package/dist/combobox/combobox-group.mjs.map +1 -0
  34. package/dist/combobox/combobox-input.d.mts +42 -0
  35. package/dist/combobox/combobox-input.d.mts.map +1 -0
  36. package/dist/combobox/combobox-input.mjs +102 -0
  37. package/dist/combobox/combobox-input.mjs.map +1 -0
  38. package/dist/combobox/combobox-label.d.mts +22 -0
  39. package/dist/combobox/combobox-label.d.mts.map +1 -0
  40. package/dist/combobox/combobox-label.mjs +32 -0
  41. package/dist/combobox/combobox-label.mjs.map +1 -0
  42. package/dist/combobox/combobox-list.d.mts +37 -0
  43. package/dist/combobox/combobox-list.d.mts.map +1 -0
  44. package/dist/combobox/combobox-list.mjs +70 -0
  45. package/dist/combobox/combobox-list.mjs.map +1 -0
  46. package/dist/combobox/combobox-option.d.mts +45 -0
  47. package/dist/combobox/combobox-option.d.mts.map +1 -0
  48. package/dist/combobox/combobox-option.mjs +88 -0
  49. package/dist/combobox/combobox-option.mjs.map +1 -0
  50. package/dist/combobox/combobox-popup.d.mts +49 -0
  51. package/dist/combobox/combobox-popup.d.mts.map +1 -0
  52. package/dist/combobox/combobox-popup.mjs +86 -0
  53. package/dist/combobox/combobox-popup.mjs.map +1 -0
  54. package/dist/combobox/combobox-root.d.mts +135 -0
  55. package/dist/combobox/combobox-root.d.mts.map +1 -0
  56. package/dist/combobox/combobox-root.mjs +523 -0
  57. package/dist/combobox/combobox-root.mjs.map +1 -0
  58. package/dist/combobox/combobox-trigger.d.mts +36 -0
  59. package/dist/combobox/combobox-trigger.d.mts.map +1 -0
  60. package/dist/combobox/combobox-trigger.mjs +92 -0
  61. package/dist/combobox/combobox-trigger.mjs.map +1 -0
  62. package/dist/combobox/index.d.mts +36 -0
  63. package/dist/combobox/index.d.mts.map +1 -0
  64. package/dist/combobox/index.mjs +36 -0
  65. package/dist/combobox/index.mjs.map +1 -0
  66. package/dist/dialog/dialog-close.d.mts +17 -10
  67. package/dist/dialog/dialog-close.d.mts.map +1 -1
  68. package/dist/dialog/dialog-close.mjs +31 -20
  69. package/dist/dialog/dialog-close.mjs.map +1 -1
  70. package/dist/dialog/dialog-context.mjs.map +1 -1
  71. package/dist/dialog/dialog-form.d.mts +12 -5
  72. package/dist/dialog/dialog-form.d.mts.map +1 -1
  73. package/dist/dialog/dialog-form.mjs +16 -28
  74. package/dist/dialog/dialog-form.mjs.map +1 -1
  75. package/dist/dialog/dialog-popup.d.mts +10 -4
  76. package/dist/dialog/dialog-popup.d.mts.map +1 -1
  77. package/dist/dialog/dialog-popup.mjs +106 -41
  78. package/dist/dialog/dialog-popup.mjs.map +1 -1
  79. package/dist/dialog/dialog-root.d.mts +14 -8
  80. package/dist/dialog/dialog-root.d.mts.map +1 -1
  81. package/dist/dialog/dialog-root.mjs +66 -11
  82. package/dist/dialog/dialog-root.mjs.map +1 -1
  83. package/dist/dialog/dialog-trigger.d.mts +3 -2
  84. package/dist/dialog/dialog-trigger.d.mts.map +1 -1
  85. package/dist/dialog/dialog-trigger.mjs.map +1 -1
  86. package/dist/dialog/index.d.mts +4 -2
  87. package/dist/dialog/index.d.mts.map +1 -1
  88. package/dist/dialog/index.mjs +4 -2
  89. package/dist/dialog/index.mjs.map +1 -1
  90. package/dist/field/field-control.d.mts +33 -0
  91. package/dist/field/field-control.d.mts.map +1 -0
  92. package/dist/field/field-control.mjs +68 -0
  93. package/dist/field/field-control.mjs.map +1 -0
  94. package/dist/field/field-description.d.mts +24 -0
  95. package/dist/field/field-description.d.mts.map +1 -0
  96. package/dist/field/field-description.mjs +34 -0
  97. package/dist/field/field-description.mjs.map +1 -0
  98. package/dist/field/field-error.d.mts +30 -0
  99. package/dist/field/field-error.d.mts.map +1 -0
  100. package/dist/field/field-error.mjs +42 -0
  101. package/dist/field/field-error.mjs.map +1 -0
  102. package/dist/field/field-label.d.mts +25 -0
  103. package/dist/field/field-label.d.mts.map +1 -0
  104. package/dist/field/field-label.mjs +46 -0
  105. package/dist/field/field-label.mjs.map +1 -0
  106. package/dist/field/field-root.d.mts +53 -0
  107. package/dist/field/field-root.d.mts.map +1 -0
  108. package/dist/field/field-root.mjs +317 -0
  109. package/dist/field/field-root.mjs.map +1 -0
  110. package/dist/field/index.d.mts +18 -0
  111. package/dist/field/index.d.mts.map +1 -0
  112. package/dist/field/index.mjs +17 -0
  113. package/dist/field/index.mjs.map +1 -0
  114. package/dist/form/form-root.d.mts +58 -0
  115. package/dist/form/form-root.d.mts.map +1 -0
  116. package/dist/form/form-root.mjs +146 -0
  117. package/dist/form/form-root.mjs.map +1 -0
  118. package/dist/form/form-submit.d.mts +31 -0
  119. package/dist/form/form-submit.d.mts.map +1 -0
  120. package/dist/form/form-submit.mjs +52 -0
  121. package/dist/form/form-submit.mjs.map +1 -0
  122. package/dist/form/index.d.mts +11 -0
  123. package/dist/form/index.d.mts.map +1 -0
  124. package/dist/form/index.mjs +11 -0
  125. package/dist/form/index.mjs.map +1 -0
  126. package/dist/index.d.mts +46 -2
  127. package/dist/index.mjs +8 -1
  128. package/dist/internal/content-focus-probe.mjs +42 -0
  129. package/dist/internal/content-focus-probe.mjs.map +1 -0
  130. package/dist/internal/field-context.d.mts +19 -0
  131. package/dist/internal/field-context.d.mts.map +1 -0
  132. package/dist/internal/field-context.mjs +14 -0
  133. package/dist/internal/field-context.mjs.map +1 -0
  134. package/dist/internal/focus-first-invalid.mjs +67 -0
  135. package/dist/internal/focus-first-invalid.mjs.map +1 -0
  136. package/dist/internal/form-status-watcher.mjs +31 -0
  137. package/dist/internal/form-status-watcher.mjs.map +1 -0
  138. package/dist/internal/modal-registry.mjs +39 -0
  139. package/dist/internal/modal-registry.mjs.map +1 -0
  140. package/dist/internal/platform-attributes.d.mts +12 -1
  141. package/dist/internal/platform-attributes.d.mts.map +1 -1
  142. package/dist/internal/types.d.mts +11 -1
  143. package/dist/internal/types.d.mts.map +1 -1
  144. package/dist/internal/use-controllable-action.mjs +35 -13
  145. package/dist/internal/use-controllable-action.mjs.map +1 -1
  146. package/dist/internal/use-field-control.mjs +107 -0
  147. package/dist/internal/use-field-control.mjs.map +1 -0
  148. package/dist/internal/use-form-owner-event.mjs +44 -0
  149. package/dist/internal/use-form-owner-event.mjs.map +1 -0
  150. package/dist/internal/use-form-reset.mjs +12 -31
  151. package/dist/internal/use-form-reset.mjs.map +1 -1
  152. package/dist/internal/use-hydrated-mount.mjs +21 -0
  153. package/dist/internal/use-hydrated-mount.mjs.map +1 -0
  154. package/dist/internal/use-latest.mjs +32 -0
  155. package/dist/internal/use-latest.mjs.map +1 -0
  156. package/dist/internal/use-modal-registration.mjs +47 -0
  157. package/dist/internal/use-modal-registration.mjs.map +1 -0
  158. package/dist/internal/use-native-group-reconciliation.mjs +6 -5
  159. package/dist/internal/use-native-group-reconciliation.mjs.map +1 -1
  160. package/dist/internal/use-native-select-value.mjs +184 -0
  161. package/dist/internal/use-native-select-value.mjs.map +1 -0
  162. package/dist/internal/use-popover-popup.mjs +8 -22
  163. package/dist/internal/use-popover-popup.mjs.map +1 -1
  164. package/dist/internal/use-popover-root.mjs +58 -23
  165. package/dist/internal/use-popover-root.mjs.map +1 -1
  166. package/dist/internal/validity.d.mts +24 -0
  167. package/dist/internal/validity.d.mts.map +1 -0
  168. package/dist/internal/validity.mjs +108 -0
  169. package/dist/internal/validity.mjs.map +1 -0
  170. package/dist/menu/menu-group.d.mts.map +1 -1
  171. package/dist/menu/menu-group.mjs +3 -2
  172. package/dist/menu/menu-group.mjs.map +1 -1
  173. package/dist/menu/menu-radio-group.mjs +9 -4
  174. package/dist/menu/menu-radio-group.mjs.map +1 -1
  175. package/dist/menu/menu-root.mjs.map +1 -1
  176. package/dist/radio-group/radio-group-root.d.mts +4 -2
  177. package/dist/radio-group/radio-group-root.d.mts.map +1 -1
  178. package/dist/radio-group/radio-group-root.mjs +34 -8
  179. package/dist/radio-group/radio-group-root.mjs.map +1 -1
  180. package/dist/select/index.d.mts +30 -0
  181. package/dist/select/index.d.mts.map +1 -0
  182. package/dist/select/index.mjs +30 -0
  183. package/dist/select/index.mjs.map +1 -0
  184. package/dist/select/select-context.mjs +13 -0
  185. package/dist/select/select-context.mjs.map +1 -0
  186. package/dist/select/select-dom.mjs +44 -0
  187. package/dist/select/select-dom.mjs.map +1 -0
  188. package/dist/select/select-group-label.d.mts +22 -0
  189. package/dist/select/select-group-label.d.mts.map +1 -0
  190. package/dist/select/select-group-label.mjs +39 -0
  191. package/dist/select/select-group-label.mjs.map +1 -0
  192. package/dist/select/select-group.d.mts +28 -0
  193. package/dist/select/select-group.d.mts.map +1 -0
  194. package/dist/select/select-group.mjs +47 -0
  195. package/dist/select/select-group.mjs.map +1 -0
  196. package/dist/select/select-option.d.mts +42 -0
  197. package/dist/select/select-option.d.mts.map +1 -0
  198. package/dist/select/select-option.mjs +65 -0
  199. package/dist/select/select-option.mjs.map +1 -0
  200. package/dist/select/select-root.d.mts +68 -0
  201. package/dist/select/select-root.d.mts.map +1 -0
  202. package/dist/select/select-root.mjs +114 -0
  203. package/dist/select/select-root.mjs.map +1 -0
  204. package/dist/select/select-separator.d.mts +20 -0
  205. package/dist/select/select-separator.d.mts.map +1 -0
  206. package/dist/select/select-separator.mjs +30 -0
  207. package/dist/select/select-separator.mjs.map +1 -0
  208. package/dist/select/select-trigger.d.mts +29 -0
  209. package/dist/select/select-trigger.d.mts.map +1 -0
  210. package/dist/select/select-trigger.mjs +48 -0
  211. package/dist/select/select-trigger.mjs.map +1 -0
  212. package/dist/select/select-value.d.mts +31 -0
  213. package/dist/select/select-value.d.mts.map +1 -0
  214. package/dist/select/select-value.mjs +101 -0
  215. package/dist/select/select-value.mjs.map +1 -0
  216. package/dist/slider/index.d.mts +32 -0
  217. package/dist/slider/index.d.mts.map +1 -0
  218. package/dist/slider/index.mjs +27 -0
  219. package/dist/slider/index.mjs.map +1 -0
  220. package/dist/slider/slider-arithmetic.mjs +120 -0
  221. package/dist/slider/slider-arithmetic.mjs.map +1 -0
  222. package/dist/slider/slider-context.mjs +13 -0
  223. package/dist/slider/slider-context.mjs.map +1 -0
  224. package/dist/slider/slider-indicator.d.mts +22 -0
  225. package/dist/slider/slider-indicator.d.mts.map +1 -0
  226. package/dist/slider/slider-indicator.mjs +36 -0
  227. package/dist/slider/slider-indicator.mjs.map +1 -0
  228. package/dist/slider/slider-label.d.mts +23 -0
  229. package/dist/slider/slider-label.d.mts.map +1 -0
  230. package/dist/slider/slider-label.mjs +44 -0
  231. package/dist/slider/slider-label.mjs.map +1 -0
  232. package/dist/slider/slider-root.d.mts +111 -0
  233. package/dist/slider/slider-root.d.mts.map +1 -0
  234. package/dist/slider/slider-root.mjs +582 -0
  235. package/dist/slider/slider-root.mjs.map +1 -0
  236. package/dist/slider/slider-thumb.d.mts +58 -0
  237. package/dist/slider/slider-thumb.d.mts.map +1 -0
  238. package/dist/slider/slider-thumb.mjs +145 -0
  239. package/dist/slider/slider-thumb.mjs.map +1 -0
  240. package/dist/slider/slider-track.d.mts +29 -0
  241. package/dist/slider/slider-track.d.mts.map +1 -0
  242. package/dist/slider/slider-track.mjs +54 -0
  243. package/dist/slider/slider-track.mjs.map +1 -0
  244. package/dist/slider/slider-value.d.mts +34 -0
  245. package/dist/slider/slider-value.d.mts.map +1 -0
  246. package/dist/slider/slider-value.mjs +38 -0
  247. package/dist/slider/slider-value.mjs.map +1 -0
  248. package/dist/switch/switch.d.mts +5 -3
  249. package/dist/switch/switch.d.mts.map +1 -1
  250. package/dist/switch/switch.mjs +24 -8
  251. package/dist/switch/switch.mjs.map +1 -1
  252. package/dist/tabs/tabs-root.mjs +13 -3
  253. package/dist/tabs/tabs-root.mjs.map +1 -1
  254. package/dist/toast/index.d.mts +25 -0
  255. package/dist/toast/index.d.mts.map +1 -0
  256. package/dist/toast/index.mjs +26 -0
  257. package/dist/toast/index.mjs.map +1 -0
  258. package/dist/toast/toast-action.d.mts +39 -0
  259. package/dist/toast/toast-action.d.mts.map +1 -0
  260. package/dist/toast/toast-action.mjs +64 -0
  261. package/dist/toast/toast-action.mjs.map +1 -0
  262. package/dist/toast/toast-close.d.mts +25 -0
  263. package/dist/toast/toast-close.d.mts.map +1 -0
  264. package/dist/toast/toast-close.mjs +46 -0
  265. package/dist/toast/toast-close.mjs.map +1 -0
  266. package/dist/toast/toast-context.mjs +19 -0
  267. package/dist/toast/toast-context.mjs.map +1 -0
  268. package/dist/toast/toast-description.d.mts +24 -0
  269. package/dist/toast/toast-description.d.mts.map +1 -0
  270. package/dist/toast/toast-description.mjs +35 -0
  271. package/dist/toast/toast-description.mjs.map +1 -0
  272. package/dist/toast/toast-root.d.mts +43 -0
  273. package/dist/toast/toast-root.d.mts.map +1 -0
  274. package/dist/toast/toast-root.mjs +204 -0
  275. package/dist/toast/toast-root.mjs.map +1 -0
  276. package/dist/toast/toast-title.d.mts +24 -0
  277. package/dist/toast/toast-title.d.mts.map +1 -0
  278. package/dist/toast/toast-title.mjs +33 -0
  279. package/dist/toast/toast-title.mjs.map +1 -0
  280. package/dist/toast/toast-viewport.d.mts +52 -0
  281. package/dist/toast/toast-viewport.d.mts.map +1 -0
  282. package/dist/toast/toast-viewport.mjs +621 -0
  283. package/dist/toast/toast-viewport.mjs.map +1 -0
  284. package/dist/toast/toast.d.mts +119 -0
  285. package/dist/toast/toast.d.mts.map +1 -0
  286. package/dist/toast/toast.mjs +153 -0
  287. package/dist/toast/toast.mjs.map +1 -0
  288. package/package.json +7 -1
@@ -0,0 +1,43 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { ToastItem, ToastPriority } from "./toast.mjs";
3
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
4
+ //#region src/toast/toast-root.d.ts
5
+ export interface ToastRootState {
6
+ readonly toast: ToastItem;
7
+ /** `toast.pending`: its promise is unsettled or its Action runs. */
8
+ readonly pending: boolean;
9
+ /** `toast.ending`: closed, kept for its exit animation. */
10
+ readonly ending: boolean;
11
+ readonly type: string | undefined;
12
+ readonly priority: ToastPriority;
13
+ }
14
+ export interface ToastRootProps extends Omit<ComponentPropsWithRef<"div">, "role" | "className" | "style" | "children" | "onKeyDown"> {
15
+ /** The toast to render: an item of the Viewport's `state.toasts`. */
16
+ toast: ToastItem;
17
+ children?: StateValue<ReactNode, ToastRootState>;
18
+ className?: StateValue<string | undefined, ToastRootState>;
19
+ style?: StateValue<CSSProperties | undefined, ToastRootState>;
20
+ render?: RenderProp<ComponentPropsWithRef<"div">, ToastRootState>;
21
+ /**
22
+ * Rendered by the Root's own Suspense guard while `children` suspend, in place of the
23
+ * invisible default. The toast's timer and announcement wait for the reveal either way.
24
+ * Parts inside it (a visually hidden `<Toast.Title>` giving the toast a name) gate nothing.
25
+ */
26
+ fallback?: ReactNode;
27
+ }
28
+ /**
29
+ * One toast: a focusable `div[role=dialog]` (`alertdialog` for `priority: "high"`) named by its
30
+ * Title and described by its Description. Escape dismisses it, ArrowDown / ArrowUp move to the
31
+ * next / previous toast. Its children render inside a Suspense guard whose fallback is the
32
+ * `fallback` prop (invisible by default), so a toast whose content suspends does not pull the whole Viewport into a boundary above it.
33
+ * When the toast closes it stays with `data-ending` (and `inert`) until its exit animations end.
34
+ *
35
+ * Owned keys (conventions 1.2): `role`, `tabIndex`, `aria-labelledby`, `aria-describedby`,
36
+ * `inert`, `data-type`, `data-pending`, `data-ending`, `onKeyDown`.
37
+ */
38
+ export declare function ToastRoot({ toast: item, children, className, style, render, fallback, ...rest }: ToastRootProps): import("react").JSX.Element;
39
+ export declare namespace ToastRoot {
40
+ var displayName: string;
41
+ }
42
+ //#endregion
43
+ //# sourceMappingURL=toast-root.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-root.d.mts","names":[],"sources":["../../src/toast/toast-root.tsx"],"mappings":";;;;iBAaiB;WACN,OAAO;;WAEP;;WAEA;WACA;WACA,UAAU;;iBAGJ,uBAAuB,KACtC;;EAIA,OAAO;EACP,WAAW,WAAW,WAAW;EACjC,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,SAAS,WAAW,8BAA8B;;;;;;EAMlD,WAAW;;;;;;;;;;;;wBA2BG,YACd,OAAO,MACP,UACA,WACA,OACA,QACA,aACG,QACF,iCAAc,IAAA;yBARD"}
@@ -0,0 +1,204 @@
1
+ "use client";
2
+ import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { useLatest } from "../internal/use-latest.mjs";
4
+ import { resolveStateValue, useRender } from "../internal/use-render.mjs";
5
+ import { exitAnimations } from "../internal/use-exit-animation.mjs";
6
+ import { ToastRootContext, useToastRootContext, useToastViewportContext } from "./toast-context.mjs";
7
+ import { Suspense, useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ //#region src/toast/toast-root.tsx
10
+ /**
11
+ * The Suspense guard's fallback: renders the Root's `fallback` (nothing by default) and tells
12
+ * the Root its content is suspended, so the timer and the announcement wait for the reveal
13
+ * (design 3.5, 21).
14
+ */
15
+ function SuspenseGuard({ children }) {
16
+ const { setSuspended } = useToastRootContext("Toast.Root");
17
+ useLayoutEffect(() => {
18
+ setSuspended(true);
19
+ return () => setSuspended(false);
20
+ }, [setSuspended]);
21
+ return children;
22
+ }
23
+ /**
24
+ * One toast: a focusable `div[role=dialog]` (`alertdialog` for `priority: "high"`) named by its
25
+ * Title and described by its Description. Escape dismisses it, ArrowDown / ArrowUp move to the
26
+ * next / previous toast. Its children render inside a Suspense guard whose fallback is the
27
+ * `fallback` prop (invisible by default), so a toast whose content suspends does not pull the whole Viewport into a boundary above it.
28
+ * When the toast closes it stays with `data-ending` (and `inert`) until its exit animations end.
29
+ *
30
+ * Owned keys (conventions 1.2): `role`, `tabIndex`, `aria-labelledby`, `aria-describedby`,
31
+ * `inert`, `data-type`, `data-pending`, `data-ending`, `onKeyDown`.
32
+ */
33
+ function ToastRoot({ toast: item, children, className, style, render, fallback = null, ...rest }) {
34
+ const viewport = useToastViewportContext("Toast.Root");
35
+ const id = item.id;
36
+ const baseId = useId();
37
+ const ids = useMemo(() => ({
38
+ title: `${baseId}title`,
39
+ description: `${baseId}description`
40
+ }), [baseId]);
41
+ const elementRef = useRef(null);
42
+ const titleRef = useRef(null);
43
+ const descriptionRef = useRef(null);
44
+ const pendingTokens = useRef(/* @__PURE__ */ new Set());
45
+ const [actionPending, setActionPendingState] = useState(false);
46
+ const suspendedRef = useRef(false);
47
+ const [suspended, setSuspendedState] = useState(false);
48
+ const idRef = useLatest(id);
49
+ const announcedOnce = useRef(false);
50
+ const revealQueued = useRef(false);
51
+ const setActionPending = useCallback((token, pending) => {
52
+ const tokens = pendingTokens.current;
53
+ if (pending) tokens.add(token);
54
+ else tokens.delete(token);
55
+ const any = tokens.size > 0;
56
+ setActionPendingState(any);
57
+ viewport.setActionPending(idRef.current, any);
58
+ }, [viewport, idRef]);
59
+ const setSuspended = useCallback((value) => {
60
+ suspendedRef.current = value;
61
+ setSuspendedState(value);
62
+ viewport.setSuspended(idRef.current, value);
63
+ }, [viewport, idRef]);
64
+ const close = useCallback((reason, event) => viewport.close([idRef.current], reason, event), [viewport, idRef]);
65
+ const registerTitle = useCallback((element) => {
66
+ titleRef.current = element;
67
+ }, []);
68
+ const registerDescription = useCallback((element) => {
69
+ descriptionRef.current = element;
70
+ }, []);
71
+ const pending = item.pending || actionPending;
72
+ const priority = item.priority ?? "normal";
73
+ const announceNow = () => {
74
+ if (item.ending || suspendedRef.current) return;
75
+ const resolver = item.announce ?? viewport.announcer();
76
+ let text;
77
+ if (resolver !== void 0) text = resolver(item);
78
+ else text = [titleRef.current?.textContent, descriptionRef.current?.textContent].map((t) => (t ?? "").trim()).filter((t) => t !== "").join(" ");
79
+ viewport.announce(item.id, text, priority);
80
+ };
81
+ const announceRef = useLatest(announceNow);
82
+ const contentCommitted = useCallback(() => {
83
+ if (!announcedOnce.current || revealQueued.current) return;
84
+ revealQueued.current = true;
85
+ queueMicrotask(() => {
86
+ revealQueued.current = false;
87
+ announceRef.current();
88
+ });
89
+ }, [announceRef]);
90
+ const state = useMemo(() => ({
91
+ toast: item,
92
+ pending,
93
+ ending: item.ending,
94
+ type: item.type,
95
+ priority
96
+ }), [
97
+ item,
98
+ pending,
99
+ priority
100
+ ]);
101
+ const context = useMemo(() => ({
102
+ toast: item,
103
+ ids,
104
+ state,
105
+ registerTitle,
106
+ registerDescription,
107
+ contentCommitted,
108
+ setActionPending,
109
+ setSuspended,
110
+ close
111
+ }), [
112
+ item,
113
+ ids,
114
+ state,
115
+ registerTitle,
116
+ registerDescription,
117
+ contentCommitted,
118
+ setActionPending,
119
+ setSuspended,
120
+ close
121
+ ]);
122
+ const rootRef = useCallback((element) => {
123
+ elementRef.current = element;
124
+ viewport.registerRoot(id, element);
125
+ return () => {
126
+ if (elementRef.current === element) elementRef.current = null;
127
+ viewport.registerRoot(id, null);
128
+ };
129
+ }, [viewport, id]);
130
+ useLayoutEffect(() => {
131
+ announcedOnce.current = true;
132
+ announceRef.current();
133
+ }, [
134
+ item,
135
+ suspended,
136
+ priority,
137
+ announceRef
138
+ ]);
139
+ useLayoutEffect(() => {
140
+ if (!item.ending) return;
141
+ const element = elementRef.current;
142
+ const baseline = viewport.exitBaseline(item.id);
143
+ const animations = element === null ? [] : exitAnimations(element).filter((animation) => !baseline?.has(animation));
144
+ if (animations.length === 0) {
145
+ viewport.drop(item.id);
146
+ return;
147
+ }
148
+ let cancelled = false;
149
+ Promise.allSettled(animations.map((animation) => animation.finished)).then(() => {
150
+ if (!cancelled) viewport.drop(item.id);
151
+ });
152
+ return () => {
153
+ cancelled = true;
154
+ };
155
+ }, [
156
+ item.ending,
157
+ item.id,
158
+ viewport
159
+ ]);
160
+ const onKeyDown = (event) => {
161
+ if (event.defaultPrevented || item.ending) return;
162
+ if (event.key === "Escape") {
163
+ event.preventDefault();
164
+ close("dismiss", event.nativeEvent);
165
+ } else if (event.key === "ArrowDown" || event.key === "ArrowUp") {
166
+ event.preventDefault();
167
+ viewport.focusSibling(id, event.key === "ArrowDown" ? 1 : -1);
168
+ }
169
+ };
170
+ const libraryProps = {
171
+ role: priority === "high" ? "alertdialog" : "dialog",
172
+ tabIndex: 0,
173
+ "aria-labelledby": ids.title,
174
+ "aria-describedby": ids.description,
175
+ inert: item.ending || void 0,
176
+ "data-type": item.type,
177
+ "data-pending": dataAttr(pending),
178
+ "data-ending": dataAttr(item.ending),
179
+ onKeyDown
180
+ };
181
+ const element = useRender({
182
+ defaultElement: "div",
183
+ render,
184
+ state,
185
+ className,
186
+ style,
187
+ children: (s) => /* @__PURE__ */ jsx(Suspense, {
188
+ fallback: /* @__PURE__ */ jsx(SuspenseGuard, { children: fallback }),
189
+ children: resolveStateValue(children, s)
190
+ }),
191
+ props: rest,
192
+ libraryProps,
193
+ ref: rootRef
194
+ });
195
+ return /* @__PURE__ */ jsx(ToastRootContext, {
196
+ value: context,
197
+ children: element
198
+ });
199
+ }
200
+ ToastRoot.displayName = "ToastRoot";
201
+ //#endregion
202
+ export { ToastRoot };
203
+
204
+ //# sourceMappingURL=toast-root.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-root.mjs","names":[],"sources":["../../src/toast/toast-root.tsx"],"sourcesContent":["\"use client\";\nimport { Suspense, useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, KeyboardEvent, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { exitAnimations } from \"../internal/use-exit-animation.js\";\nimport { useLatest } from \"../internal/use-latest.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport type { ToastItem, ToastPriority } from \"./toast.js\";\nimport { ToastRootContext, useToastRootContext, useToastViewportContext } from \"./toast-context.js\";\nimport type { ToastRootContextValue } from \"./toast-context.js\";\n\nexport interface ToastRootState {\n readonly toast: ToastItem;\n /** `toast.pending`: its promise is unsettled or its Action runs. */\n readonly pending: boolean;\n /** `toast.ending`: closed, kept for its exit animation. */\n readonly ending: boolean;\n readonly type: string | undefined;\n readonly priority: ToastPriority;\n}\n\nexport interface ToastRootProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n \"role\" | \"className\" | \"style\" | \"children\" | \"onKeyDown\"\n> {\n /** The toast to render: an item of the Viewport's `state.toasts`. */\n toast: ToastItem;\n children?: StateValue<ReactNode, ToastRootState>;\n className?: StateValue<string | undefined, ToastRootState>;\n style?: StateValue<CSSProperties | undefined, ToastRootState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ToastRootState>;\n /**\n * Rendered by the Root's own Suspense guard while `children` suspend, in place of the\n * invisible default. The toast's timer and announcement wait for the reveal either way.\n * Parts inside it (a visually hidden `<Toast.Title>` giving the toast a name) gate nothing.\n */\n fallback?: ReactNode;\n}\n\n/**\n * The Suspense guard's fallback: renders the Root's `fallback` (nothing by default) and tells\n * the Root its content is suspended, so the timer and the announcement wait for the reveal\n * (design 3.5, 21).\n */\nfunction SuspenseGuard({ children }: { children: ReactNode }) {\n const { setSuspended } = useToastRootContext(\"Toast.Root\");\n useLayoutEffect(() => {\n setSuspended(true);\n return () => setSuspended(false);\n }, [setSuspended]);\n return children;\n}\n\n/**\n * One toast: a focusable `div[role=dialog]` (`alertdialog` for `priority: \"high\"`) named by its\n * Title and described by its Description. Escape dismisses it, ArrowDown / ArrowUp move to the\n * next / previous toast. Its children render inside a Suspense guard whose fallback is the\n * `fallback` prop (invisible by default), so a toast whose content suspends does not pull the whole Viewport into a boundary above it.\n * When the toast closes it stays with `data-ending` (and `inert`) until its exit animations end.\n *\n * Owned keys (conventions 1.2): `role`, `tabIndex`, `aria-labelledby`, `aria-describedby`,\n * `inert`, `data-type`, `data-pending`, `data-ending`, `onKeyDown`.\n */\nexport function ToastRoot({\n toast: item,\n children,\n className,\n style,\n render,\n fallback = null,\n ...rest\n}: ToastRootProps) {\n const viewport = useToastViewportContext(\"Toast.Root\");\n const id = item.id;\n const baseId = useId();\n const ids = useMemo(\n () => ({ title: `${baseId}title`, description: `${baseId}description` }),\n [baseId],\n );\n const elementRef = useRef<HTMLElement | null>(null);\n const titleRef = useRef<HTMLElement | null>(null);\n const descriptionRef = useRef<HTMLElement | null>(null);\n\n // Action pending, aggregated over the Action parts inside (normally one).\n const pendingTokens = useRef(new Set<object>());\n const [actionPending, setActionPendingState] = useState(false);\n // Suspended content behind the guard: a ref for effects of the same commit, state to re-run\n // the announcement once it reveals.\n const suspendedRef = useRef(false);\n const [suspended, setSuspendedState] = useState(false);\n\n const idRef = useLatest(id);\n // The Root's announcement effect has run once: later Title / Description commits are reveals.\n const announcedOnce = useRef(false);\n const revealQueued = useRef(false);\n\n const setActionPending = useCallback(\n (token: object, pending: boolean) => {\n const tokens = pendingTokens.current;\n if (pending) tokens.add(token);\n else tokens.delete(token);\n const any = tokens.size > 0;\n setActionPendingState(any);\n viewport.setActionPending(idRef.current, any);\n },\n [viewport, idRef],\n );\n\n const setSuspended = useCallback(\n (value: boolean) => {\n suspendedRef.current = value;\n setSuspendedState(value);\n viewport.setSuspended(idRef.current, value);\n },\n [viewport, idRef],\n );\n\n const close = useCallback(\n (reason: Parameters<ToastRootContextValue[\"close\"]>[0], event: Event | undefined) =>\n viewport.close([idRef.current], reason, event),\n [viewport, idRef],\n );\n\n const registerTitle = useCallback((element: HTMLElement | null) => {\n titleRef.current = element;\n }, []);\n const registerDescription = useCallback((element: HTMLElement | null) => {\n descriptionRef.current = element;\n }, []);\n\n const pending = item.pending || actionPending;\n const priority = item.priority ?? \"normal\";\n\n // Announce once the content has committed un-suspended (design 5): the Title and Description\n // text exists now. The Viewport skips text it already announced for this toast and speaks the\n // batch a microtask later.\n const announceNow = (): void => {\n if (item.ending || suspendedRef.current) return;\n const resolver = item.announce ?? viewport.announcer();\n let text: string | null;\n if (resolver !== undefined) text = resolver(item);\n else {\n text = [titleRef.current?.textContent, descriptionRef.current?.textContent]\n .map((t) => (t ?? \"\").trim())\n .filter((t) => t !== \"\")\n .join(\" \");\n }\n viewport.announce(item.id, text, priority);\n };\n const announceRef = useLatest(announceNow);\n\n // A Title or Description inside the consumer's own `<Suspense>` commits after the Root (the\n // boundary's retry does not re-run the Root's effect). Read once the whole reveal committed,\n // so a Title and a Description revealed together are announced as one text.\n const contentCommitted = useCallback(() => {\n if (!announcedOnce.current || revealQueued.current) return;\n revealQueued.current = true;\n queueMicrotask(() => {\n revealQueued.current = false;\n announceRef.current();\n });\n }, [announceRef]);\n const state = useMemo<ToastRootState>(\n () => ({ toast: item, pending, ending: item.ending, type: item.type, priority }),\n [item, pending, priority],\n );\n\n const context = useMemo<ToastRootContextValue>(\n () => ({\n toast: item,\n ids,\n state,\n registerTitle,\n registerDescription,\n contentCommitted,\n setActionPending,\n setSuspended,\n close,\n }),\n [\n item,\n ids,\n state,\n registerTitle,\n registerDescription,\n contentCommitted,\n setActionPending,\n setSuspended,\n close,\n ],\n );\n\n const rootRef = useCallback(\n (element: HTMLElement) => {\n elementRef.current = element;\n viewport.registerRoot(id, element);\n return () => {\n if (elementRef.current === element) elementRef.current = null;\n viewport.registerRoot(id, null);\n };\n },\n [viewport, id],\n );\n\n // A layout effect, so toasts announce in queue order (before the Viewport's own effect\n // announces the queued ones).\n useLayoutEffect(() => {\n announcedOnce.current = true;\n announceRef.current();\n }, [item, suspended, priority, announceRef]);\n\n // Exit (design 10.2): keep the ending toast until the animations the ending state started\n // settle, then drop it. Animations that ran before (a progress bar, paused with the region or\n // not) are not waited for: the Viewport recorded them just before marking the toast ending.\n useLayoutEffect(() => {\n if (!item.ending) return;\n const element = elementRef.current;\n const baseline = viewport.exitBaseline(item.id);\n const animations =\n element === null\n ? []\n : exitAnimations(element).filter((animation) => !baseline?.has(animation));\n if (animations.length === 0) {\n viewport.drop(item.id);\n return;\n }\n let cancelled = false;\n void Promise.allSettled(animations.map((animation) => animation.finished)).then(() => {\n if (!cancelled) viewport.drop(item.id);\n });\n return () => {\n cancelled = true;\n };\n }, [item.ending, item.id, viewport]);\n\n const onKeyDown = (event: KeyboardEvent<HTMLElement>): void => {\n if (event.defaultPrevented || item.ending) return;\n if (event.key === \"Escape\") {\n event.preventDefault();\n close(\"dismiss\", event.nativeEvent);\n } else if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n viewport.focusSibling(id, event.key === \"ArrowDown\" ? 1 : -1);\n }\n };\n\n const libraryProps: ComponentPropsWithRef<\"div\"> & DataAttributes = {\n role: priority === \"high\" ? \"alertdialog\" : \"dialog\",\n tabIndex: 0,\n \"aria-labelledby\": ids.title,\n \"aria-describedby\": ids.description,\n inert: item.ending || undefined,\n \"data-type\": item.type,\n \"data-pending\": dataAttr(pending),\n \"data-ending\": dataAttr(item.ending),\n onKeyDown,\n };\n\n const element = useRender<ComponentPropsWithRef<\"div\">, ToastRootState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n style,\n children: (s: ToastRootState) => (\n <Suspense fallback={<SuspenseGuard>{fallback}</SuspenseGuard>}>\n {resolveStateValue(children, s)}\n </Suspense>\n ),\n props: rest,\n libraryProps,\n ref: rootRef,\n });\n\n return <ToastRootContext value={context}>{element}</ToastRootContext>;\n}\n\nToastRoot.displayName = \"ToastRoot\";\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { ToastRootState } from "./toast-root.mjs";
3
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
4
+ //#region src/toast/toast-title.d.ts
5
+ export interface ToastTitleProps extends Omit<ComponentPropsWithRef<"div">, "id" | "className" | "style" | "children"> {
6
+ /** Default: the toast's `title`. */
7
+ children?: StateValue<ReactNode, ToastRootState>;
8
+ className?: StateValue<string | undefined, ToastRootState>;
9
+ style?: StateValue<CSSProperties | undefined, ToastRootState>;
10
+ render?: RenderProp<ComponentPropsWithRef<"div">, ToastRootState>;
11
+ }
12
+ /**
13
+ * The toast's name: a `div` whose id the Root references with `aria-labelledby`. Not a heading,
14
+ * so transient notifications stay out of heading navigation. Its text is part of the default
15
+ * announcement.
16
+ *
17
+ * Owned key (conventions 1.2): `id`.
18
+ */
19
+ export declare function ToastTitle({ children, className, style, render, ...rest }: ToastTitleProps): ReactNode;
20
+ export declare namespace ToastTitle {
21
+ var displayName: string;
22
+ }
23
+ //#endregion
24
+ //# sourceMappingURL=toast-title.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-title.d.mts","names":[],"sources":["../../src/toast/toast-title.tsx"],"mappings":";;;;iBAQiB,wBAAwB,KACvC;;EAIA,WAAW,WAAW,WAAW;EACjC,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,SAAS,WAAW,8BAA8B;;;;;;;;;wBAUpC,aAAa,UAAU,WAAW,OAAO,WAAW,QAAQ,kBAAe;yBAA3E"}
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { useRender } from "../internal/use-render.mjs";
3
+ import { useToastRootContext } from "./toast-context.mjs";
4
+ import { useLayoutEffect } from "react";
5
+ //#region src/toast/toast-title.tsx
6
+ /**
7
+ * The toast's name: a `div` whose id the Root references with `aria-labelledby`. Not a heading,
8
+ * so transient notifications stay out of heading navigation. Its text is part of the default
9
+ * announcement.
10
+ *
11
+ * Owned key (conventions 1.2): `id`.
12
+ */
13
+ function ToastTitle({ children, className, style, render, ...rest }) {
14
+ const root = useToastRootContext("Toast.Title");
15
+ const { contentCommitted } = root;
16
+ useLayoutEffect(() => contentCommitted(), [contentCommitted]);
17
+ return useRender({
18
+ defaultElement: "div",
19
+ render,
20
+ state: root.state,
21
+ className,
22
+ style,
23
+ children: children ?? root.toast.title,
24
+ props: rest,
25
+ libraryProps: { id: root.ids.title },
26
+ ref: root.registerTitle
27
+ });
28
+ }
29
+ ToastTitle.displayName = "ToastTitle";
30
+ //#endregion
31
+ export { ToastTitle };
32
+
33
+ //# sourceMappingURL=toast-title.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-title.mjs","names":[],"sources":["../../src/toast/toast-title.tsx"],"sourcesContent":["\"use client\";\nimport { useLayoutEffect } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useToastRootContext } from \"./toast-context.js\";\nimport type { ToastRootState } from \"./toast-root.js\";\n\nexport interface ToastTitleProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n \"id\" | \"className\" | \"style\" | \"children\"\n> {\n /** Default: the toast's `title`. */\n children?: StateValue<ReactNode, ToastRootState>;\n className?: StateValue<string | undefined, ToastRootState>;\n style?: StateValue<CSSProperties | undefined, ToastRootState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ToastRootState>;\n}\n\n/**\n * The toast's name: a `div` whose id the Root references with `aria-labelledby`. Not a heading,\n * so transient notifications stay out of heading navigation. Its text is part of the default\n * announcement.\n *\n * Owned key (conventions 1.2): `id`.\n */\nexport function ToastTitle({ children, className, style, render, ...rest }: ToastTitleProps) {\n const root = useToastRootContext(\"Toast.Title\");\n // Mounted, or revealed by a Suspense boundary inside the Root: announce the text now present.\n const { contentCommitted } = root;\n useLayoutEffect(() => contentCommitted(), [contentCommitted]);\n return useRender<ComponentPropsWithRef<\"div\">, ToastRootState>({\n defaultElement: \"div\",\n render,\n state: root.state,\n className,\n style,\n children: children ?? root.toast.title,\n props: rest,\n libraryProps: { id: root.ids.title },\n ref: root.registerTitle,\n });\n}\n\nToastTitle.displayName = \"ToastTitle\";\n"],"mappings":";;;;;;;;;;;;AA0BA,SAAgB,WAAW,EAAE,UAAU,WAAW,OAAO,QAAQ,GAAG,QAAyB;CAC3F,MAAM,OAAO,oBAAoB,aAAa;CAE9C,MAAM,EAAE,qBAAqB;CAC7B,sBAAsB,iBAAiB,GAAG,CAAC,gBAAgB,CAAC;CAC5D,OAAO,UAAwD;EAC7D,gBAAgB;EAChB;EACA,OAAO,KAAK;EACZ;EACA;EACA,UAAU,YAAY,KAAK,MAAM;EACjC,OAAO;EACP,cAAc,EAAE,IAAI,KAAK,IAAI,MAAM;EACnC,KAAK,KAAK;CACZ,CAAC;AACH;AAEA,WAAW,cAAc"}
@@ -0,0 +1,52 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { ToastItem, ToastManager } from "./toast.mjs";
3
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
4
+ //#region src/toast/toast-viewport.d.ts
5
+ export interface ToastViewportState {
6
+ /** Rendered toasts, chronological (oldest first), exiting ones included. */
7
+ readonly toasts: readonly ToastItem[];
8
+ /** Toasts waiting beyond `limit`. */
9
+ readonly queued: number;
10
+ /** A viewport-wide pause holds (pointer over the region, focus inside, hidden document, blurred window). */
11
+ readonly paused: boolean;
12
+ }
13
+ export interface ToastViewportProps extends Omit<ComponentPropsWithRef<"section">, "popover" | "className" | "style" | "children" | "onPointerEnter" | "onPointerLeave" | "onFocus" | "onBlur" | "onKeyDown"> {
14
+ /** The queue to render. Default: the module-level `toast`. */
15
+ manager?: ToastManager;
16
+ /** Toasts rendered at once; further ones wait in order (never dropped). Default `3`. */
17
+ limit?: number;
18
+ /** Default `duration` of a toast in milliseconds; `null` for persistent. Default `5000`. */
19
+ duration?: number | null;
20
+ /**
21
+ * Keys that focus the newest toast: `event.code` values and modifier names (`"altKey"`,
22
+ * `"ctrlKey"`, `"metaKey"`, `"shiftKey"`), all of which must match, with no other modifier
23
+ * held. Default `["F8"]`; `null` installs no listener.
24
+ */
25
+ hotkey?: readonly string[] | null;
26
+ /**
27
+ * The text `document.ariaNotify()` speaks for a toast (localisation); `null` announces nothing.
28
+ * A toast's own `announce` wins. Default: the text of its Title and Description.
29
+ */
30
+ announce?: (toast: ToastItem) => string | null;
31
+ /** Usually a function of the state mapping `state.toasts` to `Toast.Root`s. */
32
+ children?: StateValue<ReactNode, ToastViewportState>;
33
+ className?: StateValue<string | undefined, ToastViewportState>;
34
+ style?: StateValue<CSSProperties | undefined, ToastViewportState>;
35
+ /** Must render an element that can carry `popover` (a `<section>` by default). */
36
+ render?: RenderProp<ComponentPropsWithRef<"section">, ToastViewportState>;
37
+ }
38
+ /**
39
+ * The toast region: a `<section popover="manual">` named "Notifications (F8)", shown in the top
40
+ * layer while it has toasts. Owns the queue (urgent state fed by `toast()`), the timers and their
41
+ * pausing, the hotkey, focus return, announcements through `document.ariaNotify()`, and the move
42
+ * into the topmost open modal `Dialog` (a region outside it would be inert).
43
+ *
44
+ * Owned keys (conventions 1.2): `popover`, `aria-label` (the consumer's own `aria-label` wins
45
+ * verbatim), `data-paused`, `data-empty`, and the pointer / focus handlers.
46
+ */
47
+ export declare function ToastViewport({ manager, limit, duration, hotkey, announce, children, className, style, render, ...rest }: ToastViewportProps): import("react").JSX.Element | null;
48
+ export declare namespace ToastViewport {
49
+ var displayName: string;
50
+ }
51
+ //#endregion
52
+ //# sourceMappingURL=toast-viewport.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-viewport.d.mts","names":[],"sources":["../../src/toast/toast-viewport.tsx"],"mappings":";;;;iBAwCiB;;WAEN,iBAAiB;;WAEjB;;WAEA;;iBAGM,2BAA2B,KAC1C;;EAYA,UAAU;;EAEV;;EAEA;;;;;;EAMA;;;;;EAKA,YAAY,OAAO;;EAEnB,WAAW,WAAW,WAAW;EACjC,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,SAAS,WAAW,kCAAkC;;;;;;;;;;;wBA0JxC,gBACd,SACA,OACA,UACA,QACA,UACA,UACA,WACA,OACA,WACG,QACF,qCAAkB,IAAA;yBAXL"}