@nizivo/react 0.0.0-stage → 0.1.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 (258) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +120 -2
  3. package/THIRD_PARTY_NOTICES +61 -0
  4. package/dist/_engines/react-aria/dialog.client.js +134 -0
  5. package/dist/_engines/react-aria/dom-allowlist.js +19 -0
  6. package/dist/_engines/react-aria/dom.js +31 -0
  7. package/dist/_engines/react-aria/locale.client.js +13 -0
  8. package/dist/_engines/react-aria/menu.client.js +225 -0
  9. package/dist/_engines/react-aria/overlay.client.js +41 -0
  10. package/dist/_engines/react-aria/popup.client.js +127 -0
  11. package/dist/_engines/react-aria/select.client.js +170 -0
  12. package/dist/_engines/react-aria/tabs.client.js +95 -0
  13. package/dist/_engines/react-aria/tooltip.client.js +72 -0
  14. package/dist/_internal/cx.js +11 -0
  15. package/dist/_internal/engine-part.d.ts +1 -0
  16. package/dist/_internal/field.js +20 -0
  17. package/dist/_internal/glyphs.js +34 -0
  18. package/dist/_internal/keys.js +62 -0
  19. package/dist/_internal/overlay.d.ts +9 -0
  20. package/dist/_virtual/_rolldown/runtime.js +13 -0
  21. package/dist/alert/alert-dismiss.client.d.ts +32 -0
  22. package/dist/alert/alert-dismiss.client.js +36 -0
  23. package/dist/alert/alert.d.ts +28 -0
  24. package/dist/alert/alert.js +44 -0
  25. package/dist/alert/index.d.ts +3 -0
  26. package/dist/alert/index.js +3 -0
  27. package/dist/augment.d.ts +13 -0
  28. package/dist/augment.js +0 -0
  29. package/dist/badge/badge.d.ts +19 -0
  30. package/dist/badge/badge.js +22 -0
  31. package/dist/badge/index.d.ts +2 -0
  32. package/dist/badge/index.js +1 -0
  33. package/dist/button/button.d.ts +54 -0
  34. package/dist/button/button.js +62 -0
  35. package/dist/button/index.d.ts +2 -0
  36. package/dist/button/index.js +1 -0
  37. package/dist/card/card.d.ts +57 -0
  38. package/dist/card/card.js +62 -0
  39. package/dist/card/card.parts.d.ts +6 -0
  40. package/dist/card/card.parts.js +14 -0
  41. package/dist/card/index.d.ts +3 -0
  42. package/dist/card/index.js +3 -0
  43. package/dist/checkbox/checkbox.client.d.ts +37 -0
  44. package/dist/checkbox/checkbox.client.js +81 -0
  45. package/dist/checkbox/index.d.ts +2 -0
  46. package/dist/checkbox/index.js +1 -0
  47. package/dist/config/config.client.d.ts +9 -0
  48. package/dist/config/config.client.js +18 -0
  49. package/dist/config/index.d.ts +2 -0
  50. package/dist/config/index.js +1 -0
  51. package/dist/container/container.d.ts +13 -0
  52. package/dist/container/container.js +16 -0
  53. package/dist/container/index.d.ts +2 -0
  54. package/dist/container/index.js +1 -0
  55. package/dist/contracts/details.d.ts +13 -0
  56. package/dist/contracts/details.js +9 -0
  57. package/dist/contracts/index.d.ts +5 -0
  58. package/dist/contracts/index.js +5 -0
  59. package/dist/contracts/merge-props.d.ts +16 -0
  60. package/dist/contracts/merge-props.js +76 -0
  61. package/dist/contracts/render.d.ts +17 -0
  62. package/dist/contracts/render.js +43 -0
  63. package/dist/contracts/state.d.ts +42 -0
  64. package/dist/contracts/state.js +42 -0
  65. package/dist/css/alert.css +2 -0
  66. package/dist/css/badge.css +2 -0
  67. package/dist/css/base.css +2 -0
  68. package/dist/css/button.css +2 -0
  69. package/dist/css/card.css +2 -0
  70. package/dist/css/checkbox.css +2 -0
  71. package/dist/css/container.css +2 -0
  72. package/dist/css/delta.css +2 -0
  73. package/dist/css/dialog.css +2 -0
  74. package/dist/css/empty-state.css +2 -0
  75. package/dist/css/field.css +2 -0
  76. package/dist/css/fieldset.css +2 -0
  77. package/dist/css/grid.css +2 -0
  78. package/dist/css/heading.css +2 -0
  79. package/dist/css/icon-button.css +2 -0
  80. package/dist/css/image.css +2 -0
  81. package/dist/css/inline-error.css +2 -0
  82. package/dist/css/inline.css +2 -0
  83. package/dist/css/input.css +2 -0
  84. package/dist/css/kbd.css +2 -0
  85. package/dist/css/menu.css +2 -0
  86. package/dist/css/meter.css +2 -0
  87. package/dist/css/native-select.css +2 -0
  88. package/dist/css/progress-bar.css +2 -0
  89. package/dist/css/progress-ring.css +2 -0
  90. package/dist/css/radio-group.css +2 -0
  91. package/dist/css/segmented-control.css +2 -0
  92. package/dist/css/select.css +2 -0
  93. package/dist/css/separator.css +2 -0
  94. package/dist/css/skeleton.css +2 -0
  95. package/dist/css/stack.css +2 -0
  96. package/dist/css/switch.css +2 -0
  97. package/dist/css/tab-nav.css +2 -0
  98. package/dist/css/tabs.css +2 -0
  99. package/dist/css/text.css +2 -0
  100. package/dist/css/textarea.css +2 -0
  101. package/dist/css/tooltip.css +2 -0
  102. package/dist/delta/delta.d.ts +32 -0
  103. package/dist/delta/delta.js +50 -0
  104. package/dist/delta/index.d.ts +2 -0
  105. package/dist/delta/index.js +1 -0
  106. package/dist/dialog/dialog.client.d.ts +25 -0
  107. package/dist/dialog/dialog.client.js +167 -0
  108. package/dist/dialog/dialog.contract.d.ts +97 -0
  109. package/dist/dialog/dialog.parts.d.ts +6 -0
  110. package/dist/dialog/dialog.parts.js +15 -0
  111. package/dist/dialog/index.d.ts +5 -0
  112. package/dist/dialog/index.js +3 -0
  113. package/dist/empty-state/empty-state.d.ts +18 -0
  114. package/dist/empty-state/empty-state.js +32 -0
  115. package/dist/empty-state/index.d.ts +2 -0
  116. package/dist/empty-state/index.js +1 -0
  117. package/dist/field/field-scope.client.d.ts +50 -0
  118. package/dist/field/field-scope.client.js +205 -0
  119. package/dist/field/field-static.d.ts +122 -0
  120. package/dist/field/field-static.js +159 -0
  121. package/dist/field/field.d.ts +5 -0
  122. package/dist/field/field.js +53 -0
  123. package/dist/field/index.d.ts +4 -0
  124. package/dist/field/index.js +4 -0
  125. package/dist/fieldset/fieldset.d.ts +36 -0
  126. package/dist/fieldset/fieldset.js +63 -0
  127. package/dist/fieldset/index.d.ts +2 -0
  128. package/dist/fieldset/index.js +1 -0
  129. package/dist/grid/grid.d.ts +38 -0
  130. package/dist/grid/grid.js +28 -0
  131. package/dist/grid/index.d.ts +2 -0
  132. package/dist/grid/index.js +1 -0
  133. package/dist/heading/heading.d.ts +27 -0
  134. package/dist/heading/heading.js +26 -0
  135. package/dist/heading/index.d.ts +2 -0
  136. package/dist/heading/index.js +1 -0
  137. package/dist/icon-button/icon-button-static.d.ts +23 -0
  138. package/dist/icon-button/icon-button-static.js +83 -0
  139. package/dist/icon-button/icon-button.client.js +29 -0
  140. package/dist/icon-button/icon-button.contract.d.ts +89 -0
  141. package/dist/icon-button/icon-button.d.ts +5 -0
  142. package/dist/icon-button/icon-button.js +21 -0
  143. package/dist/icon-button/index.d.ts +4 -0
  144. package/dist/icon-button/index.js +3 -0
  145. package/dist/image/image.d.ts +28 -0
  146. package/dist/image/image.js +24 -0
  147. package/dist/image/index.d.ts +2 -0
  148. package/dist/image/index.js +1 -0
  149. package/dist/index.d.ts +95 -0
  150. package/dist/index.js +51 -0
  151. package/dist/inline/index.d.ts +2 -0
  152. package/dist/inline/index.js +1 -0
  153. package/dist/inline/inline.d.ts +16 -0
  154. package/dist/inline/inline.js +14 -0
  155. package/dist/inline-error/index.d.ts +2 -0
  156. package/dist/inline-error/index.js +1 -0
  157. package/dist/inline-error/inline-error.d.ts +17 -0
  158. package/dist/inline-error/inline-error.js +33 -0
  159. package/dist/input/index.d.ts +2 -0
  160. package/dist/input/index.js +1 -0
  161. package/dist/input/input.client.d.ts +39 -0
  162. package/dist/input/input.client.js +82 -0
  163. package/dist/kbd/index.d.ts +2 -0
  164. package/dist/kbd/index.js +1 -0
  165. package/dist/kbd/kbd.d.ts +19 -0
  166. package/dist/kbd/kbd.js +68 -0
  167. package/dist/menu/index.d.ts +5 -0
  168. package/dist/menu/index.js +3 -0
  169. package/dist/menu/menu.client.d.ts +14 -0
  170. package/dist/menu/menu.client.js +152 -0
  171. package/dist/menu/menu.contract.d.ts +152 -0
  172. package/dist/menu/menu.parts.d.ts +6 -0
  173. package/dist/menu/menu.parts.js +17 -0
  174. package/dist/meter/index.d.ts +2 -0
  175. package/dist/meter/index.js +1 -0
  176. package/dist/meter/meter.d.ts +43 -0
  177. package/dist/meter/meter.js +59 -0
  178. package/dist/native-select/index.d.ts +2 -0
  179. package/dist/native-select/index.js +1 -0
  180. package/dist/native-select/native-select.d.ts +43 -0
  181. package/dist/native-select/native-select.js +56 -0
  182. package/dist/progress-bar/index.d.ts +2 -0
  183. package/dist/progress-bar/index.js +1 -0
  184. package/dist/progress-bar/progress-bar.d.ts +34 -0
  185. package/dist/progress-bar/progress-bar.js +55 -0
  186. package/dist/progress-ring/index.d.ts +2 -0
  187. package/dist/progress-ring/index.js +1 -0
  188. package/dist/progress-ring/progress-ring.d.ts +38 -0
  189. package/dist/progress-ring/progress-ring.js +67 -0
  190. package/dist/radio-group/index.d.ts +3 -0
  191. package/dist/radio-group/index.js +3 -0
  192. package/dist/radio-group/radio-group.client.d.ts +22 -0
  193. package/dist/radio-group/radio-group.client.js +70 -0
  194. package/dist/radio-group/radio-group.d.ts +28 -0
  195. package/dist/radio-group/radio-group.js +35 -0
  196. package/dist/segmented-control/index.d.ts +3 -0
  197. package/dist/segmented-control/index.js +3 -0
  198. package/dist/segmented-control/segmented-control.client.d.ts +61 -0
  199. package/dist/segmented-control/segmented-control.client.js +156 -0
  200. package/dist/segmented-control/segmented-control.parts.d.ts +6 -0
  201. package/dist/segmented-control/segmented-control.parts.js +9 -0
  202. package/dist/select/index.d.ts +5 -0
  203. package/dist/select/index.js +3 -0
  204. package/dist/select/select.client.d.ts +12 -0
  205. package/dist/select/select.client.js +152 -0
  206. package/dist/select/select.contract.d.ts +119 -0
  207. package/dist/select/select.parts.d.ts +6 -0
  208. package/dist/select/select.parts.js +15 -0
  209. package/dist/separator/index.d.ts +2 -0
  210. package/dist/separator/index.js +1 -0
  211. package/dist/separator/separator.d.ts +26 -0
  212. package/dist/separator/separator.js +23 -0
  213. package/dist/skeleton/index.d.ts +2 -0
  214. package/dist/skeleton/index.js +1 -0
  215. package/dist/skeleton/skeleton.d.ts +20 -0
  216. package/dist/skeleton/skeleton.js +19 -0
  217. package/dist/stack/index.d.ts +2 -0
  218. package/dist/stack/index.js +1 -0
  219. package/dist/stack/stack.d.ts +17 -0
  220. package/dist/stack/stack.js +14 -0
  221. package/dist/styles.css +536 -0
  222. package/dist/switch/index.d.ts +2 -0
  223. package/dist/switch/index.js +1 -0
  224. package/dist/switch/switch.client.d.ts +33 -0
  225. package/dist/switch/switch.client.js +63 -0
  226. package/dist/tab-nav/index.d.ts +3 -0
  227. package/dist/tab-nav/index.js +3 -0
  228. package/dist/tab-nav/tab-nav.d.ts +36 -0
  229. package/dist/tab-nav/tab-nav.js +47 -0
  230. package/dist/tab-nav/tab-nav.parts.d.ts +6 -0
  231. package/dist/tab-nav/tab-nav.parts.js +9 -0
  232. package/dist/tabs/index.d.ts +4 -0
  233. package/dist/tabs/index.js +3 -0
  234. package/dist/tabs/tabs.client.d.ts +8 -0
  235. package/dist/tabs/tabs.client.js +68 -0
  236. package/dist/tabs/tabs.contract.d.ts +89 -0
  237. package/dist/tabs/tabs.parts.d.ts +6 -0
  238. package/dist/tabs/tabs.parts.js +11 -0
  239. package/dist/text/index.d.ts +2 -0
  240. package/dist/text/index.js +1 -0
  241. package/dist/text/text.d.ts +21 -0
  242. package/dist/text/text.js +17 -0
  243. package/dist/textarea/index.d.ts +2 -0
  244. package/dist/textarea/index.js +1 -0
  245. package/dist/textarea/textarea.client.d.ts +18 -0
  246. package/dist/textarea/textarea.client.js +31 -0
  247. package/dist/theme-script/index.d.ts +2 -0
  248. package/dist/theme-script/index.js +1 -0
  249. package/dist/theme-script/theme-script.d.ts +43 -0
  250. package/dist/theme-script/theme-script.js +46 -0
  251. package/dist/tooltip/index.d.ts +5 -0
  252. package/dist/tooltip/index.js +3 -0
  253. package/dist/tooltip/tooltip.client.d.ts +12 -0
  254. package/dist/tooltip/tooltip.client.js +51 -0
  255. package/dist/tooltip/tooltip.contract.d.ts +60 -0
  256. package/dist/tooltip/tooltip.parts.d.ts +6 -0
  257. package/dist/tooltip/tooltip.parts.js +10 -0
  258. package/package.json +284 -3
