@stackone/malachite 2.31.1 → 2.33.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.
package/COMPONENTS.md CHANGED
@@ -12,7 +12,7 @@ The catalog of components exported from `@stackone/malachite`. **Reach for one o
12
12
  - **`SurfaceExpandableRow`** — A row that opens to reveal a body (used as `Surface.ExpandableRow`), for a line that carries its own controls. Not `Accordion`, which puts its header inside the toggle button, so a header holding a dropdown or a second button would be invalid: here the row surface takes the click and a cell opts out by wrapping its controls in `ExpandableRow.Controls`, while the arrow stays a real button so the keyboard reaches it. That opt-out is explicit rather than sniffing the event target for an interactive ancestor, because a control rendering into a shadow root retargets the event to its host. `sticky` pins the row while its body scrolls, offset by `stickyTopOffset` for whatever is already pinned above it; it only pins while open, since a closed row has nothing to scroll past. _Key props:_ `header`, `children`, `expanded`, `onToggle`, `sticky`, `stickyTopOffset`, `divider`, `tone`, `aria-label`, `className`, `style`.
13
13
  - **`DisclosureArrow`** — The expand/collapse triangle disclosure UI shares (`Accordion`, `Surface.ExpandableRow`). Owns its colour states so they never drift between usages: `text-primary` when expanded, `text-placeholder` otherwise, and dark on hover inside a `group` ancestor — put `group` on the clickable header or row so that hover state activates. _Key props:_ `expanded`, `size`, `className`.
14
14
  - **`Card`** — Generic content card.
15
- - **`SelectableCard`** — A card that is one option in a radio group — eyebrow, optional status tag, title, description, a count label and a top-right action slot. Use inside a `CardStrip`. Selection is controlled by the consumer: pass `selected`, which drives both the visual treatment and `aria-checked`. A selected card meets the sheet below the way a browser tab meets its toolbar — its bottom corners flare outward onto the strip’s rule — so its outline is one SVG path rather than borders, which would split into two lines at the tangent. `variant` picks the palette: `profile` (green), `library` (neutral) or `editing` (amber, for a profile with unsaved changes). `actions` stands in the card’s top-right corner, on the eyebrow row, and renders outside the control so a menu or icon button inside it stays clickable and keeps its own tab stop. Nothing else marks that corner: the flared outline, the tint and the green eyebrow already say which card is selected, so a radio there would only repeat them. `isDefault` marks the card as the account default with a pin beside the title, named for assistive tech and tooltipped for everyone else — it belongs with the name it qualifies rather than among the actions, which read as things to press. For a row-shaped selectable use `Surface.Row` instead. _Key props:_ `value`, `title`, `titleIcon`, `isDefault`, `variant` (`profile` | `library` | `editing`), `eyebrow`, `status` (`label`, `type`), `description`, `countLabel`, `actions`, `selected`, `loading` (`loadingLabel`, `loadingHint`), `disabled`, `dimmed`, `onSelect`, `tabIndex`, `aria-label`, `className`, `style`.
15
+ - **`SelectableCard`** — A card that is one option in a radio group — eyebrow, optional status tag, title, description, a count label and a top-right action slot. Use inside a `CardStrip`. Selection is controlled by the consumer: pass `selected`, which drives both the visual treatment and `aria-checked`. A selected card meets the sheet below the way a browser tab meets its toolbar — its bottom corners flare outward onto the strip’s rule — so its outline is one SVG path rather than borders, which would split into two lines at the tangent. `variant` picks the palette: `profile` (green), `library` (neutral) or `editing` (amber, for a profile with unsaved changes). `actions` stands in the card’s top-right corner, on the eyebrow row, and renders outside the control so a menu or icon button inside it stays clickable and keeps its own tab stop. Nothing else marks that corner: the flared outline, the tint and the green eyebrow already say which card is selected, so a radio there would only repeat them. `onDismiss` adds an x after `actions`, tinted like the eyebrow so it reads as part of the card — for discarding a draft card; `dismissDisabledReason` disables it and explains why in its tooltip. `isDefault` marks the card as the account default with a pin beside the title, named for assistive tech and tooltipped for everyone else — it belongs with the name it qualifies rather than among the actions, which read as things to press. For a row-shaped selectable use `Surface.Row` instead. _Key props:_ `value`, `title`, `titleIcon`, `isDefault`, `variant` (`profile` | `library` | `editing`), `eyebrow`, `status` (`label`, `type`), `description`, `countLabel`, `actions`, `onDismiss` (`dismissLabel`, `dismissDisabledReason`), `selected`, `loading` (`loadingLabel`, `loadingHint`), `disabled`, `dimmed`, `onSelect`, `tabIndex`, `aria-label`, `className`, `style`.
16
16
  - **`CardStrip`** — Horizontally scrolling radio group of cards, with edge arrows that appear only when the content overflows, an edge fade, scroll-snap and arrow-key navigation matching `SegmentedControl`. Owns interaction only: it finds its options by looking for `role="radio"` descendants carrying `data-value`, so any such child works (`SelectableCard` emits both). Pass a non-selectable terminal tile as `CardStrip.AddTile` — it sits inside the group but outside the radio set, and must be a direct child or it scrolls with the cards. Use `leading` to pin a card that should not scroll away; the strip tells the cards which slot they are in, so a pinned `SelectableCard` drops the left rule the scrolling ones draw. Set `bleed` when the strip sits in a `PageLayout`: the strip stretches past the horizontal padding of the layout so its bottom rule runs the full width of the page card, while the cards stay aligned to the gutter. With no cards at all the strip degenerates to its pinned slots alone — no trough, no scroller and no arrows — with the add tile standing beside `leading` and taking `primary` emphasis automatically, since adding the first card is the only thing on offer. _Key props:_ `value`, `tone` (`profile` | `library` | `editing` — read off the selected card unless set), `onChange`, `children`, `leading`, `arrows`, `fadeEdges`, `snap`, `bleed`, `scrollSelectedIntoView`, `aria-label`, `aria-labelledby`, `className`, `style`. `CardStrip.AddTile`: `label`, `icon`, `onClick`, `disabled`, `emphasis` (`primary` | `secondary` — left to the strip unless set: `primary` while there are no cards, `secondary` once there are), `className`.
17
17
  - **`SplitScreenLayout`** — Two-pane full-screen layout (content + preview/aside) with an optional dismiss button.
18
18
  - **`PageLayout`** — Standard page chrome: a bordered card holding a breadcrumb bar, an optional alert strip, and a header block (subtitle, title + suffix, description) above the page body. Used as `PageLayout.Regular`; `PageLayout.Empty` is the chrome-only variant for pre-auth and error screens, with `headerActions` and `background` slots. Actions are declared as data (`buttons`) rather than children, and any that do not fit collapse into an overflow `ActionMenu` via `OverflowRow`. A client-side-routed app must pass `renderLink` so crumbs and the back button go through its router instead of reloading the document. Both layouts render a `main` landmark, demoted via `role` when the app owns its own. Deliberately not a `Surface` — the page card is 16px and carries no shadow. _Key props:_ `PageLayout.Regular`: `breadcrumbLinks`, `breadcrumbActions`, `renderLink`, `title`, `titleSuffix`, `subtitle`, `description`, `buttons`, `loading`, `centered`, `noPadding`, `contentGap` (`small` | `medium` | `large` | `xlarge`, default `small`), `alert`, `role`, `aria-label`, `aria-labelledby`, `className`, `style`. `PageLayout.Empty`: `title`, `centered`, `uniformPadding`, `headerActions`, `background`, `role`, `aria-label`, `aria-labelledby`, `className`, `style`.
