@agentero/design-system 0.33.0 → 0.34.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.
@@ -5,13 +5,14 @@ import { useFieldContext as n } from "../field/context.js";
5
5
  import { InputContext as r } from "../input/context.js";
6
6
  import { inputRecipe as i } from "../input/input.js";
7
7
  import { InputGroup as a } from "../input-group/index.js";
8
- import { IconCancel as o, IconCheck as s, IconKeyboardArrowDown as c, IconSearch as l } from "./icons.js";
9
- import { tv as u } from "tailwind-variants";
10
- import { createContext as d, use as f, useRef as p, useState as m } from "react";
11
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
12
- import { Combobox as _ } from "@base-ui/react/combobox";
8
+ import { InputSearch as o } from "../input-search/input-search.js";
9
+ import { IconCancel as s, IconCheck as c, IconKeyboardArrowDown as l, IconSearch as u } from "./icons.js";
10
+ import { tv as d } from "tailwind-variants";
11
+ import { createContext as f, use as p, useRef as m, useState as h } from "react";
12
+ import { jsx as g, jsxs as _ } from "react/jsx-runtime";
13
+ import { Combobox as v } from "@base-ui/react/combobox";
13
14
  //#region src/combobox/combobox.tsx
14
- var v = u({ slots: {
15
+ var y = d({ slots: {
15
16
  action: [
16
17
  "flex size-6 shrink-0 cursor-pointer items-center justify-center self-center rounded-sm",
17
18
  "[&>svg>path]:fill-icon-input-default hover:[&>svg>path]:fill-icon-default-base-primary",
@@ -47,78 +48,94 @@ var v = u({ slots: {
47
48
  "group-data-disabled/item:data-selected:bg-bg-checkbox-disabled"
48
49
  ],
49
50
  message: ["mx-2 my-px px-3 py-2 text-sm text-text-default-base-tertiary", "empty:m-0 empty:p-0"]
50
- } }), y = v(), b = d(!1), x = ({ minInputLength: e = 0, open: t, defaultOpen: n = !1, onOpenChange: r, onOpenChangeComplete: i, onInputValueChange: a, ...o }) => {
51
- let s = !!o.multiple, [c, l] = m(n), u = p(String(o.inputValue ?? o.defaultInputValue ?? ""));
51
+ } }), b = y(), x = f(!1), S = ({ minInputLength: e = 0, open: t, defaultOpen: n = !1, onOpenChange: r, onOpenChangeComplete: i, onInputValueChange: a, ...o }) => {
52
+ let s = !!o.multiple, [c, l] = h(n), u = m(String(o.inputValue ?? o.defaultInputValue ?? ""));
52
53
  o.inputValue !== void 0 && (u.current = String(o.inputValue));
53
- let d = (t) => t.trim().length < e, f = p(!1), g = p(!1), v = (e, t) => {
54
+ let d = (t) => t.trim().length < e, f = m(!1), p = m(!1), _ = (e, t) => {
54
55
  if (e && d(u.current)) {
55
56
  t.cancel();
56
57
  return;
57
58
  }
58
59
  f.current = !1, r?.(e, t), s && !e && t.reason === "item-press" && t.cancel(), t.isCanceled || l(e);
59
60
  }, y = (e) => {
60
- i?.(e), !e && f.current && (f.current = !1, g.current = !0, queueMicrotask(() => g.current = !1));
61
- }, x = (e, n) => {
62
- if (g.current) {
63
- g.current = !1, n.cancel();
61
+ i?.(e), !e && f.current && (f.current = !1, p.current = !0, queueMicrotask(() => p.current = !1));
62
+ }, b = (e, n) => {
63
+ if (p.current) {
64
+ p.current = !1, n.cancel();
64
65
  return;
65
66
  }
66
67
  u.current = e, a?.(e, n), d(e) && t === void 0 && c && (f.current = !0, l(!1));
67
68
  }, S = t ?? (e > 0 ? c : void 0);
68
- return /* @__PURE__ */ h(b, {
69
+ return /* @__PURE__ */ g(x, {
69
70
  value: s,
70
- children: /* @__PURE__ */ h(_.Root, {
71
+ children: /* @__PURE__ */ g(v.Root, {
71
72
  open: S,
72
73
  defaultOpen: n,
73
- onOpenChange: v,
74
+ onOpenChange: _,
74
75
  onOpenChangeComplete: y,
75
- onInputValueChange: x,
76
+ onInputValueChange: b,
76
77
  ...o
77
78
  })
78
79
  });
79
80
  };
80
- x.displayName = "Combobox.Root";
81
- var S = /* @__PURE__ */ new Set([
81
+ S.displayName = "Combobox.Root";
82
+ var C = /* @__PURE__ */ new Set([
82
83
  "value",
83
84
  "defaultValue",
84
85
  "onChange"
85
- ]), C = (e) => {
86
- let i = f(r), a = n(), o = i ? Object.fromEntries(Object.entries(i).filter(([e]) => !S.has(e))) : null, s = !("aria-label" in e || "aria-labelledby" in e) && a ? { "aria-labelledby": a.labelId } : null;
86
+ ]), w = (e) => {
87
+ let i = p(r), a = n(), o = i ? Object.fromEntries(Object.entries(i).filter(([e]) => !C.has(e))) : null, s = !("aria-label" in e || "aria-labelledby" in e) && a ? { "aria-labelledby": a.labelId } : null;
87
88
  return t({
88
89
  ...o,
89
90
  ...s
90
91
  }, e);
91
- }, w = ({ variant: t = "search", showClear: n = t === "search", clearLabel: r = "Clear", triggerLabel: s = "Show options", ...u }) => {
92
- let { className: d, size: p = "md", ...m } = C(u), v = f(b);
93
- return /* @__PURE__ */ g(_.InputGroup, {
94
- render: /* @__PURE__ */ h(a.Root, {}),
92
+ }, T = ({ variant: t = "search", showClear: n = t === "search", clearLabel: c = "Clear", triggerLabel: d = "Show options", ...f }) => {
93
+ let { className: m, size: h = "md", ...y } = w(f), S = p(x);
94
+ return t === "search" && n && !S ? /* @__PURE__ */ g(v.InputGroup, {
95
+ render: /* @__PURE__ */ g("div", {}),
96
+ "data-slot": "combobox-field",
97
+ children: /* @__PURE__ */ g(r, {
98
+ value: null,
99
+ children: /* @__PURE__ */ g(v.Input, {
100
+ "data-slot": "combobox-input",
101
+ className: m,
102
+ ...y,
103
+ render: (e) => /* @__PURE__ */ g(o, {
104
+ ...e,
105
+ size: h,
106
+ clearLabel: c
107
+ })
108
+ })
109
+ })
110
+ }) : /* @__PURE__ */ _(v.InputGroup, {
111
+ render: /* @__PURE__ */ g(a.Root, {}),
95
112
  "data-slot": "combobox-field",
96
113
  className: t === "plain" ? "px-4" : void 0,
97
114
  children: [
98
- t === "search" && /* @__PURE__ */ h(a.Addon, { children: /* @__PURE__ */ h(l, {}) }),
99
- /* @__PURE__ */ h(_.Input, {
115
+ t === "search" && /* @__PURE__ */ g(a.Addon, { children: /* @__PURE__ */ g(u, {}) }),
116
+ /* @__PURE__ */ g(v.Input, {
100
117
  "data-slot": "combobox-input",
101
- "data-size": p,
102
- className: e(i({ size: p }), d),
103
- ...m
118
+ "data-size": h,
119
+ className: e(i({ size: h }), m),
120
+ ...y
104
121
  }),
105
- n && !v && /* @__PURE__ */ h(_.Clear, {
122
+ n && !S && /* @__PURE__ */ g(v.Clear, {
106
123
  "data-slot": "combobox-clear",
107
- "aria-label": r,
108
- className: y.action(),
109
- children: /* @__PURE__ */ h(o, {})
124
+ "aria-label": c,
125
+ className: b.action(),
126
+ children: /* @__PURE__ */ g(s, {})
110
127
  }),
111
- t === "select" && !v && /* @__PURE__ */ h(_.Trigger, {
128
+ t === "select" && !S && /* @__PURE__ */ g(v.Trigger, {
112
129
  "data-slot": "combobox-trigger",
113
- "aria-label": s,
114
- className: e(y.action(), y.trigger(), n && y.triggerReplaced()),
115
- children: /* @__PURE__ */ h(c, {})
130
+ "aria-label": d,
131
+ className: e(b.action(), b.trigger(), n && b.triggerReplaced()),
132
+ children: /* @__PURE__ */ g(l, {})
116
133
  })
117
134
  ]
118
135
  });
119
136
  };
120
- w.displayName = "Combobox.Input";
121
- var T = ({ className: t, side: n = "bottom", align: r = "start", sideOffset: i = 12, alignOffset: a, anchor: o, collisionPadding: s = 8, ...c }) => /* @__PURE__ */ h(_.Portal, { children: /* @__PURE__ */ h(_.Positioner, {
137
+ T.displayName = "Combobox.Input";
138
+ var E = ({ className: t, side: n = "bottom", align: r = "start", sideOffset: i = 12, alignOffset: a, anchor: o, collisionPadding: s = 8, ...c }) => /* @__PURE__ */ g(v.Portal, { children: /* @__PURE__ */ g(v.Positioner, {
122
139
  side: n,
123
140
  align: r,
124
141
  sideOffset: i,
@@ -126,49 +143,49 @@ var T = ({ className: t, side: n = "bottom", align: r = "start", sideOffset: i =
126
143
  anchor: o,
127
144
  collisionPadding: s,
128
145
  className: "isolate z-(--z-index-top-layer) pointer-events-auto",
129
- children: /* @__PURE__ */ h(_.Popup, {
146
+ children: /* @__PURE__ */ g(v.Popup, {
130
147
  "data-slot": "combobox-content",
131
- className: e(y.content(), t),
148
+ className: e(b.content(), t),
132
149
  ...c
133
150
  })
134
151
  }) });
135
- T.displayName = "Combobox.Content";
136
- var E = ({ className: t, ...n }) => {
152
+ E.displayName = "Combobox.Content";
153
+ var D = ({ className: t, ...n }) => {
137
154
  let r = "aria-label" in n || "aria-labelledby" in n;
138
- return /* @__PURE__ */ h(_.List, {
155
+ return /* @__PURE__ */ g(v.List, {
139
156
  "data-slot": "combobox-list",
140
157
  "aria-label": r ? void 0 : "Suggestions",
141
- className: e(y.list(), t),
158
+ className: e(b.list(), t),
142
159
  ...n
143
160
  });
144
161
  };
145
- E.displayName = "Combobox.List";
146
- var D = ({ className: t, children: n, ...r }) => {
147
- let i = f(b);
148
- return /* @__PURE__ */ g(_.Item, {
162
+ D.displayName = "Combobox.List";
163
+ var O = ({ className: t, children: n, ...r }) => {
164
+ let i = p(x);
165
+ return /* @__PURE__ */ _(v.Item, {
149
166
  "data-slot": "combobox-item",
150
- className: e(y.item(), t),
167
+ className: e(b.item(), t),
151
168
  ...r,
152
- children: [i && /* @__PURE__ */ h(_.ItemIndicator, {
169
+ children: [i && /* @__PURE__ */ g(v.ItemIndicator, {
153
170
  keepMounted: !0,
154
171
  "data-slot": "combobox-item-indicator",
155
- className: y.indicator(),
156
- children: /* @__PURE__ */ h(s, { className: "size-3.5" })
172
+ className: b.indicator(),
173
+ children: /* @__PURE__ */ g(c, { className: "size-3.5" })
157
174
  }), n]
158
175
  });
159
176
  };
160
- D.displayName = "Combobox.Item";
161
- var O = ({ className: t, ...n }) => /* @__PURE__ */ h(_.Empty, {
177
+ O.displayName = "Combobox.Item";
178
+ var k = ({ className: t, ...n }) => /* @__PURE__ */ g(v.Empty, {
162
179
  "data-slot": "combobox-empty",
163
- className: e(y.message(), t),
180
+ className: e(b.message(), t),
164
181
  ...n
165
182
  });
166
- O.displayName = "Combobox.Empty";
167
- var k = ({ className: t, ...n }) => /* @__PURE__ */ h(_.Status, {
183
+ k.displayName = "Combobox.Empty";
184
+ var A = ({ className: t, ...n }) => /* @__PURE__ */ g(v.Status, {
168
185
  "data-slot": "combobox-status",
169
- className: e(y.message(), t),
186
+ className: e(b.message(), t),
170
187
  ...n
171
188
  });
172
- k.displayName = "Combobox.Status";
189
+ A.displayName = "Combobox.Status";
173
190
  //#endregion
174
- export { T as Content, O as Empty, w as Input, D as Item, E as List, x as Root, k as Status, v as comboboxRecipe };
191
+ export { E as Content, k as Empty, T as Input, O as Item, D as List, S as Root, A as Status, y as comboboxRecipe };
@@ -11,6 +11,8 @@ export type FieldErrorLike = {
11
11
  */
12
12
  types?: Record<string, string | string[] | boolean | undefined>;
13
13
  } | undefined;
14
+ /** What a registered message is, which sets its place in `aria-describedby`. */
15
+ export type FieldMessageKind = 'error' | 'description';
14
16
  /**
15
17
  * State of the surrounding `Field.Root`, shared with the Field family
16
18
  * (`Field.Description`, `Field.Error`) and with controls that have no context
@@ -39,9 +41,11 @@ export type FieldContextValue = {
39
41
  /**
40
42
  * Adds a message element to `describedBy` and returns the function that
41
43
  * removes it. `Field.Description` and `Field.Error` call it from a layout
42
- * effect; a custom message element can do the same.
44
+ * effect; a custom message element can do the same. Errors are listed first,
45
+ * then descriptions, then messages registered without a `kind`, each in the
46
+ * order they registered.
43
47
  */
44
- registerMessage: (id: string) => () => void;
48
+ registerMessage: (id: string, kind?: FieldMessageKind) => () => void;
45
49
  invalid: boolean;
46
50
  disabled: boolean;
47
51
  readOnly: boolean;
@@ -141,8 +141,8 @@ export type FieldRootProps = ComponentPropsWithRef<'div'> & {
141
141
  * <Field.Root invalid={!!error} required>
142
142
  * <Field.Label>Email</Field.Label>
143
143
  * <Input type="email" />
144
- * <Field.Description>We only use this for policy documents.</Field.Description>
145
144
  * <Field.Error errors={[error]} />
145
+ * <Field.Description>We only use this for policy documents.</Field.Description>
146
146
  * </Field.Root>
147
147
  */
148
148
  export declare const Root: {
@@ -201,7 +201,9 @@ export declare const Description: {
201
201
  };
202
202
  /**
203
203
  * Validation feedback for the field, announced as an alert when it appears.
204
- * Renders nothing without a message, so it can stay mounted unconditionally;
204
+ * Place it right after the control, before `Field.Description`: the control's
205
+ * `aria-describedby` reads the error first as well. Renders nothing without a
206
+ * message, so it can stay mounted unconditionally;
205
207
  * set `invalid` on `Field.Root` alongside it. Takes `children` or an `errors`
206
208
  * array, and a form adapter can supply `errors` through `FieldContext` so a
207
209
  * bare `<Field.Error />` renders them. One per field: it takes the field's
@@ -38,31 +38,34 @@ var m = s({
38
38
  ] }
39
39
  } },
40
40
  defaultVariants: { orientation: "vertical" }
41
- }), h = m(), g = ({ className: t, ...n }) => /* @__PURE__ */ f("div", {
41
+ }), h = m(), g = (e) => e === "error" ? 0 : e === "description" ? 1 : 2, _ = ({ className: t, ...n }) => /* @__PURE__ */ f("div", {
42
42
  "data-slot": "field-group",
43
43
  className: e(h.group(), t),
44
44
  ...n
45
45
  });
46
- g.displayName = "Field.Group";
47
- var _ = ({ className: n, orientation: r = "vertical", invalid: a = !1, disabled: o = !1, readOnly: s = !1, required: u = !1, controlId: p, ...m }) => {
48
- let g = l(), _ = p ?? `${g}-control`, v = `${g}-label`, y = `${g}-description`, b = `${g}-error`, [x, S] = d([]), C = c((e) => (S((t) => t.includes(e) ? t : [...t, e]), () => S((t) => t.filter((t) => t !== e))), []), w = {
49
- controlId: _,
50
- labelId: v,
51
- descriptionId: y,
52
- errorId: b,
53
- describedBy: [...[y, b].filter((e) => x.includes(e)), ...x.filter((e) => e !== y && e !== b)].join(" ") || void 0,
54
- registerMessage: C,
46
+ _.displayName = "Field.Group";
47
+ var v = ({ className: n, orientation: r = "vertical", invalid: a = !1, disabled: o = !1, readOnly: s = !1, required: u = !1, controlId: p, ...m }) => {
48
+ let _ = l(), v = p ?? `${_}-control`, y = `${_}-label`, b = `${_}-description`, x = `${_}-error`, [S, C] = d([]), w = c((e, t) => (C((n) => n.some((t) => t.id === e) ? n : [...n, {
49
+ id: e,
50
+ kind: t
51
+ }]), () => C((t) => t.filter((t) => t.id !== e))), []), T = {
52
+ controlId: v,
53
+ labelId: y,
54
+ descriptionId: b,
55
+ errorId: x,
56
+ describedBy: [...S].sort((e, t) => g(e.kind) - g(t.kind)).map((e) => e.id).join(" ") || void 0,
57
+ registerMessage: w,
55
58
  invalid: a,
56
59
  disabled: o,
57
60
  readOnly: s,
58
61
  required: u
59
62
  };
60
63
  return /* @__PURE__ */ f(i, {
61
- value: w,
64
+ value: T,
62
65
  children: /* @__PURE__ */ f(t, {
63
66
  value: {
64
- id: v,
65
- htmlFor: _,
67
+ id: y,
68
+ htmlFor: v,
66
69
  required: u || void 0
67
70
  },
68
71
  children: /* @__PURE__ */ f("div", {
@@ -77,14 +80,14 @@ var _ = ({ className: n, orientation: r = "vertical", invalid: a = !1, disabled:
77
80
  })
78
81
  });
79
82
  };
80
- _.displayName = "Field.Root";
81
- var v = ({ className: t, ...n }) => /* @__PURE__ */ f("div", {
83
+ v.displayName = "Field.Root";
84
+ var y = ({ className: t, ...n }) => /* @__PURE__ */ f("div", {
82
85
  "data-slot": "field-content",
83
86
  className: e(h.content(), t),
84
87
  ...n
85
88
  });
86
- v.displayName = "Field.Content";
87
- var y = ({ tooltip: e, tooltipSide: t, ...i }) => /* @__PURE__ */ p("div", {
89
+ y.displayName = "Field.Content";
90
+ var b = ({ tooltip: e, tooltipSide: t, ...i }) => /* @__PURE__ */ p("div", {
88
91
  "data-slot": "field-label",
89
92
  className: h.label(),
90
93
  children: [/* @__PURE__ */ f(n, { ...i }), e && /* @__PURE__ */ f(r, {
@@ -100,23 +103,23 @@ var y = ({ tooltip: e, tooltipSide: t, ...i }) => /* @__PURE__ */ p("div", {
100
103
  })
101
104
  })]
102
105
  });
103
- y.displayName = "Field.Label";
104
- var b = ({ className: t, id: n, ...r }) => {
106
+ b.displayName = "Field.Label";
107
+ var x = ({ className: t, id: n, ...r }) => {
105
108
  let i = a(), o = n ?? i?.descriptionId, s = i?.registerMessage;
106
- return u(() => o ? s?.(o) : void 0, [s, o]), /* @__PURE__ */ f("p", {
109
+ return u(() => o ? s?.(o, "description") : void 0, [s, o]), /* @__PURE__ */ f("p", {
107
110
  "data-slot": "field-description",
108
111
  id: o,
109
112
  className: e(h.description(), t),
110
113
  ...r
111
114
  });
112
115
  };
113
- b.displayName = "Field.Description";
114
- var x = (e) => {
116
+ x.displayName = "Field.Description";
117
+ var S = (e) => {
115
118
  let t = Object.values(e?.types ?? {}).flat().filter((e) => typeof e == "string" && e.length > 0);
116
119
  return t.length ? t : e?.message ? [e.message] : [];
117
- }, S = ({ className: t, children: n, errors: r, id: i, ...o }) => {
118
- let s = a(), c = i ?? s?.errorId, l = r ?? s?.errors, d = s?.registerMessage, p = [...new Set(l?.flatMap(x))], m = n ?? (p.length > 1 ? /* @__PURE__ */ f("ul", { children: p.map((e) => /* @__PURE__ */ f("li", { children: e }, e)) }) : p[0]), g = !!m;
119
- return u(() => g && c ? d?.(c) : void 0, [
120
+ }, C = ({ className: t, children: n, errors: r, id: i, ...o }) => {
121
+ let s = a(), c = i ?? s?.errorId, l = r ?? s?.errors, d = s?.registerMessage, p = [...new Set(l?.flatMap(S))], m = n ?? (p.length > 1 ? /* @__PURE__ */ f("ul", { children: p.map((e) => /* @__PURE__ */ f("li", { children: e }, e)) }) : p[0]), g = !!m;
122
+ return u(() => g && c ? d?.(c, "error") : void 0, [
120
123
  d,
121
124
  g,
122
125
  c
@@ -129,6 +132,6 @@ var x = (e) => {
129
132
  children: m
130
133
  }) : null;
131
134
  };
132
- S.displayName = "Field.Error";
135
+ C.displayName = "Field.Error";
133
136
  //#endregion
134
- export { v as Content, b as Description, S as Error, g as Group, y as Label, _ as Root, m as fieldRecipe };
137
+ export { y as Content, x as Description, C as Error, _ as Group, b as Label, v as Root, m as fieldRecipe };
@@ -1,7 +1,7 @@
1
1
  export { fieldRecipe } from './field';
2
2
  export { FieldContext, useFieldContext } from './context';
3
3
  export type { FieldContentProps, FieldGroupProps, FieldLabelProps, FieldRootProps, FieldVariants } from './field';
4
- export type { FieldContextValue, FieldDescriptionProps, FieldErrorLike, FieldErrorProps } from './context';
4
+ export type { FieldContextValue, FieldDescriptionProps, FieldErrorLike, FieldErrorProps, FieldMessageKind } from './context';
5
5
  export declare const Field: {
6
6
  Root: {
7
7
  ({ className, orientation, invalid, disabled, readOnly, required, controlId: controlIdProp, ...props }: import('./field').FieldRootProps): import("react/jsx-runtime").JSX.Element;
@@ -18,8 +18,8 @@ export type FieldTextProps = FieldRootProps;
18
18
  * <FieldText invalid={!!error} required>
19
19
  * <Label>Email</Label>
20
20
  * <Input type="email" />
21
- * <Field.Description>We only use this for policy documents.</Field.Description>
22
21
  * <Field.Error errors={[error]} />
22
+ * <Field.Description>We only use this for policy documents.</Field.Description>
23
23
  * </FieldText>
24
24
  */
25
25
  export declare const FieldText: {
@@ -55,9 +55,9 @@ export type FormTextProps<TFieldValues extends FieldValues = FieldValues, TName
55
55
  /** The caption, rendered as the field's label. Text in almost every case. */
56
56
  label: ReactNode;
57
57
  /**
58
- * Helper text shown under the control and announced through its
59
- * `aria-describedby`. Use it for guidance the user needs before typing; put
60
- * details worth a click in `tooltip` instead.
58
+ * Helper text shown under the control, below the error when there is one,
59
+ * and announced through its `aria-describedby`. Use it for guidance the
60
+ * user needs before typing; put details worth a click in `tooltip` instead.
61
61
  */
62
62
  description?: ReactNode;
63
63
  /**
@@ -96,7 +96,7 @@ export type FormTextProps<TFieldValues extends FieldValues = FieldValues, TName
96
96
  };
97
97
  /**
98
98
  * A complete text field bound to one react-hook-form value: label, `Input`,
99
- * helper text and validation error, laid out in the standard order and wired
99
+ * validation error and helper text, laid out in the standard order and wired
100
100
  * through `useController`. It renders inside a `Form.Root`, which provides the
101
101
  * form, and needs only a `name`, which on a typed form must point at a string
102
102
  * (`FormTextPath`). The `required`, `invalid` and error states
@@ -30,8 +30,8 @@ var s = ({ name: s, control: c, rules: l, shouldUnregister: u, disabled: d, labe
30
30
  children: f
31
31
  }), /* @__PURE__ */ a(t.Content, { children: [
32
32
  /* @__PURE__ */ i(n, { ...e(x, _ ?? {}) }),
33
- p && /* @__PURE__ */ i(t.Description, { children: p }),
34
- /* @__PURE__ */ i(t.Error, { errors: b.error ? [b.error] : void 0 })
33
+ /* @__PURE__ */ i(t.Error, { errors: b.error ? [b.error] : void 0 }),
34
+ p && /* @__PURE__ */ i(t.Description, { children: p })
35
35
  ] })]
36
36
  });
37
37
  };
@@ -0,0 +1,16 @@
1
+ import { SVGProps } from 'react';
2
+ /**
3
+ * Magnifier leading InputSearch, the same glyph `Combobox` uses. Fill color
4
+ * comes from the input group addon, so the icon follows the field's state.
5
+ *
6
+ * @summary 24px search icon leading the InputSearch field
7
+ */
8
+ export declare const IconSearch: (props: SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
9
+ /**
10
+ * Circled cross on the InputSearch clear button, the same glyph `Combobox`
11
+ * uses. Fill color comes from the button's class, so the icon follows its
12
+ * hover and disabled states.
13
+ *
14
+ * @summary 24px cancel icon on the InputSearch clear button
15
+ */
16
+ export declare const IconCancel: (props: SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ //#region src/input-search/icons.tsx
3
+ var t = (t) => /* @__PURE__ */ e("svg", {
4
+ width: "24",
5
+ height: "24",
6
+ viewBox: "0 0 24 24",
7
+ fill: "none",
8
+ "aria-hidden": "true",
9
+ xmlns: "http://www.w3.org/2000/svg",
10
+ ...t,
11
+ children: /* @__PURE__ */ e("path", { d: "M9.52 15.615q-2.562 0-4.34-1.777Q3.405 12.062 3.405 9.5T5.18 5.162q1.776-1.777 4.338-1.777t4.339 1.777q1.777 1.776 1.777 4.338 0 1.071-.36 2.046a5.7 5.7 0 0 1-.96 1.696l5.754 5.754q.209.209.213.522a.7.7 0 0 1-.213.532.72.72 0 0 1-.527.217.72.72 0 0 1-.527-.217l-5.753-5.754q-.75.62-1.725.97t-2.018.35m0-1.5q1.933 0 3.273-1.341 1.342-1.34 1.342-3.274 0-1.932-1.342-3.274-1.34-1.341-3.274-1.341-1.932 0-3.274 1.34Q4.904 7.569 4.904 9.5q0 1.933 1.341 3.274 1.342 1.341 3.274 1.341" })
12
+ }), n = (t) => /* @__PURE__ */ e("svg", {
13
+ width: "24",
14
+ height: "24",
15
+ viewBox: "0 0 24 24",
16
+ fill: "none",
17
+ "aria-hidden": "true",
18
+ xmlns: "http://www.w3.org/2000/svg",
19
+ ...t,
20
+ children: /* @__PURE__ */ e("path", { d: "M12 13.0538L15.0731 16.1269C15.2115 16.2654 15.3856 16.3362 15.5952 16.3394C15.8048 16.3426 15.982 16.2718 16.1269 16.1269C16.2718 15.982 16.3442 15.8064 16.3442 15.6C16.3442 15.3936 16.2718 15.218 16.1269 15.0731L13.0538 12L16.1269 8.9269C16.2653 8.78845 16.3362 8.61442 16.3394 8.4048C16.3426 8.1952 16.2718 8.01797 16.1269 7.8731C15.982 7.72822 15.8064 7.65577 15.6 7.65577C15.3936 7.65577 15.2179 7.72822 15.0731 7.8731L12 10.9462L8.92688 7.8731C8.78842 7.73463 8.61439 7.6638 8.40478 7.6606C8.19518 7.65738 8.01794 7.72822 7.87308 7.8731C7.72819 8.01797 7.65575 8.1936 7.65575 8.4C7.65575 8.6064 7.72819 8.78203 7.87308 8.9269L10.9461 12L7.87308 15.0731C7.73461 15.2115 7.66378 15.3856 7.66058 15.5952C7.65736 15.8048 7.72819 15.982 7.87308 16.1269C8.01794 16.2718 8.19358 16.3442 8.39998 16.3442C8.60638 16.3442 8.78201 16.2718 8.92688 16.1269L12 13.0538ZM12.0016 21.5C10.6877 21.5 9.45268 21.2506 8.29655 20.752C7.1404 20.2533 6.13472 19.5766 5.2795 18.7217C4.42427 17.8669 3.74721 16.8616 3.24833 15.706C2.74944 14.5504 2.5 13.3156 2.5 12.0017C2.5 10.6877 2.74933 9.45271 3.248 8.29657C3.74667 7.14042 4.42342 6.13474 5.27825 5.27952C6.1331 4.42429 7.13834 3.74723 8.29398 3.24835C9.44959 2.74947 10.6844 2.50002 11.9983 2.50002C13.3122 2.50002 14.5473 2.74936 15.7034 3.24802C16.8596 3.74669 17.8652 4.42344 18.7205 5.27827C19.5757 6.13312 20.2527 7.13837 20.7516 8.294C21.2505 9.44962 21.5 10.6844 21.5 11.9983C21.5 13.3123 21.2506 14.5473 20.752 15.7034C20.2533 16.8596 19.5765 17.8653 18.7217 18.7205C17.8669 19.5757 16.8616 20.2528 15.706 20.7516C14.5504 21.2505 13.3156 21.5 12.0016 21.5ZM12 20C14.2333 20 16.125 19.225 17.675 17.675C19.225 16.125 20 14.2333 20 12C20 9.76667 19.225 7.875 17.675 6.325C16.125 4.775 14.2333 4 12 4C9.76664 4 7.87498 4.775 6.32498 6.325C4.77498 7.875 3.99998 9.76667 3.99998 12C3.99998 14.2333 4.77498 16.125 6.32498 17.675C7.87498 19.225 9.76664 20 12 20Z" })
21
+ });
22
+ //#endregion
23
+ export { n as IconCancel, t as IconSearch };
@@ -0,0 +1,2 @@
1
+ export { InputSearch, inputSearchRecipe } from './input-search';
2
+ export type { InputSearchProps } from './input-search';
@@ -0,0 +1,2 @@
1
+ import { InputSearch as e, inputSearchRecipe as t } from "./input-search.js";
2
+ export { e as InputSearch, t as inputSearchRecipe };
@@ -0,0 +1,96 @@
1
+ import { InputProps } from '../input';
2
+ /**
3
+ * Style recipe for InputSearch. Slots: `input` (hides the browser's own
4
+ * cancel button and search decoration, so the field shows only the clear
5
+ * button it draws) and `clear` (the clear button, the same 24px icon button
6
+ * as the Combobox clear, removed while the input is disabled).
7
+ *
8
+ * @summary tailwind-variants recipe backing the InputSearch input and clear button
9
+ */
10
+ export declare const inputSearchRecipe: import('tailwind-variants').TVReturnType<{
11
+ [key: string]: {
12
+ [key: string]: import('tailwind-merge').ClassNameValue | {
13
+ input?: import('tailwind-merge').ClassNameValue;
14
+ clear?: import('tailwind-merge').ClassNameValue;
15
+ };
16
+ };
17
+ } | {
18
+ [x: string]: {
19
+ [x: string]: import('tailwind-merge').ClassNameValue | {
20
+ input?: import('tailwind-merge').ClassNameValue;
21
+ clear?: import('tailwind-merge').ClassNameValue;
22
+ };
23
+ };
24
+ } | {}, {
25
+ input: string;
26
+ clear: string[];
27
+ }, undefined, {
28
+ [key: string]: {
29
+ [key: string]: import('tailwind-merge').ClassNameValue | {
30
+ input?: import('tailwind-merge').ClassNameValue;
31
+ clear?: import('tailwind-merge').ClassNameValue;
32
+ };
33
+ };
34
+ } | {}, {
35
+ input: string;
36
+ clear: string[];
37
+ }, import('tailwind-variants').TVReturnType<unknown, {
38
+ input: string;
39
+ clear: string[];
40
+ }, undefined, unknown, unknown, undefined>>;
41
+ export type InputSearchProps = Omit<InputProps, 'type'> & {
42
+ /**
43
+ * Shows a spinner at the end of the frame, in place of the clear button,
44
+ * while the results for the current text are on their way. Defaults to
45
+ * `false`.
46
+ */
47
+ isLoading?: boolean;
48
+ /**
49
+ * Accessible name of the clear button. Defaults to `'Clear search'`; name it
50
+ * after what is searched (`'Clear agency search'`) when a page carries
51
+ * several search fields.
52
+ */
53
+ clearLabel?: string;
54
+ };
55
+ /**
56
+ * InputSearch is a search field: a magnifier in front of the text and, once
57
+ * there is text, a clear button after it, named "Clear search" unless
58
+ * `clearLabel` says otherwise. The clear button empties the field
59
+ * and puts focus back in it, and it reports the change through `onChange` like
60
+ * a keystroke would: a real change event whose `event.target.value` is `''`,
61
+ * so a controlled field, an uncontrolled one and one registered with
62
+ * react-hook-form all clear the same way. While `isLoading` is set, a spinner
63
+ * takes the clear button's place. The clear button is not rendered while the
64
+ * input is disabled, whether `disabled` comes from the prop, from a
65
+ * surrounding `FieldText` or from a `<fieldset disabled>`.
66
+ *
67
+ * It is an [Input](?path=/docs/components-input--docs) of `type="search"`
68
+ * inside an [InputGroup](?path=/docs/components-inputgroup--docs) frame, so
69
+ * it is announced as a search box. `className` styles the frame. Every other
70
+ * prop goes to the `<input>`: the `ref`, `id`, `name`, `value`, `onChange`,
71
+ * `aria-*` and every other standard attribute. Only `type` is not accepted.
72
+ * `placeholder` defaults to `'Search'`. Inside a `FieldText` the input takes
73
+ * its label, messages and states from the field as a plain `Input` does. The
74
+ * invalid state comes from `aria-invalid`, and the frame paints the
75
+ * destructive border.
76
+ *
77
+ * Do not use it to pick a value from a list; that is
78
+ * [Combobox](?path=/docs/components-combobox--docs), whose `search` field is
79
+ * drawn by InputSearch. For a filter that should
80
+ * run only once the user pauses typing, use `DebouncedInputSearch`.
81
+ *
82
+ * @summary Search input with a leading icon, a clear button and a loading slot
83
+ * @dataAttribute {string} data-slot - Always set to "input-search" on the frame
84
+ *
85
+ * @example
86
+ * <InputSearch
87
+ * aria-label="Search agencies"
88
+ * value={query}
89
+ * onChange={event => setQuery(event.target.value)}
90
+ * isLoading={isFetching}
91
+ * />
92
+ */
93
+ export declare const InputSearch: {
94
+ ({ className, isLoading, clearLabel, placeholder, ref, onChange, ...props }: InputSearchProps): import("react/jsx-runtime").JSX.Element;
95
+ displayName: string;
96
+ };
@@ -0,0 +1,53 @@
1
+ "use client";
2
+ import { chain as e, mergeRefs as t } from "../../lib/merge-props.js";
3
+ import { InputContext as n } from "../input/context.js";
4
+ import { Input as r } from "../input/input.js";
5
+ import { InputGroup as i } from "../input-group/index.js";
6
+ import { Loading as a } from "../loading/loading.js";
7
+ import { IconCancel as o, IconSearch as s } from "./icons.js";
8
+ import { tv as c } from "tailwind-variants";
9
+ import { use as l, useMemo as u, useRef as d, useState as f } from "react";
10
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
11
+ //#region src/input-search/input-search.tsx
12
+ var h = c({ slots: {
13
+ input: "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none",
14
+ clear: [
15
+ "flex size-6 shrink-0 cursor-pointer items-center justify-center self-center rounded-sm",
16
+ "[&>svg>path]:fill-icon-input-default hover:[&>svg>path]:fill-icon-default-base-primary",
17
+ "focus-visible:outline-2 focus-visible:outline-border-input-focus",
18
+ "disabled:cursor-default disabled:[&>svg>path]:fill-icon-input-disable",
19
+ "group-has-[input:disabled]/input-group:hidden"
20
+ ]
21
+ } }), g = h(), _ = (e) => e !== void 0 && String(e) !== "", v = ({ className: c, isLoading: h = !1, clearLabel: v = "Clear search", placeholder: y = "Search", ref: b, onChange: x, ...S }) => {
22
+ let C = d(null), w = l(n)?.value, [T, E] = f(() => _(S.defaultValue)), D = S.value === void 0 ? w : S.value, O = D === void 0 ? T : _(D), k = (e) => E(e.target.value !== ""), A = u(() => t(C, b, (e) => {
23
+ e && E(e.value !== "");
24
+ }), [b]), j = () => {
25
+ let e = C.current;
26
+ e && (Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set?.call(e, ""), e.dispatchEvent(new Event("input", { bubbles: !0 })), e.focus());
27
+ };
28
+ return /* @__PURE__ */ m(i.Root, {
29
+ "data-slot": "input-search",
30
+ className: c,
31
+ children: [
32
+ /* @__PURE__ */ p(i.Addon, { children: /* @__PURE__ */ p(s, {}) }),
33
+ /* @__PURE__ */ p(r, {
34
+ ref: A,
35
+ type: "search",
36
+ placeholder: y,
37
+ ...S,
38
+ className: g.input(),
39
+ onChange: e(k, x)
40
+ }),
41
+ h ? /* @__PURE__ */ p(i.Addon, { children: /* @__PURE__ */ p(a, { size: "sm" }) }) : O && /* @__PURE__ */ p(i.Addon, { children: /* @__PURE__ */ p("button", {
42
+ type: "button",
43
+ className: g.clear(),
44
+ "aria-label": v,
45
+ onClick: j,
46
+ children: /* @__PURE__ */ p(o, {})
47
+ }) })
48
+ ]
49
+ });
50
+ };
51
+ v.displayName = "InputSearch";
52
+ //#endregion
53
+ export { v as InputSearch, h as inputSearchRecipe };