@nizivo/react 0.1.0 → 0.2.1

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 (238) hide show
  1. package/THIRD_PARTY_NOTICES +12 -5
  2. package/dist/_engines/react-aria/dialog.client.js +16 -24
  3. package/dist/_engines/react-aria/drawer.client.js +8 -0
  4. package/dist/_engines/react-aria/file-upload.client.js +50 -0
  5. package/dist/_engines/react-aria/menu.client.js +17 -13
  6. package/dist/_engines/react-aria/open-state.client.js +53 -0
  7. package/dist/_engines/react-aria/outside-press.client.js +61 -0
  8. package/dist/_engines/react-aria/overlay.client.js +6 -1
  9. package/dist/_engines/react-aria/popover.client.js +148 -0
  10. package/dist/_engines/react-aria/popup.client.js +31 -5
  11. package/dist/_engines/react-aria/select.client.js +22 -12
  12. package/dist/_engines/react-aria/toast.client.js +38 -0
  13. package/dist/_engines/react-aria/tooltip.client.js +11 -11
  14. package/dist/_internal/data-status.d.ts +3 -0
  15. package/dist/_internal/data-status.js +13 -0
  16. package/dist/_internal/glyphs.js +54 -1
  17. package/dist/_internal/modal.client.js +54 -0
  18. package/dist/_internal/nested-focus.js +33 -0
  19. package/dist/alert/alert-dismiss.client.d.ts +1 -1
  20. package/dist/alert/alert-dismiss.client.js +3 -1
  21. package/dist/app-shell/app-shell.d.ts +24 -0
  22. package/dist/app-shell/app-shell.js +56 -0
  23. package/dist/app-shell/index.d.ts +2 -0
  24. package/dist/app-shell/index.js +1 -0
  25. package/dist/avatar/avatar.d.ts +96 -0
  26. package/dist/avatar/avatar.js +94 -0
  27. package/dist/avatar/index.d.ts +2 -0
  28. package/dist/avatar/index.js +1 -0
  29. package/dist/banner/banner-dismiss.client.d.ts +32 -0
  30. package/dist/banner/banner-dismiss.client.js +38 -0
  31. package/dist/banner/banner.d.ts +34 -0
  32. package/dist/banner/banner.js +47 -0
  33. package/dist/banner/index.d.ts +3 -0
  34. package/dist/banner/index.js +3 -0
  35. package/dist/breadcrumb/breadcrumb.d.ts +46 -0
  36. package/dist/breadcrumb/breadcrumb.js +46 -0
  37. package/dist/breadcrumb/breadcrumb.parts.d.ts +6 -0
  38. package/dist/breadcrumb/breadcrumb.parts.js +9 -0
  39. package/dist/breadcrumb/index.d.ts +3 -0
  40. package/dist/breadcrumb/index.js +3 -0
  41. package/dist/button/button.d.ts +3 -2
  42. package/dist/card/card.d.ts +9 -2
  43. package/dist/chip-group/chip-group.client.d.ts +88 -0
  44. package/dist/chip-group/chip-group.client.js +157 -0
  45. package/dist/chip-group/index.d.ts +2 -0
  46. package/dist/chip-group/index.js +1 -0
  47. package/dist/choice-card/choice-card.client.d.ts +66 -0
  48. package/dist/choice-card/choice-card.client.js +138 -0
  49. package/dist/choice-card/index.d.ts +2 -0
  50. package/dist/choice-card/index.js +1 -0
  51. package/dist/config/config.client.d.ts +16 -1
  52. package/dist/config/config.client.js +18 -3
  53. package/dist/config/index.d.ts +2 -2
  54. package/dist/contracts/index.d.ts +1 -1
  55. package/dist/css/app-shell.css +2 -0
  56. package/dist/css/avatar.css +2 -0
  57. package/dist/css/banner.css +2 -0
  58. package/dist/css/base.css +1 -1
  59. package/dist/css/breadcrumb.css +2 -0
  60. package/dist/css/card.css +1 -1
  61. package/dist/css/chip-group.css +2 -0
  62. package/dist/css/choice-card.css +2 -0
  63. package/dist/css/delta.css +1 -1
  64. package/dist/css/drawer.css +2 -0
  65. package/dist/css/file-upload.css +2 -0
  66. package/dist/css/form.css +2 -0
  67. package/dist/css/heading.css +1 -1
  68. package/dist/css/kpi-tile.css +2 -0
  69. package/dist/css/metric.css +2 -0
  70. package/dist/css/mobile-tab-bar.css +2 -0
  71. package/dist/css/mobile-top-bar.css +2 -0
  72. package/dist/css/motion.css +2 -0
  73. package/dist/css/nav-item.css +2 -0
  74. package/dist/css/number-value.css +2 -0
  75. package/dist/css/page-header.css +2 -0
  76. package/dist/css/pagination.css +2 -0
  77. package/dist/css/password-input.css +2 -0
  78. package/dist/css/popover.css +2 -0
  79. package/dist/css/ranked-list.css +2 -0
  80. package/dist/css/search-field.css +2 -0
  81. package/dist/css/sidebar.css +2 -0
  82. package/dist/css/split.css +2 -0
  83. package/dist/css/sticky-bar.css +2 -0
  84. package/dist/css/table-selection.css +2 -0
  85. package/dist/css/table.css +2 -0
  86. package/dist/css/text.css +1 -1
  87. package/dist/css/toast.css +2 -0
  88. package/dist/css/top-bar.css +2 -0
  89. package/dist/css/trend-card.css +2 -0
  90. package/dist/dialog/dialog.client.d.ts +1 -1
  91. package/dist/dialog/dialog.client.js +15 -37
  92. package/dist/drawer/drawer.client.d.ts +25 -0
  93. package/dist/drawer/drawer.client.js +154 -0
  94. package/dist/drawer/drawer.contract.d.ts +98 -0
  95. package/dist/drawer/drawer.parts.d.ts +6 -0
  96. package/dist/drawer/drawer.parts.js +16 -0
  97. package/dist/drawer/index.d.ts +5 -0
  98. package/dist/drawer/index.js +3 -0
  99. package/dist/field/field-scope.client.js +9 -2
  100. package/dist/file-upload/file-upload.client.d.ts +9 -0
  101. package/dist/file-upload/file-upload.client.js +406 -0
  102. package/dist/file-upload/file-upload.contract.d.ts +112 -0
  103. package/dist/file-upload/index.d.ts +3 -0
  104. package/dist/file-upload/index.js +1 -0
  105. package/dist/file-upload/seam.d.ts +1 -0
  106. package/dist/form/form.client.d.ts +38 -0
  107. package/dist/form/form.client.js +127 -0
  108. package/dist/form/form.d.ts +36 -0
  109. package/dist/form/form.js +29 -0
  110. package/dist/form/index.d.ts +4 -0
  111. package/dist/form/index.js +4 -0
  112. package/dist/form/submit-button.client.d.ts +20 -0
  113. package/dist/form/submit-button.client.js +19 -0
  114. package/dist/heading/heading.d.ts +4 -1
  115. package/dist/i18n/format-label.d.ts +24 -0
  116. package/dist/i18n/format-label.js +19 -0
  117. package/dist/i18n/index.d.ts +2 -0
  118. package/dist/i18n/index.js +1 -0
  119. package/dist/icon-button/icon-button.client.js +1 -1
  120. package/dist/icon-button/icon-button.js +1 -1
  121. package/dist/index.d.ts +84 -5
  122. package/dist/index.js +49 -4
  123. package/dist/kpi-tile/index.d.ts +2 -0
  124. package/dist/kpi-tile/index.js +1 -0
  125. package/dist/kpi-tile/kpi-tile.d.ts +30 -0
  126. package/dist/kpi-tile/kpi-tile.js +48 -0
  127. package/dist/locales/en-US.d.ts +77 -0
  128. package/dist/locales/en-US.js +83 -0
  129. package/dist/menu/menu.contract.d.ts +1 -1
  130. package/dist/metric/index.d.ts +2 -0
  131. package/dist/metric/index.js +1 -0
  132. package/dist/metric/metric.d.ts +72 -0
  133. package/dist/metric/metric.js +116 -0
  134. package/dist/mobile-tab-bar/index.d.ts +4 -0
  135. package/dist/mobile-tab-bar/index.js +4 -0
  136. package/dist/mobile-tab-bar/mobile-tab-bar-inset.client.js +38 -0
  137. package/dist/mobile-tab-bar/mobile-tab-bar-more.client.d.ts +26 -0
  138. package/dist/mobile-tab-bar/mobile-tab-bar-more.client.js +60 -0
  139. package/dist/mobile-tab-bar/mobile-tab-bar.d.ts +39 -0
  140. package/dist/mobile-tab-bar/mobile-tab-bar.js +54 -0
  141. package/dist/mobile-tab-bar/mobile-tab-bar.parts.d.ts +6 -0
  142. package/dist/mobile-tab-bar/mobile-tab-bar.parts.js +9 -0
  143. package/dist/mobile-top-bar/index.d.ts +2 -0
  144. package/dist/mobile-top-bar/index.js +1 -0
  145. package/dist/mobile-top-bar/mobile-top-bar.d.ts +17 -0
  146. package/dist/mobile-top-bar/mobile-top-bar.js +31 -0
  147. package/dist/motion/count-up.client.d.ts +39 -0
  148. package/dist/motion/count-up.client.js +109 -0
  149. package/dist/motion/index.d.ts +2 -0
  150. package/dist/motion/index.js +1 -0
  151. package/dist/nav-item/index.d.ts +2 -0
  152. package/dist/nav-item/index.js +1 -0
  153. package/dist/nav-item/nav-item.d.ts +35 -0
  154. package/dist/nav-item/nav-item.js +50 -0
  155. package/dist/number-value/index.d.ts +2 -0
  156. package/dist/number-value/index.js +1 -0
  157. package/dist/number-value/number-value.d.ts +25 -0
  158. package/dist/number-value/number-value.js +26 -0
  159. package/dist/page-header/index.d.ts +2 -0
  160. package/dist/page-header/index.js +1 -0
  161. package/dist/page-header/page-header.d.ts +19 -0
  162. package/dist/page-header/page-header.js +39 -0
  163. package/dist/pagination/index.d.ts +2 -0
  164. package/dist/pagination/index.js +1 -0
  165. package/dist/pagination/pagination.d.ts +74 -0
  166. package/dist/pagination/pagination.js +136 -0
  167. package/dist/password-input/index.d.ts +2 -0
  168. package/dist/password-input/index.js +1 -0
  169. package/dist/password-input/password-input.client.d.ts +52 -0
  170. package/dist/password-input/password-input.client.js +106 -0
  171. package/dist/popover/index.d.ts +5 -0
  172. package/dist/popover/index.js +3 -0
  173. package/dist/popover/popover.client.d.ts +20 -0
  174. package/dist/popover/popover.client.js +113 -0
  175. package/dist/popover/popover.contract.d.ts +88 -0
  176. package/dist/popover/popover.parts.d.ts +6 -0
  177. package/dist/popover/popover.parts.js +13 -0
  178. package/dist/ranked-list/index.d.ts +3 -0
  179. package/dist/ranked-list/index.js +3 -0
  180. package/dist/ranked-list/ranked-list.d.ts +85 -0
  181. package/dist/ranked-list/ranked-list.js +153 -0
  182. package/dist/ranked-list/ranked-list.parts.d.ts +6 -0
  183. package/dist/ranked-list/ranked-list.parts.js +10 -0
  184. package/dist/search-field/index.d.ts +2 -0
  185. package/dist/search-field/index.js +1 -0
  186. package/dist/search-field/search-field.client.d.ts +55 -0
  187. package/dist/search-field/search-field.client.js +136 -0
  188. package/dist/select/select.contract.d.ts +1 -1
  189. package/dist/sidebar/index.d.ts +4 -0
  190. package/dist/sidebar/index.js +4 -0
  191. package/dist/sidebar/sidebar-item.client.d.ts +10 -0
  192. package/dist/sidebar/sidebar-item.client.js +55 -0
  193. package/dist/sidebar/sidebar.d.ts +45 -0
  194. package/dist/sidebar/sidebar.js +62 -0
  195. package/dist/sidebar/sidebar.parts.d.ts +6 -0
  196. package/dist/sidebar/sidebar.parts.js +11 -0
  197. package/dist/split/index.d.ts +3 -0
  198. package/dist/split/index.js +3 -0
  199. package/dist/split/split.d.ts +28 -0
  200. package/dist/split/split.js +33 -0
  201. package/dist/split/split.parts.d.ts +6 -0
  202. package/dist/split/split.parts.js +10 -0
  203. package/dist/sticky-bar/index.d.ts +2 -0
  204. package/dist/sticky-bar/index.js +1 -0
  205. package/dist/sticky-bar/sticky-bar.d.ts +16 -0
  206. package/dist/sticky-bar/sticky-bar.js +26 -0
  207. package/dist/styles.css +66 -7
  208. package/dist/table/index.d.ts +3 -0
  209. package/dist/table/index.js +3 -0
  210. package/dist/table/table.d.ts +101 -0
  211. package/dist/table/table.js +121 -0
  212. package/dist/table/table.parts.d.ts +6 -0
  213. package/dist/table/table.parts.js +18 -0
  214. package/dist/table-selection/index.d.ts +3 -0
  215. package/dist/table-selection/index.js +3 -0
  216. package/dist/table-selection/table-selection.client.d.ts +14 -0
  217. package/dist/table-selection/table-selection.client.js +84 -0
  218. package/dist/table-selection/table-selection.d.ts +34 -0
  219. package/dist/table-selection/table-selection.js +50 -0
  220. package/dist/text/text.d.ts +13 -2
  221. package/dist/toast/index.d.ts +4 -0
  222. package/dist/toast/index.js +3 -0
  223. package/dist/toast/seam.d.ts +2 -0
  224. package/dist/toast/store.d.ts +19 -0
  225. package/dist/toast/store.js +136 -0
  226. package/dist/toast/toast.contract.d.ts +56 -0
  227. package/dist/toast/toaster.client.d.ts +10 -0
  228. package/dist/toast/toaster.client.js +305 -0
  229. package/dist/tooltip/tooltip.contract.d.ts +1 -1
  230. package/dist/top-bar/index.d.ts +2 -0
  231. package/dist/top-bar/index.js +1 -0
  232. package/dist/top-bar/top-bar.d.ts +17 -0
  233. package/dist/top-bar/top-bar.js +35 -0
  234. package/dist/trend-card/index.d.ts +2 -0
  235. package/dist/trend-card/index.js +1 -0
  236. package/dist/trend-card/trend-card.d.ts +34 -0
  237. package/dist/trend-card/trend-card.js +74 -0
  238. package/package.json +167 -4
