@stackone/malachite 2.22.0 → 2.23.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/dist/components/BaseFormComponent.js +76 -51
- package/dist/components/BaseFormComponent.js.map +1 -1
- package/dist/components/Dropdown.js +356 -354
- package/dist/components/Dropdown.js.map +1 -1
- package/dist/components/FieldBlock.js +13 -13
- package/dist/components/FieldBlock.js.map +1 -1
- package/dist/components/MultiSelect.js +119 -117
- package/dist/components/MultiSelect.js.map +1 -1
- package/dist/index.d.ts +15 -1
- package/package.json +1 -1
|
@@ -1,72 +1,97 @@
|
|
|
1
|
-
import { jsx as e, jsxs as
|
|
2
|
-
import { useId as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import { jsx as e, jsxs as s } from "react/jsx-runtime";
|
|
2
|
+
import { useId as z } from "react";
|
|
3
|
+
import F from "./CustomIcons/ArrowUpRightIcon.js";
|
|
4
|
+
import $ from "./CustomIcons/InfoFilledIcon.js";
|
|
5
|
+
import { FormItem as w } from "./FormItem.js";
|
|
6
|
+
import { Link as O } from "./Link.js";
|
|
7
|
+
import { safeHref as _ } from "./safeHref.js";
|
|
5
8
|
import x from "./Spacer.js";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
9
|
+
import k from "./Tooltip.js";
|
|
10
|
+
import H from "./Typography/MarkdownBlock.js";
|
|
8
11
|
import h from "./Typography/Text.js";
|
|
9
|
-
import { FOCUS_RING as
|
|
10
|
-
import { renderFormItemChildren as y, NO_FIELD_ERROR as
|
|
11
|
-
const T = 0.5,
|
|
12
|
+
import { FOCUS_RING as R } from "./focusRing.js";
|
|
13
|
+
import { renderFormItemChildren as y, NO_FIELD_ERROR as L } from "./formItemState.js";
|
|
14
|
+
const T = 0.5, q = ({
|
|
12
15
|
id: t,
|
|
13
16
|
label: r,
|
|
14
|
-
description:
|
|
15
|
-
hint:
|
|
16
|
-
helperText:
|
|
17
|
+
description: i,
|
|
18
|
+
hint: l,
|
|
19
|
+
helperText: a = !1
|
|
17
20
|
}) => {
|
|
18
|
-
const o = `mal-${
|
|
19
|
-
return { controlId: p, labelId:
|
|
20
|
-
},
|
|
21
|
+
const o = `mal-${z().replace(/[^a-zA-Z0-9_-]/g, "")}-`, p = t ?? `${o}control`, f = r ? `${o}label` : void 0, n = i ? `${o}description` : void 0, m = l ? `${o}hint` : void 0, c = a ? `${o}helper` : void 0, d = [n, m, c].filter(Boolean).join(" ") || void 0;
|
|
22
|
+
return { controlId: p, labelId: f, descriptionId: n, hintId: m, helperTextId: c, describedBy: d };
|
|
23
|
+
}, ee = ({
|
|
21
24
|
label: t,
|
|
22
25
|
hint: r,
|
|
26
|
+
rightSideContent: i,
|
|
23
27
|
tooltip: l,
|
|
24
|
-
name:
|
|
25
|
-
description:
|
|
26
|
-
required:
|
|
27
|
-
requiredIndicator:
|
|
28
|
-
loading:
|
|
29
|
-
formControl:
|
|
28
|
+
name: a,
|
|
29
|
+
description: o,
|
|
30
|
+
required: p = !1,
|
|
31
|
+
requiredIndicator: f = "optional-suffix",
|
|
32
|
+
loading: n = !1,
|
|
33
|
+
formControl: m,
|
|
30
34
|
loadingComponent: c,
|
|
31
|
-
children:
|
|
32
|
-
controlId:
|
|
33
|
-
labelId:
|
|
34
|
-
descriptionId:
|
|
35
|
-
hintId:
|
|
35
|
+
children: d,
|
|
36
|
+
controlId: u,
|
|
37
|
+
labelId: v,
|
|
38
|
+
descriptionId: I,
|
|
39
|
+
hintId: N,
|
|
36
40
|
fullWidth: b = !1
|
|
37
41
|
}) => {
|
|
38
|
-
const
|
|
39
|
-
return /* @__PURE__ */
|
|
40
|
-
(t
|
|
41
|
-
/* @__PURE__ */
|
|
42
|
+
const g = m ? /* @__PURE__ */ e(w, { control: m, name: a, children: d }) : y(d, L);
|
|
43
|
+
return /* @__PURE__ */ s(x, { direction: "vertical", size: 6, align: "stretch", fullWidth: b, children: [
|
|
44
|
+
(t || r || o || i) && /* @__PURE__ */ s(x, { direction: "vertical", size: 4, align: "stretch", children: [
|
|
45
|
+
/* @__PURE__ */ s("div", { className: "flex justify-between items-start", children: [
|
|
42
46
|
/* @__PURE__ */ e(
|
|
43
|
-
|
|
47
|
+
E,
|
|
44
48
|
{
|
|
45
49
|
text: t,
|
|
46
|
-
required:
|
|
47
|
-
requiredIndicator:
|
|
50
|
+
required: p,
|
|
51
|
+
requiredIndicator: f,
|
|
48
52
|
tooltip: l,
|
|
49
|
-
id:
|
|
50
|
-
htmlFor:
|
|
53
|
+
id: v,
|
|
54
|
+
htmlFor: n ? void 0 : u
|
|
51
55
|
}
|
|
52
56
|
),
|
|
53
|
-
r && /* @__PURE__ */
|
|
57
|
+
(r || i) && /* @__PURE__ */ s("div", { className: "flex items-start gap-2", children: [
|
|
58
|
+
r && /* @__PURE__ */ e(B, { text: r, id: N }),
|
|
59
|
+
i && /* @__PURE__ */ e(j, { ...i })
|
|
60
|
+
] })
|
|
54
61
|
] }),
|
|
55
|
-
|
|
62
|
+
o && /* @__PURE__ */ e(D, { text: o, id: I })
|
|
56
63
|
] }),
|
|
57
|
-
|
|
64
|
+
n ? c : g
|
|
58
65
|
] });
|
|
59
|
-
}, j = (
|
|
66
|
+
}, j = (t) => {
|
|
67
|
+
const r = _(t.href);
|
|
68
|
+
return r ? /* @__PURE__ */ s(
|
|
69
|
+
O,
|
|
70
|
+
{
|
|
71
|
+
href: r,
|
|
72
|
+
target: "_blank",
|
|
73
|
+
rel: "noopener noreferrer",
|
|
74
|
+
color: "dimmed",
|
|
75
|
+
size: "xsmall",
|
|
76
|
+
underline: !1,
|
|
77
|
+
className: "shrink-0 whitespace-nowrap inline-flex items-center gap-1 relative top-[3px]",
|
|
78
|
+
children: [
|
|
79
|
+
t.text,
|
|
80
|
+
/* @__PURE__ */ e(F, { size: 13 })
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
) : null;
|
|
84
|
+
}, B = ({ text: t, id: r }) => /* @__PURE__ */ e("span", { id: r, children: /* @__PURE__ */ e(h, { size: "xsmall", color: "dimmed", className: "pr-2 relative top-[3px]", children: t }) }), D = ({ text: t, id: r }) => /* @__PURE__ */ e("div", { className: "pl-2 text-left", id: r, children: /* @__PURE__ */ e(H, { color: "dimmed", size: "small", text: t ?? "", omitMargin: !0 }) }), E = ({
|
|
60
85
|
text: t,
|
|
61
86
|
required: r,
|
|
62
|
-
requiredIndicator:
|
|
63
|
-
tooltip:
|
|
64
|
-
id:
|
|
87
|
+
requiredIndicator: i,
|
|
88
|
+
tooltip: l,
|
|
89
|
+
id: a,
|
|
65
90
|
htmlFor: o
|
|
66
|
-
}) => t ? /* @__PURE__ */
|
|
67
|
-
/* @__PURE__ */ e("label", { id:
|
|
68
|
-
|
|
69
|
-
|
|
91
|
+
}) => t ? /* @__PURE__ */ s("div", { className: "flex items-center", children: [
|
|
92
|
+
/* @__PURE__ */ e("label", { id: a, htmlFor: o, children: /* @__PURE__ */ e(h, { size: "xsmall", color: "primary", fontWeight: "semi-bold", className: "pl-2", children: t }) }),
|
|
93
|
+
i === "optional-suffix" && !r && /* @__PURE__ */ e("span", { "aria-hidden": "true", children: /* @__PURE__ */ e(h, { size: "xsmall", color: "dimmed", className: "ml-1", children: "(Optional)" }) }),
|
|
94
|
+
i === "asterisk" && r && /* @__PURE__ */ e(
|
|
70
95
|
"span",
|
|
71
96
|
{
|
|
72
97
|
"aria-hidden": "true",
|
|
@@ -74,18 +99,18 @@ const T = 0.5, W = ({
|
|
|
74
99
|
children: "*"
|
|
75
100
|
}
|
|
76
101
|
),
|
|
77
|
-
|
|
102
|
+
l && /* @__PURE__ */ e(k, { text: l, placement: "right", delay: T, children: /* @__PURE__ */ e(
|
|
78
103
|
"button",
|
|
79
104
|
{
|
|
80
105
|
type: "button",
|
|
81
106
|
"aria-label": `More information about ${t}`,
|
|
82
|
-
className: `ml-1 -mt-[2px] inline-flex items-center text-[var(--malachite-text-dimmed)] cursor-help ${
|
|
83
|
-
children: /* @__PURE__ */ e(
|
|
107
|
+
className: `ml-1 -mt-[2px] inline-flex items-center text-[var(--malachite-text-dimmed)] cursor-help ${R}`,
|
|
108
|
+
children: /* @__PURE__ */ e($, { size: 14 })
|
|
84
109
|
}
|
|
85
110
|
) })
|
|
86
111
|
] }) : /* @__PURE__ */ e("div", {});
|
|
87
112
|
export {
|
|
88
|
-
|
|
89
|
-
|
|
113
|
+
ee as default,
|
|
114
|
+
q as useFormFieldIds
|
|
90
115
|
};
|
|
91
116
|
//# sourceMappingURL=BaseFormComponent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseFormComponent.js","sources":["../../src/components/BaseFormComponent.tsx"],"sourcesContent":["import React, { useId } from 'react';\nimport type { Control, FieldPath, FieldValues } from 'react-hook-form';\nimport InfoFilledIcon from './CustomIcons/InfoFilledIcon';\nimport FormItem from './FormItem';\nimport Spacer from './Spacer';\nimport Tooltip from './Tooltip';\nimport MarkdownBlock from './Typography/MarkdownBlock';\nimport Text from './Typography/Text';\nimport { FOCUS_RING } from './focusRing';\nimport { type FormItemChildren, NO_FIELD_ERROR, renderFormItemChildren } from './formItemState';\n\n/** Tooltip's own default of 1s reads as broken; 0.5 matches the rest of the library. */\nconst TOOLTIP_DELAY_SECONDS = 0.5;\n\n/** The ids that wire a form field's label / description / hint to its control. */\nexport interface FormFieldIds {\n controlId: string;\n labelId?: string;\n descriptionId?: string;\n hintId?: string;\n helperTextId?: string;\n describedBy?: string;\n}\n\ninterface FormFieldIdOptions {\n /** A caller-supplied id always wins, so consumers can label the control themselves. */\n id?: string;\n label?: string;\n description?: string;\n hint?: string;\n helperText?: boolean;\n}\n\n/**\n * Generates the stable ids a form field needs to be announced correctly. Shared by\n * `Input`, `TextArea`, `Dropdown` and `MultiSelect` so all four wire up identically.\n */\nexport const useFormFieldIds = ({\n id,\n label,\n description,\n hint,\n helperText = false,\n}: FormFieldIdOptions): FormFieldIds => {\n // useId() emits \":r0:\", and a colon is invalid in a CSS id selector, so a consumer's\n // querySelector(`#${id}`) throws. Stripping only the delimiters keeps ids unique.\n const generatedId = `mal-${useId().replace(/[^a-zA-Z0-9_-]/g, '')}-`;\n const controlId = id ?? `${generatedId}control`;\n const labelId = label ? `${generatedId}label` : undefined;\n const descriptionId = description ? `${generatedId}description` : undefined;\n const hintId = hint ? `${generatedId}hint` : undefined;\n const helperTextId = helperText ? `${generatedId}helper` : undefined;\n const describedBy =\n [descriptionId, hintId, helperTextId].filter(Boolean).join(' ') || undefined;\n\n return { controlId, labelId, descriptionId, hintId, helperTextId, describedBy };\n};\n\ninterface BaseFormComponentProps {\n label?: string;\n description?: string;\n hint?: string;\n tooltip?: string;\n required?: boolean;\n requiredIndicator?: RequiredIndicator;\n name: FieldPath<FieldValues>;\n defaultValue?: string;\n loading?: boolean;\n formControl?: Control<FieldValues, unknown>;\n loadingComponent: React.ReactNode;\n children?: FormItemChildren;\n /** Accessibility wiring, from `useFormFieldIds` — see `FormFieldIds`. */\n controlId?: string;\n labelId?: string;\n descriptionId?: string;\n hintId?: string;\n fullWidth?: boolean;\n}\n\nconst BaseFormComponent: React.FC<BaseFormComponentProps> = ({\n label,\n hint,\n tooltip,\n name,\n description,\n required = false,\n requiredIndicator = 'optional-suffix',\n loading = false,\n formControl,\n loadingComponent,\n children,\n controlId,\n labelId,\n descriptionId,\n hintId,\n fullWidth = false,\n}) => {\n const finalComponent = formControl ? (\n <FormItem control={formControl} name={name}>\n {children}\n </FormItem>\n ) : (\n renderFormItemChildren(children, NO_FIELD_ERROR)\n );\n\n const topHeader = () => (\n <Spacer direction=\"vertical\" size={4} align=\"stretch\">\n <div className=\"flex justify-between items-start\">\n <Label\n text={label}\n required={required}\n requiredIndicator={requiredIndicator}\n tooltip={tooltip}\n id={labelId}\n // No control is rendered while loading, so an htmlFor would be an orphan.\n htmlFor={loading ? undefined : controlId}\n />\n {hint && <Hint text={hint} id={hintId} />}\n </div>\n {description && <Description text={description} id={descriptionId} />}\n </Spacer>\n );\n\n const showHeader = label ?? hint ?? description;\n\n return (\n <Spacer direction=\"vertical\" size={6} align=\"stretch\" fullWidth={fullWidth}>\n {showHeader && topHeader()}\n {!loading ? finalComponent : loadingComponent}\n </Spacer>\n );\n};\n\nconst Hint = ({ text, id }: { text?: string; id?: string }) => {\n return (\n <span id={id}>\n <Text size=\"xsmall\" color=\"dimmed\" className=\"pr-2 relative top-[3px]\">\n {text}\n </Text>\n </span>\n );\n};\n\nconst Description = ({ text, id }: { text?: string; id?: string }) => {\n return (\n <div className=\"pl-2 text-left\" id={id}>\n <MarkdownBlock color=\"dimmed\" size=\"small\" text={text ?? ''} omitMargin={true} />\n </div>\n );\n};\n\nexport type RequiredIndicator = 'optional-suffix' | 'asterisk' | 'none';\n\nconst Label = ({\n text,\n required,\n requiredIndicator,\n tooltip,\n id,\n htmlFor,\n}: {\n text?: string;\n required: boolean;\n requiredIndicator: RequiredIndicator;\n tooltip?: string;\n id?: string;\n htmlFor?: string;\n}) => {\n return text ? (\n <div className=\"flex items-center\">\n <label id={id} htmlFor={htmlFor}>\n <Text size=\"xsmall\" color=\"primary\" fontWeight=\"semi-bold\" className=\"pl-2\">\n {text}\n </Text>\n </label>\n {/* Sibling of the <label>, not a child: Testing Library's getByLabelText matches\n on textContent, so a marker inside it breaks getByLabelText('<label>'). */}\n {requiredIndicator === 'optional-suffix' && !required && (\n <span aria-hidden=\"true\">\n <Text size=\"xsmall\" color=\"dimmed\" className=\"ml-1\">\n (Optional)\n </Text>\n </span>\n )}\n {requiredIndicator === 'asterisk' && required && (\n <span\n aria-hidden=\"true\"\n className=\"ml-1 text-[var(--malachite-destructive-foreground,rgb(196,62,62))]\"\n >\n *\n </span>\n )}\n {tooltip && (\n <Tooltip text={tooltip} placement=\"right\" delay={TOOLTIP_DELAY_SECONDS}>\n <button\n type=\"button\"\n aria-label={`More information about ${text}`}\n className={`ml-1 -mt-[2px] inline-flex items-center text-[var(--malachite-text-dimmed)] cursor-help ${FOCUS_RING}`}\n >\n <InfoFilledIcon size={14} />\n </button>\n </Tooltip>\n )}\n </div>\n ) : (\n <div />\n );\n};\n\nexport default BaseFormComponent;\n"],"names":["TOOLTIP_DELAY_SECONDS","useFormFieldIds","id","label","description","hint","helperText","generatedId","useId","controlId","labelId","descriptionId","hintId","helperTextId","describedBy","BaseFormComponent","tooltip","name","required","requiredIndicator","loading","formControl","loadingComponent","children","fullWidth","finalComponent","jsx","FormItem","renderFormItemChildren","NO_FIELD_ERROR","jsxs","Spacer","Label","Hint","Description","text","Text","MarkdownBlock","htmlFor","Tooltip","FOCUS_RING","InfoFilledIcon"],"mappings":";;;;;;;;;;AAYA,MAAMA,IAAwB,KAyBjBC,IAAkB,CAAC;AAAA,EAC5B,IAAAC;AAAA,EACA,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,MAAAC;AAAA,EACA,YAAAC,IAAa;AACjB,MAAwC;AAGpC,QAAMC,IAAc,OAAOC,EAAA,EAAQ,QAAQ,mBAAmB,EAAE,CAAC,KAC3DC,IAAYP,KAAM,GAAGK,CAAW,WAChCG,IAAUP,IAAQ,GAAGI,CAAW,UAAU,QAC1CI,IAAgBP,IAAc,GAAGG,CAAW,gBAAgB,QAC5DK,IAASP,IAAO,GAAGE,CAAW,SAAS,QACvCM,IAAeP,IAAa,GAAGC,CAAW,WAAW,QACrDO,IACF,CAACH,GAAeC,GAAQC,CAAY,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KAAK;AAEvE,SAAO,EAAE,WAAAJ,GAAW,SAAAC,GAAS,eAAAC,GAAe,QAAAC,GAAQ,cAAAC,GAAc,aAAAC,EAAA;AACtE,GAuBMC,IAAsD,CAAC;AAAA,EACzD,OAAAZ;AAAA,EACA,MAAAE;AAAA,EACA,SAAAW;AAAA,EACA,MAAAC;AAAA,EACA,aAAAb;AAAA,EACA,UAAAc,IAAW;AAAA,EACX,mBAAAC,IAAoB;AAAA,EACpB,SAAAC,IAAU;AAAA,EACV,aAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAd;AAAA,EACA,SAAAC;AAAA,EACA,eAAAC;AAAA,EACA,QAAAC;AAAA,EACA,WAAAY,IAAY;AAChB,MAAM;AACF,QAAMC,IAAiBJ,IACnB,gBAAAK,EAACC,GAAA,EAAS,SAASN,GAAa,MAAAJ,GAC3B,UAAAM,EAAA,CACL,IAEAK,EAAuBL,GAAUM,CAAc;AAuBnD,SACI,gBAAAC,EAACC,KAAO,WAAU,YAAW,MAAM,GAAG,OAAM,WAAU,WAAAP,GACjD,UAAA;AAAA,KAJUrB,KAASE,KAAQD,MAjBhC,gBAAA0B,EAACC,GAAA,EAAO,WAAU,YAAW,MAAM,GAAG,OAAM,WACxC,UAAA;AAAA,MAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,oCACX,UAAA;AAAA,QAAA,gBAAAJ;AAAA,UAACM;AAAA,UAAA;AAAA,YACG,MAAM7B;AAAA,YACN,UAAAe;AAAA,YACA,mBAAAC;AAAA,YACA,SAAAH;AAAA,YACA,IAAIN;AAAA,YAEJ,SAASU,IAAU,SAAYX;AAAA,UAAA;AAAA,QAAA;AAAA,QAElCJ,KAAQ,gBAAAqB,EAACO,GAAA,EAAK,MAAM5B,GAAM,IAAIO,EAAA,CAAQ;AAAA,MAAA,GAC3C;AAAA,MACCR,KAAe,gBAAAsB,EAACQ,GAAA,EAAY,MAAM9B,GAAa,IAAIO,EAAA,CAAe;AAAA,IAAA,GACvE;AAAA,IAQMS,IAA2BE,IAAjBG;AAAA,EAAiB,GACjC;AAER,GAEMQ,IAAO,CAAC,EAAE,MAAAE,GAAM,IAAAjC,QAEd,gBAAAwB,EAAC,QAAA,EAAK,IAAAxB,GACF,UAAA,gBAAAwB,EAACU,GAAA,EAAK,MAAK,UAAS,OAAM,UAAS,WAAU,2BACxC,UAAAD,EAAA,CACL,GACJ,GAIFD,IAAc,CAAC,EAAE,MAAAC,GAAM,IAAAjC,0BAEpB,OAAA,EAAI,WAAU,kBAAiB,IAAAA,GAC5B,4BAACmC,GAAA,EAAc,OAAM,UAAS,MAAK,SAAQ,MAAMF,KAAQ,IAAI,YAAY,IAAM,GACnF,GAMFH,IAAQ,CAAC;AAAA,EACX,MAAAG;AAAA,EACA,UAAAjB;AAAA,EACA,mBAAAC;AAAA,EACA,SAAAH;AAAA,EACA,IAAAd;AAAA,EACA,SAAAoC;AACJ,MAQWH,IACH,gBAAAL,EAAC,OAAA,EAAI,WAAU,qBACX,UAAA;AAAA,EAAA,gBAAAJ,EAAC,SAAA,EAAM,IAAAxB,GAAQ,SAAAoC,GACX,UAAA,gBAAAZ,EAACU,KAAK,MAAK,UAAS,OAAM,WAAU,YAAW,aAAY,WAAU,QAChE,aACL,GACJ;AAAA,EAGCjB,MAAsB,qBAAqB,CAACD,KACzC,gBAAAQ,EAAC,UAAK,eAAY,QACd,UAAA,gBAAAA,EAACU,GAAA,EAAK,MAAK,UAAS,OAAM,UAAS,WAAU,QAAO,wBAEpD,GACJ;AAAA,EAEHjB,MAAsB,cAAcD,KACjC,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,eAAY;AAAA,MACZ,WAAU;AAAA,MACb,UAAA;AAAA,IAAA;AAAA,EAAA;AAAA,EAIJV,uBACIuB,GAAA,EAAQ,MAAMvB,GAAS,WAAU,SAAQ,OAAOhB,GAC7C,UAAA,gBAAA0B;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,MAAK;AAAA,MACL,cAAY,0BAA0BS,CAAI;AAAA,MAC1C,WAAW,2FAA2FK,CAAU;AAAA,MAEhH,UAAA,gBAAAd,EAACe,GAAA,EAAe,MAAM,GAAA,CAAI;AAAA,IAAA;AAAA,EAAA,EAC9B,CACJ;AAAA,EAAA,CAER,sBAEC,OAAA,EAAI;"}
|
|
1
|
+
{"version":3,"file":"BaseFormComponent.js","sources":["../../src/components/BaseFormComponent.tsx"],"sourcesContent":["import React, { useId } from 'react';\nimport type { Control, FieldPath, FieldValues } from 'react-hook-form';\nimport ArrowUpRightIcon from './CustomIcons/ArrowUpRightIcon';\nimport InfoFilledIcon from './CustomIcons/InfoFilledIcon';\nimport FormItem from './FormItem';\nimport Link from './Link';\nimport { safeHref } from './safeHref';\nimport Spacer from './Spacer';\nimport Tooltip from './Tooltip';\nimport MarkdownBlock from './Typography/MarkdownBlock';\nimport Text from './Typography/Text';\nimport { FOCUS_RING } from './focusRing';\nimport { type FormItemChildren, NO_FIELD_ERROR, renderFormItemChildren } from './formItemState';\n\n/** Tooltip's own default of 1s reads as broken; 0.5 matches the rest of the library. */\nconst TOOLTIP_DELAY_SECONDS = 0.5;\n\n/** The ids that wire a form field's label / description / hint to its control. */\nexport interface FormFieldIds {\n controlId: string;\n labelId?: string;\n descriptionId?: string;\n hintId?: string;\n helperTextId?: string;\n describedBy?: string;\n}\n\ninterface FormFieldIdOptions {\n /** A caller-supplied id always wins, so consumers can label the control themselves. */\n id?: string;\n label?: string;\n description?: string;\n hint?: string;\n helperText?: boolean;\n}\n\n/**\n * Generates the stable ids a form field needs to be announced correctly. Shared by\n * `Input`, `TextArea`, `Dropdown` and `MultiSelect` so all four wire up identically.\n */\nexport const useFormFieldIds = ({\n id,\n label,\n description,\n hint,\n helperText = false,\n}: FormFieldIdOptions): FormFieldIds => {\n // useId() emits \":r0:\", and a colon is invalid in a CSS id selector, so a consumer's\n // querySelector(`#${id}`) throws. Stripping only the delimiters keeps ids unique.\n const generatedId = `mal-${useId().replace(/[^a-zA-Z0-9_-]/g, '')}-`;\n const controlId = id ?? `${generatedId}control`;\n const labelId = label ? `${generatedId}label` : undefined;\n const descriptionId = description ? `${generatedId}description` : undefined;\n const hintId = hint ? `${generatedId}hint` : undefined;\n const helperTextId = helperText ? `${generatedId}helper` : undefined;\n const describedBy =\n [descriptionId, hintId, helperTextId].filter(Boolean).join(' ') || undefined;\n\n return { controlId, labelId, descriptionId, hintId, helperTextId, describedBy };\n};\n\ninterface BaseFormComponentProps {\n label?: string;\n description?: string;\n hint?: string;\n rightSideContent?: RightSideContent;\n tooltip?: string;\n required?: boolean;\n requiredIndicator?: RequiredIndicator;\n name: FieldPath<FieldValues>;\n defaultValue?: string;\n loading?: boolean;\n formControl?: Control<FieldValues, unknown>;\n loadingComponent: React.ReactNode;\n children?: FormItemChildren;\n /** Accessibility wiring, from `useFormFieldIds` — see `FormFieldIds`. */\n controlId?: string;\n labelId?: string;\n descriptionId?: string;\n hintId?: string;\n fullWidth?: boolean;\n}\n\nconst BaseFormComponent: React.FC<BaseFormComponentProps> = ({\n label,\n hint,\n rightSideContent,\n tooltip,\n name,\n description,\n required = false,\n requiredIndicator = 'optional-suffix',\n loading = false,\n formControl,\n loadingComponent,\n children,\n controlId,\n labelId,\n descriptionId,\n hintId,\n fullWidth = false,\n}) => {\n const finalComponent = formControl ? (\n <FormItem control={formControl} name={name}>\n {children}\n </FormItem>\n ) : (\n renderFormItemChildren(children, NO_FIELD_ERROR)\n );\n\n const topHeader = () => (\n <Spacer direction=\"vertical\" size={4} align=\"stretch\">\n <div className=\"flex justify-between items-start\">\n <Label\n text={label}\n required={required}\n requiredIndicator={requiredIndicator}\n tooltip={tooltip}\n id={labelId}\n // No control is rendered while loading, so an htmlFor would be an orphan.\n htmlFor={loading ? undefined : controlId}\n />\n {(hint || rightSideContent) && (\n <div className=\"flex items-start gap-2\">\n {hint && <Hint text={hint} id={hintId} />}\n {rightSideContent && <RightSide {...rightSideContent} />}\n </div>\n )}\n </div>\n {description && <Description text={description} id={descriptionId} />}\n </Spacer>\n );\n\n const showHeader = label || hint || description || rightSideContent;\n\n return (\n <Spacer direction=\"vertical\" size={6} align=\"stretch\" fullWidth={fullWidth}>\n {showHeader && topHeader()}\n {!loading ? finalComponent : loadingComponent}\n </Spacer>\n );\n};\n\n/**\n * What sits at the far end of a field's label row. Data rather than a node, so nothing\n * arbitrary reaches the row; discriminated so a further kind is additive. Plain text is\n * already `hint`.\n */\nexport type RightSideContent = {\n type?: 'link';\n text: string;\n href: string;\n};\n\nconst RightSide = (content: RightSideContent) => {\n const safe = safeHref(content.href);\n\n if (!safe) {\n return null;\n }\n\n return (\n <Link\n href={safe}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n color=\"dimmed\"\n size=\"xsmall\"\n underline={false}\n className=\"shrink-0 whitespace-nowrap inline-flex items-center gap-1 relative top-[3px]\"\n >\n {content.text}\n <ArrowUpRightIcon size={13} />\n </Link>\n );\n};\n\nconst Hint = ({ text, id }: { text?: string; id?: string }) => {\n return (\n <span id={id}>\n <Text size=\"xsmall\" color=\"dimmed\" className=\"pr-2 relative top-[3px]\">\n {text}\n </Text>\n </span>\n );\n};\n\nconst Description = ({ text, id }: { text?: string; id?: string }) => {\n return (\n <div className=\"pl-2 text-left\" id={id}>\n <MarkdownBlock color=\"dimmed\" size=\"small\" text={text ?? ''} omitMargin={true} />\n </div>\n );\n};\n\nexport type RequiredIndicator = 'optional-suffix' | 'asterisk' | 'none';\n\nconst Label = ({\n text,\n required,\n requiredIndicator,\n tooltip,\n id,\n htmlFor,\n}: {\n text?: string;\n required: boolean;\n requiredIndicator: RequiredIndicator;\n tooltip?: string;\n id?: string;\n htmlFor?: string;\n}) => {\n return text ? (\n <div className=\"flex items-center\">\n <label id={id} htmlFor={htmlFor}>\n <Text size=\"xsmall\" color=\"primary\" fontWeight=\"semi-bold\" className=\"pl-2\">\n {text}\n </Text>\n </label>\n {/* Sibling of the <label>, not a child: Testing Library's getByLabelText matches\n on textContent, so a marker inside it breaks getByLabelText('<label>'). */}\n {requiredIndicator === 'optional-suffix' && !required && (\n <span aria-hidden=\"true\">\n <Text size=\"xsmall\" color=\"dimmed\" className=\"ml-1\">\n (Optional)\n </Text>\n </span>\n )}\n {requiredIndicator === 'asterisk' && required && (\n <span\n aria-hidden=\"true\"\n className=\"ml-1 text-[var(--malachite-destructive-foreground,rgb(196,62,62))]\"\n >\n *\n </span>\n )}\n {tooltip && (\n <Tooltip text={tooltip} placement=\"right\" delay={TOOLTIP_DELAY_SECONDS}>\n <button\n type=\"button\"\n aria-label={`More information about ${text}`}\n className={`ml-1 -mt-[2px] inline-flex items-center text-[var(--malachite-text-dimmed)] cursor-help ${FOCUS_RING}`}\n >\n <InfoFilledIcon size={14} />\n </button>\n </Tooltip>\n )}\n </div>\n ) : (\n <div />\n );\n};\n\nexport default BaseFormComponent;\n"],"names":["TOOLTIP_DELAY_SECONDS","useFormFieldIds","id","label","description","hint","helperText","generatedId","useId","controlId","labelId","descriptionId","hintId","helperTextId","describedBy","BaseFormComponent","rightSideContent","tooltip","name","required","requiredIndicator","loading","formControl","loadingComponent","children","fullWidth","finalComponent","jsx","FormItem","renderFormItemChildren","NO_FIELD_ERROR","jsxs","Spacer","Label","Hint","RightSide","Description","content","safe","safeHref","Link","ArrowUpRightIcon","text","Text","MarkdownBlock","htmlFor","Tooltip","FOCUS_RING","InfoFilledIcon"],"mappings":"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"}
|