@stackone/malachite 2.75.0 → 2.77.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.
@@ -1,74 +1,84 @@
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";
1
+ import { jsx as e, jsxs as a } from "react/jsx-runtime";
2
+ import { useId as k } from "react";
3
+ import w from "./CustomIcons/ArrowUpRightIcon.js";
4
+ import F from "./CustomIcons/InfoFilledIcon.js";
5
+ import { FormItem as $ } from "./FormItem.js";
6
+ import { Link as y } from "./Link.js";
8
7
  import x from "./Spacer.js";
9
- import k from "./Tooltip.js";
10
- import H from "./Typography/MarkdownBlock.js";
8
+ import O from "./Tooltip.js";
9
+ import _ from "./Typography/MarkdownBlock.js";
11
10
  import h from "./Typography/Text.js";
12
- import { FOCUS_RING as R } from "./focusRing.js";
13
- import { renderFormItemChildren as y, NO_FIELD_ERROR as L } from "./formItemState.js";
11
+ import { FOCUS_RING as u } from "./focusRing.js";
12
+ import { renderFormItemChildren as H, NO_FIELD_ERROR as R } from "./formItemState.js";
13
+ import { safeHref as L } from "./safeHref.js";
14
14
  const T = 0.5, q = ({
15
- id: t,
16
- label: r,
17
- description: i,
15
+ id: r,
16
+ label: t,
17
+ description: o,
18
18
  hint: l,
19
- helperText: a = !1
19
+ helperText: s = !1
20
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;
21
+ const i = `mal-${k().replace(/[^a-zA-Z0-9_-]/g, "")}-`, p = r ?? `${i}control`, f = t ? `${i}label` : void 0, n = o ? `${i}description` : void 0, m = l ? `${i}hint` : void 0, c = s ? `${i}helper` : void 0, d = [n, m, c].filter(Boolean).join(" ") || void 0;
22
22
  return { controlId: p, labelId: f, descriptionId: n, hintId: m, helperTextId: c, describedBy: d };
23
23
  }, ee = ({
24
- label: t,
25
- hint: r,
26
- rightSideContent: i,
24
+ label: r,
25
+ hint: t,
26
+ rightSideContent: o,
27
27
  tooltip: l,
28
- name: a,
29
- description: o,
28
+ name: s,
29
+ description: i,
30
30
  required: p = !1,
31
31
  requiredIndicator: f = "optional-suffix",
32
32
  loading: n = !1,
33
33
  formControl: m,
34
34
  loadingComponent: c,
35
35
  children: d,
36
- controlId: u,
37
- labelId: v,
36
+ controlId: v,
37
+ labelId: b,
38
38
  descriptionId: I,
39
39
  hintId: N,
40
- fullWidth: b = !1
40
+ fullWidth: g = !1
41
41
  }) => {
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
+ const z = m ? /* @__PURE__ */ e($, { control: m, name: s, children: d }) : H(d, R);
43
+ return /* @__PURE__ */ a(x, { direction: "vertical", size: 6, align: "stretch", fullWidth: g, children: [
44
+ (r || t || i || o) && /* @__PURE__ */ a(x, { direction: "vertical", size: 4, align: "stretch", children: [
45
+ /* @__PURE__ */ a("div", { className: "flex justify-between items-start", children: [
46
46
  /* @__PURE__ */ e(
47
47
  E,
48
48
  {
49
- text: t,
49
+ text: r,
50
50
  required: p,
51
51
  requiredIndicator: f,
52
52
  tooltip: l,
53
- id: v,
54
- htmlFor: n ? void 0 : u
53
+ id: b,
54
+ htmlFor: n ? void 0 : v
55
55
  }
56
56
  ),
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 })
57
+ (t || o) && /* @__PURE__ */ a("div", { className: "flex items-start gap-2", children: [
58
+ t && /* @__PURE__ */ e(B, { text: t, id: N }),
59
+ o && /* @__PURE__ */ e(j, { ...o })
60
60
  ] })
61
61
  ] }),
62
- o && /* @__PURE__ */ e(D, { text: o, id: I })
62
+ i && /* @__PURE__ */ e(D, { text: i, id: I })
63
63
  ] }),
64
- n ? c : g
64
+ n ? c : z
65
65
  ] });
