@ngrok/mantle 0.72.0 → 0.73.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 (156) hide show
  1. package/README.md +0 -33
  2. package/dist/accordion.d.ts +1 -1
  3. package/dist/agent.json +2 -1
  4. package/dist/alert-dialog.d.ts +4 -4
  5. package/dist/alert.d.ts +3 -3
  6. package/dist/anchor.d.ts +1 -1
  7. package/dist/{as-child-DQHfEmYB.d.ts → as-child-C2PttRwz.d.ts} +1 -1
  8. package/dist/badge.d.ts +2 -2
  9. package/dist/{button-BMgAxAwM.d.ts → button-CoGmk7_d.d.ts} +3 -3
  10. package/dist/button.d.ts +3 -3
  11. package/dist/card.d.ts +1 -1
  12. package/dist/checkbox.d.ts +1 -1
  13. package/dist/checkbox.js +1 -1
  14. package/dist/checkbox.js.map +1 -1
  15. package/dist/code-block.d.ts +40 -14
  16. package/dist/code-block.js +2 -2
  17. package/dist/code-block.js.map +1 -1
  18. package/dist/code-block_highlight-utils.d.ts +1 -1
  19. package/dist/code-block_highlight-utils.js +1 -1
  20. package/dist/code.d.ts +1 -1
  21. package/dist/color.d.ts +1 -1
  22. package/dist/combobox.d.ts +2 -2
  23. package/dist/combobox.js +1 -1
  24. package/dist/combobox.js.map +1 -1
  25. package/dist/command.d.ts +3 -3
  26. package/dist/command.js +1 -1
  27. package/dist/compose-refs-DZ3cPi47.js.map +1 -1
  28. package/dist/{copy-to-clipboard-DjOD_Mwb.js → copy-to-clipboard-CNMRyck4.js} +1 -1
  29. package/dist/{copy-to-clipboard-DjOD_Mwb.js.map → copy-to-clipboard-CNMRyck4.js.map} +1 -1
  30. package/dist/data-table.d.ts +3 -3
  31. package/dist/data-table.js +1 -1
  32. package/dist/data-table.js.map +1 -1
  33. package/dist/{deep-non-nullable-VFm1T3JZ.d.ts → deep-non-nullable-CT7hWCFG.d.ts} +1 -1
  34. package/dist/description-list.d.ts +1 -1
  35. package/dist/{dialog-BHzl9eye.js → dialog-B1KCB7JT.js} +2 -2
  36. package/dist/dialog-B1KCB7JT.js.map +1 -0
  37. package/dist/dialog.d.ts +2 -2
  38. package/dist/dialog.js +1 -1
  39. package/dist/{direction-DtBAQn7p.d.ts → direction-CVntIxOS.d.ts} +1 -1
  40. package/dist/{direction-DsB-pD9V.js → direction-HqPHXGIs.js} +1 -1
  41. package/dist/{direction-DsB-pD9V.js.map → direction-HqPHXGIs.js.map} +1 -1
  42. package/dist/{dropdown-menu-CzUNYIfA.d.ts → dropdown-menu-DVvNlA72.d.ts} +2 -2
  43. package/dist/{dropdown-menu-Ducs2SEn.js → dropdown-menu-DY4w933w.js} +2 -2
  44. package/dist/{dropdown-menu-Ducs2SEn.js.map → dropdown-menu-DY4w933w.js.map} +1 -1
  45. package/dist/dropdown-menu.d.ts +1 -1
  46. package/dist/dropdown-menu.js +1 -1
  47. package/dist/empty.d.ts +2 -2
  48. package/dist/field.d.ts +601 -0
  49. package/dist/field.js +2 -0
  50. package/dist/field.js.map +1 -0
  51. package/dist/hooks.d.ts +3 -3
  52. package/dist/hooks.js +1 -1
  53. package/dist/hooks.js.map +1 -1
  54. package/dist/{icon-DKMJm20j.d.ts → icon-D_BMDi_q.d.ts} +2 -2
  55. package/dist/{icon-button-BnK4K7YK.d.ts → icon-button-Dty-yfE2.d.ts} +3 -3
  56. package/dist/icon.d.ts +3 -3
  57. package/dist/icons.d.ts +3 -3
  58. package/dist/icons.js +1 -1
  59. package/dist/{in-view-pia_SVdE.js → in-view-BLZVEGFC.js} +1 -1
  60. package/dist/{in-view-pia_SVdE.js.map → in-view-BLZVEGFC.js.map} +1 -1
  61. package/dist/{in-view-Da08Bx6l.d.ts → in-view-DdIrfU4u.d.ts} +1 -1
  62. package/dist/{index-DkMUaYsw.d.ts → index-CVk4t5hk.d.ts} +1 -1
  63. package/dist/{index-DOJUH34Z.d.ts → index-DIBURJqf.d.ts} +3 -3
  64. package/dist/{index-rtz7SwEq.d.ts → index-TI92Xpg5.d.ts} +1 -1
  65. package/dist/index-j46YISoN.d.ts +22 -0
  66. package/dist/input.d.ts +192 -3
  67. package/dist/input.js +1 -1
  68. package/dist/input.js.map +1 -1
  69. package/dist/{is-input-CUEWaxtA.js → is-input-CEEoHxXN.js} +1 -1
  70. package/dist/{is-input-CUEWaxtA.js.map → is-input-CEEoHxXN.js.map} +1 -1
  71. package/dist/{kbd-CAVUiqBT.js → kbd-CbMxDL9E.js} +1 -1
  72. package/dist/{kbd-CAVUiqBT.js.map → kbd-CbMxDL9E.js.map} +1 -1
  73. package/dist/kbd.js +1 -1
  74. package/dist/label-x6FcOpxc.js +2 -0
  75. package/dist/label-x6FcOpxc.js.map +1 -0
  76. package/dist/label.d.ts +9 -0
  77. package/dist/label.js +1 -2
  78. package/dist/llms.txt +2 -1
  79. package/dist/media-object.d.ts +1 -1
  80. package/dist/multi-select.d.ts +2 -2
  81. package/dist/multi-select.js +1 -1
  82. package/dist/multi-select.js.map +1 -1
  83. package/dist/otp-input.d.ts +2 -2
  84. package/dist/otp-input.js +1 -1
  85. package/dist/otp-input.js.map +1 -1
  86. package/dist/pagination.d.ts +3 -3
  87. package/dist/pagination.js +1 -1
  88. package/dist/popover-CoZxokw_.js +2 -0
  89. package/dist/popover-CoZxokw_.js.map +1 -0
  90. package/dist/popover.js +1 -2
  91. package/dist/{primitive-tyw4V7Vf.d.ts → primitive-Ed9cel2r.d.ts} +1 -1
  92. package/dist/radio-group.d.ts +1 -1
  93. package/dist/radio-group.js +1 -1
  94. package/dist/{resolve-pre-rendered-props-Bqg41IkV.js → resolve-pre-rendered-props-BfWe69-w.js} +1 -1
  95. package/dist/{resolve-pre-rendered-props-Bqg41IkV.js.map → resolve-pre-rendered-props-BfWe69-w.js.map} +1 -1
  96. package/dist/{resolve-pre-rendered-props-CdqAcY5m.d.ts → resolve-pre-rendered-props-DxvamgE6.d.ts} +2 -2
  97. package/dist/sandboxed-on-click.d.ts +1 -1
  98. package/dist/{select-DZutJxyr.d.ts → select-8ymlL8kC.d.ts} +3 -3
  99. package/dist/select-BBB_e15a.js +2 -0
  100. package/dist/select-BBB_e15a.js.map +1 -0
  101. package/dist/select.d.ts +1 -1
  102. package/dist/select.js +1 -1
  103. package/dist/{separator-DSOIrnhj.js → separator-awchG4LI.js} +1 -1
  104. package/dist/{separator-DSOIrnhj.js.map → separator-awchG4LI.js.map} +1 -1
  105. package/dist/separator.d.ts +1 -1
  106. package/dist/separator.js +1 -1
  107. package/dist/sheet.d.ts +2 -2
  108. package/dist/sheet.js +1 -1
  109. package/dist/sheet.js.map +1 -1
  110. package/dist/slot.d.ts +2 -22
  111. package/dist/{sort-DzCsa6Qj.js → sort-mXo37xN2.js} +2 -2
  112. package/dist/{sort-DzCsa6Qj.js.map → sort-mXo37xN2.js.map} +1 -1
  113. package/dist/split-button.d.ts +3 -3
  114. package/dist/split-button.js +1 -1
  115. package/dist/{svg-only-BtBvFy-N.d.ts → svg-only-CLbMy439.d.ts} +2 -2
  116. package/dist/switch.d.ts +2 -1
  117. package/dist/switch.js +1 -1
  118. package/dist/switch.js.map +1 -1
  119. package/dist/{table-BsNJBKiq.d.ts → table-BWxS7pXj.d.ts} +1 -1
  120. package/dist/{table-Cl4nlRMR.js → table-CHd39aT-.js} +1 -1
  121. package/dist/{table-Cl4nlRMR.js.map → table-CHd39aT-.js.map} +1 -1
  122. package/dist/table.d.ts +1 -1
  123. package/dist/table.js +1 -1
  124. package/dist/tabs.js +1 -1
  125. package/dist/text-area.d.ts +1 -1
  126. package/dist/text-area.js +1 -1
  127. package/dist/text-area.js.map +1 -1
  128. package/dist/theme.d.ts +2 -2
  129. package/dist/{themes-DIEYkvNl.d.ts → themes-f2W5S6xS.d.ts} +1 -1
  130. package/dist/toast.d.ts +3 -3
  131. package/dist/{traffic-policy-file-C6LHYrIU.js → traffic-policy-file-BwHHdhWJ.js} +1 -1
  132. package/dist/{traffic-policy-file-C6LHYrIU.js.map → traffic-policy-file-BwHHdhWJ.js.map} +1 -1
  133. package/dist/{types-DoV0R5Ja.d.ts → types-DnghL1WE.d.ts} +1 -1
  134. package/dist/types.d.ts +5 -5
  135. package/dist/use-copy-to-clipboard-CTgtLjUg.js +2 -0
  136. package/dist/{use-copy-to-clipboard-C7vsjJe-.js.map → use-copy-to-clipboard-CTgtLjUg.js.map} +1 -1
  137. package/dist/use-isomorphic-layout-effect-CNSD0lhi.js +2 -0
  138. package/dist/use-isomorphic-layout-effect-CNSD0lhi.js.map +1 -0
  139. package/dist/{use-prefers-reduced-motion-aXfsyo-k.js → use-prefers-reduced-motion-YUurmkwx.js} +1 -1
  140. package/dist/{use-prefers-reduced-motion-aXfsyo-k.js.map → use-prefers-reduced-motion-YUurmkwx.js.map} +1 -1
  141. package/dist/utils.d.ts +2 -2
  142. package/dist/utils.js +1 -1
  143. package/dist/validation-BYME8rWN.js +2 -0
  144. package/dist/validation-BYME8rWN.js.map +1 -0
  145. package/dist/validation-DF1z7YDr.d.ts +108 -0
  146. package/dist/{variant-props-DUmSIQK8.d.ts → variant-props-B4io4uA_.d.ts} +2 -2
  147. package/dist/{with-style-props-3iFrBR08.d.ts → with-style-props-CW8buMhK.d.ts} +1 -1
  148. package/package.json +15 -10
  149. package/dist/dialog-BHzl9eye.js.map +0 -1
  150. package/dist/index-C91lxoX9.d.ts +0 -146
  151. package/dist/label.js.map +0 -1
  152. package/dist/popover.js.map +0 -1
  153. package/dist/select-DOgdZO0Q.js +0 -2
  154. package/dist/select-DOgdZO0Q.js.map +0 -1
  155. package/dist/types-DG0WQLTL.d.ts +0 -78
  156. package/dist/use-copy-to-clipboard-C7vsjJe-.js +0 -2