@@ -1,35 +1,21 @@
1
1
  "use client";
2
2
  import { cx } from "../_internal/cx.js";
3
3
  import { renderElement, toRenderFn } from "../contracts/render.js";
4
+ import { useLabels } from "../config/config.client.js";
4
5
  import { CloseGlyph } from "../_internal/glyphs.js";
6
+ import { ModalNestingScope, initialFocus, useModalNesting } from "../_internal/modal.client.js";
5
7
  import { Close, Description, Popup, Root, Title, Trigger } from "../_engines/react-aria/dialog.client.js";
6
- import { createContext, use, useLayoutEffect, useMemo, useState } from "react";
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { createContext, use } from "react";
9
+ import { jsx } from "react/jsx-runtime";
8
10
  //#region src/dialog/dialog.client.tsx
9
- const NestingContext = createContext(null);
10
11
  /** `Dialog.Root`'s `returnFocus`, for its Popup. */
11
12
  const ReturnFocusContext = createContext(true);
12
13
  const renderDiv = toRenderFn(void 0, "div");
13
14
  const renderP = toRenderFn(void 0, "p");
14
- const TABBABLE = "a[href], button, input, select, textarea, summary, [tabindex], [contenteditable]:not([contenteditable=\"false\"])";
15
- /**
16
- * Focus on open (§12.2): an element the consumer marked `autoFocus` keeps it (the engine sees focus
17
- * inside and leaves it); an alertdialog focuses its least destructive action, the first
18
- * `Dialog.Close`; a dialog focuses the first tabbable element in its `Dialog.Body`; otherwise the
19
- * engine focuses the popup itself, so a long text starts at its top.
20
- */
21
- function initialFocus(role) {
22
- return (content) => {
23
- if (role === "alertdialog") return content.querySelector("[data-slot=\"dialog-footer\"] [data-slot=\"dialog-close\"]:not(:disabled)") ?? content.querySelector("[data-slot=\"dialog-close\"]:not(:disabled)");
24
- const body = content.querySelector("[data-slot=\"dialog-body\"]");
25
- if (body === null) return null;
26
- for (const element of body.querySelectorAll(TABBABLE)) if (element.tabIndex >= 0 && !element.matches(":disabled") && element.getClientRects().length > 0) return element;
27
- return null;
28
- };
29
- }
15
+ /** Focus on open (§12.2), from the Dialog's own slots. */
30
16
  const INITIAL_FOCUS = {
31
- dialog: initialFocus("dialog"),
32
- alertdialog: initialFocus("alertdialog")
17
+ dialog: initialFocus("dialog", "dialog"),
18
+ alertdialog: initialFocus("dialog", "alertdialog")
33
19
  };