66
- }, j = (t) => {
67
- const r = _(t.href);
68
- return r ? /* @__PURE__ */ s(
69
- O,
66
+ }, j = (r) => {
67
+ if (r.type === "button")
68
+ return /* @__PURE__ */ e(
69
+ "button",
70
+ {
71
+ type: "button",
72
+ onClick: r.onClick,
73
+ className: `relative top-[3px] shrink-0 cursor-pointer whitespace-nowrap border-0 bg-transparent p-0 text-[length:var(--malachite-font-size-xsmall)] font-medium text-[var(--malachite-accent-foreground)] hover:underline ${u}`,
74
+ children: r.text
75
+ }
76
+ );
77
+ const t = L(r.href);
78
+ return t ? /* @__PURE__ */ a(
79
+ y,
70
80
  {
71
- href: r,
81
+ href: t,
72
82
  target: "_blank",
73
83
  rel: "noopener noreferrer",
74
84
  color: "dimmed",
@@ -76,22 +86,22 @@ const T = 0.5, q = ({
76
86
  underline: !1,
77
87
  className: "shrink-0 whitespace-nowrap inline-flex items-center gap-1 relative top-[3px]",
78
88
  children: [
79
- t.text,
80
- /* @__PURE__ */ e(F, { size: 13 })
89
+ r.text,
90
+ /* @__PURE__ */ e(w, { size: 13 })
81
91
  ]
82
92
  }
83
93
  ) : 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 = ({
85
- text: t,
86
- required: r,
87
- requiredIndicator: i,
94
+ }, B = ({ text: r, id: t }) => /* @__PURE__ */ e("span", { id: t, children: /* @__PURE__ */ e(h, { size: "xsmall", color: "dimmed", className: "pr-2 relative top-[3px]", children: r }) }), D = ({ text: r, id: t }) => /* @__PURE__ */ e("div", { className: "pl-2 text-left", id: t, children: /* @__PURE__ */ e(_, { color: "dimmed", size: "small", text: r ?? "", omitMargin: !0 }) }), E = ({
95
+ text: r,
96
+ required: t,
97
+ requiredIndicator: o,
88
98
  tooltip: l,
89
- id: a,
90
- htmlFor: o
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(
99
+ id: s,
100
+ htmlFor: i
101
+ }) => r ? /* @__PURE__ */ a("div", { className: "flex items-center", children: [
102
+ /* @__PURE__ */ e("label", { id: s, htmlFor: i, children: /* @__PURE__ */ e(h, { size: "xsmall", color: "primary", fontWeight: "semi-bold", className: "pl-2", children: r }) }),
103
+ o === "optional-suffix" && !t && /* @__PURE__ */ e("span", { "aria-hidden": "true", children: /* @__PURE__ */ e(h, { size: "xsmall", color: "dimmed", className: "ml-1", children: "(Optional)" }) }),
104
+ o === "asterisk" && t && /* @__PURE__ */ e(
95
105
  "span",
96
106
  {
97
107
  "aria-hidden": "true",
@@ -99,13 +109,13 @@ const T = 0.5, q = ({
99
109
  children: "*"
100
110
  }
101
111
  ),
102
- l && /* @__PURE__ */ e(k, { text: l, placement: "right", delay: T, children: /* @__PURE__ */ e(
112
+ l && /* @__PURE__ */ e(O, { text: l, placement: "right", delay: T, children: /* @__PURE__ */ e(
103
113
  "button",
104
114
  {
105
115
  type: "button",
106
- "aria-label": `More information about ${t}`,
107
- className: `ml-1 -mt-[2px] inline-flex items-center text-[var(--malachite-text-dimmed)] cursor-help ${R}`,
108
- children: /* @__PURE__ */ e($, { size: 14 })
116
+ "aria-label": `More information about ${r}`,
117
+ className: `ml-1 -mt-[2px] inline-flex items-center text-[var(--malachite-text-dimmed)] cursor-help ${u}`,
118
+ children: /* @__PURE__ */ e(F, { size: 14 })
109
119
  }
110
120
  ) })
111
121
  ] }) : /* @__PURE__ */ e("div", {});
@@ -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 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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"}
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 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';\nimport { safeHref } from './safeHref';\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 | {\n type?: 'link';\n text: string;\n href: string;\n }\n | {\n /** An action on the form itself, such as showing a panel of help beside it. */\n type: 'button';\n text: string;\n onClick: () => void;\n };\n\nconst RightSide = (content: RightSideContent) => {\n if (content.type === 'button') {\n return (\n <button\n type=\"button\"\n onClick={content.onClick}\n className={`relative top-[3px] shrink-0 cursor-pointer whitespace-nowrap border-0 bg-transparent p-0 text-[length:var(--malachite-font-size-xsmall)] font-medium text-[var(--malachite-accent-foreground)] hover:underline ${FOCUS_RING}`}\n >\n {content.text}\n </button>\n );\n }\n\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","FOCUS_RING","safe","safeHref","Link","ArrowUpRightIcon","text","Text","MarkdownBlock","htmlFor","Tooltip","InfoFilledIcon"],"mappings":"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"}
@@ -1,169 +1,186 @@
1
- import { jsx as r, jsxs as l, Fragment as j } from "react/jsx-runtime";
2
- import { useId as B, useState as h, useRef as n, useEffect as P, useCallback as V } from "react";
3
- import { createPortal as le } from "react-dom";
4
- import { ShadowRootWrapper as te } from "../ShadowRootWrapper.js";
5
- import ie from "./CalloutStrip.js";
6
- import ne from "./CustomIcons/DismissIcon.js";
7
- import { getDeepActiveElement as oe } from "./activeElement.js";
8
- import { GLASS_SURFACE_STYLE as se } from "./glassSurface.js";
9
- import { MODAL_TRAY_BACKGROUND as ce, MODAL_TRAY_CAPTION_COLOR as de } from "./modalTray.js";
10
- import { useOverlayBehaviour as me, OVERLAY_ICON_BUTTON_CLASSES as ue } from "./overlayBehaviour.js";
11
- import { OVERLAY_ELEVATED_ATTR as pe, overlayIdentity as F } from "./portalOverlay.js";
12
- const U = {
1
+ import { jsx as e, jsxs as l, Fragment as V } from "react/jsx-runtime";
2
+ import { useId as F, useState as g, useRef as i, useEffect as U, useCallback as W } from "react";
3
+ import { createPortal as ce } from "react-dom";
4
+ import { ShadowRootWrapper as de } from "../ShadowRootWrapper.js";
5
+ import me from "./CalloutStrip.js";
6
+ import ue from "./CustomIcons/DismissIcon.js";
7
+ import { getDeepActiveElement as pe } from "./activeElement.js";
8
+ import { GLASS_SURFACE_STYLE as fe } from "./glassSurface.js";
9
+ import { MODAL_TRAY_BACKGROUND as xe, MODAL_TRAY_CAPTION_COLOR as he } from "./modalTray.js";
10
+ import { useOverlayBehaviour as ve, OVERLAY_ICON_BUTTON_CLASSES as be } from "./overlayBehaviour.js";
11
+ import { OVERLAY_ELEVATED_ATTR as ge, overlayIdentity as G } from "./portalOverlay.js";
12
+ const q = {
13
13
  small: "420px",
14
14
  medium: "612px",
15
- large: "760px"
16
- }, v = 200, xe = "flex-[0_1_auto] h-[min(600px,calc(100dvh-160px))]", Ie = ({
15
+ large: "760px",
16
+ fullscreen: "100%"
17
+ }, N = 200, z = "flex-[0_1_auto] h-[min(600px,calc(100dvh-160px))]", Oe = ({
17
18
  open: c,
18
19
  onClose: d,
19
- title: u,
20
- subtitle: p,
21
- icon: b,
22
- headerExtra: g,
23
- titleAdornment: N,
24
- tray: e,
25
- headerDivider: w = !1,
26
- footer: R,
27
- size: _ = "medium",
28
- showCloseButton: W = !0,
29
- closeOnOverlayClick: z = !0,
30
- bodyPadding: A = !0,
31
- bodyHeight: G = "auto",
32
- callouts: x,
33
- renderLink: q,
34
- role: H = "dialog",
35
- "aria-label": K,
36
- "aria-labelledby": T,
37
- "aria-describedby": X,
20
+ title: p,
21
+ subtitle: f,
22
+ icon: w,
23
+ headerExtra: y,
24
+ titleAdornment: R,
25
+ tray: K,
26
+ headerDivider: _ = !1,
27
+ footer: A,
28
+ size: x = "medium",
29
+ surface: X = "card",
30
+ showCloseButton: Z = !0,
31
+ closeOnOverlayClick: H = !0,
32
+ bodyPadding: T = !0,
33
+ bodyHeight: I = "auto",
34
+ callouts: J,
35
+ renderLink: Q,
36
+ role: ee = "dialog",
37
+ "aria-label": ae,
38
+ "aria-labelledby": $,
39
+ "aria-describedby": re,
38
40
  busy: o = !1,
39
- children: I
41
+ children: h
40
42
  }) => {
41
- const k = B(), S = B(), m = (x == null ? void 0 : x.filter((a) => a.message.trim())) ?? [], [f, $] = h(!1), [Z, O] = h(!1), [J, E] = h(!1), C = n(null), s = n(null), t = n(null), L = n(o), D = n(d);
42
- P(() => {
43
- L.current = o, D.current = d;
43
+ var P;
44
+ const k = F(), S = F(), m = X === "none", a = m ? void 0 : K, u = ((P = m ? void 0 : J) == null ? void 0 : P.filter((r) => r.message.trim())) ?? [], [v, O] = g(!1), [le, C] = g(!1), [te, E] = g(!1), L = i(null), s = i(null), t = i(null), D = i(o), M = i(d);
45
+ U(() => {
46
+ D.current = o, M.current = d;
44
47
  }, [o, d]);
45
- const M = V(() => {
46
- L.current || D.current();
47
- }, []), y = n(null), {
48
- ref: Y,
49
- isTopmost: Q,
50
- zIndex: ee,
51
- elevated: re
52
- } = me({
48
+ const B = W(() => {
49
+ D.current || M.current();
50
+ }, []), Y = i(null), {
51
+ ref: j,
52
+ isTopmost: ne,
53
+ zIndex: ie,
54
+ elevated: oe
55
+ } = ve({
53
56
  open: c,
54
57
  onClose: d,
55
- hostRef: y
56
- }), ae = V(
57
- (a) => {
58
- C.current = a, Y(a);
58
+ hostRef: Y
59
+ }), se = W(
60
+ (r) => {
61
+ L.current = r, j(r);
59
62
  },
60
- [Y]
63
+ [j]
61
64
  );
62
- return P(() => {
63
- var a;
65
+ if (U(() => {
66
+ var r;
64
67
  if (c)
65
- O(!0), E(!1), t.current && (clearTimeout(t.current), t.current = null), s.current = requestAnimationFrame(() => {
66
- s.current = null, $(!0);
68
+ C(!0), E(!1), t.current && (clearTimeout(t.current), t.current = null), s.current = requestAnimationFrame(() => {
69
+ s.current = null, O(!0);
67
70
  });
68
71
  else {
69
- const i = oe();
70
- i && ((a = C.current) != null && a.contains(i)) && i.blur(), E(!0), $(!1), t.current = setTimeout(() => {
71
- t.current = null, O(!1);
72
- }, v);
72
+ const n = pe();
73
+ n && ((r = L.current) != null && r.contains(n)) && n.blur(), E(!0), O(!1), t.current = setTimeout(() => {
74
+ t.current = null, C(!1);
75
+ }, N);
73
76
  }
74
77
  return () => {
75
78
  s.current !== null && (cancelAnimationFrame(s.current), s.current = null), t.current && (clearTimeout(t.current), t.current = null);
76
79
  };
77
- }, [c]), Z ? le(
80
+ }, [c]), !le)
81
+ return null;
82
+ let b = "relative flex max-h-full w-full flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]";
83
+ return m ? b = "relative flex max-h-full w-full flex-col outline-none" : a && (b = "relative flex max-h-full w-full flex-col gap-[4px] rounded-[20px] p-[4px] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]"), ce(
78
84
  // Host carries the stacking context — ShadowRootWrapper's `isolation` would otherwise
79
85
  // flatten our z-index. Not promoted to the top layer, so host dialogs can cover us.
80
- /* @__PURE__ */ r(
81
- te,
86
+ /* @__PURE__ */ e(
87
+ de,
82
88
  {
83
- hostRef: y,
84
- hostStyle: { position: "relative", zIndex: ee },
85
- hostProps: re ? { ...F("modal"), [pe]: "" } : F("modal"),
89
+ hostRef: Y,
90
+ hostStyle: { position: "relative", zIndex: ie },
91
+ hostProps: oe ? { ...G("modal"), [ge]: "" } : G("modal"),
86
92
  children: /* @__PURE__ */ l(
87
93
  "div",
88
94
  {
89
95
  className: `fixed inset-0 z-[1000] flex items-center justify-center p-[16px] ${c ? "" : "pointer-events-none"}`,
90
96
  children: [
91
- /* @__PURE__ */ r(
97
+ /* @__PURE__ */ e(
92
98
  "div",
93
99
  {
94
100
  "aria-hidden": "true",
95
- onClick: z ? M : void 0,
96
- className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${f ? "opacity-100" : "opacity-0"}`
101
+ onClick: H ? B : void 0,
102
+ className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${v ? "opacity-100" : "opacity-0"}`
97
103
  }
98
104
  ),
99
105
  /* @__PURE__ */ l(
100
106
  "div",
101
107
  {
102
- ref: ae,
103
- role: H,
104
- "aria-hidden": J ? "true" : void 0,
105
- "aria-modal": Q ? "true" : void 0,
108
+ ref: se,
109
+ role: ee,
110
+ "aria-hidden": te ? "true" : void 0,
111
+ "aria-modal": ne ? "true" : void 0,
106
112
  "aria-describedby": [
107
- ...m.map((a, i) => `${S}-${i}`),
108
- X,
109
- e != null && e.caption ? k : null
113
+ ...u.map((r, n) => `${S}-${n}`),
114
+ re,
115
+ a != null && a.caption ? k : null
110
116
  ].filter(Boolean).join(" ") || void 0,
111
117
  "aria-busy": o || void 0,
112
118
  tabIndex: -1,
113
- "aria-label": T ? void 0 : K ?? (typeof u == "string" ? u : void 0),
114
- "aria-labelledby": T,
115
- className: e ? "relative flex max-h-full w-full flex-col gap-[4px] rounded-[20px] p-[4px] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]" : "relative flex max-h-full w-full flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]",
119
+ "aria-label": $ ? void 0 : ae ?? (typeof p == "string" ? p : void 0),
120
+ "aria-labelledby": $,
121
+ className: b,
116
122
  style: {
117
- maxWidth: e ? `calc(${U[_]} + 8px)` : U[_],
118
- ...e ? {
119
- backgroundColor: ce[e.tone ?? "neutral"]
123
+ maxWidth: a ? `calc(${q[x]} + 8px)` : q[x],
124
+ ...x === "fullscreen" ? { height: "100%" } : {},
125
+ ...a ? {
126
+ backgroundColor: xe[a.tone ?? "neutral"]
120
127
  } : {},
121
128
  // Inline: Tailwind scale/translate utilities silently break inside
122
129
  // shadow roots (see CLAUDE.md Shadow DOM caveats).
123
- transform: f ? "scale(1)" : "scale(0.96)",
124
- opacity: f ? 1 : 0,
125
- transition: `transform ${v}ms ease-out, opacity ${v}ms ease-out`
130
+ transform: v ? "scale(1)" : "scale(0.96)",
131
+ opacity: v ? 1 : 0,
132
+ transition: `transform ${N}ms ease-out, opacity ${N}ms ease-out`
126
133
  },
127
134
  children: [
128
- /* @__PURE__ */ l(
135
+ m ? (
136
+ // Still a scroll body: the page behind is locked, so content taller
137
+ // than the viewport has nowhere else to scroll.
138
+ /* @__PURE__ */ e(
139
+ "div",
140
+ {
141
+ className: `min-h-0 ${I === "tall" ? z : "flex-1"} overflow-y-auto`,
142
+ children: h
143
+ }
144
+ )
145
+ ) : /* @__PURE__ */ l(
129
146
  "div",
130
147
  {
131
- className: e ? "flex min-h-0 flex-col overflow-hidden rounded-[16px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] [box-shadow:var(--malachite-shadow-glow-lg,var(--malachite-shadow-xl))]" : "contents",
148
+ className: a ? "flex min-h-0 flex-1 flex-col overflow-hidden rounded-[16px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] [box-shadow:var(--malachite-shadow-glow-lg,var(--malachite-shadow-xl))]" : "contents",
132
149
  children: [
133
150
  /* @__PURE__ */ l(
134
151
  "div",
135
152
  {
136
- className: `flex gap-[20px] p-[20px] ${p ? "items-start" : "items-center"} ${w ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
153
+ className: `flex gap-[20px] p-[20px] ${f ? "items-start" : "items-center"} ${_ ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
137
154
  children: [
138
155
  /* @__PURE__ */ l("div", { className: "flex h-[18px] min-w-0 flex-1 items-center gap-[12px]", children: [
139
156
  /* @__PURE__ */ l("div", { className: "flex min-w-0 items-center gap-[8px]", children: [
140
- b ? /* @__PURE__ */ r("span", { className: "flex shrink-0 items-center", children: b }) : null,
157
+ w ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: w }) : null,
141
158
  /* @__PURE__ */ l("div", { className: "flex min-w-0 flex-col gap-[4px]", children: [
142
- /* @__PURE__ */ r("span", { className: "truncate text-[14px] font-medium leading-[1.25] tracking-[-0.14px] text-[var(--malachite-text-primary)]", children: u }),
143
- p ? /* @__PURE__ */ r("span", { className: "text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]", children: p }) : null
159
+ /* @__PURE__ */ e("span", { className: "truncate text-[14px] font-medium leading-[1.25] tracking-[-0.14px] text-[var(--malachite-text-primary)]", children: p }),
160
+ f ? /* @__PURE__ */ e("span", { className: "text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]", children: f }) : null
144
161
  ] })
145
162
  ] }),
146
- N ? /* @__PURE__ */ l(j, { children: [
147
- /* @__PURE__ */ r(
163
+ R ? /* @__PURE__ */ l(V, { children: [
164
+ /* @__PURE__ */ e(
148
165
  "span",
149
166
  {
150
167
  "aria-hidden": "true",
151
168
  className: "h-[12px] w-px shrink-0 bg-[var(--malachite-card-border)]"
152
169
  }
153
170
  ),
154
- /* @__PURE__ */ r("span", { className: "flex min-w-0 items-center overflow-hidden", children: N })
171
+ /* @__PURE__ */ e("span", { className: "flex min-w-0 items-center overflow-hidden", children: R })
155
172
  ] }) : null
156
173
  ] }),
157
- g ? /* @__PURE__ */ r("span", { className: "flex shrink-0 items-center", children: g }) : null,
158
- W ? /* @__PURE__ */ r(
174
+ y ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: y }) : null,
175
+ Z ? /* @__PURE__ */ e(
159
176
  "button",
160
177
  {
161
178
  type: "button",
162
179
  "aria-label": "Close",
163
- onClick: M,
180
+ onClick: B,
164
181
  disabled: o,
165
- className: ue,
166
- children: /* @__PURE__ */ r(ne, { size: 10 })
182
+ className: be,
183
+ children: /* @__PURE__ */ e(ue, { size: 10 })
167
184
  }
168
185
  ) : null
169
186
  ]
@@ -172,51 +189,51 @@ const U = {
172
189
  /* @__PURE__ */ l(
173
190
  "div",
174
191
  {
175
- className: `min-h-0 ${G === "tall" ? xe : "flex-1"} overflow-y-auto ${A && m.length === 0 ? "px-[20px]" : ""}`,
192
+ className: `min-h-0 ${I === "tall" ? z : "flex-1"} overflow-y-auto ${T && u.length === 0 ? "px-[20px]" : ""}`,
176
193
  children: [
177
- m.map((a, i) => /* @__PURE__ */ r(
178
- ie,
194
+ u.map((r, n) => /* @__PURE__ */ e(
195
+ me,
179
196
  {
180
- id: `${S}-${i}`,
181
- type: a.type,
182
- message: a.message,
183
- renderLink: q
197
+ id: `${S}-${n}`,
198
+ type: r.type,
199
+ message: r.message,
200
+ renderLink: Q
184
201
  },
185
- i
202
+ n
186
203
  )),
187
- A ? /* @__PURE__ */ r(
204
+ T ? /* @__PURE__ */ e(
188
205
  "div",
189
206
  {
190
- className: m.length > 0 ? "px-[20px] pt-[18px] pb-[20px]" : `pb-[20px] ${w ? "pt-[18px]" : ""}`,
191
- children: I
207
+ className: u.length > 0 ? "px-[20px] pt-[18px] pb-[20px]" : `pb-[20px] ${_ ? "pt-[18px]" : ""}`,
208
+ children: h
192
209
  }
193
- ) : I
210
+ ) : h
194
211
  ]
195
212
  }
196
213
  ),
197
- R ? /* @__PURE__ */ r(
214
+ A ? /* @__PURE__ */ e(
198
215
  "div",
199
216
  {
200
217
  className: "flex min-h-[56px] shrink-0 items-center border-0 border-t border-solid border-[var(--malachite-card-border)] px-[12px]",
201
- style: se,
202
- children: R
218
+ style: fe,
219
+ children: A
203
220
  }
204
221
  ) : null
205
222
  ]
206
223
  }
207
224
  ),
208
- e != null && e.caption ? /* @__PURE__ */ r(
225
+ a != null && a.caption ? /* @__PURE__ */ e(
209
226
  "div",
210
227
  {
211
228
  id: k,
212
229
  className: "flex h-[48px] shrink-0 items-center justify-center px-[16px] text-[13px] tracking-[0.13px]",
213
- style: { color: de[e.tone ?? "neutral"] },
230
+ style: { color: he[a.tone ?? "neutral"] },
214
231
  children: /* @__PURE__ */ l("span", { children: [
215
- e.caption.label ? /* @__PURE__ */ l(j, { children: [
216
- /* @__PURE__ */ r("span", { className: "font-medium", children: e.caption.label }),
232
+ a.caption.label ? /* @__PURE__ */ l(V, { children: [
233
+ /* @__PURE__ */ e("span", { className: "font-medium", children: a.caption.label }),
217
234
  " "
218
235
  ] }) : null,
219
- e.caption.message
236
+ a.caption.message
220
237
  ] })
221
238
  }
222
239
  ) : null
@@ -229,10 +246,10 @@ const U = {
229
246
  }
230
247
  ),
231
248
  document.body
232
- ) : null;
249
+ );
233
250
  };
234
251
  export {
235
- Ie as Modal,
236
- Ie as default
252
+ Oe as Modal,
253
+ Oe as default
237
254
  };
238
255
  //# sourceMappingURL=Modal.js.map