@@ -0,0 +1,34 @@
1
+ import { RenderProp } from "../contracts/render.js";
2
+ import { ComponentPropsWithRef, ReactElement, ReactNode } from "react";
3
+ //#region src/progress-bar/progress-bar.d.ts
4
+ /** Figma "Tone" (Brand, Warning, Critical) plus `success` and `neutral`. */
5
+ export type ProgressBarTone = "brand" | "success" | "warning" | "critical" | "neutral";
6
+ export interface ProgressBarState {
7
+ tone: ProgressBarTone;
8
+ /** The clamped value, or `null` while indeterminate. */
9
+ value: number | null;
10
+ max: number;
11
+ indeterminate: boolean;
12
+ }
13
+ export interface ProgressBarProps extends Omit<ComponentPropsWithRef<"div">, "children"> {
14
+ /** Clamped to `0…max`. @default 0 */
15
+ value?: number;
16
+ /** Must be above zero. @default 100 */
17
+ max?: number;
18
+ /** The visible name. Without it, name the bar with `aria-label` or `aria-labelledby`. */
19
+ label?: ReactNode;
20
+ /** Shows the value as a percentage beside the label (hidden from assistive technology, which reads the bar itself). @default true */
21
+ showValue?: boolean;
22
+ /** Work is under way but its amount is unknown: the bar has no value. @default false */
23
+ indeterminate?: boolean;
24
+ /** @default 'brand' */
25
+ tone?: ProgressBarTone;
26
+ /** BCP 47 tag for the percentage. @default 'en-US' */
27
+ locale?: string;
28
+ /** Replaces the shown percentage and is read instead of it, for example "3 of 5 steps". */
29
+ valueText?: string;
30
+ /** Composition of the root; the native `<progress>` inside keeps its semantics. */
31
+ render?: RenderProp<ProgressBarState>;
32
+ }
33
+ export declare function ProgressBar({ value, max, label, showValue, indeterminate, tone, locale, valueText, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, render, className, ...rest }: ProgressBarProps): ReactElement;
34
+ //#endregion
@@ -0,0 +1,55 @@
1
+ import { cx } from "../_internal/cx.js";
2
+ import { renderElement } from "../contracts/render.js";
3
+ import { useId } from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/progress-bar/progress-bar.tsx
6
+ function ProgressBar({ value = 0, max = 100, label, showValue = true, indeterminate = false, tone = "brand", locale = "en-US", valueText, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, render, className, ...rest }) {
7
+ const labelId = useId();
8
+ const range = Number.isFinite(max) && max > 0 ? max : 100;
9
+ const current = indeterminate ? null : clamp(value, range);
10
+ const shown = current === null ? void 0 : valueText ?? new Intl.NumberFormat(locale, {
11
+ style: "percent",
12
+ maximumFractionDigits: 0
13
+ }).format(current / range);
14
+ const hasLabel = label != null;
15
+ const hasValue = showValue && shown !== void 0;
16
+ return renderElement("div", render, {
17
+ tone,
18
+ value: current,
19
+ max: range,
20
+ indeterminate
21
+ }, {
22
+ "data-slot": "progress-bar",
23
+ "data-tone": tone,
24
+ ...rest,
25
+ className: cx("nz-progress-bar", className),
26
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [(hasLabel || hasValue) && /* @__PURE__ */ jsxs("div", {
27
+ className: "nz-progress-bar-header",
28
+ "data-slot": "progress-bar-header",
29
+ children: [hasLabel && /* @__PURE__ */ jsx("span", {
30
+ id: labelId,
31
+ className: "nz-progress-bar-label",
32
+ "data-slot": "progress-bar-label",
33
+ children: label
34
+ }), hasValue && /* @__PURE__ */ jsx("span", {
35
+ className: "nz-progress-bar-value",
36
+ "data-slot": "progress-bar-value",
37
+ "aria-hidden": "true",
38
+ children: shown
39
+ })]
40
+ }), /* @__PURE__ */ jsx("progress", {
41
+ className: "nz-progress-bar-track",
42
+ "data-slot": "progress-bar-track",
43
+ max: range,
44
+ value: current ?? void 0,
45
+ "aria-label": ariaLabel,
46
+ "aria-labelledby": ariaLabelledBy ?? (hasLabel ? labelId : void 0),
47
+ "aria-valuetext": current === null ? void 0 : valueText
48
+ })] })
49
+ });
50
+ }
51
+ function clamp(value, max) {
52
+ return Number.isFinite(value) ? Math.min(Math.max(value, 0), max) : 0;
53
+ }
54
+ //#endregion
55
+ export { ProgressBar };
@@ -0,0 +1,2 @@
1
+ import { ProgressRing, ProgressRingProps, ProgressRingSize, ProgressRingState, ProgressRingTone } from "./progress-ring.js";
2
+ export { ProgressRing, type ProgressRingProps, type ProgressRingSize, type ProgressRingState, type ProgressRingTone };
@@ -0,0 +1 @@
1
+ export { ProgressRing } from "./progress-ring.js";
@@ -0,0 +1,38 @@
1
+ import { RenderProp } from "../contracts/render.js";
2
+ import { ComponentPropsWithRef, ReactElement, ReactNode } from "react";
3
+ //#region src/progress-ring/progress-ring.d.ts
4
+ export type ProgressRingTone = "brand" | "success" | "warning" | "critical" | "neutral";
5
+ /** 48 / 72 / 96 px; Figma draws only 72. */
6
+ export type ProgressRingSize = "sm" | "md" | "lg";
7
+ export interface ProgressRingState {
8
+ tone: ProgressRingTone;
9
+ size: ProgressRingSize;
10
+ /** The value clamped to `0…max`. */
11
+ value: number;
12
+ max: number;
13
+ }
14
+ export interface ProgressRingProps extends Omit<ComponentPropsWithRef<"div">, "role"> {
15
+ /** Figma "Value" (25 / 50 / 75 / 100 there). Clamped to `0…max`. */
16
+ value: number;
17
+ /** Must be above zero. @default 100 */
18
+ max?: number;
19
+ /** @default 'brand' */
20
+ tone?: ProgressRingTone;
21
+ /** @default 'md' */
22
+ size?: ProgressRingSize;
23
+ /**
24
+ * Exposes the ring as a `meter` (a measurement, such as a goal reached) instead of a `progressbar`
25
+ * (work under way). @default false
26
+ */
27
+ meter?: boolean;
28
+ /** BCP 47 tag for the percentage. @default 'en-US' */
29
+ locale?: string;
30
+ /** What assistive technology reads instead of the percentage. Set it whenever `children` shows something else. */
31
+ valueText?: string;
32
+ /** The centre, shown to sighted users only (the ring's children are presentational). @default the percentage */
33
+ children?: ReactNode;
34
+ /** Name the ring with `aria-label` or `aria-labelledby`. */
35
+ render?: RenderProp<ProgressRingState>;
36
+ }
37
+ export declare function ProgressRing({ value, max, tone, size, meter, locale, valueText, render, className, children, ...rest }: ProgressRingProps): ReactElement;
38
+ //#endregion
@@ -0,0 +1,67 @@
1
+ import { cx } from "../_internal/cx.js";
2
+ import { renderElement } from "../contracts/render.js";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/progress-ring/progress-ring.tsx
5
+ const CENTRE = 36;
6
+ /** Figma's inner-radius ratio 0.8 at 72 px: a 7.2-unit ring on the 32.4 radius midline. */
7
+ const STROKE = 7.2;
8
+ const RADIUS = CENTRE - STROKE / 2;
9
+ function ProgressRing({ value, max = 100, tone = "brand", size = "md", meter = false, locale = "en-US", valueText, render, className, children, ...rest }) {
10
+ const range = Number.isFinite(max) && max > 0 ? max : 100;
11
+ const current = Number.isFinite(value) ? Math.min(Math.max(value, 0), range) : 0;
12
+ const percent = new Intl.NumberFormat(locale, {
13
+ style: "percent",
14
+ maximumFractionDigits: 0
15
+ }).format(current / range);
16
+ const arc = current / range * 100;
17
+ return renderElement("div", render, {
18
+ tone,
19
+ size,
20
+ value: current,
21
+ max: range
22
+ }, {
23
+ role: meter ? "meter" : "progressbar",
24
+ "aria-valuenow": current,
25
+ "aria-valuemin": 0,
26
+ "aria-valuemax": range,
27
+ "aria-valuetext": valueText ?? percent,
28
+ "data-slot": "progress-ring",
29
+ "data-tone": tone,
30
+ "data-size": size,
31
+ ...rest,
32
+ className: cx("nz-progress-ring", className),
33
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("svg", {
34
+ className: "nz-progress-ring-svg",
35
+ viewBox: `0 0 72 72`,
36
+ "aria-hidden": "true",
37
+ focusable: "false",
38
+ children: [/* @__PURE__ */ jsx("circle", {
39
+ className: "nz-progress-ring-track",
40
+ "data-slot": "progress-ring-track",
41
+ cx: CENTRE,
42
+ cy: CENTRE,
43
+ r: RADIUS,
44
+ fill: "none",
45
+ strokeWidth: STROKE
46
+ }), /* @__PURE__ */ jsx("circle", {
47
+ className: "nz-progress-ring-fill",
48
+ "data-slot": "progress-ring-fill",
49
+ cx: CENTRE,
50
+ cy: CENTRE,
51
+ r: RADIUS,
52
+ fill: "none",
53
+ strokeWidth: STROKE,
54
+ pathLength: 100,
55
+ strokeDasharray: `${arc} 100`,
56
+ transform: `rotate(-90 ${CENTRE} ${CENTRE})`
57
+ })]
58
+ }), /* @__PURE__ */ jsx("span", {
59
+ className: "nz-progress-ring-label",
60
+ "data-slot": "progress-ring-label",
61
+ "aria-hidden": "true",
62
+ children: children ?? percent
63
+ })] })
64
+ });
65
+ }
66
+ //#endregion
67
+ export { ProgressRing };
@@ -0,0 +1,3 @@
1
+ import { RadioGroup, RadioGroupChangeReason, RadioGroupProps } from "./radio-group.js";
2
+ import { Radio, RadioProps, RadioState } from "./radio-group.client.js";
3
+ export { Radio, RadioGroup, type RadioGroupChangeReason, type RadioGroupProps, type RadioProps, type RadioState };
@@ -0,0 +1,3 @@
1
+ import { Radio } from "./radio-group.client.js";
2
+ import { RadioGroup } from "./radio-group.js";
3
+ export { Radio, RadioGroup };
@@ -0,0 +1,22 @@
1
+ import { RenderProp } from "../contracts/render.js";
2
+ import { ComponentPropsWithRef, ReactElement, ReactNode } from "react";
3
+ //#region src/radio-group/radio-group.client.d.ts
4
+ /** What a `render` function receives for the root `<label>`. */
5
+ export interface RadioState {
6
+ disabled: boolean;
7
+ }
8
+ export interface RadioProps extends Omit<ComponentPropsWithRef<"input">, "type" | "value" | "name" | "checked" | "defaultChecked" | "required" | "readOnly" | "children" | "size"> {
9
+ /** Submitted under the group's name when this radio is checked. */
10
+ value: string;
11
+ /** Composition of the root `<label>`, the hit target. */
12
+ render?: RenderProp<RadioState>;
13
+ /** The label, after the circle. */
14
+ children?: ReactNode;
15
+ }
16
+ /**
17
+ * One option of a `RadioGroup`. `className` and `style` go on the root `<label>`; every other
18
+ * attribute, `ref` included, goes on the native `<input>`. Name, checked state and `required` come
19
+ * from the group.
20
+ */
21
+ export declare function Radio({ value, disabled, render, className, style, children, ...rest }: RadioProps): ReactElement;
22
+ //#endregion
@@ -0,0 +1,70 @@
1
+ "use client";
2
+ import { cx } from "../_internal/cx.js";
3
+ import { mergeProps } from "../contracts/merge-props.js";
4
+ import { renderElement } from "../contracts/render.js";
5
+ import { details } from "../contracts/details.js";
6
+ import { stateAttrs } from "../contracts/state.js";
7
+ import { presented } from "../_internal/field.js";
8
+ import { createContext, use, useMemo } from "react";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ //#region src/radio-group/radio-group.client.tsx
11
+ const RadioGroupContext = createContext(null);
12
+ /** Internal: rendered only by `RadioGroup`. Every prop but `onValueChange` is serialisable. */
13
+ function RadioGroupScope({ name, value, defaultValue, required, onValueChange, children }) {
14
+ const scope = useMemo(() => ({
15
+ name,
16
+ value,
17
+ defaultValue,
18
+ required,
19
+ onValueChange
20
+ }), [
21
+ name,
22
+ value,
23
+ defaultValue,
24
+ required,
25
+ onValueChange
26
+ ]);
27
+ return /* @__PURE__ */ jsx(RadioGroupContext, {
28
+ value: scope,
29
+ children
30
+ });
31
+ }
32
+ /**
33
+ * One option of a `RadioGroup`. `className` and `style` go on the root `<label>`; every other
34
+ * attribute, `ref` included, goes on the native `<input>`. Name, checked state and `required` come
35
+ * from the group.
36
+ */
37
+ function Radio({ value, disabled, render, className, style, children, ...rest }) {
38
+ const group = use(RadioGroupContext);
39
+ const controlled = group !== null && group.value !== void 0;
40
+ const own = {
41
+ name: group?.name,
42
+ required: group?.required === true ? true : void 0,
43
+ disabled,
44
+ checked: controlled ? group.value === value : void 0,
45
+ defaultChecked: !controlled && group?.defaultValue !== void 0 ? group.defaultValue === value : void 0,
46
+ onChange(event) {
47
+ if (event.currentTarget.checked) group?.onValueChange?.(value, details("input", event.nativeEvent));
48
+ }
49
+ };
50
+ const state = { disabled: disabled === true };
51
+ return renderElement("label", render, state, {
52
+ "data-slot": "radio",
53
+ ...stateAttrs(state),
54
+ className: cx("nz-radio nz-hit-target", className),
55
+ style,
56
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
57
+ ...mergeProps(own, rest),
58
+ type: "radio",
59
+ value,
60
+ className: "nz-radio-input",
61
+ "data-slot": "radio-input"
62
+ }), presented(children) && /* @__PURE__ */ jsx("span", {
63
+ className: "nz-radio-label",
64
+ "data-slot": "radio-label",
65
+ children
66
+ })] })
67
+ });
68
+ }
69
+ //#endregion
70
+ export { Radio, RadioGroupScope };
@@ -0,0 +1,28 @@
1
+ import { ChangeDetails } from "../contracts/details.js";
2
+ import { Orientation } from "../contracts/state.js";
3
+ import { FieldsetProps } from "../fieldset/fieldset.js";
4
+ import { ReactElement, ReactNode } from "react";
5
+ //#region src/radio-group/radio-group.d.ts
6
+ /** Every change comes from the native `change` event of the radio that became checked. */
7
+ export type RadioGroupChangeReason = "input";
8
+ export interface RadioGroupProps extends Omit<FieldsetProps, "children" | "role" | "name" | "defaultValue" | "onChange"> {
9
+ /** The name every radio submits under. @default a generated name, unique per group */
10
+ name?: string;
11
+ /** Controlled: the checked radio's `value`, or `null` for none. */
12
+ value?: string | null;
13
+ /** Uncontrolled initial value. */
14
+ defaultValue?: string;
15
+ /** Called with the newly checked radio's `value`, after that radio's own `onChange`. */
16
+ onValueChange?: (value: string, details: ChangeDetails<RadioGroupChangeReason>) => void;
17
+ /** Layout of the radios; native arrow keys move both ways either way. @default 'vertical' */
18
+ orientation?: Orientation;
19
+ /** `Radio` elements, possibly with other content between them. */
20
+ children?: ReactNode;
21
+ }
22
+ /**
23
+ * A native `<fieldset role="radiogroup">` with a `<legend>` (Fieldset), plus `aria-required` and
24
+ * `aria-invalid`, which role `group` does not allow but `radiogroup` does (FIELD-CONTRACT.md).
25
+ * `required` marks the legend and makes every radio `required`; `disabled` is the fieldset's own.
26
+ */
27
+ export declare function RadioGroup({ name, value, defaultValue, onValueChange, orientation, required, className, children, ...rest }: RadioGroupProps): ReactElement;
28
+ //#endregion
@@ -0,0 +1,35 @@
1
+ import { cx } from "../_internal/cx.js";
2
+ import { presented } from "../_internal/field.js";
3
+ import { Fieldset } from "../fieldset/fieldset.js";
4
+ import { RadioGroupScope } from "./radio-group.client.js";
5
+ import { useId } from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+ //#region src/radio-group/radio-group.tsx
8
+ /**
9
+ * A native `<fieldset role="radiogroup">` with a `<legend>` (Fieldset), plus `aria-required` and
10
+ * `aria-invalid`, which role `group` does not allow but `radiogroup` does (FIELD-CONTRACT.md).
11
+ * `required` marks the legend and makes every radio `required`; `disabled` is the fieldset's own.
12
+ */
13
+ function RadioGroup({ name, value, defaultValue, onValueChange, orientation = "vertical", required = false, className, children, ...rest }) {
14
+ const generated = useId();
15
+ return /* @__PURE__ */ jsx(Fieldset, {
16
+ ...rest,
17
+ required,
18
+ role: "radiogroup",
19
+ "aria-required": required || void 0,
20
+ "aria-invalid": presented(rest.error) || void 0,
21
+ "data-slot": "radio-group",
22
+ "data-orientation": orientation,
23
+ className: cx("nz-radio-group", className),
24
+ children: /* @__PURE__ */ jsx(RadioGroupScope, {
25
+ name: name ?? `${generated}-radio`,
26
+ value,
27
+ defaultValue,
28
+ required,
29
+ onValueChange,
30
+ children
31
+ })
32
+ });
33
+ }
34
+ //#endregion
35
+ export { RadioGroup };
@@ -0,0 +1,3 @@
1
+ import { SegmentedControlChangeReason, SegmentedControlItem, SegmentedControlItemProps, SegmentedControlItemState, SegmentedControlRoot, SegmentedControlRootProps, SegmentedControlRootState } from "./segmented-control.client.js";
2
+ import { segmented_control_parts_d_exports } from "./segmented-control.parts.js";
3
+ export { segmented_control_parts_d_exports as SegmentedControl, type SegmentedControlChangeReason, SegmentedControlItem, type SegmentedControlItemProps, type SegmentedControlItemState, SegmentedControlRoot, type SegmentedControlRootProps, type SegmentedControlRootState };
@@ -0,0 +1,3 @@
1
+ import { SegmentedControlItem, SegmentedControlRoot } from "./segmented-control.client.js";
2
+ import { segmented_control_parts_exports } from "./segmented-control.parts.js";
3
+ export { segmented_control_parts_exports as SegmentedControl, SegmentedControlItem, SegmentedControlRoot };
@@ -0,0 +1,61 @@
1
+ import { RenderProp } from "../contracts/render.js";
2
+ import { ControlSize } from "../augment.js";
3
+ import { ChangeDetails } from "../contracts/details.js";
4
+ import { ComponentPropsWithRef, JSX, ReactNode } from "react";
5
+ //#region src/segmented-control/segmented-control.client.d.ts
6
+ /** Why the value changed: the user checked a radio (a pointer or a key; the browser does not say). */
7
+ export type SegmentedControlChangeReason = "input";
8
+ export interface SegmentedControlRootState {
9
+ size: ControlSize;
10
+ disabled: boolean;
11
+ invalid: boolean;
12
+ }
13
+ export interface SegmentedControlRootProps extends Omit<ComponentPropsWithRef<"div">, "defaultValue" | "onChange" | "role"> {
14
+ /** Controlled: the selected item's `value`, or `null` for none. */
15
+ value?: string | null;
16
+ /** The item selected at first (uncontrolled; `form.reset()` returns to it). */
17
+ defaultValue?: string;
18
+ /**
19
+ * Called when the user selects an item. `details.reason` is `'input'` (as on RadioGroup and
20
+ * Checkbox); `details.event` is the native `change` event.
21
+ */
22
+ onValueChange?: (value: string, details: ChangeDetails<SegmentedControlChangeReason>) => void;
23
+ /**
24
+ * The radios' shared name, and the `FormData` key. Without one (and outside a named Field), a
25
+ * generated name groups the radios.
26
+ */
27
+ name?: string;
28
+ /** The `<form>` the radios belong to, when they are outside it. */
29
+ form?: string;
30
+ required?: boolean;
31
+ /** Disables every item. */
32
+ disabled?: boolean;
33
+ /** An error message is presented (set by a Field). */
34
+ invalid?: boolean;
35
+ /** 32 / 40 / 48 px track. @default 'md' */
36
+ size?: ControlSize;
37
+ /** Stretches the track to its container and shares the width equally between items. @default false */
38
+ fullWidth?: boolean;
39
+ render?: RenderProp<SegmentedControlRootState>;
40
+ children?: ReactNode;
41
+ }
42
+ export interface SegmentedControlItemState {
43
+ disabled: boolean;
44
+ }
45
+ export interface SegmentedControlItemProps extends Omit<ComponentPropsWithRef<"label">, "htmlFor" | "aria-label"> {
46
+ /** This item's value: what `onValueChange` receives and the form submits. */
47
+ value: string;
48
+ disabled?: boolean;
49
+ /** A decorative glyph before the text (16 px). */
50
+ icon?: ReactNode;
51
+ /**
52
+ * Names an icon-only item (no `children`): it goes on the radio, which is what assistive
53
+ * technology announces.
54
+ */
55
+ "aria-label"?: string;
56
+ render?: RenderProp<SegmentedControlItemState>;
57
+ children?: ReactNode;
58
+ }
59
+ export declare function SegmentedControlRoot({ value, defaultValue, onValueChange, name, form, required, disabled, invalid, size, fullWidth, "aria-describedby": describedBy, "aria-labelledby": labelledBy, render, className, children, ...rest }: SegmentedControlRootProps): JSX.Element;
60
+ export declare function SegmentedControlItem({ value, disabled, icon, "aria-label": ariaLabel, render, className, children, ...rest }: SegmentedControlItemProps): JSX.Element;
61
+ //#endregion
@@ -0,0 +1,156 @@
1
+ "use client";
2
+ import { cx } from "../_internal/cx.js";
3
+ import { mergeProps } from "../contracts/merge-props.js";
4
+ import { renderElement } from "../contracts/render.js";
5
+ import { details } from "../contracts/details.js";
6
+ import { stateAttrs } from "../contracts/state.js";
7
+ import { useFieldControl } from "../field/field-scope.client.js";
8
+ import { createContext, use, useId, useMemo } from "react";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ //#region src/segmented-control/segmented-control.client.tsx
11
+ const GroupContext = createContext(null);
12
+ /**
13
+ * True while a radio's keydown is being handled. An arrow key moves focus to the next radio as the
14
+ * keydown's default action, in the same task, so a focus seen while this is set came from a key.
15
+ */
16
+ let keyDown = false;
17
+ function onKeyDown() {
18
+ keyDown = true;
19
+ setTimeout(() => {
20
+ keyDown = false;
21
+ }, 0);
22
+ }
23
+ /**
24
+ * WebKit does not match :focus-visible on a radio reached with an arrow key, so the item marks a
25
+ * keyboard focus itself (nz.base draws the outline for `[data-focus-visible]`). Written on the DOM,
26
+ * not through state: re-rendering a focused radio makes React re-write its `name`, and Chromium then
27
+ * stops treating an unchecked group as one Tab stop.
28
+ */
29
+ function markFocus(event) {
30
+ const visible = event.currentTarget.matches(":focus-visible") || keyDown;
31
+ event.currentTarget.closest(".nz-segmented-control-item")?.toggleAttribute("data-focus-visible", visible);
32
+ }
33
+ function clearFocus(event) {
34
+ event.currentTarget.closest(".nz-segmented-control-item")?.removeAttribute("data-focus-visible");
35
+ }
36
+ function SegmentedControlRoot({ value, defaultValue, onValueChange, name, form, required, disabled, invalid, size = "md", fullWidth = false, "aria-describedby": describedBy, "aria-labelledby": labelledBy, render, className, children, ...rest }) {
37
+ const field = useFieldControl({
38
+ name,
39
+ required,
40
+ disabled,
41
+ invalid,
42
+ "aria-describedby": describedBy
43
+ });
44
+ const generated = useId();
45
+ const { required: radioRequired, onInvalid, onInput, onBlur } = field.controlProps;
46
+ const groupName = field.name ?? generated;
47
+ const group = useMemo(() => ({
48
+ name: groupName,
49
+ value,
50
+ defaultValue,
51
+ disabled: field.disabled,
52
+ radio: definedProps({
53
+ required: radioRequired,
54
+ form,
55
+ onInvalid,
56
+ onInput,
57
+ onBlur
58
+ }),
59
+ onValueChange
60
+ }), [
61
+ groupName,
62
+ value,
63
+ defaultValue,
64
+ field.disabled,
65
+ radioRequired,
66
+ form,
67
+ onInvalid,
68
+ onInput,
69
+ onBlur,
70
+ onValueChange
71
+ ]);
72
+ return /* @__PURE__ */ jsx(GroupContext, {
73
+ value: group,
74
+ children: renderElement("div", render, {
75
+ size,
76
+ disabled: field.disabled,
77
+ invalid: field.invalid
78
+ }, {
79
+ "data-slot": "segmented-control",
80
+ "data-size": size,
81
+ "data-full-width": fullWidth ? "" : void 0,
82
+ ...stateAttrs({
83
+ disabled: field.disabled,
84
+ invalid: field.invalid,
85
+ required: field.required
86
+ }),
87
+ ...rest,
88
+ role: "radiogroup",
89
+ "aria-labelledby": labelledBy ?? field.labelledBy,
90
+ "aria-describedby": field.describedBy,
91
+ "aria-invalid": field.invalid ? true : void 0,
92
+ "aria-required": field.required ? true : void 0,
93
+ className: cx("nz-segmented-control", className),
94
+ children
95
+ })
96
+ });
97
+ }
98
+ /** Drops `undefined` values, so a spread never writes an empty attribute or handler. */
99
+ function definedProps(props) {
100
+ const out = {};
101
+ for (const [key, value] of Object.entries(props)) if (value !== void 0) out[key] = value;
102
+ return out;
103
+ }
104
+ function SegmentedControlItem({ value, disabled, icon, "aria-label": ariaLabel, render, className, children, ...rest }) {
105
+ const group = use(GroupContext);
106
+ if (group === null) throw new Error("SegmentedControl.Item must be inside SegmentedControl.Root");
107
+ const off = disabled === true || group.disabled;
108
+ const checked = group.value === void 0 ? { defaultChecked: group.defaultValue === value } : { checked: group.value === value };
109
+ const onChange = (event) => {
110
+ if (event.currentTarget.checked) group.onValueChange?.(value, details("input", event.nativeEvent));
111
+ };
112
+ return renderElement("label", render, { disabled: off }, {
113
+ "data-slot": "segmented-control-item",
114
+ ...stateAttrs({ disabled: off }),
115
+ ...rest,
116
+ className: cx("nz-segmented-control-item", className),
117
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
118
+ /* @__PURE__ */ jsx("input", {
119
+ ...mergeProps(group.radio, {
120
+ onChange,
121
+ onFocus: markFocus,
122
+ onBlur: clearFocus,
123
+ onKeyDown
124
+ }),
125
+ ...checked,
126
+ type: "radio",
127
+ className: "nz-segmented-control-input",
128
+ "data-slot": "segmented-control-input",
129
+ name: group.name,
130
+ value,
131
+ disabled: off || void 0,
132
+ "aria-label": ariaLabel
133
+ }),
134
+ icon != null && /* @__PURE__ */ jsx("span", {
135
+ className: "nz-segmented-control-icon",
136
+ "data-slot": "segmented-control-icon",
137
+ "aria-hidden": "true",
138
+ children: icon
139
+ }),
140
+ children != null && /* @__PURE__ */ jsxs("span", {
141
+ className: "nz-segmented-control-label",
142
+ "data-slot": "segmented-control-label",
143
+ children: [/* @__PURE__ */ jsx("span", {
144
+ className: "nz-segmented-control-text",
145
+ children
146
+ }), /* @__PURE__ */ jsx("span", {
147
+ className: "nz-segmented-control-sizer",
148
+ "aria-hidden": "true",
149
+ children
150
+ })]
151
+ })
152
+ ] })
153
+ });
154
+ }
155
+ //#endregion
156
+ export { SegmentedControlItem, SegmentedControlRoot };
@@ -0,0 +1,6 @@
1
+ import { SegmentedControlItem, SegmentedControlRoot } from "./segmented-control.client.js";
2
+ declare namespace segmented_control_parts_d_exports {
3
+ export { SegmentedControlItem as Item, SegmentedControlRoot as Root };
4
+ }
5
+ //#endregion
6
+ export { SegmentedControlItem as Item, SegmentedControlRoot as Root, segmented_control_parts_d_exports };
@@ -0,0 +1,9 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
+ import { SegmentedControlItem, SegmentedControlRoot } from "./segmented-control.client.js";
3
+ //#region src/segmented-control/segmented-control.parts.ts
4
+ var segmented_control_parts_exports = /* @__PURE__ */ __exportAll({
5
+ Item: () => SegmentedControlItem,
6
+ Root: () => SegmentedControlRoot
7
+ });
8
+ //#endregion
9
+ export { SegmentedControlItem as Item, SegmentedControlRoot as Root, segmented_control_parts_exports };
@@ -0,0 +1,5 @@
1
+ import { OpenReason } from "../contracts/details.js";
2
+ import { SelectGroupLabelProps, SelectGroupProps, SelectItemProps, SelectItemState, SelectLabels, SelectPopupProps, SelectPopupState, SelectRootProps, SelectRootState, SelectSeparatorProps, SelectTriggerProps, SelectTriggerState, SelectValueProps, SelectValueReason, SelectValueState } from "./select.contract.js";
3
+ import { SelectGroup, SelectGroupLabel, SelectItem, SelectPopup, SelectRoot, SelectSeparator, SelectTrigger, SelectValue } from "./select.client.js";
4
+ import { select_parts_d_exports } from "./select.parts.js";
5
+ export { type OpenReason, select_parts_d_exports as Select, SelectGroup, SelectGroupLabel, type SelectGroupLabelProps, type SelectGroupProps, SelectItem, type SelectItemProps, type SelectItemState, type SelectLabels, SelectPopup, type SelectPopupProps, type SelectPopupState, SelectRoot, type SelectRootProps, type SelectRootState, SelectSeparator, type SelectSeparatorProps, SelectTrigger, type SelectTriggerProps, type SelectTriggerState, SelectValue, type SelectValueProps, type SelectValueReason, type SelectValueState };
@@ -0,0 +1,3 @@
1
+ import { SelectGroup, SelectGroupLabel, SelectItem, SelectPopup, SelectRoot, SelectSeparator, SelectTrigger, SelectValue } from "./select.client.js";
2
+ import { select_parts_exports } from "./select.parts.js";
3
+ export { select_parts_exports as Select, SelectGroup, SelectGroupLabel, SelectItem, SelectPopup, SelectRoot, SelectSeparator, SelectTrigger, SelectValue };
@@ -0,0 +1,12 @@
1
+ import { SelectGroupLabelProps, SelectGroupProps, SelectItemProps, SelectPopupProps, SelectRootProps, SelectSeparatorProps, SelectTriggerProps, SelectValueProps } from "./select.contract.js";
2
+ import { JSX } from "react";
3
+ //#region src/select/select.client.d.ts
4
+ export declare function SelectRoot({ size, name, required, disabled, invalid, "aria-labelledby": labelledBy, className, ...props }: SelectRootProps): JSX.Element;
5
+ export declare function SelectTrigger({ id, "aria-describedby": describedBy, className, leadingIcon, indicator, render, children, ...rest }: SelectTriggerProps): JSX.Element;
6
+ export declare function SelectValue({ className, render, ...rest }: SelectValueProps): JSX.Element;
7
+ export declare function SelectPopup({ side, align, sideOffset, container, className, style, children }: SelectPopupProps): JSX.Element;
8
+ export declare function SelectItem({ className, textValue, indicator, render, children, ...rest }: SelectItemProps): JSX.Element;
9
+ export declare function SelectGroup({ className, render, ...rest }: SelectGroupProps): JSX.Element;
10
+ export declare function SelectGroupLabel({ className, render, ...rest }: SelectGroupLabelProps): JSX.Element;
11
+ export declare function SelectSeparator({ className, render, ...rest }: SelectSeparatorProps): JSX.Element;
12
+ //#endregion