@@ -1 +1 @@
1
- {"version":3,"file":"FieldMessage.js","sources":["../../src/components/FieldMessage.tsx"],"sourcesContent":["import type React from 'react';\n\nconst MESSAGE_CLASSES =\n 'text-[length:var(--malachite-font-size-small,13px)] text-left pl-2 text-[var(--malachite-destructive-foreground,rgb(196,62,62))]';\n\ninterface FieldMessageProps {\n id?: string;\n message?: string;\n /** The controls that sit their message under a helper line need the gap; `Input` does not. */\n spaced?: boolean;\n}\n\n/**\n * A field's validation message. The live region is mounted whether or not there is anything\n * to say, because a region inserted with its text already inside it is not a mutation and\n * screen readers stay silent — which would lose the first rejection, the one that matters.\n * Out of flow while empty, so a flex parent's `gap` reserves no space beside it.\n */\nexport const FieldMessage: React.FC<FieldMessageProps> = ({ id, message, spaced = false }) => (\n <div\n id={id}\n // Polite rather than assertive: the message is also the field's description via\n // aria-describedby, and an interrupting region says it a second time.\n aria-live=\"polite\"\n className={message ? `${spaced ? 'mt-1 ' : ''}${MESSAGE_CLASSES}` : 'absolute'}\n >\n {message}\n </div>\n);\n\nexport default FieldMessage;\n"],"names":["MESSAGE_CLASSES","FieldMessage","id","message","spaced","jsx"],"mappings":";AAEA,MAAMA,IACF,oIAeSC,IAA4C,CAAC,EAAE,IAAAC,GAAI,SAAAC,GAAS,QAAAC,IAAS,SAC9E,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACG,IAAAH;AAAA,IAGA,aAAU;AAAA,IACV,WAAWC,IAAU,GAAGC,IAAS,UAAU,EAAE,GAAGJ,CAAe,KAAK;AAAA,IAEnE,UAAAG;AAAA,EAAA;AACL;"}
1
+ {"version":3,"file":"FieldMessage.js","sources":["../../src/components/FieldMessage.tsx"],"sourcesContent":["import type React from 'react';\n\nconst MESSAGE_CLASSES =\n 'text-[length:var(--malachite-font-size-small,13px)] text-left pl-2 text-[var(--malachite-destructive-foreground,rgb(196,62,62))]';\n\ninterface FieldMessageProps {\n id?: string;\n message?: string;\n /** The controls that sit their message under a helper line need the gap. */\n spaced?: boolean;\n}\n\n/**\n * A field's validation message. The live region is mounted whether or not there is anything\n * to say, because a region inserted with its text already inside it is not a mutation and\n * screen readers stay silent — which would lose the first rejection, the one that matters.\n * Out of flow while empty, so a flex parent's `gap` reserves no space beside it.\n */\nexport const FieldMessage: React.FC<FieldMessageProps> = ({ id, message, spaced = false }) => (\n <div\n id={id}\n // Polite rather than assertive: the message is also the field's description via\n // aria-describedby, and an interrupting region says it a second time.\n aria-live=\"polite\"\n className={message ? `${spaced ? 'mt-1 ' : ''}${MESSAGE_CLASSES}` : 'absolute'}\n >\n {message}\n </div>\n);\n\nexport default FieldMessage;\n"],"names":["MESSAGE_CLASSES","FieldMessage","id","message","spaced","jsx"],"mappings":";AAEA,MAAMA,IACF,oIAeSC,IAA4C,CAAC,EAAE,IAAAC,GAAI,SAAAC,GAAS,QAAAC,IAAS,SAC9E,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACG,IAAAH;AAAA,IAGA,aAAU;AAAA,IACV,WAAWC,IAAU,GAAGC,IAAS,UAAU,EAAE,GAAGJ,CAAe,KAAK;AAAA,IAEnE,UAAAG;AAAA,EAAA;AACL;"}
@@ -1,4 +1,4 @@
1
- import { jsx as a, jsxs as n, Fragment as K } from "react/jsx-runtime";
1
+ import { jsx as r, jsxs as n, Fragment as K } from "react/jsx-runtime";
2
2
  import { useState as j, useEffect as xe, useRef as ge } from "react";
3
3
  import be, { useFormFieldIds as we } from "../BaseFormComponent.js";
4
4
  import { Button as Q } from "../Button.js";