@@ -0,0 +1,601 @@
1
+ import { t as WithAsChild } from "./as-child-C2PttRwz.js";
2
+ import { n as IconButtonProps } from "./icon-button-Dty-yfE2.js";
3
+ import { a as ValidationState, c as parseValidation, i as ValidationProp, l as resolveValidation, n as ParsedValidation, o as WithValidation, r as Validation, s as isAriaInvalid, t as AriaInvalid } from "./validation-DF1z7YDr.js";
4
+ import { t as Slot } from "./index-j46YISoN.js";
5
+ import * as _$react from "react";
6
+ import { ComponentProps, ReactElement, ReactNode } from "react";
7
+ import * as _$_radix_ui_react_popover0 from "@radix-ui/react-popover";
8
+
9
+ //#region src/components/field/field-context.d.ts
10
+ /**
11
+ * ARIA props that `Field.Control` applies to the field's focusable control.
12
+ */
13
+ type FieldControlAriaProps = {
14
+ /**
15
+ * IDREFs for helper or error text that describe the focusable control.
16
+ */
17
+ "aria-describedby"?: string;
18
+ /**
19
+ * IDREFs for error text that represent the control's current error state.
20
+ */
21
+ "aria-errormessage"?: string;
22
+ /**
23
+ * The resolved ARIA invalid state for the focusable control.
24
+ */
25
+ "aria-invalid"?: ComponentProps<"input">["aria-invalid"];
26
+ };
27
+ /**
28
+ * Context value owned by `Field.Item` and consumed by message/control parts.
29
+ *
30
+ * `Field.Item` owns the two stable slot IDs (one for the description, one for
31
+ * the error list) so consumers don't manage ARIA wiring themselves. The IDs
32
+ * are emitted unconditionally; ARIA treats unresolved IDREFs as no-ops, so
33
+ * dangling IDs (when no description or error list is rendered) are harmless.
34
+ */
35
+ //#endregion
36
+ //#region src/components/field/error-helpers.d.ts
37
+ /**
38
+ * A validation message accepted by `Field.Errors`. Non-string absence values
39
+ * are allowed so consumers can pass mapped validator output directly while
40
+ * still rendering only real strings.
41
+ */
42
+ type FieldErrorMessage = string | null | undefined | false;
43
+ /**
44
+ * Options for checking a manual `Field.ErrorList` subtree.
45
+ */
46
+ //#endregion
47
+ //#region src/components/field/field.d.ts
48
+ /**
49
+ * Props for the `Field.Errors` convenience renderer. It owns its generated
50
+ * children, so use `Field.ErrorList` / `Field.ErrorItem` directly when custom
51
+ * list contents or polymorphic list markup are needed.
52
+ */
53
+ type FieldErrorsProps = Omit<ComponentProps<"ul">, "children" | "id"> & {
54
+ /**
55
+ * Validation messages to render. Strings are trimmed, and empty, nullish,
56
+ * or false values are ignored before rendering the list.
57
+ */
58
+ messages?: readonly FieldErrorMessage[];
59
+ };
60
+ type FieldControlSlotProps = Omit<ComponentProps<typeof Slot>, "aria-describedby" | "aria-errormessage" | "aria-invalid" | "children">;
61
+ /**
62
+ * Element-child form of `Field.Control`. Renders via `Slot`, so it accepts
63
+ * any HTML/Slot props and a forwarded ref — those land on the single child
64
+ * element along with the generated ARIA props.
65
+ */
66
+ type FieldControlElementProps = FieldControlSlotProps & WithValidation & {
67
+ /**
68
+ * A single control element to receive the field ARIA props.
69
+ */
70
+ children: ReactElement;
71
+ };
72
+ /**
73
+ * Render-prop form of `Field.Control`. The caller owns the rendered element,
74
+ * so `Field.Control` itself renders nothing — extra DOM props and `ref` have
75
+ * no element to attach to and are intentionally not part of this variant.
76
+ * Slot props are marked `never` so passing e.g. `className` alongside a
77
+ * render-prop child is a type error rather than a silently ignored prop.
78
+ */
79
+ type FieldControlRenderProps = WithValidation & {
80
+ /**
81
+ * A render function that places the field ARIA props onto a control of
82
+ * the caller's choosing. Used for compound controls or wrappers where
83
+ * `Slot` cannot reach the focusable element.
84
+ */
85
+ children: (props: FieldControlAriaProps) => ReactNode;
86
+ } & { [K in keyof FieldControlSlotProps]?: never };
87
+ /**
88
+ * Compound component for semantic, accessible form fields. Composes a
89
+ * `Field.Label`, control (`Input`, `Select`, etc.), `Field.Description`, and
90
+ * validation errors (`Field.Errors` / `Field.ErrorList` + `Field.ErrorItem`)
91
+ * with consistent spacing and ARIA wiring. Stack multiple fields with
92
+ * `Field.Group`; use `Field.Set` + `Field.Legend` for radios / related
93
+ * checkboxes that share one accessible name.
94
+ *
95
+ * @see https://mantle.ngrok.com/components/field
96
+ *
97
+ * @example
98
+ * Composition:
99
+ * ```
100
+ * Field.Group
101
+ * └── Field.Item
102
+ * ├── Field.LabelRow
103
+ * │ ├── Field.Label
104
+ * │ │ └── Field.Optional
105
+ * │ └── Field.Help
106
+ * │ ├── Field.HelpTrigger
107
+ * │ └── Field.HelpContent
108
+ * ├── Field.Control
109
+ * │ └── (control)
110
+ * ├── Field.Errors (or)
111
+ * ├── Field.ErrorList
112
+ * │ └── Field.ErrorItem
113
+ * └── Field.Description
114
+ * ```
115
+ *
116
+ * @example
117
+ * ```tsx
118
+ * <Field.Group>
119
+ * <Field.Item>
120
+ * <Field.LabelRow>
121
+ * <Field.Label htmlFor="api-key">
122
+ * API key <Field.Optional />
123
+ * </Field.Label>
124
+ * <Field.Help>
125
+ * <Field.HelpTrigger label="What is an API key?" />
126
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
127
+ * </Field.Help>
128
+ * </Field.LabelRow>
129
+ * <Field.Control>
130
+ * <Input id="api-key" name="apiKey" />
131
+ * </Field.Control>
132
+ * <Field.Errors messages={["API key is required."]} />
133
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
134
+ * </Field.Item>
135
+ * </Field.Group>
136
+ * ```
137
+ */
138
+ declare const Field: {
139
+ /**
140
+ * A single form field. Provides message IDs and validation state to
141
+ * `Field.Control`; rendered errors infer `"error"` validation.
142
+ *
143
+ * @see https://mantle.ngrok.com/components/field
144
+ *
145
+ * @example
146
+ * ```tsx
147
+ * <Field.Group>
148
+ * <Field.Item>
149
+ * <Field.LabelRow>
150
+ * <Field.Label htmlFor="api-key">
151
+ * API key <Field.Optional />
152
+ * </Field.Label>
153
+ * <Field.Help>
154
+ * <Field.HelpTrigger label="What is an API key?" />
155
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
156
+ * </Field.Help>
157
+ * </Field.LabelRow>
158
+ * <Field.Control>
159
+ * <Input id="api-key" name="apiKey" />
160
+ * </Field.Control>
161
+ * <Field.Errors messages={["API key is required."]} />
162
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
163
+ * </Field.Item>
164
+ * </Field.Group>
165
+ * ```
166
+ */
167
+ readonly Item: _$react.ForwardRefExoticComponent<Omit<_$react.ClassAttributes<HTMLDivElement> & _$react.HTMLAttributes<HTMLDivElement> & WithAsChild & WithValidation, "ref"> & _$react.RefAttributes<HTMLDivElement>>;
168
+ /**
169
+ * Applies generated field ARIA props and validation state to a single
170
+ * focusable control. Accepts either a single React element child (cloned
171
+ * via `Slot`) or a render-prop child that receives the ARIA props for
172
+ * cases where `Slot` cannot reach the focusable element — for example a
173
+ * `<label>`-wrapped native checkbox, or a third-party component that
174
+ * needs the props placed manually on an inner input.
175
+ *
176
+ * @see https://mantle.ngrok.com/components/field
177
+ *
178
+ * @example
179
+ * ```tsx
180
+ * // Element child — Slot clones the generated ARIA props onto <Input/>.
181
+ * <Field.Item>
182
+ * <Field.Label htmlFor="api-key">API key</Field.Label>
183
+ * <Field.Control>
184
+ * <Input id="api-key" name="apiKey" />
185
+ * </Field.Control>
186
+ * <Field.Errors messages={["API key is required."]} />
187
+ * </Field.Item>
188
+ * ```
189
+ *
190
+ * @example
191
+ * ```tsx
192
+ * // Render-prop child — caller spreads the ARIA props onto an inner
193
+ * // element when the focusable target is nested (e.g. inside a <label>).
194
+ * <Field.Item>
195
+ * <Field.Control>
196
+ * {(ariaProps) => (
197
+ * <label>
198
+ * Accept terms
199
+ * <input type="checkbox" {...ariaProps} />
200
+ * </label>
201
+ * )}
202
+ * </Field.Control>
203
+ * <Field.Errors messages={["You must accept the terms."]} />
204
+ * </Field.Item>
205
+ * ```
206
+ */
207
+ readonly Control: _$react.ForwardRefExoticComponent<(Omit<FieldControlElementProps, "ref"> | Omit<FieldControlRenderProps, "ref">) & _$react.RefAttributes<HTMLElement>>;
208
+ /**
209
+ * Layout container that stacks multiple `Field.Item`s vertically.
210
+ *
211
+ * @see https://mantle.ngrok.com/components/field
212
+ *
213
+ * @example
214
+ * ```tsx
215
+ * <Field.Group>
216
+ * <Field.Item>
217
+ * <Field.LabelRow>
218
+ * <Field.Label htmlFor="api-key">
219
+ * API key <Field.Optional />
220
+ * </Field.Label>
221
+ * <Field.Help>
222
+ * <Field.HelpTrigger label="What is an API key?" />
223
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
224
+ * </Field.Help>
225
+ * </Field.LabelRow>
226
+ * <Field.Control>
227
+ * <Input id="api-key" name="apiKey" />
228
+ * </Field.Control>
229
+ * <Field.Errors messages={["API key is required."]} />
230
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
231
+ * </Field.Item>
232
+ * </Field.Group>
233
+ * ```
234
+ */
235
+ readonly Group: _$react.ForwardRefExoticComponent<Omit<_$react.ClassAttributes<HTMLDivElement> & _$react.HTMLAttributes<HTMLDivElement> & WithAsChild, "ref"> & _$react.RefAttributes<HTMLDivElement>>;
236
+ /**
237
+ * Semantic `<fieldset>` for related controls that share one accessible
238
+ * name from `Field.Legend`.
239
+ *
240
+ * @see https://mantle.ngrok.com/components/field
241
+ *
242
+ * @example
243
+ * ```tsx
244
+ * <Field.Set>
245
+ * <Field.Legend>Notification frequency</Field.Legend>
246
+ * <RadioGroup.Root name="frequency" defaultValue="daily">
247
+ * <RadioGroup.Item value="daily" id="freq-daily">…</RadioGroup.Item>
248
+ * <RadioGroup.Item value="weekly" id="freq-weekly">…</RadioGroup.Item>
249
+ * </RadioGroup.Root>
250
+ * </Field.Set>
251
+ * ```
252
+ */
253
+ readonly Set: _$react.ForwardRefExoticComponent<Omit<_$react.DetailedHTMLProps<_$react.FieldsetHTMLAttributes<HTMLFieldSetElement>, HTMLFieldSetElement>, "ref"> & _$react.RefAttributes<HTMLFieldSetElement>>;
254
+ /**
255
+ * Caption for `Field.Set`. Renders a semantic `<legend>`.
256
+ *
257
+ * @see https://mantle.ngrok.com/components/field
258
+ *
259
+ * @example
260
+ * ```tsx
261
+ * <Field.Set>
262
+ * <Field.Legend>Notification frequency</Field.Legend>
263
+ * <RadioGroup.Root name="frequency" defaultValue="daily">
264
+ * <RadioGroup.Item value="daily" id="freq-daily">…</RadioGroup.Item>
265
+ * <RadioGroup.Item value="weekly" id="freq-weekly">…</RadioGroup.Item>
266
+ * </RadioGroup.Root>
267
+ * </Field.Set>
268
+ * ```
269
+ */
270
+ readonly Legend: _$react.ForwardRefExoticComponent<Omit<_$react.DetailedHTMLProps<_$react.HTMLAttributes<HTMLLegendElement>, HTMLLegendElement>, "ref"> & _$react.RefAttributes<HTMLLegendElement>>;
271
+ /**
272
+ * The Mantle `Label`, exposed on `Field` for field composition.
273
+ *
274
+ * @see https://mantle.ngrok.com/components/label
275
+ *
276
+ * @example
277
+ * ```tsx
278
+ * <Field.Group>
279
+ * <Field.Item>
280
+ * <Field.LabelRow>
281
+ * <Field.Label htmlFor="api-key">
282
+ * API key <Field.Optional />
283
+ * </Field.Label>
284
+ * <Field.Help>
285
+ * <Field.HelpTrigger label="What is an API key?" />
286
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
287
+ * </Field.Help>
288
+ * </Field.LabelRow>
289
+ * <Field.Control>
290
+ * <Input id="api-key" name="apiKey" />
291
+ * </Field.Control>
292
+ * <Field.Errors messages={["API key is required."]} />
293
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
294
+ * </Field.Item>
295
+ * </Field.Group>
296
+ * ```
297
+ */
298
+ readonly Label: _$react.ForwardRefExoticComponent<Omit<_$react.DetailedHTMLProps<_$react.LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "ref"> & {
299
+ disabled?: boolean;
300
+ } & _$react.RefAttributes<HTMLLabelElement>>;
301
+ /**
302
+ * Horizontal layout container for the label area of a field. Aligns a
303
+ * `<Field.Label>` (which may contain `Field.Optional`) with adjacent affordances
304
+ * like a help-icon `Popover.Trigger` on a shared center line with `gap-1`.
305
+ *
306
+ * @see https://mantle.ngrok.com/components/field
307
+ *
308
+ * @example
309
+ * ```tsx
310
+ * <Field.Group>
311
+ * <Field.Item>
312
+ * <Field.LabelRow>
313
+ * <Field.Label htmlFor="api-key">
314
+ * API key <Field.Optional />
315
+ * </Field.Label>
316
+ * <Field.Help>
317
+ * <Field.HelpTrigger label="What is an API key?" />
318
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
319
+ * </Field.Help>
320
+ * </Field.LabelRow>
321
+ * <Field.Control>
322
+ * <Input id="api-key" name="apiKey" />
323
+ * </Field.Control>
324
+ * <Field.Errors messages={["API key is required."]} />
325
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
326
+ * </Field.Item>
327
+ * </Field.Group>
328
+ * ```
329
+ */
330
+ readonly LabelRow: _$react.ForwardRefExoticComponent<Omit<_$react.ClassAttributes<HTMLDivElement> & _$react.HTMLAttributes<HTMLDivElement> & WithAsChild, "ref"> & _$react.RefAttributes<HTMLDivElement>>;
331
+ /**
332
+ * `Popover.Root` re-export for the help-affordance pattern. Pair with
333
+ * `Field.HelpTrigger` and `Field.HelpContent` to drop a `?` button next to
334
+ * a label without manually composing Popover + IconButton + QuestionIcon.
335
+ *
336
+ * @see https://mantle.ngrok.com/components/field
337
+ *
338
+ * @example
339
+ * ```tsx
340
+ * <Field.Group>
341
+ * <Field.Item>
342
+ * <Field.LabelRow>
343
+ * <Field.Label htmlFor="api-key">
344
+ * API key <Field.Optional />
345
+ * </Field.Label>
346
+ * <Field.Help>
347
+ * <Field.HelpTrigger label="What is an API key?" />
348
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
349
+ * </Field.Help>
350
+ * </Field.LabelRow>
351
+ * <Field.Control>
352
+ * <Input id="api-key" name="apiKey" />
353
+ * </Field.Control>
354
+ * <Field.Errors messages={["API key is required."]} />
355
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
356
+ * </Field.Item>
357
+ * </Field.Group>
358
+ * ```
359
+ */
360
+ readonly Help: _$react.FC<_$_radix_ui_react_popover0.PopoverProps>;
361
+ /**
362
+ * Trigger for a `Field.Help` popover — a ghost `IconButton` with a default
363
+ * `QuestionIcon`. Requires a contextual `label`; pass `icon` to swap the
364
+ * glyph, or other `IconButton` props (`size`, `appearance`, etc.) to customize.
365
+ *
366
+ * @see https://mantle.ngrok.com/components/field
367
+ *
368
+ * @example
369
+ * ```tsx
370
+ * <Field.Group>
371
+ * <Field.Item>
372
+ * <Field.LabelRow>
373
+ * <Field.Label htmlFor="api-key">
374
+ * API key <Field.Optional />
375
+ * </Field.Label>
376
+ * <Field.Help>
377
+ * <Field.HelpTrigger label="What is an API key?" />
378
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
379
+ * </Field.Help>
380
+ * </Field.LabelRow>
381
+ * <Field.Control>
382
+ * <Input id="api-key" name="apiKey" />
383
+ * </Field.Control>
384
+ * <Field.Errors messages={["API key is required."]} />
385
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
386
+ * </Field.Item>
387
+ * </Field.Group>
388
+ * ```
389
+ */
390
+ readonly HelpTrigger: _$react.ForwardRefExoticComponent<Partial<Omit<IconButtonProps, "icon" | "label">> & Pick<IconButtonProps, "label"> & {
391
+ /**
392
+ * The icon to render inside the trigger button. Defaults to a Phosphor
393
+ * `QuestionIcon` so the most common case only needs a contextual label.
394
+ */
395
+ icon?: ReactNode;
396
+ } & _$react.RefAttributes<HTMLButtonElement>>;
397
+ /**
398
+ * Body of a `Field.Help` popover. Re-exports `Popover.Content` so all
399
+ * positioning / sizing options (`side`, `align`, `preferredWidth`, etc.)
400
+ * work as expected.
401
+ *
402
+ * @see https://mantle.ngrok.com/components/field
403
+ *
404
+ * @example
405
+ * ```tsx
406
+ * <Field.Group>
407
+ * <Field.Item>
408
+ * <Field.LabelRow>
409
+ * <Field.Label htmlFor="api-key">
410
+ * API key <Field.Optional />
411
+ * </Field.Label>
412
+ * <Field.Help>
413
+ * <Field.HelpTrigger label="What is an API key?" />
414
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
415
+ * </Field.Help>
416
+ * </Field.LabelRow>
417
+ * <Field.Control>
418
+ * <Input id="api-key" name="apiKey" />
419
+ * </Field.Control>
420
+ * <Field.Errors messages={["API key is required."]} />
421
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
422
+ * </Field.Item>
423
+ * </Field.Group>
424
+ * ```
425
+ */
426
+ readonly HelpContent: _$react.ForwardRefExoticComponent<Omit<Omit<_$_radix_ui_react_popover0.PopoverContentProps & _$react.RefAttributes<HTMLDivElement>, "ref"> & {
427
+ preferredWidth?: `max-w-${string}`;
428
+ } & _$react.RefAttributes<HTMLDivElement>, "ref"> & _$react.RefAttributes<HTMLDivElement>>;
429
+ /**
430
+ * Inline "(Optional)" suffix to mark a field as optional. Default content
431
+ * is `(Optional)`; pass children to translate or replace it. Place inside
432
+ * the `<Field.Label>` so screen readers announce it as part of the accessible
433
+ * name.
434
+ *
435
+ * @see https://mantle.ngrok.com/components/field
436
+ *
437
+ * @example
438
+ * ```tsx
439
+ * <Field.Group>
440
+ * <Field.Item>
441
+ * <Field.LabelRow>
442
+ * <Field.Label htmlFor="api-key">
443
+ * API key <Field.Optional />
444
+ * </Field.Label>
445
+ * <Field.Help>
446
+ * <Field.HelpTrigger label="What is an API key?" />
447
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
448
+ * </Field.Help>
449
+ * </Field.LabelRow>
450
+ * <Field.Control>
451
+ * <Input id="api-key" name="apiKey" />
452
+ * </Field.Control>
453
+ * <Field.Errors messages={["API key is required."]} />
454
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
455
+ * </Field.Item>
456
+ * </Field.Group>
457
+ * ```
458
+ */
459
+ readonly Optional: _$react.ForwardRefExoticComponent<Omit<_$react.ClassAttributes<HTMLSpanElement> & _$react.HTMLAttributes<HTMLSpanElement> & WithAsChild, "ref"> & _$react.RefAttributes<HTMLSpanElement>>;
460
+ /**
461
+ * Helper / hint text rendered below the control in the muted body color.
462
+ *
463
+ * @see https://mantle.ngrok.com/components/field
464
+ *
465
+ * @example
466
+ * ```tsx
467
+ * <Field.Group>
468
+ * <Field.Item>
469
+ * <Field.LabelRow>
470
+ * <Field.Label htmlFor="api-key">
471
+ * API key <Field.Optional />
472
+ * </Field.Label>
473
+ * <Field.Help>
474
+ * <Field.HelpTrigger label="What is an API key?" />
475
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
476
+ * </Field.Help>
477
+ * </Field.LabelRow>
478
+ * <Field.Control>
479
+ * <Input id="api-key" name="apiKey" />
480
+ * </Field.Control>
481
+ * <Field.Errors messages={["API key is required."]} />
482
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
483
+ * </Field.Item>
484
+ * </Field.Group>
485
+ * ```
486
+ */
487
+ readonly Description: _$react.ForwardRefExoticComponent<Omit<Omit<_$react.DetailedHTMLProps<_$react.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, "id"> & WithAsChild, "ref"> & _$react.RefAttributes<HTMLParagraphElement>>;
488
+ /**
489
+ * Convenience renderer for validation messages. Trims string messages,
490
+ * filters empty values, and renders a `Field.ErrorList` with one
491
+ * `Field.ErrorItem` for each remaining message.
492
+ *
493
+ * @see https://mantle.ngrok.com/components/field
494
+ *
495
+ * @example
496
+ * ```tsx
497
+ * <Field.Group>
498
+ * <Field.Item>
499
+ * <Field.LabelRow>
500
+ * <Field.Label htmlFor="api-key">
501
+ * API key <Field.Optional />
502
+ * </Field.Label>
503
+ * <Field.Help>
504
+ * <Field.HelpTrigger label="What is an API key?" />
505
+ * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>
506
+ * </Field.Help>
507
+ * </Field.LabelRow>
508
+ * <Field.Control>
509
+ * <Input id="api-key" name="apiKey" />
510
+ * </Field.Control>
511
+ * <Field.Errors messages={["API key is required."]} />
512
+ * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>
513
+ * </Field.Item>
514
+ * </Field.Group>
515
+ * ```
516
+ */
517
+ readonly Errors: _$react.ForwardRefExoticComponent<Omit<FieldErrorsProps, "ref"> & _$react.RefAttributes<HTMLUListElement>>;
518
+ /**
519
+ * Wraps one or more `Field.ErrorItem` children in a semantic `<ul>`.
520
+ * Renders nothing when given no renderable children.
521
+ *
522
+ * @see https://mantle.ngrok.com/components/field
523
+ *
524
+ * @example
525
+ * ```tsx
526
+ * <Field.Group>
527
+ * <Field.Item>
528
+ * <Field.Label htmlFor="username">Username</Field.Label>
529
+ * <Field.Control>
530
+ * <Input id="username" name="username" />
531
+ * </Field.Control>
532
+ * <Field.ErrorList>
533
+ * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>
534
+ * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>
535
+ * </Field.ErrorList>
536
+ * <Field.Description>Pick something memorable.</Field.Description>
537
+ * </Field.Item>
538
+ * </Field.Group>
539
+ * ```
540
+ */
541
+ readonly ErrorList: _$react.ForwardRefExoticComponent<Omit<Omit<_$react.DetailedHTMLProps<_$react.HTMLAttributes<HTMLUListElement>, HTMLUListElement>, "id"> & WithAsChild, "ref"> & _$react.RefAttributes<HTMLUListElement>>;
542
+ /**
543
+ * A single error message list item for a field. Renders an `<li>` in
544
+ * `text-danger-600` and must be nested inside a `Field.ErrorList`.
545
+ *
546
+ * @see https://mantle.ngrok.com/components/field
547
+ *
548
+ * @example
549
+ * ```tsx
550
+ * <Field.Group>
551
+ * <Field.Item>
552
+ * <Field.Label htmlFor="username">Username</Field.Label>
553
+ * <Field.Control>
554
+ * <Input id="username" name="username" />
555
+ * </Field.Control>
556
+ * <Field.ErrorList>
557
+ * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>
558
+ * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>
559
+ * </Field.ErrorList>
560
+ * <Field.Description>Pick something memorable.</Field.Description>
561
+ * </Field.Item>
562
+ * </Field.Group>
563
+ * ```
564
+ */
565
+ readonly ErrorItem: _$react.ForwardRefExoticComponent<Omit<_$react.DetailedHTMLProps<_$react.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & _$react.RefAttributes<HTMLLIElement>>;
566
+ };
567
+ //#endregion
568
+ //#region src/components/field/field-error-messages.d.ts
569
+ /**
570
+ * Shapes commonly found in `field.state.meta.errors` from TanStack React Form
571
+ * across its built-in validators (Standard Schema / Zod issues, raw strings,
572
+ * thrown `Error` instances) plus the falsy slots Standard Schema can produce.
573
+ */
574
+ type FieldError = {
575
+ readonly message?: string | undefined;
576
+ } | string | null | undefined | false;
577
+ /**
578
+ * Reduce a TanStack React Form field's `meta.errors` array (or any array of
579
+ * mixed string / `{ message }` / nullish error entries) to a clean `string[]`
580
+ * for passing directly to `Field.Errors`' `messages` prop.
581
+ *
582
+ * Handles the shapes TanStack form yields for Zod, Standard Schema, and
583
+ * thrown `Error` validators: items may be strings, objects with `.message`,
584
+ * `undefined`, `null`, or `false`. Empty / whitespace-only messages are
585
+ * dropped so callers don't have to filter again.
586
+ *
587
+ * @example
588
+ * ```tsx
589
+ * <Field.Item>
590
+ * <Field.Label htmlFor={field.name}>Email</Field.Label>
591
+ * <Field.Control>
592
+ * <Input id={field.name} value={field.state.value} />
593
+ * </Field.Control>
594
+ * <Field.Errors messages={toErrorMessages(field.state.meta.errors)} />
595
+ * </Field.Item>
596
+ * ```
597
+ */
598
+ declare const toErrorMessages: (errors: readonly FieldError[] | null | undefined) => string[];
599
+ //#endregion
600
+ export { type AriaInvalid, Field, type FieldError, type ParsedValidation, type Validation, type ValidationProp, type ValidationState, type WithValidation, isAriaInvalid, parseValidation, resolveValidation, toErrorMessages };
601
+ //# sourceMappingURL=field.d.ts.map
package/dist/field.js ADDED
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./slot-D_ZUrdEW.js";import{t as n}from"./icon-button-ZKN0sRIJ.js";import{i as r,n as i,r as a,t as o}from"./validation-BYME8rWN.js";import{t as s}from"./use-isomorphic-layout-effect-CNSD0lhi.js";import{t as c}from"./label-x6FcOpxc.js";import{t as l}from"./popover-CoZxokw_.js";import{Children as u,Fragment as d,cloneElement as f,createContext as p,forwardRef as m,isValidElement as h,useCallback as g,useContext as _,useId as v,useMemo as y,useState as b}from"react";import x from"tiny-invariant";import{jsx as S}from"react/jsx-runtime";import{QuestionIcon as C}from"@phosphor-icons/react/Question";const w=p(null),T=({"aria-invalid":e,context:t,validation:n})=>{let r=a({"aria-invalid":e,defaultAriaInvalid:!1,validation:n??t?.validation});return{ariaProps:{"aria-describedby":t?`${t.descriptionId} ${t.errorId}`:void 0,"aria-errormessage":r.isInvalid&&t?t.errorId:void 0,"aria-invalid":r.ariaInvalid},validation:r.validation}},E=e=>e?.map(e=>typeof e==`string`?e.trim():``).filter(e=>e.length>0)??[],D=e=>!(e==null||typeof e==`boolean`||typeof e==`string`&&e.trim().length===0),O=({children:e,errorItemType:t})=>{let n=!1;return u.forEach(e,e=>{if(!(n||e==null||typeof e==`boolean`)){if(typeof e==`string`){e.trim().length>0&&(n=!0);return}if(!h(e)){n=!0;return}if(e.type===t){n=D(e.props.children);return}if(e.type===d){n=O({children:e.props.children,errorItemType:t});return}n=!0}}),n},k=m(({className:t,...n},r)=>S(`fieldset`,{ref:r,"data-slot":`field-set`,className:e(`flex w-full min-w-0 flex-col gap-4 border-0 p-0`,t),...n}));k.displayName=`FieldSet`;const A=m(({className:t,...n},r)=>S(`legend`,{ref:r,"data-slot":`field-legend`,className:e(`text-strong mb-1.5 text-sm font-medium font-sans`,t),...n}));A.displayName=`FieldLegend`;const j=m(({asChild:n,className:r,...i},a)=>S(n?t:`div`,{ref:a,"data-slot":`field-label-row`,className:e(`flex items-center gap-1`,r),...i}));j.displayName=`FieldLabelRow`;const M=l.Root,N=m(({appearance:t=`ghost`,className:r,icon:i=S(C,{}),label:a,size:o=`xs`,type:s=`button`,...c},u)=>S(l.Trigger,{asChild:!0,children:S(n,{ref:u,appearance:t,className:e(`text-body -my-0.5`,r),icon:i,label:a,size:o,type:s,...c})}));N.displayName=`FieldHelpTrigger`;const P=m((e,t)=>S(l.Content,{ref:t,"data-slot":`field-help-content`,...e}));P.displayName=`FieldHelpContent`;const F=m(({asChild:n,children:r,className:i,...a},o)=>S(n?t:`span`,{ref:o,"data-slot":`field-optional`,className:e(`text-muted text-sm font-normal font-sans`,i),...a,children:r??`(Optional)`}));F.displayName=`FieldOptional`;const I=m(({asChild:n,className:r,...i},a)=>S(n?t:`div`,{ref:a,"data-slot":`field-group`,className:e(`flex w-full flex-col gap-4`,r),...i}));I.displayName=`FieldGroup`;const L=m(({asChild:n,children:i,className:a,validation:s,...c},l)=>{let u=n?t:`div`,d=v(),f=v(),[p,m]=b(!1),h=r(s??(p?`error`:void 0)),_=g(()=>(m(!0),()=>{m(!1)}),[]),x=y(()=>({descriptionId:d,errorId:f,hasErrors:p,registerError:_,validation:h}),[d,f,p,_,h]);return S(w.Provider,{value:x,children:S(o,{validation:h,children:S(u,{ref:l,"data-slot":`field-item`,"data-validation":h,className:e(`flex w-full flex-col gap-1.5`,a),...c,children:i})})})});L.displayName=`FieldItem`;const R=m(({children:e,validation:n,...r},i)=>{let a=_(w);if(typeof e==`function`){let t=T({context:a,validation:n});return S(o,{validation:t.validation,children:e(t.ariaProps)})}x(h(e),`Field.Control expects a single React element child (or a render-prop function). Got a non-element value (string, array, fragment, null, or undefined). Wrap the control in a single element, or use the function child form: <Field.Control>{(props) => <YourControl {...props} />}</Field.Control>.`);let s=T({"aria-invalid":e.props[`aria-invalid`],context:a,validation:n});return S(o,{validation:s.validation,children:S(t,{ref:i,...r,children:f(e,s.ariaProps)})})});R.displayName=`FieldControl`;const z=m(({asChild:n,className:r,...i},a)=>S(n?t:`p`,{ref:a,"data-slot":`field-description`,id:_(w)?.descriptionId,className:e(`text-body text-sm leading-4`,`[:where([data-slot=field-error-list]+&)]:-mt-1.5`,r),...i}));z.displayName=`FieldDescription`;const B=m(({children:t,className:n,...r},i)=>D(t)?S(`li`,{ref:i,"data-slot":`field-error`,className:e(`text-danger-600 text-sm leading-4`,n),...r,children:t}):null);B.displayName=`FieldErrorItem`;const V=m(({messages:e,...t},n)=>S(H,{ref:n,...t,children:E(e).map((e,t)=>S(B,{children:e},t))}));V.displayName=`FieldErrors`;const H=m(({asChild:n,children:r,className:i,...a},o)=>{let c=O({children:r,errorItemType:B}),l=_(w),u=l?.registerError;return s(()=>{if(!(!c||u==null))return u()},[c,u]),c?S(n?t:`ul`,{ref:o,"data-slot":`field-error-list`,id:l?.errorId,role:`list`,className:e(`m-0 flex w-full flex-col list-none p-0`,i),...a,children:r}):null});H.displayName=`FieldErrorList`;const U={Item:L,Control:R,Group:I,Set:k,Legend:A,Label:c,LabelRow:j,Help:M,HelpTrigger:N,HelpContent:P,Optional:F,Description:z,Errors:V,ErrorList:H,ErrorItem:B},W=e=>E(e?.map(e=>typeof e==`string`||!e?e:e.message));export{U as Field,i as isAriaInvalid,a as parseValidation,r as resolveValidation,W as toErrorMessages};
2
+ //# sourceMappingURL=field.js.map