34
20
  function DialogRoot({ returnFocus = true, ...props }) {
35
21
  return /* @__PURE__ */ jsx(ReturnFocusContext, {
@@ -51,10 +37,8 @@ function DialogTrigger({ className, render, ...rest }) {
51
37
  });
52
38
  }
53
39
  function DialogPopup({ role = "dialog", size = "md", backdrop, container, className, children, ...rest }) {
54
- const parent = use(NestingContext);
40
+ const { parent, nesting, childOpen } = useModalNesting();
55
41
  const returnFocus = use(ReturnFocusContext);
56
- const [openChildren, setOpenChildren] = useState(0);
57
- const nesting = useMemo(() => ({ childOpened: (delta) => setOpenChildren((n) => n + delta) }), []);
58
42
  return /* @__PURE__ */ jsx(Popup, {
59
43
  ...rest,
60
44
  role,
@@ -77,22 +61,15 @@ function DialogPopup({ role = "dialog", size = "md", backdrop, container, classN
77
61
  className: cx("nz-dialog-popup", className),
78
62
  "data-slot": "dialog-popup",
79
63
  "data-size": size,
80
- "data-nested-open": openChildren > 0 ? "" : void 0,
64
+ "data-nested-open": childOpen ? "" : void 0,
81
65
  render: renderDiv,
82
- children: /* @__PURE__ */ jsxs(NestingContext, {
83
- value: nesting,
84
- children: [parent !== null && /* @__PURE__ */ jsx(OpenSignal, { parent }), children]
66
+ children: /* @__PURE__ */ jsx(ModalNestingScope, {
67
+ parent,
68
+ nesting,
69
+ children
85
70
  })
86
71
  });
87
72
  }
88
- /** Mounted only while this popup's content is mounted, i.e. while it is open. */
89
- function OpenSignal({ parent }) {
90
- useLayoutEffect(() => {
91
- parent.childOpened(1);
92
- return () => parent.childOpened(-1);
93
- }, [parent]);
94
- return null;
95
- }
96
73
  const HEADINGS = {
97
74
  2: toRenderFn(void 0, "h2"),
98
75
  3: toRenderFn(void 0, "h3"),
@@ -139,7 +116,8 @@ function DialogFooter({ className, render, ...rest }) {
139
116
  * builder cost the Dialog entry about 280 B gzip against its 31 KiB cap. An overlay-lane case
140
117
  * compares the two.
141
118
  */
142
- function DialogClose({ className, render, children, labels, ...rest }) {
119
+ function DialogClose({ className, render, children, labels: labelsProp, ...rest }) {
120
+ const labels = useLabels("dialog", labelsProp);
143
121
  return /* @__PURE__ */ jsx(Close, {
144
122
  ...rest,
145
123
  className: cx("nz-dialog-close", className),
@@ -0,0 +1,25 @@
1
+ import { DrawerBodyProps, DrawerCloseProps, DrawerDescriptionProps, DrawerFooterProps, DrawerHeaderProps, DrawerPopupProps, DrawerRootProps, DrawerTitleProps, DrawerTriggerProps } from "./drawer.contract.js";
2
+ import { JSX } from "react";
3
+ //#region src/drawer/drawer.client.d.ts
4
+ export declare function DrawerRoot({ returnFocus, ...props }: DrawerRootProps): JSX.Element;
5
+ /**
6
+ * Without `render`, its own `<button>` with `nz-hit-target` and, from drawer.css, a 24 x 24 px
7
+ * minimum (WCAG 2.2 2.5.8, as the Dialog's, M27). A composed Button or IconButton keeps its own size.
8
+ */
9
+ export declare function DrawerTrigger({ className, render, ...rest }: DrawerTriggerProps): JSX.Element;
10
+ export declare function DrawerPopup({ side, backdrop, container, className, children, ...rest }: DrawerPopupProps): JSX.Element;
11
+ /** Figma's Header frame: the title, an optional description and badges, above a 1 px rule. */
12
+ export declare function DrawerHeader({ className, render, ...rest }: DrawerHeaderProps): JSX.Element;
13
+ export declare function DrawerTitle({ level, className, render, ...rest }: DrawerTitleProps): JSX.Element;
14
+ export declare function DrawerDescription({ className, render, ...rest }: DrawerDescriptionProps): JSX.Element;
15
+ /** The only scroller inside the drawer; it fills the height between the header and the footer. */
16
+ export declare function DrawerBody({ className, render, ...rest }: DrawerBodyProps): JSX.Element;
17
+ /** Figma's Footer frame: actions that share its width, above a 1 px rule. */
18
+ export declare function DrawerFooter({ className, render, ...rest }: DrawerFooterProps): JSX.Element;
19
+ /**
20
+ * With `render` or `children`, the consumer's button. With neither, an IconButton (tertiary, `md`)
21
+ * showing the core close glyph, named by `labels.close`: the IconButton element's markup written out,
22
+ * as `Dialog.Close` does, so the Drawer entry does not pull in IconButton's tooltip chain.
23
+ */
24
+ export declare function DrawerClose({ className, render, children, labels: labelsProp, ...rest }: DrawerCloseProps): JSX.Element;
25
+ //#endregion
@@ -0,0 +1,154 @@
1
+ "use client";
2
+ import { cx } from "../_internal/cx.js";
3
+ import { renderElement, toRenderFn } from "../contracts/render.js";
4
+ import { useLabels } from "../config/config.client.js";
5
+ import { CloseGlyph } from "../_internal/glyphs.js";
6
+ import { ModalNestingScope, initialFocus, useModalNesting } from "../_internal/modal.client.js";
7
+ import { Close, Description, Popup, Root, Title, Trigger } from "../_engines/react-aria/dialog.client.js";
8
+ import { useDirection } from "../_engines/react-aria/drawer.client.js";
9
+ import { createContext, use } from "react";
10
+ import { jsx } from "react/jsx-runtime";
11
+ //#region src/drawer/drawer.client.tsx
12
+ /** `Drawer.Root`'s `returnFocus`, for its Popup. */
13
+ const ReturnFocusContext = createContext(true);
14
+ const renderDiv = toRenderFn(void 0, "div");
15
+ const renderP = toRenderFn(void 0, "p");
16
+ /** A drawer is always a dialog (an alertdialog is the Dialog's job). */
17
+ const ROLE = "dialog";
18
+ /** Focus on open (§12.2): the first tabbable element in `Drawer.Body`, else the drawer itself. */
19
+ const INITIAL_FOCUS = initialFocus("drawer", ROLE);
20
+ function DrawerRoot({ returnFocus = true, ...props }) {
21
+ return /* @__PURE__ */ jsx(ReturnFocusContext, {
22
+ value: returnFocus,
23
+ children: /* @__PURE__ */ jsx(Root, { ...props })
24
+ });
25
+ }
26
+ /**
27
+ * Without `render`, its own `<button>` with `nz-hit-target` and, from drawer.css, a 24 x 24 px
28
+ * minimum (WCAG 2.2 2.5.8, as the Dialog's, M27). A composed Button or IconButton keeps its own size.
29
+ */
30
+ function DrawerTrigger({ className, render, ...rest }) {
31
+ return /* @__PURE__ */ jsx(Trigger, {
32
+ ...rest,
33
+ className: cx("nz-drawer-trigger", render === void 0 && "nz-hit-target", className),
34
+ "data-slot": "drawer-trigger",
35
+ render: toRenderFn(render, "button")
36
+ });
37
+ }
38
+ function DrawerPopup({ side = "end", backdrop, container, className, children, ...rest }) {
39
+ const { parent, nesting, childOpen } = useModalNesting();
40
+ const returnFocus = use(ReturnFocusContext);
41
+ const ltr = useDirection() === "ltr";
42
+ const physical = side === "bottom" ? side : side === "end" === ltr ? "right" : "left";
43
+ return /* @__PURE__ */ jsx(Popup, {
44
+ ...rest,
45
+ role: ROLE,
46
+ container,
47
+ backdrop: backdrop ?? parent === null,
48
+ positioner: {
49
+ className: "nz-drawer-positioner",
50
+ "data-slot": "drawer-positioner",
51
+ "data-side": physical
52
+ },
53
+ backdropProps: {
54
+ className: "nz-drawer-backdrop",
55
+ "data-slot": "drawer-backdrop"
56
+ },
57
+ contentProps: {
58
+ className: "nz-drawer-content",
59
+ "data-slot": "drawer-content"
60
+ },
61
+ initialFocus: INITIAL_FOCUS,
62
+ returnFocus,
63
+ className: cx("nz-drawer-popup", className),
64
+ "data-slot": "drawer-popup",
65
+ "data-side": physical,
66
+ "data-nested-open": childOpen ? "" : void 0,
67
+ render: renderDiv,
68
+ children: /* @__PURE__ */ jsx(ModalNestingScope, {
69
+ parent,
70
+ nesting,
71
+ children
72
+ })
73
+ });
74
+ }
75
+ /** Figma's Header frame: the title, an optional description and badges, above a 1 px rule. */
76
+ function DrawerHeader({ className, render, ...rest }) {
77
+ return renderElement("div", render, {}, {
78
+ ...rest,
79
+ className: cx("nz-drawer-header", className),
80
+ "data-slot": "drawer-header"
81
+ });
82
+ }
83
+ const HEADINGS = {
84
+ 2: toRenderFn(void 0, "h2"),
85
+ 3: toRenderFn(void 0, "h3"),
86
+ 4: toRenderFn(void 0, "h4"),
87
+ 5: toRenderFn(void 0, "h5"),
88
+ 6: toRenderFn(void 0, "h6")
89
+ };
90
+ function DrawerTitle({ level = 2, className, render, ...rest }) {
91
+ return /* @__PURE__ */ jsx(Title, {
92
+ ...rest,
93
+ level,
94
+ className: cx("nz-drawer-title", className),
95
+ "data-slot": "drawer-title",
96
+ render: render === void 0 ? HEADINGS[level] : toRenderFn(render, `h${level}`)
97
+ });
98
+ }
99
+ function DrawerDescription({ className, render, ...rest }) {
100
+ return /* @__PURE__ */ jsx(Description, {
101
+ ...rest,
102
+ className: cx("nz-drawer-description", className),
103
+ "data-slot": "drawer-description",
104
+ render: render === void 0 ? renderP : toRenderFn(render, "p")
105
+ });
106
+ }
107
+ /** The only scroller inside the drawer; it fills the height between the header and the footer. */
108
+ function DrawerBody({ className, render, ...rest }) {
109
+ return renderElement("div", render, {}, {
110
+ ...rest,
111
+ className: cx("nz-drawer-body", className),
112
+ "data-slot": "drawer-body"
113
+ });
114
+ }
115
+ /** Figma's Footer frame: actions that share its width, above a 1 px rule. */
116
+ function DrawerFooter({ className, render, ...rest }) {
117
+ return renderElement("div", render, {}, {
118
+ ...rest,
119
+ className: cx("nz-drawer-footer", className),
120
+ "data-slot": "drawer-footer"
121
+ });
122
+ }
123
+ /**
124
+ * With `render` or `children`, the consumer's button. With neither, an IconButton (tertiary, `md`)
125
+ * showing the core close glyph, named by `labels.close`: the IconButton element's markup written out,
126
+ * as `Dialog.Close` does, so the Drawer entry does not pull in IconButton's tooltip chain.
127
+ */
128
+ function DrawerClose({ className, render, children, labels: labelsProp, ...rest }) {
129
+ const labels = useLabels("drawer", labelsProp);
130
+ return /* @__PURE__ */ jsx(Close, {
131
+ ...rest,
132
+ className: cx("nz-drawer-close", className),
133
+ "data-slot": "drawer-close",
134
+ render: toRenderFn(render ?? (children === void 0 ? closeIcon(rest["aria-label"] ?? labels?.close ?? "Close") : void 0), "button"),
135
+ children
136
+ });
137
+ }
138
+ function closeIcon(label) {
139
+ return /* @__PURE__ */ jsx("button", {
140
+ type: "button",
141
+ className: "nz-icon-button nz-hit-target",
142
+ "data-variant": "tertiary",
143
+ "data-size": "md",
144
+ "aria-label": label,
145
+ children: /* @__PURE__ */ jsx("span", {
146
+ className: "nz-icon-button-icon",
147
+ "data-slot": "icon-button-icon",
148
+ "aria-hidden": "true",
149
+ children: /* @__PURE__ */ jsx(CloseGlyph, {})
150
+ })
151
+ });
152
+ }
153
+ //#endregion
154
+ export { DrawerBody, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPopup, DrawerRoot, DrawerTitle, DrawerTrigger };
@@ -0,0 +1,98 @@
1
+ import { RenderProp } from "../contracts/render.js";
2
+ import { ChangeDetails, OpenReason } from "../contracts/details.js";
3
+ import { ReturnFocusTarget } from "../_internal/overlay.js";
4
+ import "../dialog/dialog.contract.js";
5
+ import { ComponentPropsWithRef, ReactNode } from "react";
6
+ //#region src/drawer/drawer.contract.d.ts
7
+ /**
8
+ * The edge the drawer slides in from, in logical terms: `start` and `end` follow the writing direction
9
+ * (`end` is the right edge in a left-to-right page, as Figma draws the Drawer); `bottom` is the sheet,
10
+ * as AppShell's "More" sheet below 640 px.
11
+ */
12
+ export type DrawerSide = "start" | "end" | "bottom";
13
+ export type DrawerTitleLevel = 2 | 3 | 4 | 5 | 6;
14
+ /**
15
+ * Strings the Drawer renders (§9.3 rule 7, §16.4). `close` is the accessible name of the default
16
+ * `Drawer.Close` (an IconButton showing the close glyph), set through that part's `labels`.
17
+ * Engine-owned with React Aria (not overridable): `dismiss`, the visually hidden "Dismiss" button
18
+ * rendered inside the drawer.
19
+ */
20
+ export interface DrawerLabels {
21
+ /** @default 'Close' */
22
+ close: string;
23
+ dismiss: string;
24
+ }
25
+ export interface DrawerRootProps {
26
+ open?: boolean;
27
+ defaultOpen?: boolean;
28
+ /** `details.reason` is `'unknown'` with React Aria, which reports no cause. */
29
+ onOpenChange?: (open: boolean, details: ChangeDetails<OpenReason>) => void;
30
+ /**
31
+ * Where focus goes when the drawer closes (§12.2 Focus return), as `Dialog.Root`'s: the trigger,
32
+ * else the trigger of the overlay it was opened from, else `<body>` with a development warning; an
33
+ * element ref or a function returning one goes first; `false` leaves focus alone.
34
+ * @default true
35
+ */
36
+ returnFocus?: ReturnFocusTarget;
37
+ children: ReactNode;
38
+ }
39
+ export interface DrawerTriggerState {
40
+ open: boolean;
41
+ pressed: boolean;
42
+ focusVisible: boolean;
43
+ disabled: boolean;
44
+ }
45
+ export interface DrawerPopupState {
46
+ entering: boolean;
47
+ exiting: boolean;
48
+ }
49
+ export interface DrawerCloseState {
50
+ pressed: boolean;
51
+ focusVisible: boolean;
52
+ disabled: boolean;
53
+ }
54
+ export interface DrawerTriggerProps extends Omit<ComponentPropsWithRef<"button">, "children"> {
55
+ /** Must render a `<button>`, for example `render={<Button>View order</Button>}`. */
56
+ render?: RenderProp<DrawerTriggerState>;
57
+ children?: ReactNode;
58
+ }
59
+ export interface DrawerPopupProps extends Omit<ComponentPropsWithRef<"div">, "children" | "role"> {
60
+ /** The edge it slides in from. @default 'end' */
61
+ side?: DrawerSide;
62
+ /** The scrim element. Defaults to on for the root modal and off when opened from another modal. */
63
+ backdrop?: boolean;
64
+ /** Portal container. Defaults to the parent overlay, else `document.body` (§12.1 L2). */
65
+ container?: Element | null;
66
+ children: ReactNode;
67
+ }
68
+ export interface DrawerHeaderProps extends ComponentPropsWithRef<"div"> {
69
+ render?: RenderProp<Record<string, never>>;
70
+ }
71
+ export interface DrawerTitleProps extends Omit<ComponentPropsWithRef<"h2">, "id"> {
72
+ /** @default 2 */
73
+ level?: DrawerTitleLevel;
74
+ render?: RenderProp<Record<string, never>>;
75
+ }
76
+ export interface DrawerDescriptionProps extends Omit<ComponentPropsWithRef<"p">, "id"> {
77
+ render?: RenderProp<Record<string, never>>;
78
+ }
79
+ export interface DrawerBodyProps extends ComponentPropsWithRef<"div"> {
80
+ render?: RenderProp<Record<string, never>>;
81
+ }
82
+ export interface DrawerFooterProps extends ComponentPropsWithRef<"div"> {
83
+ render?: RenderProp<Record<string, never>>;
84
+ }
85
+ export interface DrawerCloseProps extends Omit<ComponentPropsWithRef<"button">, "children"> {
86
+ /**
87
+ * Must render a `<button>`, for example `render={<Button>Cancel</Button>}`. With neither `render`
88
+ * nor `children`, the part is an IconButton showing the close glyph, named by `labels.close`, which
89
+ * sits in the header's end corner when it is a direct child of `Drawer.Popup`.
90
+ */
91
+ render?: RenderProp<DrawerCloseState>;
92
+ /** Text content, rendered in a plain `<button>`; leave it out for the default IconButton. */
93
+ children?: ReactNode;
94
+ /** The default IconButton's accessible name; an `aria-label` you pass wins. */
95
+ labels?: Partial<Pick<DrawerLabels, "close">>;
96
+ }
97
+ //#endregion
98
+ export type { OpenReason };
@@ -0,0 +1,6 @@
1
+ import { DrawerBody, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPopup, DrawerRoot, DrawerTitle, DrawerTrigger } from "./drawer.client.js";
2
+ declare namespace drawer_parts_d_exports {
3
+ export { DrawerBody as Body, DrawerClose as Close, DrawerDescription as Description, DrawerFooter as Footer, DrawerHeader as Header, DrawerPopup as Popup, DrawerRoot as Root, DrawerTitle as Title, DrawerTrigger as Trigger };
4
+ }
5
+ //#endregion
6
+ export { DrawerBody as Body, DrawerClose as Close, DrawerDescription as Description, DrawerFooter as Footer, DrawerHeader as Header, DrawerPopup as Popup, DrawerRoot as Root, DrawerTitle as Title, DrawerTrigger as Trigger, drawer_parts_d_exports };
@@ -0,0 +1,16 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
+ import { DrawerBody, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPopup, DrawerRoot, DrawerTitle, DrawerTrigger } from "./drawer.client.js";
3
+ //#region src/drawer/drawer.parts.ts
4
+ var drawer_parts_exports = /* @__PURE__ */ __exportAll({
5
+ Body: () => DrawerBody,
6
+ Close: () => DrawerClose,
7
+ Description: () => DrawerDescription,
8
+ Footer: () => DrawerFooter,
9
+ Header: () => DrawerHeader,
10
+ Popup: () => DrawerPopup,
11
+ Root: () => DrawerRoot,
12
+ Title: () => DrawerTitle,
13
+ Trigger: () => DrawerTrigger
14
+ });
15
+ //#endregion
16
+ export { DrawerBody as Body, DrawerClose as Close, DrawerDescription as Description, DrawerFooter as Footer, DrawerHeader as Header, DrawerPopup as Popup, DrawerRoot as Root, DrawerTitle as Title, DrawerTrigger as Trigger, drawer_parts_exports };
@@ -0,0 +1,5 @@
1
+ import { OpenReason } from "../contracts/details.js";
2
+ import { DrawerBodyProps, DrawerCloseProps, DrawerCloseState, DrawerDescriptionProps, DrawerFooterProps, DrawerHeaderProps, DrawerLabels, DrawerPopupProps, DrawerPopupState, DrawerRootProps, DrawerSide, DrawerTitleLevel, DrawerTitleProps, DrawerTriggerProps, DrawerTriggerState } from "./drawer.contract.js";
3
+ import { DrawerBody, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPopup, DrawerRoot, DrawerTitle, DrawerTrigger } from "./drawer.client.js";
4
+ import { drawer_parts_d_exports } from "./drawer.parts.js";
5
+ export { drawer_parts_d_exports as Drawer, DrawerBody, type DrawerBodyProps, DrawerClose, type DrawerCloseProps, type DrawerCloseState, DrawerDescription, type DrawerDescriptionProps, DrawerFooter, type DrawerFooterProps, DrawerHeader, type DrawerHeaderProps, type DrawerLabels, DrawerPopup, type DrawerPopupProps, type DrawerPopupState, DrawerRoot, type DrawerRootProps, type DrawerSide, DrawerTitle, type DrawerTitleLevel, type DrawerTitleProps, DrawerTrigger, type DrawerTriggerProps, type DrawerTriggerState, type OpenReason };
@@ -0,0 +1,3 @@
1
+ import { DrawerBody, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPopup, DrawerRoot, DrawerTitle, DrawerTrigger } from "./drawer.client.js";
2
+ import { drawer_parts_exports } from "./drawer.parts.js";
3
+ export { drawer_parts_exports as Drawer, DrawerBody, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPopup, DrawerRoot, DrawerTitle, DrawerTrigger };
@@ -6,12 +6,19 @@ import { createContext, use, useEffect, useLayoutEffect, useMemo, useRef, useSta
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/field/field-scope.client.tsx
8
8
  const FieldContext = createContext(null);
9
+ /**
10
+ * Internal: what `Form` (form/form.client.tsx) provides, its presented errors by Field `name` (one
11
+ * message each). It lives here, not in the form folder, so the Field's module graph gains no client
12
+ * module; the form leaf imports it.
13
+ */
14
+ const FormScope = createContext(null);
9
15
  /** Internal: rendered only by `Field`. Every prop is serialisable. */
10
16
  function FieldScope({ anatomy, name, messages, children }) {
11
17
  const [native, setNative] = useState(null);
12
18
  const [toFocus, setToFocus] = useState(null);
13
19
  const { ids, label, description, required, disabled, readOnly, validateOn } = anatomy;
14
- const error = presented(anatomy.error) ? anatomy.error : native;
20
+ const formError = name === void 0 ? void 0 : use(FormScope)?.get(name);
21
+ const error = presented(anatomy.error) ? anatomy.error : formError ?? native;
15
22
  const invalid = presented(error);
16
23
  const region = useRef(null);
17
24
  const [said, say] = useState("");
@@ -202,4 +209,4 @@ function isValidatable(element) {
202
209
  return "validity" in element && "willValidate" in element;
203
210
  }
204
211
  //#endregion
205
- export { FieldScope, useFieldControl };
212
+ export { FieldScope, FormScope, useFieldControl };
@@ -0,0 +1,9 @@
1
+ import { FileUploadProps } from "./file-upload.contract.js";
2
+ import { JSX } from "react";
3
+ //#region src/file-upload/file-upload.client.d.ts
4
+ /**
5
+ * `className` and `style` go on the root; every other input prop, `ref` included, goes on the
6
+ * native `<input type="file">`.
7
+ */
8
+ export declare function FileUpload({ id, name, accept, multiple, maxSize, disabled, required, invalid, hint, icon, items, onFilesChange, onReject, onRemove, onRetry, onCancel, labels: labelsProp, locale, className, style, "aria-invalid": ariaInvalid, "aria-describedby": describedByProp, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...rest }: FileUploadProps): JSX.Element;
9
+ //#endregion