@@ -26,8 +26,8 @@ const J = {
26
26
  small: "rounded-[var(--malachite-radius-10,10px)]",
27
27
  medium: "rounded-xl",
28
28
  large: "rounded-[var(--malachite-radius-xxl,14px)]"
29
- }, $e = (r, e) => {
30
- switch (r) {
29
+ }, $e = (a, e) => {
30
+ switch (a) {
31
31
  case "ghost":
32
32
  return {
33
33
  wrapper: [
@@ -50,7 +50,7 @@ const J = {
50
50
  };
51
51
  }
52
52
  }, Je = ({
53
- label: r,
53
+ label: a,
54
54
  hint: e,
55
55
  tooltip: i,
56
56
  placeholder: x,
@@ -67,34 +67,34 @@ const J = {
67
67
  variant: F = "default",
68
68
  defaultValue: $,
69
69
  disabled: u,
70
- prefixValue: Z,
71
- prefixSecondaryValue: _,
70
+ prefixValue: M,
71
+ prefixSecondaryValue: T,
72
72
  ellipsis: O = !1,
73
- formControl: D,
73
+ formControl: Z,
74
74
  buttons: v,
75
- onCopyClick: M,
75
+ onCopyClick: _,
76
76
  showCopyButton: ee,
77
77
  onChange: b,
78
- value: ae,
78
+ value: re,
79
79
  onBlur: w,
80
80
  helperText: f,
81
81
  showPasswordToggle: I = !0,
82
- id: re,
82
+ id: ae,
83
83
  "aria-label": te,
84
84
  "aria-labelledby": ie,
85
85
  "aria-describedby": le
86
86
  }) => {
87
- const { controlId: P, labelId: se, descriptionId: A, hintId: G, helperTextId: y } = we({
88
- id: re,
89
- label: r,
87
+ const { controlId: D, labelId: se, descriptionId: P, hintId: A, helperTextId: y } = we({
88
+ id: ae,
89
+ label: a,
90
90
  description: R,
91
91
  hint: e,
92
92
  helperText: !0
93
- }), [C, oe] = j(!1), [de, ce] = j($ || ""), [N, H] = j(!1);
93
+ }), [C, oe] = j(!1), [de, ce] = j($ || ""), [N, G] = j(!1);
94
94
  xe(() => {
95
95
  if (N) {
96
96
  const t = setTimeout(() => {
97
- H(!1);
97
+ G(!1);
98
98
  }, 1e3);
99
99
  return () => clearTimeout(t);
100
100
  }
@@ -102,18 +102,18 @@ const J = {
102
102
  const ne = (t) => (l) => {
103
103
  const c = l.target.value;
104
104
  ce(c), b == null || b(c), t == null || t(c);
105
- }, T = ge(void 0), B = (t) => Se({
105
+ }, H = ge(void 0), B = (t) => Se({
106
106
  component: "Input",
107
107
  name: s,
108
- value: ae,
108
+ value: re,
109
109
  formValue: t,
110
110
  defaultValue: $,
111
- bound: !!D,
111
+ bound: !!Z,
112
112
  uncontrolledValue: de
113
- }), L = M ? () => {
114
- const t = B(T.current);
115
- t && (navigator.clipboard.writeText(t), H(!0), M());
116
- } : void 0, me = o === "password" ? C ? "text" : "password" : o, he = m || Z || _, pe = J[d], ue = (t) => {
113
+ }), L = _ ? () => {
114
+ const t = B(H.current);
115
+ t && (navigator.clipboard.writeText(t), G(!0), _());
116
+ } : void 0, me = o === "password" ? C ? "text" : "password" : o, he = m || M || T, pe = J[d], ue = (t) => {
117
117
  const l = $e(F, t);
118
118
  return [
119
119
  "relative",
@@ -127,46 +127,53 @@ const J = {
127
127
  J[d]
128
128
  ].filter(Boolean).join(" ");
129
129
  };
130
- return /* @__PURE__ */ a(
130
+ return /* @__PURE__ */ r(
131
131
  be,
132
132
  {
133
- label: r,
133
+ label: a,
134
134
  hint: e,
135
135
  tooltip: i,
136
136
  name: s,
137
137
  required: h,
138
138
  requiredIndicator: g,
139
139
  loading: Y,
140
- formControl: D,
140
+ formControl: Z,
141
141
  description: R,
142
- controlId: P,
142
+ controlId: D,
143
143
  labelId: se,
144
- descriptionId: A,
145
- hintId: G,
146
- loadingComponent: /* @__PURE__ */ a(ze, { heightClass: pe, helperText: !!f }),
144
+ descriptionId: P,
145
+ hintId: A,
146
+ loadingComponent: /* @__PURE__ */ r(
147
+ ze,
148
+ {
149
+ heightClass: pe,
150
+ helperText: !!f,
151
+ helperTextMarginTop: !0
152
+ }
153
+ ),
147
154
  children: ({ error: t, message: l, onFieldChange: c, onFieldBlur: k, value: U }) => {
148
- T.current = U;
155
+ H.current = U;
149
156
  const E = B(U), W = ee ?? !!(L && u && E), z = p ?? t, S = p === !1 ? void 0 : l, X = z && !S, ve = X || W || (v == null ? void 0 : v.length) || o === "password" && I, q = `${y}-error`, fe = [
157
+ P,
150
158
  A,
151
- G,
152
159
  f ? y : void 0,
153
160
  S ? q : void 0,
154
161
  le
155
162
  ].filter(Boolean).join(" ") || void 0;
156
163
  return /* @__PURE__ */ n(K, { children: [
157
164
  /* @__PURE__ */ n("div", { className: ue(z), children: [
158
- he && /* @__PURE__ */ a("div", { className: "flex items-center pl-3 pr-1 flex-shrink-0 pointer-events-none", children: /* @__PURE__ */ a(
159
- Ze,
165
+ he && /* @__PURE__ */ r("div", { className: "flex items-center pl-3 pr-1 flex-shrink-0 pointer-events-none", children: /* @__PURE__ */ r(
166
+ Me,
160
167
  {
161
- prefixValue: Z,
162
- prefixSecondaryValue: _,
168
+ prefixValue: M,
169
+ prefixSecondaryValue: T,
163
170
  icon: m
164
171
  }
165
172
  ) }),
166
- /* @__PURE__ */ a(
173
+ /* @__PURE__ */ r(
167
174
  "input",
168
175
  {
169
- id: P,
176
+ id: D,
170
177
  type: me,
171
178
  placeholder: x,
172
179
  value: E,
@@ -191,8 +198,8 @@ const J = {
191
198
  {
192
199
  className: `flex items-center pl-1 flex-shrink-0 ${o === "password" && I ? "pr-0" : "pr-3"}`,
193
200
  children: [
194
- /* @__PURE__ */ a(
195
- _e,
201
+ /* @__PURE__ */ r(
202
+ Te,
196
203
  {
197
204
  error: X,
198
205
  defaultValue: E,
@@ -205,30 +212,30 @@ const J = {
205
212
  onTogglePassword: () => oe(!C)
206
213
  }
207
214
  ),
208
- /* @__PURE__ */ a(De, { buttons: v })
215
+ /* @__PURE__ */ r(Ze, { buttons: v })
209
216
  ]
210
217
  }
211
218
  )
212
219
  ] }),
213
- f && /* @__PURE__ */ a(
220
+ f && /* @__PURE__ */ r(
214
221
  "div",
215
222
  {
216
223
  id: y,
217
- className: "text-[length:var(--malachite-font-size-small,13px)] text-left pl-2 text-[var(--malachite-text-dimmed,rgb(161,161,161))]",
224
+ className: "mt-1 text-[length:var(--malachite-font-size-small,13px)] text-left pl-2 text-[var(--malachite-text-dimmed,rgb(161,161,161))]",
218
225
  children: f
219
226
  }
220
227
  ),
221
- /* @__PURE__ */ a(Ee, { id: q, message: S })
228
+ /* @__PURE__ */ r(Ee, { id: q, message: S, spaced: !0 })
222
229
  ] });
223
230
  }
224
231
  }
225
232
  );
226
- }, Ze = ({ prefixValue: r, prefixSecondaryValue: e, icon: i }) => /* @__PURE__ */ n("div", { className: "flex items-center gap-1", children: [
227
- i && /* @__PURE__ */ a("span", { className: "flex items-center justify-center text-[var(--malachite-text-dimmed)] w-4 h-4 flex-shrink-0", children: i }),
228
- r && /* @__PURE__ */ a("span", { className: "text-[length:var(--malachite-font-size-medium,14px)] leading-[1.4] text-[var(--malachite-text-dimmed)] whitespace-nowrap", children: r }),
229
- e && /* @__PURE__ */ a("span", { className: "text-[length:var(--malachite-font-size-medium,14px)] leading-[1.4] text-[var(--malachite-text-dimmed)] whitespace-nowrap", children: e })
230
- ] }), _e = ({
231
- error: r,
233
+ }, Me = ({ prefixValue: a, prefixSecondaryValue: e, icon: i }) => /* @__PURE__ */ n("div", { className: "flex items-center gap-1", children: [
234
+ i && /* @__PURE__ */ r("span", { className: "flex items-center justify-center text-[var(--malachite-text-dimmed)] w-4 h-4 flex-shrink-0", children: i }),
235
+ a && /* @__PURE__ */ r("span", { className: "text-[length:var(--malachite-font-size-medium,14px)] leading-[1.4] text-[var(--malachite-text-dimmed)] whitespace-nowrap", children: a }),
236
+ e && /* @__PURE__ */ r("span", { className: "text-[length:var(--malachite-font-size-medium,14px)] leading-[1.4] text-[var(--malachite-text-dimmed)] whitespace-nowrap", children: e })
237
+ ] }), Te = ({
238
+ error: a,
232
239
  defaultValue: e,
233
240
  onCopyClick: i,
234
241
  showCopyButton: x = !1,
@@ -238,14 +245,14 @@ const J = {
238
245
  showPasswordToggle: g = !0,
239
246
  onTogglePassword: p
240
247
  }) => /* @__PURE__ */ n("div", { className: "flex items-center gap-1", children: [
241
- r && // Decorative: the rejection is carried by the message beneath the field, so
248
+ a && // Decorative: the rejection is carried by the message beneath the field, so
242
249
  // announcing an unnamed icon here would only repeat it as "info".
243
- /* @__PURE__ */ a(
250
+ /* @__PURE__ */ r(
244
251
  "div",
245
252
  {
246
253
  "aria-hidden": "true",
247
254
  className: "flex items-center justify-center w-5 h-5 flex-shrink-0",
248
- children: /* @__PURE__ */ a(
255
+ children: /* @__PURE__ */ r(
249
256
  ke,
250
257
  {
251
258
  size: 16,
@@ -254,35 +261,35 @@ const J = {
254
261
  )
255
262
  }
256
263
  ),
257
- x && i && e && /* @__PURE__ */ a(
264
+ x && i && e && /* @__PURE__ */ r(
258
265
  "button",
259
266
  {
260
267
  onClick: i,
261
268
  type: "button",
262
269
  className: "flex items-center justify-center w-5 h-5 hover:bg-[var(--malachite-primary-border)] rounded transition-colors flex-shrink-0 cursor-pointer",
263
- children: m ? /* @__PURE__ */ a(
270
+ children: m ? /* @__PURE__ */ r(
264
271
  Ie,
265
272
  {
266
273
  size: 16,
267
274
  style: { color: "var(--malachite-success-foreground)" }
268
275
  }
269
- ) : /* @__PURE__ */ a(ye, { size: 16 })
276
+ ) : /* @__PURE__ */ r(ye, { size: 16 })
270
277
  }
271
278
  ),
272
- s === "password" && g && /* @__PURE__ */ a(Q, { variant: "no-style", onClick: p, type: "button", size: "small", children: h ? /* @__PURE__ */ a(
279
+ s === "password" && g && /* @__PURE__ */ r(Q, { variant: "no-style", onClick: p, type: "button", size: "small", children: h ? /* @__PURE__ */ r(
273
280
  Ce,
274
281
  {
275
282
  size: 16,
276
283
  style: { color: "var(--malachite-text-dimmed)" }
277
284
  }
278
- ) : /* @__PURE__ */ a(
285
+ ) : /* @__PURE__ */ r(
279
286
  Ne,
280
287
  {
281
288
  size: 16,
282
289
  style: { color: "var(--malachite-text-dimmed)" }
283
290
  }
284
291
  ) })
285
- ] }), De = ({ buttons: r }) => r != null && r.length ? /* @__PURE__ */ a(K, { children: r.map((e) => /* @__PURE__ */ a(
292
+ ] }), Ze = ({ buttons: a }) => a != null && a.length ? /* @__PURE__ */ r(K, { children: a.map((e) => /* @__PURE__ */ r(
286
293
  Q,
287
294
  {
288
295
  variant: e.variant || (e.danger ? "destructive" : "outline"),
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sources":["../../../src/components/Input/Input.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport type { Control, FieldPath, FieldValues } from 'react-hook-form';\nimport BaseFormComponent, { type RequiredIndicator, useFormFieldIds } from '../BaseFormComponent';\nimport { Button } from '../Button';\nimport CheckCircleFilled from '../CustomIcons/CheckCircleFilled';\nimport CopyIcon from '../CustomIcons/CopyIcon';\nimport EyeClosedIcon from '../CustomIcons/EyeClosedIcon';\nimport EyeIcon from '../CustomIcons/EyeIcon';\nimport InfoIcon from '../CustomIcons/InfoIcon';\nimport FieldMessage from '../FieldMessage';\nimport LoadingInput from '../LoadingInput';\nimport { paintedFieldValue } from '../devWarning';\nimport type { ButtonDefinition, InputSize, InputType, InputVariant } from './types';\n\ninterface InputProps {\n label?: string;\n hint?: string;\n tooltip?: string;\n placeholder?: string;\n icon?: React.ReactNode;\n readOnly?: boolean;\n name: FieldPath<FieldValues> | string;\n type?: InputType;\n description?: string;\n size?: InputSize;\n variant?: InputVariant;\n required?: boolean;\n requiredIndicator?: RequiredIndicator;\n error?: boolean;\n loading?: boolean;\n defaultValue?: string;\n disabled?: boolean;\n prefixValue?: string;\n prefixSecondaryValue?: string;\n ellipsis?: boolean;\n formControl?: Control<FieldValues, unknown>;\n buttons?: ButtonDefinition[];\n onCopyClick?: () => void;\n showCopyButton?: boolean;\n onChange?: (value: string) => void;\n /** Controlled value, for a source of truth outside the form (URL, app state). */\n value?: string;\n onBlur?: () => void;\n helperText?: string;\n showPasswordToggle?: boolean;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n}\n\n// Figma specs one Input, at 42px / px-16 / 15px / radius 14 — the large tier. The smaller\n// tiers have no Input master, so they follow Search, which shares the field chrome.\nconst SIZE_HEIGHT: Record<InputSize, string> = {\n small: 'h-[var(--malachite-control-height-small,28px)]',\n medium: 'h-[var(--malachite-control-height-medium,32px)]',\n large: 'h-[var(--malachite-control-height-large,42px)]',\n};\n\nconst SIZE_TEXT: Record<InputSize, string> = {\n small: 'text-[length:var(--malachite-font-size-small,13px)]',\n medium: 'text-[length:var(--malachite-font-size-small,13px)]',\n large: 'text-[length:var(--malachite-font-size-15,15px)] leading-[1.4]',\n};\n\nconst SIZE_PADDING: Record<InputSize, string> = {\n small: 'px-[10px]',\n medium: 'px-[10px]',\n large: 'px-[16px]',\n};\n\nconst SIZE_RADIUS: Record<InputSize, string> = {\n small: 'rounded-[var(--malachite-radius-10,10px)]',\n medium: 'rounded-xl',\n large: 'rounded-[var(--malachite-radius-xxl,14px)]',\n};\n\nconst getVariantClasses = (\n variant: InputVariant,\n error?: boolean,\n): {\n wrapper: string[];\n shadow: string;\n borderRadius: string;\n} => {\n switch (variant) {\n case 'ghost':\n return {\n wrapper: [\n error\n ? 'border-0 border-b border-solid border-[var(--malachite-destructive-border)]'\n : '',\n error\n ? 'focus-within:border-[var(--malachite-destructive-border-hover)] hover:border-[var(--malachite-destructive-border-hover)]'\n : '',\n ],\n shadow: 'shadow-none',\n borderRadius: 'rounded-none',\n };\n case 'default':\n default:\n return {\n wrapper: [\n 'border border-solid',\n error\n ? 'border-[var(--malachite-destructive-border)]'\n : 'border-[var(--malachite-card-border)]',\n error\n ? 'focus-within:border-[var(--malachite-destructive-border-hover)] hover:border-[var(--malachite-destructive-border-hover)]'\n : 'focus-within:border-[var(--malachite-control-border-hover)] hover:border-[var(--malachite-control-border-hover)]',\n ],\n shadow: error ? 'shadow-error' : 'shadow-default',\n borderRadius: '',\n };\n }\n};\n\nconst Input: React.FC<InputProps> = ({\n label,\n hint,\n tooltip,\n placeholder,\n icon,\n name,\n required,\n requiredIndicator,\n error,\n description,\n loading = false,\n readOnly = false,\n type = 'text',\n size = 'large',\n variant = 'default',\n defaultValue,\n disabled,\n prefixValue,\n prefixSecondaryValue,\n ellipsis = false,\n formControl,\n buttons,\n onCopyClick,\n showCopyButton,\n onChange,\n value,\n onBlur,\n helperText,\n showPasswordToggle = true,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n}) => {\n const { controlId, labelId, descriptionId, hintId, helperTextId } = useFormFieldIds({\n id,\n label,\n description,\n hint,\n helperText: true,\n });\n const [showPassword, setShowPassword] = useState(false);\n const [inputValue, setInputValue] = useState(defaultValue || '');\n const [copied, setCopied] = useState(false);\n\n useEffect(() => {\n if (copied) {\n const timer = setTimeout(() => {\n setCopied(false);\n }, 1000);\n return () => clearTimeout(timer);\n }\n }, [copied]);\n\n const handleChange =\n (reportToForm?: (value: unknown) => void) => (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n onChange?.(newValue);\n reportToForm?.(newValue);\n };\n\n const formValueRef = useRef<unknown>(undefined);\n const paintedValue = (formValue: unknown): string =>\n paintedFieldValue({\n component: 'Input',\n name,\n value,\n formValue,\n defaultValue,\n bound: !!formControl,\n uncontrolledValue: inputValue,\n });\n\n const handleCopyClick = onCopyClick\n ? () => {\n const copyValue = paintedValue(formValueRef.current);\n if (copyValue) {\n navigator.clipboard.writeText(copyValue);\n setCopied(true);\n onCopyClick();\n }\n }\n : undefined;\n\n const actualInputType = type === 'password' ? (showPassword ? 'text' : 'password') : type;\n\n const hasPrefix = icon || prefixValue || prefixSecondaryValue;\n\n // The skeleton stands in for the field, so it reads the same height the wrapper does.\n const heightClass = SIZE_HEIGHT[size];\n\n const buildWrapperClasses = (isError: boolean): string => {\n const variantStyles = getVariantClasses(variant, isError);\n\n return [\n 'relative',\n 'flex items-center',\n 'w-full',\n variantStyles.borderRadius || SIZE_RADIUS[size],\n disabled\n ? 'bg-[var(--malachite-card-dimmed-background)]'\n : 'bg-[var(--malachite-card-background)]',\n 'transition-colors duration-200 ease-in-out',\n variantStyles.shadow,\n ...(disabled ? [] : variantStyles.wrapper),\n SIZE_HEIGHT[size],\n ]\n .filter(Boolean)\n .join(' ');\n };\n\n return (\n <BaseFormComponent\n label={label}\n hint={hint}\n tooltip={tooltip}\n name={name}\n required={required}\n requiredIndicator={requiredIndicator}\n loading={loading}\n formControl={formControl}\n description={description}\n controlId={controlId}\n labelId={labelId}\n descriptionId={descriptionId}\n hintId={hintId}\n loadingComponent={<LoadingInput heightClass={heightClass} helperText={!!helperText} />}\n >\n {({ error: fieldError, message, onFieldChange, onFieldBlur, value: formValue }) => {\n formValueRef.current = formValue;\n const displayValue = paintedValue(formValue);\n const shouldShowCopyButton =\n showCopyButton ?? !!(handleCopyClick && disabled && displayValue);\n const isError = error ?? fieldError;\n // `error={false}` opts out of the resolver entirely, message included: a\n // screen that has dealt with the rejection its own way would otherwise keep\n // reporting it in destructive text and through `aria-describedby`.\n // The message is its own line rather than a replacement for the helper text:\n // a field that explains where to find its value still has to say why what was\n // typed was rejected, and dropping one for the other left the field marked red\n // with nothing anywhere saying what was wrong.\n const errorMessage = error === false ? undefined : message;\n // The icon is the only signal a consumer-forced `error` has; beside a message it\n // is duplication, and it crowds the suffix next to a reveal or copy control.\n const showErrorIcon = isError && !errorMessage;\n const hasSuffix =\n showErrorIcon ||\n shouldShowCopyButton ||\n buttons?.length ||\n (type === 'password' && showPasswordToggle);\n const errorMessageId = `${helperTextId}-error`;\n const describedBy =\n [\n descriptionId,\n hintId,\n helperText ? helperTextId : undefined,\n errorMessage ? errorMessageId : undefined,\n ariaDescribedBy,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n return (\n <>\n <div className={buildWrapperClasses(isError)}>\n {hasPrefix && (\n <div className=\"flex items-center pl-3 pr-1 flex-shrink-0 pointer-events-none\">\n <CompositeIcon\n prefixValue={prefixValue}\n prefixSecondaryValue={prefixSecondaryValue}\n icon={icon}\n />\n </div>\n )}\n\n <input\n id={controlId}\n type={actualInputType}\n placeholder={placeholder}\n value={displayValue}\n onChange={handleChange(onFieldChange)}\n onBlur={() => {\n onBlur?.();\n onFieldBlur?.();\n }}\n disabled={disabled || readOnly}\n readOnly={readOnly}\n autoComplete=\"off\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={isError || undefined}\n aria-required={required || undefined}\n aria-describedby={describedBy}\n className={`flex-1 bg-transparent border-none outline-none text-[var(--malachite-text-primary)] placeholder:text-[var(--malachite-text-placeholder)] disabled:text-[var(--malachite-text-primary)] disabled:cursor-not-allowed ${SIZE_TEXT[size]} ${SIZE_PADDING[size]} ${ellipsis ? 'min-w-0 truncate' : ''}`}\n name={name}\n />\n\n {hasSuffix && (\n <div\n className={`flex items-center pl-1 flex-shrink-0 ${type === 'password' && showPasswordToggle ? 'pr-0' : 'pr-3'}`}\n >\n <Suffix\n error={showErrorIcon}\n defaultValue={displayValue}\n onCopyClick={handleCopyClick}\n showCopyButton={shouldShowCopyButton}\n copied={copied}\n type={type}\n showPassword={showPassword}\n showPasswordToggle={showPasswordToggle}\n onTogglePassword={() => setShowPassword(!showPassword)}\n />\n <InputButtons buttons={buttons} />\n </div>\n )}\n </div>\n {helperText && (\n <div\n id={helperTextId}\n className=\"text-[length:var(--malachite-font-size-small,13px)] text-left pl-2 text-[var(--malachite-text-dimmed,rgb(161,161,161))]\"\n >\n {helperText}\n </div>\n )}\n <FieldMessage id={errorMessageId} message={errorMessage} />\n </>\n );\n }}\n </BaseFormComponent>\n );\n};\n\nconst CompositeIcon: React.FC<{\n prefixValue?: string;\n prefixSecondaryValue?: string;\n icon?: React.ReactNode;\n}> = ({ prefixValue, prefixSecondaryValue, icon }) => {\n return (\n <div className=\"flex items-center gap-1\">\n {icon && (\n <span className=\"flex items-center justify-center text-[var(--malachite-text-dimmed)] w-4 h-4 flex-shrink-0\">\n {icon}\n </span>\n )}\n {prefixValue && (\n <span className=\"text-[length:var(--malachite-font-size-medium,14px)] leading-[1.4] text-[var(--malachite-text-dimmed)] whitespace-nowrap\">\n {prefixValue}\n </span>\n )}\n {prefixSecondaryValue && (\n <span className=\"text-[length:var(--malachite-font-size-medium,14px)] leading-[1.4] text-[var(--malachite-text-dimmed)] whitespace-nowrap\">\n {prefixSecondaryValue}\n </span>\n )}\n </div>\n );\n};\n\nconst Suffix: React.FC<{\n error?: boolean;\n defaultValue?: string;\n onCopyClick?: () => void;\n showCopyButton?: boolean;\n copied?: boolean;\n type?: InputType;\n showPassword?: boolean;\n showPasswordToggle?: boolean;\n onTogglePassword?: () => void;\n}> = ({\n error,\n defaultValue,\n onCopyClick,\n showCopyButton = false,\n copied = false,\n type,\n showPassword,\n showPasswordToggle = true,\n onTogglePassword,\n}) => {\n return (\n <div className=\"flex items-center gap-1\">\n {error && (\n // Decorative: the rejection is carried by the message beneath the field, so\n // announcing an unnamed icon here would only repeat it as \"info\".\n <div\n aria-hidden=\"true\"\n className=\"flex items-center justify-center w-5 h-5 flex-shrink-0\"\n >\n <InfoIcon\n size={16}\n className=\"text-[var(--malachite-destructive-foreground,rgb(196,62,62))]\"\n />\n </div>\n )}\n {showCopyButton && onCopyClick && defaultValue && (\n <button\n onClick={onCopyClick}\n type=\"button\"\n className=\"flex items-center justify-center w-5 h-5 hover:bg-[var(--malachite-primary-border)] rounded transition-colors flex-shrink-0 cursor-pointer\"\n >\n {copied ? (\n <CheckCircleFilled\n size={16}\n style={{ color: 'var(--malachite-success-foreground)' }}\n />\n ) : (\n <CopyIcon size={16} />\n )}\n </button>\n )}\n {type === 'password' && showPasswordToggle && (\n <Button variant=\"no-style\" onClick={onTogglePassword} type=\"button\" size=\"small\">\n {showPassword ? (\n <EyeClosedIcon\n size={16}\n style={{ color: 'var(--malachite-text-dimmed)' }}\n />\n ) : (\n <EyeIcon\n size={16}\n style={{ color: 'var(--malachite-text-dimmed)' }}\n />\n )}\n </Button>\n )}\n </div>\n );\n};\n\nconst InputButtons: React.FC<{\n buttons?: ButtonDefinition[];\n}> = ({ buttons }) => {\n if (!buttons?.length) {\n return null;\n }\n\n return (\n <>\n {buttons.map((button) => (\n <Button\n key={button.label}\n variant={button.variant || (button.danger ? 'destructive' : 'outline')}\n size={button.size || 'small'}\n disabled={button.disabled}\n icon={button.icon}\n tooltip={button.tooltip}\n onClick={button.onClick}\n className=\"ml-1\"\n >\n {button.label}\n </Button>\n ))}\n </>\n );\n};\n\nexport default Input;\n"],"names":["SIZE_HEIGHT","SIZE_TEXT","SIZE_PADDING","SIZE_RADIUS","getVariantClasses","variant","error","Input","label","hint","tooltip","placeholder","icon","name","required","requiredIndicator","description","loading","readOnly","type","size","defaultValue","disabled","prefixValue","prefixSecondaryValue","ellipsis","formControl","buttons","onCopyClick","showCopyButton","onChange","value","onBlur","helperText","showPasswordToggle","id","ariaLabel","ariaLabelledBy","ariaDescribedBy","controlId","labelId","descriptionId","hintId","helperTextId","useFormFieldIds","showPassword","setShowPassword","useState","inputValue","setInputValue","copied","setCopied","useEffect","timer","handleChange","reportToForm","e","newValue","formValueRef","useRef","paintedValue","formValue","paintedFieldValue","handleCopyClick","copyValue","actualInputType","hasPrefix","heightClass","buildWrapperClasses","isError","variantStyles","jsx","BaseFormComponent","LoadingInput","fieldError","message","onFieldChange","onFieldBlur","displayValue","shouldShowCopyButton","errorMessage","showErrorIcon","hasSuffix","errorMessageId","describedBy","jsxs","Fragment","CompositeIcon","Suffix","InputButtons","FieldMessage","onTogglePassword","InfoIcon","CheckCircleFilled","CopyIcon","Button","EyeClosedIcon","EyeIcon","button"],"mappings":"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"}
1
+ {"version":3,"file":"Input.js","sources":["../../../src/components/Input/Input.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport type { Control, FieldPath, FieldValues } from 'react-hook-form';\nimport BaseFormComponent, { type RequiredIndicator, useFormFieldIds } from '../BaseFormComponent';\nimport { Button } from '../Button';\nimport CheckCircleFilled from '../CustomIcons/CheckCircleFilled';\nimport CopyIcon from '../CustomIcons/CopyIcon';\nimport EyeClosedIcon from '../CustomIcons/EyeClosedIcon';\nimport EyeIcon from '../CustomIcons/EyeIcon';\nimport InfoIcon from '../CustomIcons/InfoIcon';\nimport FieldMessage from '../FieldMessage';\nimport LoadingInput from '../LoadingInput';\nimport { paintedFieldValue } from '../devWarning';\nimport type { ButtonDefinition, InputSize, InputType, InputVariant } from './types';\n\ninterface InputProps {\n label?: string;\n hint?: string;\n tooltip?: string;\n placeholder?: string;\n icon?: React.ReactNode;\n readOnly?: boolean;\n name: FieldPath<FieldValues> | string;\n type?: InputType;\n description?: string;\n size?: InputSize;\n variant?: InputVariant;\n required?: boolean;\n requiredIndicator?: RequiredIndicator;\n error?: boolean;\n loading?: boolean;\n defaultValue?: string;\n disabled?: boolean;\n prefixValue?: string;\n prefixSecondaryValue?: string;\n ellipsis?: boolean;\n formControl?: Control<FieldValues, unknown>;\n buttons?: ButtonDefinition[];\n onCopyClick?: () => void;\n showCopyButton?: boolean;\n onChange?: (value: string) => void;\n /** Controlled value, for a source of truth outside the form (URL, app state). */\n value?: string;\n onBlur?: () => void;\n helperText?: React.ReactNode;\n showPasswordToggle?: boolean;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n}\n\n// Figma specs one Input, at 42px / px-16 / 15px / radius 14 — the large tier. The smaller\n// tiers have no Input master, so they follow Search, which shares the field chrome.\nconst SIZE_HEIGHT: Record<InputSize, string> = {\n small: 'h-[var(--malachite-control-height-small,28px)]',\n medium: 'h-[var(--malachite-control-height-medium,32px)]',\n large: 'h-[var(--malachite-control-height-large,42px)]',\n};\n\nconst SIZE_TEXT: Record<InputSize, string> = {\n small: 'text-[length:var(--malachite-font-size-small,13px)]',\n medium: 'text-[length:var(--malachite-font-size-small,13px)]',\n large: 'text-[length:var(--malachite-font-size-15,15px)] leading-[1.4]',\n};\n\nconst SIZE_PADDING: Record<InputSize, string> = {\n small: 'px-[10px]',\n medium: 'px-[10px]',\n large: 'px-[16px]',\n};\n\nconst SIZE_RADIUS: Record<InputSize, string> = {\n small: 'rounded-[var(--malachite-radius-10,10px)]',\n medium: 'rounded-xl',\n large: 'rounded-[var(--malachite-radius-xxl,14px)]',\n};\n\nconst getVariantClasses = (\n variant: InputVariant,\n error?: boolean,\n): {\n wrapper: string[];\n shadow: string;\n borderRadius: string;\n} => {\n switch (variant) {\n case 'ghost':\n return {\n wrapper: [\n error\n ? 'border-0 border-b border-solid border-[var(--malachite-destructive-border)]'\n : '',\n error\n ? 'focus-within:border-[var(--malachite-destructive-border-hover)] hover:border-[var(--malachite-destructive-border-hover)]'\n : '',\n ],\n shadow: 'shadow-none',\n borderRadius: 'rounded-none',\n };\n case 'default':\n default:\n return {\n wrapper: [\n 'border border-solid',\n error\n ? 'border-[var(--malachite-destructive-border)]'\n : 'border-[var(--malachite-card-border)]',\n error\n ? 'focus-within:border-[var(--malachite-destructive-border-hover)] hover:border-[var(--malachite-destructive-border-hover)]'\n : 'focus-within:border-[var(--malachite-control-border-hover)] hover:border-[var(--malachite-control-border-hover)]',\n ],\n shadow: error ? 'shadow-error' : 'shadow-default',\n borderRadius: '',\n };\n }\n};\n\nconst Input: React.FC<InputProps> = ({\n label,\n hint,\n tooltip,\n placeholder,\n icon,\n name,\n required,\n requiredIndicator,\n error,\n description,\n loading = false,\n readOnly = false,\n type = 'text',\n size = 'large',\n variant = 'default',\n defaultValue,\n disabled,\n prefixValue,\n prefixSecondaryValue,\n ellipsis = false,\n formControl,\n buttons,\n onCopyClick,\n showCopyButton,\n onChange,\n value,\n onBlur,\n helperText,\n showPasswordToggle = true,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n}) => {\n const { controlId, labelId, descriptionId, hintId, helperTextId } = useFormFieldIds({\n id,\n label,\n description,\n hint,\n helperText: true,\n });\n const [showPassword, setShowPassword] = useState(false);\n const [inputValue, setInputValue] = useState(defaultValue || '');\n const [copied, setCopied] = useState(false);\n\n useEffect(() => {\n if (copied) {\n const timer = setTimeout(() => {\n setCopied(false);\n }, 1000);\n return () => clearTimeout(timer);\n }\n }, [copied]);\n\n const handleChange =\n (reportToForm?: (value: unknown) => void) => (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n onChange?.(newValue);\n reportToForm?.(newValue);\n };\n\n const formValueRef = useRef<unknown>(undefined);\n const paintedValue = (formValue: unknown): string =>\n paintedFieldValue({\n component: 'Input',\n name,\n value,\n formValue,\n defaultValue,\n bound: !!formControl,\n uncontrolledValue: inputValue,\n });\n\n const handleCopyClick = onCopyClick\n ? () => {\n const copyValue = paintedValue(formValueRef.current);\n if (copyValue) {\n navigator.clipboard.writeText(copyValue);\n setCopied(true);\n onCopyClick();\n }\n }\n : undefined;\n\n const actualInputType = type === 'password' ? (showPassword ? 'text' : 'password') : type;\n\n const hasPrefix = icon || prefixValue || prefixSecondaryValue;\n\n // The skeleton stands in for the field, so it reads the same height the wrapper does.\n const heightClass = SIZE_HEIGHT[size];\n\n const buildWrapperClasses = (isError: boolean): string => {\n const variantStyles = getVariantClasses(variant, isError);\n\n return [\n 'relative',\n 'flex items-center',\n 'w-full',\n variantStyles.borderRadius || SIZE_RADIUS[size],\n disabled\n ? 'bg-[var(--malachite-card-dimmed-background)]'\n : 'bg-[var(--malachite-card-background)]',\n 'transition-colors duration-200 ease-in-out',\n variantStyles.shadow,\n ...(disabled ? [] : variantStyles.wrapper),\n SIZE_HEIGHT[size],\n ]\n .filter(Boolean)\n .join(' ');\n };\n\n return (\n <BaseFormComponent\n label={label}\n hint={hint}\n tooltip={tooltip}\n name={name}\n required={required}\n requiredIndicator={requiredIndicator}\n loading={loading}\n formControl={formControl}\n description={description}\n controlId={controlId}\n labelId={labelId}\n descriptionId={descriptionId}\n hintId={hintId}\n loadingComponent={\n <LoadingInput\n heightClass={heightClass}\n helperText={!!helperText}\n helperTextMarginTop\n />\n }\n >\n {({ error: fieldError, message, onFieldChange, onFieldBlur, value: formValue }) => {\n formValueRef.current = formValue;\n const displayValue = paintedValue(formValue);\n const shouldShowCopyButton =\n showCopyButton ?? !!(handleCopyClick && disabled && displayValue);\n const isError = error ?? fieldError;\n // `error={false}` opts out of the resolver entirely, message included: a\n // screen that has dealt with the rejection its own way would otherwise keep\n // reporting it in destructive text and through `aria-describedby`.\n // The message is its own line rather than a replacement for the helper text:\n // a field that explains where to find its value still has to say why what was\n // typed was rejected, and dropping one for the other left the field marked red\n // with nothing anywhere saying what was wrong.\n const errorMessage = error === false ? undefined : message;\n // The icon is the only signal a consumer-forced `error` has; beside a message it\n // is duplication, and it crowds the suffix next to a reveal or copy control.\n const showErrorIcon = isError && !errorMessage;\n const hasSuffix =\n showErrorIcon ||\n shouldShowCopyButton ||\n buttons?.length ||\n (type === 'password' && showPasswordToggle);\n const errorMessageId = `${helperTextId}-error`;\n const describedBy =\n [\n descriptionId,\n hintId,\n helperText ? helperTextId : undefined,\n errorMessage ? errorMessageId : undefined,\n ariaDescribedBy,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n return (\n <>\n <div className={buildWrapperClasses(isError)}>\n {hasPrefix && (\n <div className=\"flex items-center pl-3 pr-1 flex-shrink-0 pointer-events-none\">\n <CompositeIcon\n prefixValue={prefixValue}\n prefixSecondaryValue={prefixSecondaryValue}\n icon={icon}\n />\n </div>\n )}\n\n <input\n id={controlId}\n type={actualInputType}\n placeholder={placeholder}\n value={displayValue}\n onChange={handleChange(onFieldChange)}\n onBlur={() => {\n onBlur?.();\n onFieldBlur?.();\n }}\n disabled={disabled || readOnly}\n readOnly={readOnly}\n autoComplete=\"off\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={isError || undefined}\n aria-required={required || undefined}\n aria-describedby={describedBy}\n className={`flex-1 bg-transparent border-none outline-none text-[var(--malachite-text-primary)] placeholder:text-[var(--malachite-text-placeholder)] disabled:text-[var(--malachite-text-primary)] disabled:cursor-not-allowed ${SIZE_TEXT[size]} ${SIZE_PADDING[size]} ${ellipsis ? 'min-w-0 truncate' : ''}`}\n name={name}\n />\n\n {hasSuffix && (\n <div\n className={`flex items-center pl-1 flex-shrink-0 ${type === 'password' && showPasswordToggle ? 'pr-0' : 'pr-3'}`}\n >\n <Suffix\n error={showErrorIcon}\n defaultValue={displayValue}\n onCopyClick={handleCopyClick}\n showCopyButton={shouldShowCopyButton}\n copied={copied}\n type={type}\n showPassword={showPassword}\n showPasswordToggle={showPasswordToggle}\n onTogglePassword={() => setShowPassword(!showPassword)}\n />\n <InputButtons buttons={buttons} />\n </div>\n )}\n </div>\n {helperText && (\n <div\n id={helperTextId}\n className=\"mt-1 text-[length:var(--malachite-font-size-small,13px)] text-left pl-2 text-[var(--malachite-text-dimmed,rgb(161,161,161))]\"\n >\n {helperText}\n </div>\n )}\n <FieldMessage id={errorMessageId} message={errorMessage} spaced />\n </>\n );\n }}\n </BaseFormComponent>\n );\n};\n\nconst CompositeIcon: React.FC<{\n prefixValue?: string;\n prefixSecondaryValue?: string;\n icon?: React.ReactNode;\n}> = ({ prefixValue, prefixSecondaryValue, icon }) => {\n return (\n <div className=\"flex items-center gap-1\">\n {icon && (\n <span className=\"flex items-center justify-center text-[var(--malachite-text-dimmed)] w-4 h-4 flex-shrink-0\">\n {icon}\n </span>\n )}\n {prefixValue && (\n <span className=\"text-[length:var(--malachite-font-size-medium,14px)] leading-[1.4] text-[var(--malachite-text-dimmed)] whitespace-nowrap\">\n {prefixValue}\n </span>\n )}\n {prefixSecondaryValue && (\n <span className=\"text-[length:var(--malachite-font-size-medium,14px)] leading-[1.4] text-[var(--malachite-text-dimmed)] whitespace-nowrap\">\n {prefixSecondaryValue}\n </span>\n )}\n </div>\n );\n};\n\nconst Suffix: React.FC<{\n error?: boolean;\n defaultValue?: string;\n onCopyClick?: () => void;\n showCopyButton?: boolean;\n copied?: boolean;\n type?: InputType;\n showPassword?: boolean;\n showPasswordToggle?: boolean;\n onTogglePassword?: () => void;\n}> = ({\n error,\n defaultValue,\n onCopyClick,\n showCopyButton = false,\n copied = false,\n type,\n showPassword,\n showPasswordToggle = true,\n onTogglePassword,\n}) => {\n return (\n <div className=\"flex items-center gap-1\">\n {error && (\n // Decorative: the rejection is carried by the message beneath the field, so\n // announcing an unnamed icon here would only repeat it as \"info\".\n <div\n aria-hidden=\"true\"\n className=\"flex items-center justify-center w-5 h-5 flex-shrink-0\"\n >\n <InfoIcon\n size={16}\n className=\"text-[var(--malachite-destructive-foreground,rgb(196,62,62))]\"\n />\n </div>\n )}\n {showCopyButton && onCopyClick && defaultValue && (\n <button\n onClick={onCopyClick}\n type=\"button\"\n className=\"flex items-center justify-center w-5 h-5 hover:bg-[var(--malachite-primary-border)] rounded transition-colors flex-shrink-0 cursor-pointer\"\n >\n {copied ? (\n <CheckCircleFilled\n size={16}\n style={{ color: 'var(--malachite-success-foreground)' }}\n />\n ) : (\n <CopyIcon size={16} />\n )}\n </button>\n )}\n {type === 'password' && showPasswordToggle && (\n <Button variant=\"no-style\" onClick={onTogglePassword} type=\"button\" size=\"small\">\n {showPassword ? (\n <EyeClosedIcon\n size={16}\n style={{ color: 'var(--malachite-text-dimmed)' }}\n />\n ) : (\n <EyeIcon\n size={16}\n style={{ color: 'var(--malachite-text-dimmed)' }}\n />\n )}\n </Button>\n )}\n </div>\n );\n};\n\nconst InputButtons: React.FC<{\n buttons?: ButtonDefinition[];\n}> = ({ buttons }) => {\n if (!buttons?.length) {\n return null;\n }\n\n return (\n <>\n {buttons.map((button) => (\n <Button\n key={button.label}\n variant={button.variant || (button.danger ? 'destructive' : 'outline')}\n size={button.size || 'small'}\n disabled={button.disabled}\n icon={button.icon}\n tooltip={button.tooltip}\n onClick={button.onClick}\n className=\"ml-1\"\n >\n {button.label}\n </Button>\n ))}\n </>\n );\n};\n\nexport default Input;\n"],"names":["SIZE_HEIGHT","SIZE_TEXT","SIZE_PADDING","SIZE_RADIUS","getVariantClasses","variant","error","Input","label","hint","tooltip","placeholder","icon","name","required","requiredIndicator","description","loading","readOnly","type","size","defaultValue","disabled","prefixValue","prefixSecondaryValue","ellipsis","formControl","buttons","onCopyClick","showCopyButton","onChange","value","onBlur","helperText","showPasswordToggle","id","ariaLabel","ariaLabelledBy","ariaDescribedBy","controlId","labelId","descriptionId","hintId","helperTextId","useFormFieldIds","showPassword","setShowPassword","useState","inputValue","setInputValue","copied","setCopied","useEffect","timer","handleChange","reportToForm","e","newValue","formValueRef","useRef","paintedValue","formValue","paintedFieldValue","handleCopyClick","copyValue","actualInputType","hasPrefix","heightClass","buildWrapperClasses","isError","variantStyles","jsx","BaseFormComponent","LoadingInput","fieldError","message","onFieldChange","onFieldBlur","displayValue","shouldShowCopyButton","errorMessage","showErrorIcon","hasSuffix","errorMessageId","describedBy","jsxs","Fragment","CompositeIcon","Suffix","InputButtons","FieldMessage","onTogglePassword","InfoIcon","CheckCircleFilled","CopyIcon","Button","EyeClosedIcon","EyeIcon","button"],"mappings":"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"}