@stackone/malachite 2.32.0 → 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/dist/components/FieldMessage.js.map +1 -1
- package/dist/components/Input/Input.js +65 -58
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/SelectionBar.js +1 -1
- package/dist/components/SelectionBar.js.map +1 -1
- package/dist/components/SidePanel.js +60 -36
- package/dist/components/SidePanel.js.map +1 -1
- package/dist/components/TextArea/TextArea.js +1 -1
- package/dist/components/TextArea/TextArea.js.map +1 -1
- package/dist/components/Tooltip.js +57 -56
- package/dist/components/Tooltip.js.map +1 -1
- package/dist/components/Typography/CodeText.js +45 -22
- package/dist/components/Typography/CodeText.js.map +1 -1
- package/dist/components/Typography/EllipsisText.js +14 -12
- package/dist/components/Typography/EllipsisText.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/tailwind.css.js +1 -1
- package/package.json +1 -1
|
@@ -1,57 +1,58 @@
|
|
|
1
|
-
import { jsx as e, jsxs as
|
|
2
|
-
import { useState as
|
|
1
|
+
import { jsx as e, jsxs as a } from "react/jsx-runtime";
|
|
2
|
+
import { useState as g, useRef as s, useEffect as V } from "react";
|
|
3
3
|
import { createPortal as L } from "react-dom";
|
|
4
4
|
import { ShadowRootWrapper as M } from "../ShadowRootWrapper.js";
|
|
5
|
-
import
|
|
5
|
+
import W from "./CustomIcons/ArrowLeftIcon.js";
|
|
6
6
|
import j from "./CustomIcons/DismissIcon.js";
|
|
7
|
+
import w from "./Typography/EllipsisText.js";
|
|
7
8
|
import { useOverlayBehaviour as D, OVERLAY_ICON_BUTTON_CLASSES as I } from "./overlayBehaviour.js";
|
|
8
9
|
import { OVERLAY_ELEVATED_ATTR as F, overlayIdentity as R } from "./portalOverlay.js";
|
|
9
|
-
const S = 200, X = (
|
|
10
|
-
open:
|
|
10
|
+
const S = 200, X = (l) => typeof l == "number" ? `${l}px` : l, Z = ({
|
|
11
|
+
open: l,
|
|
11
12
|
onClose: n,
|
|
12
13
|
title: i,
|
|
13
14
|
subtitle: o,
|
|
14
15
|
titleExtra: c,
|
|
15
16
|
description: d,
|
|
16
|
-
headerDivider:
|
|
17
|
+
headerDivider: A = !1,
|
|
17
18
|
icon: m,
|
|
18
19
|
headerExtra: u,
|
|
19
20
|
footer: p,
|
|
20
21
|
onBack: f,
|
|
21
|
-
maxWidth:
|
|
22
|
-
"aria-label":
|
|
22
|
+
maxWidth: k = 1080,
|
|
23
|
+
"aria-label": z,
|
|
23
24
|
"aria-labelledby": x,
|
|
24
25
|
bodyPadding: h = !0,
|
|
25
|
-
stacking:
|
|
26
|
+
stacking: E = "default",
|
|
26
27
|
children: b
|
|
27
28
|
}) => {
|
|
28
|
-
const [v,
|
|
29
|
+
const [v, N] = g(!1), [O, y] = g(!1), t = s(null), r = s(null), T = s(null), {
|
|
29
30
|
ref: _,
|
|
30
31
|
isTopmost: $,
|
|
31
32
|
zIndex: C,
|
|
32
|
-
elevated:
|
|
33
|
+
elevated: P
|
|
33
34
|
} = D({
|
|
34
|
-
open:
|
|
35
|
+
open: l,
|
|
35
36
|
onClose: n,
|
|
36
|
-
elevated:
|
|
37
|
-
hostRef:
|
|
37
|
+
elevated: E === "above-app-overlays",
|
|
38
|
+
hostRef: T
|
|
38
39
|
});
|
|
39
|
-
return V(() => (
|
|
40
|
-
t.current = null,
|
|
41
|
-
})) : (
|
|
42
|
-
r.current = null,
|
|
40
|
+
return V(() => (l ? (y(!0), r.current && (clearTimeout(r.current), r.current = null), t.current = requestAnimationFrame(() => {
|
|
41
|
+
t.current = null, N(!0);
|
|
42
|
+
})) : (N(!1), r.current = setTimeout(() => {
|
|
43
|
+
r.current = null, y(!1);
|
|
43
44
|
}, S)), () => {
|
|
44
45
|
t.current !== null && (cancelAnimationFrame(t.current), t.current = null), r.current && (clearTimeout(r.current), r.current = null);
|
|
45
|
-
}), [
|
|
46
|
+
}), [l]), O ? L(
|
|
46
47
|
// Host carries the stacking context — ShadowRootWrapper's `isolation` would
|
|
47
48
|
// otherwise flatten our z-index and let sticky page elements paint over us.
|
|
48
49
|
/* @__PURE__ */ e(
|
|
49
50
|
M,
|
|
50
51
|
{
|
|
51
|
-
hostRef:
|
|
52
|
+
hostRef: T,
|
|
52
53
|
hostStyle: { position: "relative", zIndex: C },
|
|
53
|
-
hostProps:
|
|
54
|
-
children: /* @__PURE__ */
|
|
54
|
+
hostProps: P ? { ...R("sidepanel"), [F]: "" } : R("sidepanel"),
|
|
55
|
+
children: /* @__PURE__ */ a("div", { className: "fixed inset-0 z-[1000]", children: [
|
|
55
56
|
/* @__PURE__ */ e(
|
|
56
57
|
"div",
|
|
57
58
|
{
|
|
@@ -60,30 +61,30 @@ const S = 200, X = (a) => typeof a == "number" ? `${a}px` : a, K = ({
|
|
|
60
61
|
className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${v ? "opacity-100" : "opacity-0"}`
|
|
61
62
|
}
|
|
62
63
|
),
|
|
63
|
-
/* @__PURE__ */
|
|
64
|
+
/* @__PURE__ */ a(
|
|
64
65
|
"div",
|
|
65
66
|
{
|
|
66
67
|
ref: _,
|
|
67
68
|
role: "dialog",
|
|
68
69
|
"aria-modal": $ ? "true" : void 0,
|
|
69
70
|
tabIndex: -1,
|
|
70
|
-
"aria-label": x ? void 0 :
|
|
71
|
+
"aria-label": x ? void 0 : z ?? (typeof i == "string" ? i : void 0),
|
|
71
72
|
"aria-labelledby": x,
|
|
72
73
|
className: "absolute top-[8px] right-[8px] bottom-[8px] flex 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-lg)]",
|
|
73
74
|
style: {
|
|
74
|
-
width: `min(calc(100% - 16px), ${X(
|
|
75
|
+
width: `min(calc(100% - 16px), ${X(k)})`,
|
|
75
76
|
// Inline: Tailwind translate utilities silently break inside
|
|
76
77
|
// shadow roots (see CLAUDE.md Shadow DOM caveats).
|
|
77
78
|
transform: v ? "translateX(0)" : "translateX(calc(100% + 16px))",
|
|
78
79
|
transition: `transform ${S}ms ease-in-out`
|
|
79
80
|
},
|
|
80
81
|
children: [
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
+
/* @__PURE__ */ a(
|
|
82
83
|
"div",
|
|
83
84
|
{
|
|
84
|
-
className: `flex flex-col gap-[20px] px-[20px] py-[18px] ${
|
|
85
|
+
className: `flex flex-col gap-[20px] px-[20px] py-[18px] ${A ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
|
|
85
86
|
children: [
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
+
/* @__PURE__ */ a("div", { className: "flex items-center gap-[12px]", children: [
|
|
87
88
|
f ? /* @__PURE__ */ e(
|
|
88
89
|
"button",
|
|
89
90
|
{
|
|
@@ -91,16 +92,39 @@ const S = 200, X = (a) => typeof a == "number" ? `${a}px` : a, K = ({
|
|
|
91
92
|
"aria-label": "Back",
|
|
92
93
|
onClick: f,
|
|
93
94
|
className: I,
|
|
94
|
-
children: /* @__PURE__ */ e(
|
|
95
|
+
children: /* @__PURE__ */ e(W, { size: 16 })
|
|
95
96
|
}
|
|
96
97
|
) : null,
|
|
97
98
|
m ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: m }) : null,
|
|
98
|
-
/* @__PURE__ */
|
|
99
|
-
/* @__PURE__ */
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
/* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-baseline gap-[12px]", children: [
|
|
100
|
+
/* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-baseline gap-[8px]", children: [
|
|
101
|
+
/* @__PURE__ */ a("div", { className: "flex min-w-0 items-baseline gap-[8px]", children: [
|
|
102
|
+
/* @__PURE__ */ e("span", { className: "flex min-w-0 max-w-full shrink-0", children: /* @__PURE__ */ e(
|
|
103
|
+
w,
|
|
104
|
+
{
|
|
105
|
+
tooltip: i,
|
|
106
|
+
tooltipWhenTruncated: !0,
|
|
107
|
+
tooltipPlacement: "bottom",
|
|
108
|
+
className: "min-w-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold",
|
|
109
|
+
children: i
|
|
110
|
+
}
|
|
111
|
+
) }),
|
|
112
|
+
o ? /* @__PURE__ */ e(
|
|
113
|
+
w,
|
|
114
|
+
{
|
|
115
|
+
tooltip: o,
|
|
116
|
+
tooltipWhenTruncated: !0,
|
|
117
|
+
tooltipPlacement: "bottom",
|
|
118
|
+
color: "secondary",
|
|
119
|
+
className: "min-w-0 text-[13px]",
|
|
120
|
+
children: o
|
|
121
|
+
}
|
|
122
|
+
) : null
|
|
123
|
+
] }),
|
|
124
|
+
c ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: c }) : null
|
|
125
|
+
] }),
|
|
126
|
+
u ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-baseline", children: u }) : null
|
|
102
127
|
] }),
|
|
103
|
-
u ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: u }) : null,
|
|
104
128
|
/* @__PURE__ */ e(
|
|
105
129
|
"button",
|
|
106
130
|
{
|
|
@@ -134,7 +158,7 @@ const S = 200, X = (a) => typeof a == "number" ? `${a}px` : a, K = ({
|
|
|
134
158
|
) : null;
|
|
135
159
|
};
|
|
136
160
|
export {
|
|
137
|
-
|
|
138
|
-
|
|
161
|
+
Z as SidePanel,
|
|
162
|
+
Z as default
|
|
139
163
|
};
|
|
140
164
|
//# sourceMappingURL=SidePanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanel.js","sources":["../../src/components/SidePanel.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport { OVERLAY_ICON_BUTTON_CLASSES, useOverlayBehaviour } from './overlayBehaviour';\nimport { OVERLAY_ELEVATED_ATTR, overlayIdentity } from './portalOverlay';\n\nexport interface SidePanelProps {\n open: boolean;\n /** Dismiss handler — close button, ESC, or overlay click. */\n onClose: () => void;\n title: React.ReactNode;\n /** Secondary text, inline after the title. */\n subtitle?: React.ReactNode;\n /** Content at the end of the title row, after the subtitle (e.g. a status tag). */\n titleExtra?: React.ReactNode;\n /** Block paragraph below the title row, spanning the header width. */\n description?: React.ReactNode;\n /** Divider under the header. Default: false. */\n headerDivider?: boolean;\n /** Leading header slot, typically a logo or icon. */\n icon?: React.ReactNode;\n /** Content pinned right in the header, before the close button. */\n headerExtra?: React.ReactNode;\n footer?: React.ReactNode;\n /** Renders a back button before the header icon. */\n onBack?: () => void;\n /** Maximum panel width. Default: 1080. */\n maxWidth?: number | string;\n /** Accessible dialog name; required when `title` isn't a plain string. */\n 'aria-label'?: string;\n /** ID of a visible element naming the dialog (alternative to `aria-label`). */\n 'aria-labelledby'?: string;\n /** Whether the body gets default padding. Default: true. */\n bodyPadding?: boolean;\n /** `above-app-overlays` lifts the overlay stack clear of chrome pinned near max-int. */\n stacking?: 'default' | 'above-app-overlays';\n children: React.ReactNode;\n}\n\nconst TRANSITION_MS = 200;\n\nconst toCssSize = (value: number | string): string =>\n typeof value === 'number' ? `${value}px` : value;\n\n/**\n * A right-hand slide-in overlay panel (drawer) for inspecting or editing an entity\n * without leaving the page. Portals to `document.body`, locks background scroll and\n * traps keyboard focus while open (restoring both on close), dismisses on ESC\n * (topmost open overlay only), overlay click or the close button, and exposes header\n * (back/icon/title/subtitle/extra), scrollable body and optional footer slots.\n */\nconst SidePanel: React.FC<SidePanelProps> = ({\n open,\n onClose,\n title,\n subtitle,\n titleExtra,\n description,\n headerDivider = false,\n icon,\n headerExtra,\n footer,\n onBack,\n maxWidth = 1080,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n bodyPadding = true,\n stacking = 'default',\n children,\n}) => {\n const [isVisible, setIsVisible] = useState(false);\n const [isMounted, setIsMounted] = useState(false);\n const frameRef = useRef<number | null>(null);\n const unmountTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hostRef = useRef<HTMLDivElement | null>(null);\n const {\n ref: handlePanelRef,\n isTopmost,\n zIndex,\n elevated,\n } = useOverlayBehaviour({\n open,\n onClose,\n elevated: stacking === 'above-app-overlays',\n hostRef,\n });\n\n useEffect(() => {\n if (open) {\n setIsMounted(true);\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n frameRef.current = requestAnimationFrame(() => {\n frameRef.current = null;\n setIsVisible(true);\n });\n } else {\n setIsVisible(false);\n unmountTimerRef.current = setTimeout(() => {\n unmountTimerRef.current = null;\n setIsMounted(false);\n }, TRANSITION_MS);\n }\n return () => {\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n };\n }, [open]);\n\n if (!isMounted) {\n return null;\n }\n\n return createPortal(\n // Host carries the stacking context — ShadowRootWrapper's `isolation` would\n // otherwise flatten our z-index and let sticky page elements paint over us.\n <ShadowRootWrapper\n hostRef={hostRef}\n hostStyle={{ position: 'relative', zIndex }}\n hostProps={\n elevated\n ? { ...overlayIdentity('sidepanel'), [OVERLAY_ELEVATED_ATTR]: '' }\n : overlayIdentity('sidepanel')\n }\n >\n <div className=\"fixed inset-0 z-[1000]\">\n <div\n aria-hidden=\"true\"\n onClick={onClose}\n className={`absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${\n isVisible ? 'opacity-100' : 'opacity-0'\n }`}\n />\n <div\n ref={handlePanelRef}\n role=\"dialog\"\n // Only the topmost overlay may claim it, or a screen reader can still\n // browse the one underneath.\n aria-modal={isTopmost ? 'true' : undefined}\n tabIndex={-1}\n // Prefer aria-labelledby; only fall back to aria-label when it's absent.\n aria-label={\n ariaLabelledBy\n ? undefined\n : (ariaLabel ?? (typeof title === 'string' ? title : undefined))\n }\n aria-labelledby={ariaLabelledBy}\n className=\"absolute top-[8px] right-[8px] bottom-[8px] flex 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-lg)]\"\n style={{\n width: `min(calc(100% - 16px), ${toCssSize(maxWidth)})`,\n // Inline: Tailwind translate utilities silently break inside\n // shadow roots (see CLAUDE.md Shadow DOM caveats).\n transform: isVisible ? 'translateX(0)' : 'translateX(calc(100% + 16px))',\n transition: `transform ${TRANSITION_MS}ms ease-in-out`,\n }}\n >\n <div\n className={`flex flex-col gap-[20px] px-[20px] py-[18px] ${\n headerDivider\n ? 'border-0 border-b border-solid border-[var(--malachite-card-border)]'\n : ''\n }`}\n >\n <div className=\"flex items-center gap-[12px]\">\n {onBack ? (\n <button\n type=\"button\"\n aria-label=\"Back\"\n onClick={onBack}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <ArrowLeftIcon size={16} />\n </button>\n ) : null}\n {icon ? (\n <span className=\"flex shrink-0 items-center\">{icon}</span>\n ) : null}\n <div className=\"flex min-w-0 flex-1 items-center gap-[8px]\">\n <span className=\"shrink-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold text-[var(--malachite-text-primary)]\">\n {title}\n </span>\n {subtitle ? (\n <span className=\"min-w-0 truncate text-[13px] text-[var(--malachite-text-secondary)]\">\n {subtitle}\n </span>\n ) : null}\n {titleExtra ? (\n <span className=\"flex shrink-0 items-center\">{titleExtra}</span>\n ) : null}\n </div>\n {headerExtra ? (\n <span className=\"flex shrink-0 items-center\">{headerExtra}</span>\n ) : null}\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={onClose}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <DismissIcon size={10} />\n </button>\n </div>\n {description ? (\n <div className=\"text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]\">\n {description}\n </div>\n ) : null}\n </div>\n <div\n className={`min-h-0 flex-1 overflow-y-auto ${bodyPadding ? 'px-[28px]' : ''}`}\n >\n {bodyPadding ? <div className=\"py-[28px]\">{children}</div> : children}\n </div>\n {footer ? (\n <div className=\"border-0 border-t border-solid border-[var(--malachite-card-border)] px-[24px] py-[16px]\">\n {footer}\n </div>\n ) : null}\n </div>\n </div>\n </ShadowRootWrapper>,\n document.body,\n );\n};\n\nexport default SidePanel;\nexport { SidePanel };\n"],"names":["TRANSITION_MS","toCssSize","value","SidePanel","open","onClose","title","subtitle","titleExtra","description","headerDivider","icon","headerExtra","footer","onBack","maxWidth","ariaLabel","ariaLabelledBy","bodyPadding","stacking","children","isVisible","setIsVisible","useState","isMounted","setIsMounted","frameRef","useRef","unmountTimerRef","hostRef","handlePanelRef","isTopmost","zIndex","elevated","useOverlayBehaviour","useEffect","createPortal","jsx","ShadowRootWrapper","overlayIdentity","OVERLAY_ELEVATED_ATTR","jsxs","OVERLAY_ICON_BUTTON_CLASSES","ArrowLeftIcon","DismissIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SidePanel.js","sources":["../../src/components/SidePanel.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport EllipsisText from './Typography/EllipsisText';\nimport { OVERLAY_ICON_BUTTON_CLASSES, useOverlayBehaviour } from './overlayBehaviour';\nimport { OVERLAY_ELEVATED_ATTR, overlayIdentity } from './portalOverlay';\n\nexport interface SidePanelProps {\n open: boolean;\n /** Dismiss handler — close button, ESC, or overlay click. */\n onClose: () => void;\n title: React.ReactNode;\n /** Secondary text, inline after the title. */\n subtitle?: React.ReactNode;\n /** Content at the end of the title row, after the subtitle (e.g. a status tag). */\n titleExtra?: React.ReactNode;\n /** Block paragraph below the title row, spanning the header width. */\n description?: React.ReactNode;\n /** Divider under the header. Default: false. */\n headerDivider?: boolean;\n /** Leading header slot, typically a logo or icon. */\n icon?: React.ReactNode;\n /** Content pinned right in the header, before the close button. */\n headerExtra?: React.ReactNode;\n footer?: React.ReactNode;\n /** Renders a back button before the header icon. */\n onBack?: () => void;\n /** Maximum panel width. Default: 1080. */\n maxWidth?: number | string;\n /** Accessible dialog name; required when `title` isn't a plain string. */\n 'aria-label'?: string;\n /** ID of a visible element naming the dialog (alternative to `aria-label`). */\n 'aria-labelledby'?: string;\n /** Whether the body gets default padding. Default: true. */\n bodyPadding?: boolean;\n /** `above-app-overlays` lifts the overlay stack clear of chrome pinned near max-int. */\n stacking?: 'default' | 'above-app-overlays';\n children: React.ReactNode;\n}\n\nconst TRANSITION_MS = 200;\n\nconst toCssSize = (value: number | string): string =>\n typeof value === 'number' ? `${value}px` : value;\n\n/**\n * A right-hand slide-in overlay panel (drawer) for inspecting or editing an entity\n * without leaving the page. Portals to `document.body`, locks background scroll and\n * traps keyboard focus while open (restoring both on close), dismisses on ESC\n * (topmost open overlay only), overlay click or the close button, and exposes header\n * (back/icon/title/subtitle/extra), scrollable body and optional footer slots.\n */\nconst SidePanel: React.FC<SidePanelProps> = ({\n open,\n onClose,\n title,\n subtitle,\n titleExtra,\n description,\n headerDivider = false,\n icon,\n headerExtra,\n footer,\n onBack,\n maxWidth = 1080,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n bodyPadding = true,\n stacking = 'default',\n children,\n}) => {\n const [isVisible, setIsVisible] = useState(false);\n const [isMounted, setIsMounted] = useState(false);\n const frameRef = useRef<number | null>(null);\n const unmountTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hostRef = useRef<HTMLDivElement | null>(null);\n const {\n ref: handlePanelRef,\n isTopmost,\n zIndex,\n elevated,\n } = useOverlayBehaviour({\n open,\n onClose,\n elevated: stacking === 'above-app-overlays',\n hostRef,\n });\n\n useEffect(() => {\n if (open) {\n setIsMounted(true);\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n frameRef.current = requestAnimationFrame(() => {\n frameRef.current = null;\n setIsVisible(true);\n });\n } else {\n setIsVisible(false);\n unmountTimerRef.current = setTimeout(() => {\n unmountTimerRef.current = null;\n setIsMounted(false);\n }, TRANSITION_MS);\n }\n return () => {\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n };\n }, [open]);\n\n if (!isMounted) {\n return null;\n }\n\n return createPortal(\n // Host carries the stacking context — ShadowRootWrapper's `isolation` would\n // otherwise flatten our z-index and let sticky page elements paint over us.\n <ShadowRootWrapper\n hostRef={hostRef}\n hostStyle={{ position: 'relative', zIndex }}\n hostProps={\n elevated\n ? { ...overlayIdentity('sidepanel'), [OVERLAY_ELEVATED_ATTR]: '' }\n : overlayIdentity('sidepanel')\n }\n >\n <div className=\"fixed inset-0 z-[1000]\">\n <div\n aria-hidden=\"true\"\n onClick={onClose}\n className={`absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${\n isVisible ? 'opacity-100' : 'opacity-0'\n }`}\n />\n <div\n ref={handlePanelRef}\n role=\"dialog\"\n // Only the topmost overlay may claim it, or a screen reader can still\n // browse the one underneath.\n aria-modal={isTopmost ? 'true' : undefined}\n tabIndex={-1}\n // Prefer aria-labelledby; only fall back to aria-label when it's absent.\n aria-label={\n ariaLabelledBy\n ? undefined\n : (ariaLabel ?? (typeof title === 'string' ? title : undefined))\n }\n aria-labelledby={ariaLabelledBy}\n className=\"absolute top-[8px] right-[8px] bottom-[8px] flex 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-lg)]\"\n style={{\n width: `min(calc(100% - 16px), ${toCssSize(maxWidth)})`,\n // Inline: Tailwind translate utilities silently break inside\n // shadow roots (see CLAUDE.md Shadow DOM caveats).\n transform: isVisible ? 'translateX(0)' : 'translateX(calc(100% + 16px))',\n transition: `transform ${TRANSITION_MS}ms ease-in-out`,\n }}\n >\n <div\n className={`flex flex-col gap-[20px] px-[20px] py-[18px] ${\n headerDivider\n ? 'border-0 border-b border-solid border-[var(--malachite-card-border)]'\n : ''\n }`}\n >\n <div className=\"flex items-center gap-[12px]\">\n {onBack ? (\n <button\n type=\"button\"\n aria-label=\"Back\"\n onClick={onBack}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <ArrowLeftIcon size={16} />\n </button>\n ) : null}\n {icon ? (\n <span className=\"flex shrink-0 items-center\">{icon}</span>\n ) : null}\n <div className=\"flex min-w-0 flex-1 items-baseline gap-[12px]\">\n <div className=\"flex min-w-0 flex-1 items-baseline gap-[8px]\">\n <div className=\"flex min-w-0 items-baseline gap-[8px]\">\n <span className=\"flex min-w-0 max-w-full shrink-0\">\n <EllipsisText\n tooltip={title}\n tooltipWhenTruncated\n tooltipPlacement=\"bottom\"\n className=\"min-w-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold\"\n >\n {title}\n </EllipsisText>\n </span>\n {subtitle ? (\n <EllipsisText\n tooltip={subtitle}\n tooltipWhenTruncated\n tooltipPlacement=\"bottom\"\n color=\"secondary\"\n className=\"min-w-0 text-[13px]\"\n >\n {subtitle}\n </EllipsisText>\n ) : null}\n </div>\n {titleExtra ? (\n <span className=\"flex shrink-0 items-center\">\n {titleExtra}\n </span>\n ) : null}\n </div>\n {headerExtra ? (\n <span className=\"flex shrink-0 items-baseline\">\n {headerExtra}\n </span>\n ) : null}\n </div>\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={onClose}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <DismissIcon size={10} />\n </button>\n </div>\n {description ? (\n <div className=\"text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]\">\n {description}\n </div>\n ) : null}\n </div>\n <div\n className={`min-h-0 flex-1 overflow-y-auto ${bodyPadding ? 'px-[28px]' : ''}`}\n >\n {bodyPadding ? <div className=\"py-[28px]\">{children}</div> : children}\n </div>\n {footer ? (\n <div className=\"border-0 border-t border-solid border-[var(--malachite-card-border)] px-[24px] py-[16px]\">\n {footer}\n </div>\n ) : null}\n </div>\n </div>\n </ShadowRootWrapper>,\n document.body,\n );\n};\n\nexport default SidePanel;\nexport { SidePanel };\n"],"names":["TRANSITION_MS","toCssSize","value","SidePanel","open","onClose","title","subtitle","titleExtra","description","headerDivider","icon","headerExtra","footer","onBack","maxWidth","ariaLabel","ariaLabelledBy","bodyPadding","stacking","children","isVisible","setIsVisible","useState","isMounted","setIsMounted","frameRef","useRef","unmountTimerRef","hostRef","handlePanelRef","isTopmost","zIndex","elevated","useOverlayBehaviour","useEffect","createPortal","jsx","ShadowRootWrapper","overlayIdentity","OVERLAY_ELEVATED_ATTR","jsxs","OVERLAY_ICON_BUTTON_CLASSES","ArrowLeftIcon","EllipsisText","DismissIcon"],"mappings":"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"}
|
|
@@ -185,7 +185,7 @@ const ze = (t) => {
|
|
|
185
185
|
"div",
|
|
186
186
|
{
|
|
187
187
|
id: k,
|
|
188
|
-
className: "text-[length:var(--malachite-font-size-small,13px)] text-left pl-2 text-[var(--malachite-text-dimmed,rgb(161,161,161))]",
|
|
188
|
+
className: "mt-1 text-[length:var(--malachite-font-size-small,13px)] text-left pl-2 text-[var(--malachite-text-dimmed,rgb(161,161,161))]",
|
|
189
189
|
children: N
|
|
190
190
|
}
|
|
191
191
|
) : null, de = (r) => /* @__PURE__ */ a(je, { id: J, message: r, spaced: !0 });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextArea.js","sources":["../../../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import React, { useCallback, useLayoutEffect, 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 CopyIcon from '../CustomIcons/CopyIcon';\nimport InfoIcon from '../CustomIcons/InfoIcon';\nimport FieldMessage from '../FieldMessage';\nimport { paintedFieldValue } from '../devWarning';\nimport type { ButtonDefinition, TextAreaSize } from './types';\n\n/**\n * `assistant` is the chrome for a field sitting in an AI context (e.g. `Chat.Composer`'s\n * policy-assistant tone): the field's own focus border recolours to the assistant violet\n * instead of the default accent — same indicator, different colour, not an extra one. Same\n * naming precedent as `PillButton`'s own `tone`.\n */\ntype TextAreaTone = 'default' | 'assistant';\n\ninterface TextAreaProps {\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 description?: string;\n size?: TextAreaSize;\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 onChange?: (value: string) => void;\n value?: string;\n onBlur?: () => void;\n /** Key handling the control cannot own, e.g. Enter-to-submit in a chat composer. */\n onKeyDown?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n /**\n * A control that belongs inside the field, pinned bottom-right — a chat composer's send.\n * The field reserves room for it, so text cannot run underneath.\n */\n inFieldAction?: React.ReactNode;\n /** See `TextAreaTone`. Defaults to `'default'`, so no existing field changes. */\n tone?: TextAreaTone;\n helperText?: string;\n rows?: number;\n /**\n * Grows the field from `rows` up to this many lines as content is typed, then scrolls\n * internally rather than growing further. Omitted keeps the field at a fixed `rows`\n * height, the pre-existing behaviour.\n */\n maxRows?: number;\n maxLength?: number;\n resize?: 'none' | 'vertical' | 'horizontal' | 'both';\n /**\n * When false, lines are not soft-wrapped — long content scrolls horizontally\n * instead of wrapping (native `wrap=\"off\"`). Useful for one-value-per-line\n * content like URLs. Defaults to true.\n */\n wrap?: boolean;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n}\n\nconst getSizeClasses = (size: TextAreaSize): string => {\n switch (size) {\n case 'small':\n return 'text-sm';\n case 'medium':\n return 'text-[length:var(--malachite-font-size-15,15px)] leading-[1.4]';\n case 'large':\n return 'text-base';\n default:\n return 'text-[length:var(--malachite-font-size-15,15px)] leading-[1.4]';\n }\n};\n\n/**\n * A rejection always wins the border colour, regardless of `tone`: a field the caller has\n * flagged invalid stays destructive-red on focus even inside an assistant surface.\n *\n * Each branch spells its two classes out in full rather than interpolating a shared colour\n * variable into them. Tailwind extracts candidates by scanning source text, so a class built\n * at runtime is one Tailwind never sees — and the CSS is simply absent, with no build error.\n * The assistant pair was surviving only because the same literal appears in a spec's\n * assertion, which the content glob also scans: rewording that assertion would have silently\n * dropped the violet focus border.\n */\nconst focusBorderClasses = (isError: boolean, tone: TextAreaTone): string => {\n if (isError) {\n return 'focus-within:border-[var(--malachite-destructive-border-hover)] hover:border-[var(--malachite-destructive-border-hover)]';\n }\n\n if (tone === 'assistant') {\n return 'focus-within:border-[var(--malachite-assistant-foreground)] hover:border-[var(--malachite-assistant-foreground)]';\n }\n\n return 'focus-within:border-[var(--malachite-control-border-hover)] hover:border-[var(--malachite-control-border-hover)]';\n};\n\n// Shared by the static min-height and the auto-grow ceiling, so a field's grown height\n// lines up with the same row metrics its resting height already used.\nconst rowHeightPx = (size: TextAreaSize, rows: number): number => {\n const baseHeight = {\n small: 20,\n medium: 22,\n large: 24,\n }[size];\n\n // Every size renders `py-[12px]`, so the vertical padding is 24 regardless of size.\n const padding = 24;\n\n return baseHeight * rows + padding;\n};\n\nconst getMinHeight = (size: TextAreaSize, rows: number): string => `${rowHeightPx(size, rows)}px`;\n\nconst TextArea: React.FC<TextAreaProps> = ({\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 size = 'medium',\n defaultValue,\n disabled,\n prefixValue,\n prefixSecondaryValue,\n // ellipsis = false,\n formControl,\n buttons,\n onCopyClick,\n onChange,\n onKeyDown,\n inFieldAction,\n tone = 'default',\n value,\n onBlur,\n helperText,\n rows = 4,\n maxRows,\n maxLength,\n resize = 'vertical',\n wrap = true,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n}) => {\n const { controlId, labelId, descriptionId, hintId, helperTextId } = useFormFieldIds({\n id,\n label,\n description,\n hint,\n helperText: true,\n });\n const [internalValue, setInternalValue] = useState(defaultValue || '');\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n // Reset-then-measure rather than growing incrementally: `scrollHeight` on a field already\n // taller than its content stays stuck at that height, so the reset is what lets a paste\n // followed by a delete shrink the field back down, not just grow it. Mutates the DOM\n // directly instead of round-tripping through React state, so typing a character never\n // re-renders this component just to change its own height.\n const resizeToFit = useCallback(() => {\n const el = textareaRef.current;\n if (!el || maxRows === undefined) {\n return;\n }\n\n const maxHeight = rowHeightPx(size, maxRows);\n el.style.height = 'auto';\n const nextHeight = Math.min(el.scrollHeight, maxHeight);\n el.style.height = `${nextHeight}px`;\n el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden';\n }, [maxRows, size]);\n\n // Catches every change `onChange` on the element itself would miss: the initial mount,\n // and a value the parent sets from outside (e.g. clearing the composer after send).\n // biome-ignore lint/correctness/useExhaustiveDependencies: `value` is not read in the body, but a controlled `value` changing from outside is exactly the case `onChange` cannot see, so the effect has to re-run on it anyway.\n useLayoutEffect(() => {\n resizeToFit();\n }, [resizeToFit, value]);\n\n const isControlled = value !== undefined;\n const paintedValue = (formValue: unknown): string =>\n paintedFieldValue({\n component: 'TextArea',\n name,\n value,\n formValue,\n defaultValue,\n bound: !!formControl,\n uncontrolledValue: internalValue,\n });\n\n const handleChange =\n (reportToForm?: (value: unknown) => void) =>\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value;\n if (!isControlled) {\n setInternalValue(newValue);\n }\n // The browser has already applied the keystroke to the element by the time this\n // fires, so `scrollHeight` already reflects it — no need to wait for a re-render.\n resizeToFit();\n onChange?.(newValue);\n reportToForm?.(newValue);\n };\n\n const hasPrefix = icon || prefixValue || prefixSecondaryValue;\n\n const errorMessageId = `${helperTextId}-error`;\n\n const renderTextArea = (\n isError: boolean,\n resolvedHelperText?: string,\n onFieldChange?: (value: unknown) => void,\n onFieldBlur?: () => void,\n errorMessage?: string,\n formValue?: unknown,\n ) => {\n const textAreaValue = paintedValue(formValue);\n // The icon is the only signal a consumer-forced `error` has; beside a message it is\n // duplication, and it crowds the suffix next to a reveal or copy control.\n const showErrorIcon = isError && !errorMessage;\n const hasSuffix =\n showErrorIcon || (onCopyClick && disabled && textAreaValue) || buttons?.length;\n const describedBy =\n [\n descriptionId,\n hintId,\n resolvedHelperText ? helperTextId : undefined,\n errorMessage ? errorMessageId : undefined,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n const wrapperClasses = [\n 'relative',\n 'flex',\n 'w-full',\n 'rounded-xl',\n 'border border-solid',\n disabled\n ? 'bg-[var(--malachite-card-dimmed-background)]'\n : 'bg-[var(--malachite-card-background)]',\n 'transition-colors duration-200 ease-in-out',\n isError ? 'shadow-error' : 'shadow-default',\n isError\n ? 'border-[var(--malachite-destructive-border)]'\n : 'border-[var(--malachite-card-border)]',\n // One border-hover colour, not two overlapping utilities for the same states: a\n // duplicate pair used to sit above this one, fixed at the default accent — since\n // it targeted the identical `focus-within`/`hover` selectors, a `tone` swap here\n // would otherwise leave a second, conflicting colour in the class list.\n //\n // No separate ring on top of it: the recoloured border IS this field's focus\n // indicator, the same as the default tone's. Adding a ring here drew a second,\n // concentric outline around the first on `assistant` — the field already has one,\n // it only needed to change colour.\n disabled ? '' : focusBorderClasses(isError, tone),\n ]\n .filter(Boolean)\n .join(' ');\n\n const textAreaClasses = [\n 'flex-1',\n 'bg-transparent',\n 'border-none',\n 'outline-none',\n 'text-[var(--malachite-text-primary)]',\n 'placeholder:text-[var(--malachite-text-placeholder)]',\n 'disabled:text-[var(--malachite-text-dimmed)]',\n 'disabled:cursor-not-allowed',\n getSizeClasses(size),\n // Emitted as one side each when an action sits in the field: `px` and `pr` are\n // the same specificity, so which wins would rest on Tailwind's output order.\n inFieldAction ? 'pl-[16px] pr-[52px]' : 'px-[16px]',\n 'py-[12px]',\n resize === 'none'\n ? 'resize-none'\n : resize === 'vertical'\n ? 'resize-y'\n : resize === 'horizontal'\n ? 'resize-x'\n : 'resize',\n wrap ? '' : 'whitespace-pre overflow-x-auto min-w-0',\n ]\n .filter(Boolean)\n .join(' ');\n\n const textAreaElement = (\n <textarea\n ref={textareaRef}\n id={controlId}\n placeholder={placeholder}\n value={textAreaValue}\n onChange={handleChange(onFieldChange)}\n onBlur={() => {\n onBlur?.();\n onFieldBlur?.();\n }}\n onKeyDown={onKeyDown}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={isError || undefined}\n aria-required={required || undefined}\n aria-describedby={describedBy}\n disabled={disabled || !!prefixValue || !!prefixSecondaryValue || readOnly}\n readOnly={readOnly}\n wrap={wrap ? undefined : 'off'}\n rows={rows}\n maxLength={maxLength}\n style={{ minHeight: getMinHeight(size, rows) }}\n className={textAreaClasses}\n name={name}\n />\n );\n\n return (\n <div className={wrapperClasses}>\n {hasPrefix && (\n <div className=\"flex pt-3 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 {textAreaElement}\n\n {inFieldAction && (\n <div className=\"absolute bottom-2 right-2 flex items-center\">\n {inFieldAction}\n </div>\n )}\n\n {hasSuffix && (\n <div className=\"flex pt-3 pl-1 pr-3 flex-shrink-0\">\n <Suffix\n error={showErrorIcon}\n disabled={disabled}\n defaultValue={textAreaValue}\n onCopyClick={onCopyClick}\n />\n <TextAreaButtons buttons={buttons} />\n </div>\n )}\n </div>\n );\n };\n\n const renderHelperText = () =>\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 ) : null;\n\n const renderErrorMessage = (errorMessage?: string) => (\n <FieldMessage id={errorMessageId} message={errorMessage} spaced />\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={<LoadingTextArea size={size} rows={rows} />}\n >\n {({ error: fieldError, message, onFieldChange, onFieldBlur, value: formValue }) => {\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\n // The message is its own line rather than a replacement for the helper text:\n // a field that explains what it wants still has to say why what was typed was\n // rejected, and dropping one for the other left the field marked red with\n // nothing anywhere saying what was wrong.\n const errorMessage = error === false ? undefined : message;\n\n return (\n <>\n {renderTextArea(\n isError,\n helperText,\n onFieldChange,\n onFieldBlur,\n errorMessage,\n formValue,\n )}\n {renderHelperText()}\n {renderErrorMessage(errorMessage)}\n </>\n );\n }}\n </BaseFormComponent>\n );\n};\n\nconst LoadingTextArea: React.FC<{ size?: TextAreaSize; rows?: number }> = ({\n size = 'medium',\n rows = 4,\n}) => {\n return (\n // Decorative height placeholder — kept out of the a11y tree so it is not announced\n // as an unlabelled box (same as Skeleton and LoadingInput).\n <div\n aria-busy=\"true\"\n aria-hidden=\"true\"\n className=\"w-full rounded-xl border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-border)] flex items-center justify-center shadow-[var(--malachite-shadow-default)]\"\n style={{ minHeight: getMinHeight(size, rows) }}\n />\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-start gap-1\">\n {icon && (\n <span className=\"flex items-center justify-center text-[var(--malachite-text-dimmed)] w-4 h-4 flex-shrink-0 mt-1\">\n {icon}\n </span>\n )}\n {prefixValue && (\n <span className=\"text-[length:var(--malachite-font-size-15,15px)] 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-15,15px)] 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 disabled?: boolean;\n defaultValue?: string;\n onCopyClick?: () => void;\n}> = ({ error, disabled, defaultValue, onCopyClick }) => {\n return (\n <div className=\"flex items-start gap-1\">\n {error && (\n // Decorative: the rejection is carried by the message beneath the field.\n <div\n aria-hidden=\"true\"\n className=\"flex items-center justify-center w-5 h-5 flex-shrink-0 mt-1\"\n >\n <InfoIcon\n size={16}\n className=\"text-[var(--malachite-destructive-foreground,rgb(196,62,62))]\"\n />\n </div>\n )}\n {onCopyClick && disabled && defaultValue && (\n <button\n onClick={() => {\n navigator.clipboard.writeText(defaultValue);\n onCopyClick();\n }}\n type=\"button\"\n aria-label=\"Copy to clipboard\"\n className=\"flex items-center justify-center w-5 h-5 hover:bg-[var(--malachite-primary-border)] rounded transition-colors flex-shrink-0 mt-1\"\n >\n <CopyIcon size={16} />\n </button>\n )}\n </div>\n );\n};\n\nconst TextAreaButtons: React.FC<{\n buttons?: ButtonDefinition[];\n}> = ({ buttons }) => {\n if (!buttons?.length) {\n return null;\n }\n\n return (\n <div className=\"flex flex-col gap-1 mt-1\">\n {buttons.map((button) => (\n <Button\n key={button.label}\n variant={button.danger ? 'destructive' : 'outline'}\n size=\"small\"\n disabled={button.disabled}\n icon={button.icon}\n tooltip={button.tooltip}\n onClick={button.onClick}\n >\n {button.label}\n </Button>\n ))}\n </div>\n );\n};\n\nexport default TextArea;\n"],"names":["getSizeClasses","size","focusBorderClasses","isError","tone","rowHeightPx","rows","getMinHeight","TextArea","label","hint","tooltip","placeholder","icon","name","required","requiredIndicator","error","description","loading","readOnly","defaultValue","disabled","prefixValue","prefixSecondaryValue","formControl","buttons","onCopyClick","onChange","onKeyDown","inFieldAction","value","onBlur","helperText","maxRows","maxLength","resize","wrap","id","ariaLabel","ariaLabelledBy","controlId","labelId","descriptionId","hintId","helperTextId","useFormFieldIds","internalValue","setInternalValue","useState","textareaRef","useRef","resizeToFit","useCallback","el","maxHeight","nextHeight","useLayoutEffect","isControlled","paintedValue","formValue","paintedFieldValue","handleChange","reportToForm","e","newValue","hasPrefix","errorMessageId","renderTextArea","resolvedHelperText","onFieldChange","onFieldBlur","errorMessage","textAreaValue","showErrorIcon","hasSuffix","describedBy","wrapperClasses","textAreaClasses","textAreaElement","jsx","jsxs","CompositeIcon","Suffix","TextAreaButtons","renderHelperText","renderErrorMessage","FieldMessage","BaseFormComponent","LoadingTextArea","fieldError","message","Fragment","InfoIcon","CopyIcon","button","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TextArea.js","sources":["../../../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import React, { useCallback, useLayoutEffect, 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 CopyIcon from '../CustomIcons/CopyIcon';\nimport InfoIcon from '../CustomIcons/InfoIcon';\nimport FieldMessage from '../FieldMessage';\nimport { paintedFieldValue } from '../devWarning';\nimport type { ButtonDefinition, TextAreaSize } from './types';\n\n/**\n * `assistant` is the chrome for a field sitting in an AI context (e.g. `Chat.Composer`'s\n * policy-assistant tone): the field's own focus border recolours to the assistant violet\n * instead of the default accent — same indicator, different colour, not an extra one. Same\n * naming precedent as `PillButton`'s own `tone`.\n */\ntype TextAreaTone = 'default' | 'assistant';\n\ninterface TextAreaProps {\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 description?: string;\n size?: TextAreaSize;\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 onChange?: (value: string) => void;\n value?: string;\n onBlur?: () => void;\n /** Key handling the control cannot own, e.g. Enter-to-submit in a chat composer. */\n onKeyDown?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n /**\n * A control that belongs inside the field, pinned bottom-right — a chat composer's send.\n * The field reserves room for it, so text cannot run underneath.\n */\n inFieldAction?: React.ReactNode;\n /** See `TextAreaTone`. Defaults to `'default'`, so no existing field changes. */\n tone?: TextAreaTone;\n helperText?: React.ReactNode;\n rows?: number;\n /**\n * Grows the field from `rows` up to this many lines as content is typed, then scrolls\n * internally rather than growing further. Omitted keeps the field at a fixed `rows`\n * height, the pre-existing behaviour.\n */\n maxRows?: number;\n maxLength?: number;\n resize?: 'none' | 'vertical' | 'horizontal' | 'both';\n /**\n * When false, lines are not soft-wrapped — long content scrolls horizontally\n * instead of wrapping (native `wrap=\"off\"`). Useful for one-value-per-line\n * content like URLs. Defaults to true.\n */\n wrap?: boolean;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n}\n\nconst getSizeClasses = (size: TextAreaSize): string => {\n switch (size) {\n case 'small':\n return 'text-sm';\n case 'medium':\n return 'text-[length:var(--malachite-font-size-15,15px)] leading-[1.4]';\n case 'large':\n return 'text-base';\n default:\n return 'text-[length:var(--malachite-font-size-15,15px)] leading-[1.4]';\n }\n};\n\n/**\n * A rejection always wins the border colour, regardless of `tone`: a field the caller has\n * flagged invalid stays destructive-red on focus even inside an assistant surface.\n *\n * Each branch spells its two classes out in full rather than interpolating a shared colour\n * variable into them. Tailwind extracts candidates by scanning source text, so a class built\n * at runtime is one Tailwind never sees — and the CSS is simply absent, with no build error.\n * The assistant pair was surviving only because the same literal appears in a spec's\n * assertion, which the content glob also scans: rewording that assertion would have silently\n * dropped the violet focus border.\n */\nconst focusBorderClasses = (isError: boolean, tone: TextAreaTone): string => {\n if (isError) {\n return 'focus-within:border-[var(--malachite-destructive-border-hover)] hover:border-[var(--malachite-destructive-border-hover)]';\n }\n\n if (tone === 'assistant') {\n return 'focus-within:border-[var(--malachite-assistant-foreground)] hover:border-[var(--malachite-assistant-foreground)]';\n }\n\n return 'focus-within:border-[var(--malachite-control-border-hover)] hover:border-[var(--malachite-control-border-hover)]';\n};\n\n// Shared by the static min-height and the auto-grow ceiling, so a field's grown height\n// lines up with the same row metrics its resting height already used.\nconst rowHeightPx = (size: TextAreaSize, rows: number): number => {\n const baseHeight = {\n small: 20,\n medium: 22,\n large: 24,\n }[size];\n\n // Every size renders `py-[12px]`, so the vertical padding is 24 regardless of size.\n const padding = 24;\n\n return baseHeight * rows + padding;\n};\n\nconst getMinHeight = (size: TextAreaSize, rows: number): string => `${rowHeightPx(size, rows)}px`;\n\nconst TextArea: React.FC<TextAreaProps> = ({\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 size = 'medium',\n defaultValue,\n disabled,\n prefixValue,\n prefixSecondaryValue,\n // ellipsis = false,\n formControl,\n buttons,\n onCopyClick,\n onChange,\n onKeyDown,\n inFieldAction,\n tone = 'default',\n value,\n onBlur,\n helperText,\n rows = 4,\n maxRows,\n maxLength,\n resize = 'vertical',\n wrap = true,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n}) => {\n const { controlId, labelId, descriptionId, hintId, helperTextId } = useFormFieldIds({\n id,\n label,\n description,\n hint,\n helperText: true,\n });\n const [internalValue, setInternalValue] = useState(defaultValue || '');\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n // Reset-then-measure rather than growing incrementally: `scrollHeight` on a field already\n // taller than its content stays stuck at that height, so the reset is what lets a paste\n // followed by a delete shrink the field back down, not just grow it. Mutates the DOM\n // directly instead of round-tripping through React state, so typing a character never\n // re-renders this component just to change its own height.\n const resizeToFit = useCallback(() => {\n const el = textareaRef.current;\n if (!el || maxRows === undefined) {\n return;\n }\n\n const maxHeight = rowHeightPx(size, maxRows);\n el.style.height = 'auto';\n const nextHeight = Math.min(el.scrollHeight, maxHeight);\n el.style.height = `${nextHeight}px`;\n el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden';\n }, [maxRows, size]);\n\n // Catches every change `onChange` on the element itself would miss: the initial mount,\n // and a value the parent sets from outside (e.g. clearing the composer after send).\n // biome-ignore lint/correctness/useExhaustiveDependencies: `value` is not read in the body, but a controlled `value` changing from outside is exactly the case `onChange` cannot see, so the effect has to re-run on it anyway.\n useLayoutEffect(() => {\n resizeToFit();\n }, [resizeToFit, value]);\n\n const isControlled = value !== undefined;\n const paintedValue = (formValue: unknown): string =>\n paintedFieldValue({\n component: 'TextArea',\n name,\n value,\n formValue,\n defaultValue,\n bound: !!formControl,\n uncontrolledValue: internalValue,\n });\n\n const handleChange =\n (reportToForm?: (value: unknown) => void) =>\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value;\n if (!isControlled) {\n setInternalValue(newValue);\n }\n // The browser has already applied the keystroke to the element by the time this\n // fires, so `scrollHeight` already reflects it — no need to wait for a re-render.\n resizeToFit();\n onChange?.(newValue);\n reportToForm?.(newValue);\n };\n\n const hasPrefix = icon || prefixValue || prefixSecondaryValue;\n\n const errorMessageId = `${helperTextId}-error`;\n\n const renderTextArea = (\n isError: boolean,\n resolvedHelperText?: React.ReactNode,\n onFieldChange?: (value: unknown) => void,\n onFieldBlur?: () => void,\n errorMessage?: string,\n formValue?: unknown,\n ) => {\n const textAreaValue = paintedValue(formValue);\n // The icon is the only signal a consumer-forced `error` has; beside a message it is\n // duplication, and it crowds the suffix next to a reveal or copy control.\n const showErrorIcon = isError && !errorMessage;\n const hasSuffix =\n showErrorIcon || (onCopyClick && disabled && textAreaValue) || buttons?.length;\n const describedBy =\n [\n descriptionId,\n hintId,\n resolvedHelperText ? helperTextId : undefined,\n errorMessage ? errorMessageId : undefined,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n const wrapperClasses = [\n 'relative',\n 'flex',\n 'w-full',\n 'rounded-xl',\n 'border border-solid',\n disabled\n ? 'bg-[var(--malachite-card-dimmed-background)]'\n : 'bg-[var(--malachite-card-background)]',\n 'transition-colors duration-200 ease-in-out',\n isError ? 'shadow-error' : 'shadow-default',\n isError\n ? 'border-[var(--malachite-destructive-border)]'\n : 'border-[var(--malachite-card-border)]',\n // One border-hover colour, not two overlapping utilities for the same states: a\n // duplicate pair used to sit above this one, fixed at the default accent — since\n // it targeted the identical `focus-within`/`hover` selectors, a `tone` swap here\n // would otherwise leave a second, conflicting colour in the class list.\n //\n // No separate ring on top of it: the recoloured border IS this field's focus\n // indicator, the same as the default tone's. Adding a ring here drew a second,\n // concentric outline around the first on `assistant` — the field already has one,\n // it only needed to change colour.\n disabled ? '' : focusBorderClasses(isError, tone),\n ]\n .filter(Boolean)\n .join(' ');\n\n const textAreaClasses = [\n 'flex-1',\n 'bg-transparent',\n 'border-none',\n 'outline-none',\n 'text-[var(--malachite-text-primary)]',\n 'placeholder:text-[var(--malachite-text-placeholder)]',\n 'disabled:text-[var(--malachite-text-dimmed)]',\n 'disabled:cursor-not-allowed',\n getSizeClasses(size),\n // Emitted as one side each when an action sits in the field: `px` and `pr` are\n // the same specificity, so which wins would rest on Tailwind's output order.\n inFieldAction ? 'pl-[16px] pr-[52px]' : 'px-[16px]',\n 'py-[12px]',\n resize === 'none'\n ? 'resize-none'\n : resize === 'vertical'\n ? 'resize-y'\n : resize === 'horizontal'\n ? 'resize-x'\n : 'resize',\n wrap ? '' : 'whitespace-pre overflow-x-auto min-w-0',\n ]\n .filter(Boolean)\n .join(' ');\n\n const textAreaElement = (\n <textarea\n ref={textareaRef}\n id={controlId}\n placeholder={placeholder}\n value={textAreaValue}\n onChange={handleChange(onFieldChange)}\n onBlur={() => {\n onBlur?.();\n onFieldBlur?.();\n }}\n onKeyDown={onKeyDown}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={isError || undefined}\n aria-required={required || undefined}\n aria-describedby={describedBy}\n disabled={disabled || !!prefixValue || !!prefixSecondaryValue || readOnly}\n readOnly={readOnly}\n wrap={wrap ? undefined : 'off'}\n rows={rows}\n maxLength={maxLength}\n style={{ minHeight: getMinHeight(size, rows) }}\n className={textAreaClasses}\n name={name}\n />\n );\n\n return (\n <div className={wrapperClasses}>\n {hasPrefix && (\n <div className=\"flex pt-3 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 {textAreaElement}\n\n {inFieldAction && (\n <div className=\"absolute bottom-2 right-2 flex items-center\">\n {inFieldAction}\n </div>\n )}\n\n {hasSuffix && (\n <div className=\"flex pt-3 pl-1 pr-3 flex-shrink-0\">\n <Suffix\n error={showErrorIcon}\n disabled={disabled}\n defaultValue={textAreaValue}\n onCopyClick={onCopyClick}\n />\n <TextAreaButtons buttons={buttons} />\n </div>\n )}\n </div>\n );\n };\n\n const renderHelperText = () =>\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 ) : null;\n\n const renderErrorMessage = (errorMessage?: string) => (\n <FieldMessage id={errorMessageId} message={errorMessage} spaced />\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={<LoadingTextArea size={size} rows={rows} />}\n >\n {({ error: fieldError, message, onFieldChange, onFieldBlur, value: formValue }) => {\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\n // The message is its own line rather than a replacement for the helper text:\n // a field that explains what it wants still has to say why what was typed was\n // rejected, and dropping one for the other left the field marked red with\n // nothing anywhere saying what was wrong.\n const errorMessage = error === false ? undefined : message;\n\n return (\n <>\n {renderTextArea(\n isError,\n helperText,\n onFieldChange,\n onFieldBlur,\n errorMessage,\n formValue,\n )}\n {renderHelperText()}\n {renderErrorMessage(errorMessage)}\n </>\n );\n }}\n </BaseFormComponent>\n );\n};\n\nconst LoadingTextArea: React.FC<{ size?: TextAreaSize; rows?: number }> = ({\n size = 'medium',\n rows = 4,\n}) => {\n return (\n // Decorative height placeholder — kept out of the a11y tree so it is not announced\n // as an unlabelled box (same as Skeleton and LoadingInput).\n <div\n aria-busy=\"true\"\n aria-hidden=\"true\"\n className=\"w-full rounded-xl border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-border)] flex items-center justify-center shadow-[var(--malachite-shadow-default)]\"\n style={{ minHeight: getMinHeight(size, rows) }}\n />\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-start gap-1\">\n {icon && (\n <span className=\"flex items-center justify-center text-[var(--malachite-text-dimmed)] w-4 h-4 flex-shrink-0 mt-1\">\n {icon}\n </span>\n )}\n {prefixValue && (\n <span className=\"text-[length:var(--malachite-font-size-15,15px)] 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-15,15px)] 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 disabled?: boolean;\n defaultValue?: string;\n onCopyClick?: () => void;\n}> = ({ error, disabled, defaultValue, onCopyClick }) => {\n return (\n <div className=\"flex items-start gap-1\">\n {error && (\n // Decorative: the rejection is carried by the message beneath the field.\n <div\n aria-hidden=\"true\"\n className=\"flex items-center justify-center w-5 h-5 flex-shrink-0 mt-1\"\n >\n <InfoIcon\n size={16}\n className=\"text-[var(--malachite-destructive-foreground,rgb(196,62,62))]\"\n />\n </div>\n )}\n {onCopyClick && disabled && defaultValue && (\n <button\n onClick={() => {\n navigator.clipboard.writeText(defaultValue);\n onCopyClick();\n }}\n type=\"button\"\n aria-label=\"Copy to clipboard\"\n className=\"flex items-center justify-center w-5 h-5 hover:bg-[var(--malachite-primary-border)] rounded transition-colors flex-shrink-0 mt-1\"\n >\n <CopyIcon size={16} />\n </button>\n )}\n </div>\n );\n};\n\nconst TextAreaButtons: React.FC<{\n buttons?: ButtonDefinition[];\n}> = ({ buttons }) => {\n if (!buttons?.length) {\n return null;\n }\n\n return (\n <div className=\"flex flex-col gap-1 mt-1\">\n {buttons.map((button) => (\n <Button\n key={button.label}\n variant={button.danger ? 'destructive' : 'outline'}\n size=\"small\"\n disabled={button.disabled}\n icon={button.icon}\n tooltip={button.tooltip}\n onClick={button.onClick}\n >\n {button.label}\n </Button>\n ))}\n </div>\n );\n};\n\nexport default TextArea;\n"],"names":["getSizeClasses","size","focusBorderClasses","isError","tone","rowHeightPx","rows","getMinHeight","TextArea","label","hint","tooltip","placeholder","icon","name","required","requiredIndicator","error","description","loading","readOnly","defaultValue","disabled","prefixValue","prefixSecondaryValue","formControl","buttons","onCopyClick","onChange","onKeyDown","inFieldAction","value","onBlur","helperText","maxRows","maxLength","resize","wrap","id","ariaLabel","ariaLabelledBy","controlId","labelId","descriptionId","hintId","helperTextId","useFormFieldIds","internalValue","setInternalValue","useState","textareaRef","useRef","resizeToFit","useCallback","el","maxHeight","nextHeight","useLayoutEffect","isControlled","paintedValue","formValue","paintedFieldValue","handleChange","reportToForm","e","newValue","hasPrefix","errorMessageId","renderTextArea","resolvedHelperText","onFieldChange","onFieldBlur","errorMessage","textAreaValue","showErrorIcon","hasSuffix","describedBy","wrapperClasses","textAreaClasses","textAreaElement","jsx","jsxs","CompositeIcon","Suffix","TextAreaButtons","renderHelperText","renderErrorMessage","FieldMessage","BaseFormComponent","LoadingTextArea","fieldError","message","Fragment","InfoIcon","CopyIcon","button","Button"],"mappings":";;;;;;;;AAyEA,MAAMA,KAAiB,CAACC,MAA+B;AACnD,UAAQA,GAAA;AAAA,IACJ,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX;AACI,aAAO;AAAA,EAAA;AAEnB,GAaMC,KAAqB,CAACC,GAAkBC,MACtCD,IACO,6HAGPC,MAAS,cACF,qHAGJ,oHAKLC,IAAc,CAACJ,GAAoBK,OAClB;AAAA,EACf,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,GACTL,CAAI,IAKcK,IAFJ,IAKdC,IAAe,CAACN,GAAoBK,MAAyB,GAAGD,EAAYJ,GAAMK,CAAI,CAAC,MAEvFE,KAAoC,CAAC;AAAA,EACvC,OAAAC;AAAA,EACA,MAAAC;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,MAAAC;AAAA,EACA,MAAAC;AAAA,EACA,UAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,UAAAC,IAAW;AAAA,EACX,MAAAnB,IAAO;AAAA,EACP,cAAAoB;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC;AAAA,EACA,sBAAAC;AAAA;AAAA,EAEA,aAAAC;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,eAAAC;AAAA,EACA,MAAA1B,IAAO;AAAA,EACP,OAAA2B;AAAA,EACA,QAAAC;AAAA,EACA,YAAAC;AAAA,EACA,MAAA3B,IAAO;AAAA,EACP,SAAA4B;AAAA,EACA,WAAAC;AAAA,EACA,QAAAC,IAAS;AAAA,EACT,MAAAC,IAAO;AAAA,EACP,IAAAC;AAAA,EACA,cAAcC;AAAA,EACd,mBAAmBC;AACvB,MAAM;AACF,QAAM,EAAE,WAAAC,GAAW,SAAAC,IAAS,eAAAC,GAAe,QAAAC,GAAQ,cAAAC,EAAA,IAAiBC,GAAgB;AAAA,IAChF,IAAAR;AAAA,IACA,OAAA7B;AAAA,IACA,aAAAS;AAAA,IACA,MAAAR;AAAA,IACA,YAAY;AAAA,EAAA,CACf,GACK,CAACqC,IAAeC,EAAgB,IAAIC,GAAS5B,KAAgB,EAAE,GAC/D6B,IAAcC,GAAmC,IAAI,GAOrDC,IAAcC,GAAY,MAAM;AAClC,UAAMC,IAAKJ,EAAY;AACvB,QAAI,CAACI,KAAMpB,MAAY;AACnB;AAGJ,UAAMqB,IAAYlD,EAAYJ,GAAMiC,CAAO;AAC3C,IAAAoB,EAAG,MAAM,SAAS;AAClB,UAAME,IAAa,KAAK,IAAIF,EAAG,cAAcC,CAAS;AACtD,IAAAD,EAAG,MAAM,SAAS,GAAGE,CAAU,MAC/BF,EAAG,MAAM,YAAYA,EAAG,eAAeC,IAAY,SAAS;AAAA,EAChE,GAAG,CAACrB,GAASjC,CAAI,CAAC;AAKlB,EAAAwD,GAAgB,MAAM;AAClB,IAAAL,EAAA;AAAA,EACJ,GAAG,CAACA,GAAarB,CAAK,CAAC;AAEvB,QAAM2B,KAAe3B,MAAU,QACzB4B,KAAe,CAACC,MAClBC,GAAkB;AAAA,IACd,WAAW;AAAA,IACX,MAAA/C;AAAA,IACA,OAAAiB;AAAA,IACA,WAAA6B;AAAA,IACA,cAAAvC;AAAA,IACA,OAAO,CAAC,CAACI;AAAA,IACT,mBAAmBsB;AAAA,EAAA,CACtB,GAECe,KACF,CAACC,MACD,CAACC,MAA8C;AAC3C,UAAMC,IAAWD,EAAE,OAAO;AAC1B,IAAKN,MACDV,GAAiBiB,CAAQ,GAI7Bb,EAAA,GACAxB,KAAA,QAAAA,EAAWqC,IACXF,KAAA,QAAAA,EAAeE;AAAA,EACnB,GAEEC,KAAYrD,KAAQU,KAAeC,GAEnC2C,IAAiB,GAAGtB,CAAY,UAEhCuB,KAAiB,CACnBjE,GACAkE,GACAC,GACAC,GACAC,GACAZ,MACC;AACD,UAAMa,IAAgBd,GAAaC,CAAS,GAGtCc,IAAgBvE,KAAW,CAACqE,GAC5BG,KACFD,KAAkB/C,KAAeL,KAAYmD,MAAkB/C,KAAA,gBAAAA,EAAS,SACtEkD,KACF;AAAA,MACIjC;AAAA,MACAC;AAAA,MACAyB,IAAqBxB,IAAe;AAAA,MACpC2B,IAAeL,IAAiB;AAAA,IAAA,EAE/B,OAAO,OAAO,EACd,KAAK,GAAG,KAAK,QAChBU,KAAiB;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAvD,IACM,iDACA;AAAA,MACN;AAAA,MACAnB,IAAU,iBAAiB;AAAA,MAC3BA,IACM,iDACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUNmB,IAAW,KAAKpB,GAAmBC,GAASC,CAAI;AAAA,IAAA,EAE/C,OAAO,OAAO,EACd,KAAK,GAAG,GAEP0E,KAAkB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA9E,GAAeC,CAAI;AAAA;AAAA;AAAA,MAGnB6B,IAAgB,wBAAwB;AAAA,MACxC;AAAA,MACAM,MAAW,SACL,gBACAA,MAAW,aACT,aACAA,MAAW,eACT,aACA;AAAA,MACVC,IAAO,KAAK;AAAA,IAAA,EAEX,OAAO,OAAO,EACd,KAAK,GAAG,GAEP0C,KACF,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,KAAK9B;AAAA,QACL,IAAIT;AAAA,QACJ,aAAA7B;AAAA,QACA,OAAO6D;AAAA,QACP,UAAUX,GAAaQ,CAAa;AAAA,QACpC,QAAQ,MAAM;AACV,UAAAtC,KAAA,QAAAA,KACAuC,KAAA,QAAAA;AAAA,QACJ;AAAA,QACA,WAAA1C;AAAA,QACA,cAAYU;AAAA,QACZ,mBAAiBC;AAAA,QACjB,gBAAcrC,KAAW;AAAA,QACzB,iBAAeY,KAAY;AAAA,QAC3B,oBAAkB6D;AAAA,QAClB,UAAUtD,KAAY,CAAC,CAACC,KAAe,CAAC,CAACC,KAAwBJ;AAAA,QACjE,UAAAA;AAAA,QACA,MAAMiB,IAAO,SAAY;AAAA,QACzB,MAAA/B;AAAA,QACA,WAAA6B;AAAA,QACA,OAAO,EAAE,WAAW5B,EAAaN,GAAMK,CAAI,EAAA;AAAA,QAC3C,WAAWwE;AAAA,QACX,MAAAhE;AAAA,MAAA;AAAA,IAAA;AAIR,WACI,gBAAAmE,EAAC,OAAA,EAAI,WAAWJ,IACX,UAAA;AAAA,MAAAX,MACG,gBAAAc,EAAC,OAAA,EAAI,WAAU,yDACX,UAAA,gBAAAA;AAAA,QAACE;AAAA,QAAA;AAAA,UACG,aAAA3D;AAAA,UACA,sBAAAC;AAAA,UACA,MAAAX;AAAA,QAAA;AAAA,MAAA,GAER;AAAA,MAGHkE;AAAA,MAEAjD,KACG,gBAAAkD,EAAC,OAAA,EAAI,WAAU,+CACV,UAAAlD,GACL;AAAA,MAGH6C,MACG,gBAAAM,EAAC,OAAA,EAAI,WAAU,qCACX,UAAA;AAAA,QAAA,gBAAAD;AAAA,UAACG;AAAA,UAAA;AAAA,YACG,OAAOT;AAAA,YACP,UAAApD;AAAA,YACA,cAAcmD;AAAA,YACd,aAAA9C;AAAA,UAAA;AAAA,QAAA;AAAA,QAEJ,gBAAAqD,EAACI,MAAgB,SAAA1D,EAAA,CAAkB;AAAA,MAAA,EAAA,CACvC;AAAA,IAAA,GAER;AAAA,EAER,GAEM2D,KAAmB,MACrBpD,IACI,gBAAA+C;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,IAAInC;AAAA,MACJ,WAAU;AAAA,MAET,UAAAZ;AAAA,IAAA;AAAA,EAAA,IAEL,MAEFqD,KAAqB,CAACd,MACxB,gBAAAQ,EAACO,IAAA,EAAa,IAAIpB,GAAgB,SAASK,GAAc,QAAM,GAAA,CAAC;AAGpE,SACI,gBAAAQ;AAAA,IAACQ;AAAA,IAAA;AAAA,MACG,OAAA/E;AAAA,MACA,MAAAC;AAAA,MACA,SAAAC;AAAA,MACA,MAAAG;AAAA,MACA,UAAAC;AAAA,MACA,mBAAAC;AAAA,MACA,SAAAG;AAAA,MACA,aAAAM;AAAA,MACA,aAAAP;AAAA,MACA,WAAAuB;AAAA,MACA,SAAAC;AAAA,MACA,eAAAC;AAAA,MACA,QAAAC;AAAA,MACA,kBAAkB,gBAAAoC,EAACS,IAAA,EAAgB,MAAAxF,GAAY,MAAAK,EAAA,CAAY;AAAA,MAE1D,UAAA,CAAC,EAAE,OAAOoF,GAAY,SAAAC,GAAS,eAAArB,GAAe,aAAAC,GAAa,OAAOX,QAAgB;AAC/E,cAAMzD,IAAUc,KAASyE,GASnBlB,IAAevD,MAAU,KAAQ,SAAY0E;AAEnD,eACI,gBAAAV,EAAAW,IAAA,EACK,UAAA;AAAA,UAAAxB;AAAA,YACGjE;AAAA,YACA8B;AAAA,YACAqC;AAAA,YACAC;AAAA,YACAC;AAAA,YACAZ;AAAA,UAAA;AAAA,UAEHyB,GAAA;AAAA,UACAC,GAAmBd,CAAY;AAAA,QAAA,GACpC;AAAA,MAER;AAAA,IAAA;AAAA,EAAA;AAGZ,GAEMiB,KAAoE,CAAC;AAAA,EACvE,MAAAxF,IAAO;AAAA,EACP,MAAAK,IAAO;AACX;AAAA;AAAA;AAAA,EAIQ,gBAAA0E;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,aAAU;AAAA,MACV,eAAY;AAAA,MACZ,WAAU;AAAA,MACV,OAAO,EAAE,WAAWzE,EAAaN,GAAMK,CAAI,EAAA;AAAA,IAAE;AAAA,EAAA;AAAA,GAKnD4E,KAID,CAAC,EAAE,aAAA3D,GAAa,sBAAAC,GAAsB,MAAAX,QAEnC,gBAAAoE,EAAC,OAAA,EAAI,WAAU,0BACV,UAAA;AAAA,EAAApE,KACG,gBAAAmE,EAAC,QAAA,EAAK,WAAU,mGACX,UAAAnE,GACL;AAAA,EAEHU,KACG,gBAAAyD,EAAC,QAAA,EAAK,WAAU,wHACX,UAAAzD,GACL;AAAA,EAEHC,KACG,gBAAAwD,EAAC,QAAA,EAAK,WAAU,wHACX,UAAAxD,EAAA,CACL;AAAA,GAER,GAIF2D,KAKD,CAAC,EAAE,OAAAlE,GAAO,UAAAK,GAAU,cAAAD,GAAc,aAAAM,QAE/B,gBAAAsD,EAAC,OAAA,EAAI,WAAU,0BACV,UAAA;AAAA,EAAAhE;AAAA,EAEG,gBAAA+D;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,eAAY;AAAA,MACZ,WAAU;AAAA,MAEV,UAAA,gBAAAA;AAAA,QAACa;AAAA,QAAA;AAAA,UACG,MAAM;AAAA,UACN,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACd;AAAA,EAAA;AAAA,EAGPlE,KAAeL,KAAYD,KACxB,gBAAA2D;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,SAAS,MAAM;AACX,kBAAU,UAAU,UAAU3D,CAAY,GAC1CM,EAAA;AAAA,MACJ;AAAA,MACA,MAAK;AAAA,MACL,cAAW;AAAA,MACX,WAAU;AAAA,MAEV,UAAA,gBAAAqD,EAACc,IAAA,EAAS,MAAM,GAAA,CAAI;AAAA,IAAA;AAAA,EAAA;AACxB,GAER,GAIFV,KAED,CAAC,EAAE,SAAA1D,QACCA,KAAA,QAAAA,EAAS,2BAKT,OAAA,EAAI,WAAU,4BACV,UAAAA,EAAQ,IAAI,CAACqE,MACV,gBAAAf;AAAA,EAACgB;AAAA,EAAA;AAAA,IAEG,SAASD,EAAO,SAAS,gBAAgB;AAAA,IACzC,MAAK;AAAA,IACL,UAAUA,EAAO;AAAA,IACjB,MAAMA,EAAO;AAAA,IACb,SAASA,EAAO;AAAA,IAChB,SAASA,EAAO;AAAA,IAEf,UAAAA,EAAO;AAAA,EAAA;AAAA,EARHA,EAAO;AAAA,CAUnB,GACL,IAlBO;"}
|
|
@@ -1,64 +1,65 @@
|
|
|
1
|
-
import { jsx as l, jsxs as
|
|
2
|
-
import E, { useState as x, useRef as
|
|
3
|
-
import { createPortal as
|
|
4
|
-
import { ensureOverlayStyles as
|
|
5
|
-
import { useTopLayer as
|
|
6
|
-
const
|
|
1
|
+
import { jsx as l, jsxs as H, Fragment as D } from "react/jsx-runtime";
|
|
2
|
+
import E, { useState as x, useRef as f, useCallback as J, useId as Q, useEffect as P, useInsertionEffect as Z } from "react";
|
|
3
|
+
import { createPortal as ee } from "react-dom";
|
|
4
|
+
import { ensureOverlayStyles as te, overlayIdentity as ne } from "./portalOverlay.js";
|
|
5
|
+
import { useTopLayer as re } from "./topLayer.js";
|
|
6
|
+
const oe = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), ie = (n) => n.split(oe).map((i, p) => /* @__PURE__ */ H(E.Fragment, { children: [
|
|
7
7
|
i,
|
|
8
8
|
/* @__PURE__ */ l("wbr", {})
|
|
9
|
-
] },
|
|
9
|
+
] }, p)), se = {
|
|
10
10
|
minWidth: 0,
|
|
11
11
|
overflow: "hidden"
|
|
12
|
-
},
|
|
12
|
+
}, C = {
|
|
13
13
|
flex: 1,
|
|
14
14
|
minWidth: 0
|
|
15
|
-
},
|
|
15
|
+
}, V = 8, pe = ({
|
|
16
16
|
text: n,
|
|
17
17
|
children: i,
|
|
18
|
-
delay:
|
|
19
|
-
wrapChildren:
|
|
20
|
-
triggerAs:
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
delay: p = 1,
|
|
19
|
+
wrapChildren: j = !1,
|
|
20
|
+
triggerAs: k = "div",
|
|
21
|
+
inline: R = !1,
|
|
22
|
+
placement: z = "top",
|
|
23
|
+
isShrinkable: L = !1,
|
|
23
24
|
maxWidth: m = "320px",
|
|
24
25
|
fill: h = !1,
|
|
25
26
|
shouldShow: c,
|
|
26
|
-
describesTrigger:
|
|
27
|
+
describesTrigger: T = !0
|
|
27
28
|
}) => {
|
|
28
|
-
const
|
|
29
|
+
const N = L || h ? { ...L ? se : {}, ...h ? C : {} } : void 0, [t, g] = x(!1), [d, O] = x(!1), u = f(null), r = f(null), o = J(() => {
|
|
29
30
|
u.current && (clearTimeout(u.current), u.current = null), r.current !== null && (cancelAnimationFrame(r.current), r.current = null);
|
|
30
|
-
}, []),
|
|
31
|
-
|
|
31
|
+
}, []), F = () => {
|
|
32
|
+
O(!0), r.current !== null && cancelAnimationFrame(r.current), r.current = requestAnimationFrame(() => {
|
|
32
33
|
r.current = null, g(!0);
|
|
33
34
|
});
|
|
34
|
-
}, v =
|
|
35
|
-
|
|
36
|
-
const
|
|
35
|
+
}, v = f(null), y = f(null);
|
|
36
|
+
re(v, t);
|
|
37
|
+
const I = Q(), s = n != null && n !== "" && n !== !1, Y = (e) => {
|
|
37
38
|
e.stopPropagation(), !(!s || c && !c()) && (o(), u.current = setTimeout(() => {
|
|
38
|
-
|
|
39
|
-
},
|
|
40
|
-
},
|
|
39
|
+
F();
|
|
40
|
+
}, p * 1e3));
|
|
41
|
+
}, U = (e) => {
|
|
41
42
|
e.stopPropagation(), o(), g(!1);
|
|
42
|
-
}, U = () => {
|
|
43
|
-
!s || c && !c() || (o(), T());
|
|
44
43
|
}, q = () => {
|
|
44
|
+
!s || c && !c() || (o(), F());
|
|
45
|
+
}, G = () => {
|
|
45
46
|
o(), g(!1);
|
|
46
|
-
}, [,
|
|
47
|
+
}, [, S] = x({});
|
|
47
48
|
P(() => {
|
|
48
49
|
if (!t)
|
|
49
50
|
return () => {
|
|
50
51
|
o();
|
|
51
52
|
};
|
|
52
53
|
const e = () => {
|
|
53
|
-
|
|
54
|
+
S({});
|
|
54
55
|
};
|
|
55
56
|
return window.addEventListener("scroll", e, !0), window.addEventListener("resize", e), () => {
|
|
56
57
|
o(), window.removeEventListener("scroll", e, !0), window.removeEventListener("resize", e);
|
|
57
58
|
};
|
|
58
59
|
}, [t, o]), P(() => {
|
|
59
|
-
t &&
|
|
60
|
+
t && S({});
|
|
60
61
|
}, [t]);
|
|
61
|
-
const
|
|
62
|
+
const K = () => {
|
|
62
63
|
if (!y.current)
|
|
63
64
|
return { display: "none" };
|
|
64
65
|
const e = y.current.getBoundingClientRect(), a = {
|
|
@@ -84,14 +85,14 @@ const re = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), oe = (n) => n.split(re).map((i
|
|
|
84
85
|
visibility: t ? "visible" : "hidden",
|
|
85
86
|
transition: "opacity 150ms ease-in-out, transform 150ms ease-in-out, visibility 150ms ease-in-out"
|
|
86
87
|
}, b = () => {
|
|
87
|
-
var
|
|
88
|
-
const w = e.left + e.width / 2,
|
|
89
|
-
if (
|
|
88
|
+
var $;
|
|
89
|
+
const w = e.left + e.width / 2, B = (($ = v.current) == null ? void 0 : $.getBoundingClientRect().width) ?? 0;
|
|
90
|
+
if (B === 0)
|
|
90
91
|
return w;
|
|
91
|
-
const
|
|
92
|
-
return
|
|
92
|
+
const M = B / 2, W = V + M, _ = window.innerWidth - V - M;
|
|
93
|
+
return W > _ ? w : Math.min(Math.max(w, W), _);
|
|
93
94
|
};
|
|
94
|
-
switch (
|
|
95
|
+
switch (z) {
|
|
95
96
|
case "top":
|
|
96
97
|
return {
|
|
97
98
|
...a,
|
|
@@ -128,37 +129,37 @@ const re = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), oe = (n) => n.split(re).map((i
|
|
|
128
129
|
transform: `translate(-50%, -100%) ${t ? "scale(1)" : "scale(0.95)"}`
|
|
129
130
|
};
|
|
130
131
|
}
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
s && d &&
|
|
132
|
+
}, A = s && d && T ? I : void 0;
|
|
133
|
+
Z(() => {
|
|
134
|
+
s && d && te();
|
|
134
135
|
}, [s, d]);
|
|
135
|
-
const
|
|
136
|
-
"aria-describedby": [i.props["aria-describedby"],
|
|
136
|
+
const X = j || !E.isValidElement(i) ? /* @__PURE__ */ l("span", { "aria-describedby": A, style: h ? C : void 0, children: i }) : E.cloneElement(i, {
|
|
137
|
+
"aria-describedby": [i.props["aria-describedby"], A].filter(Boolean).join(" ") || void 0
|
|
137
138
|
});
|
|
138
|
-
return /* @__PURE__ */
|
|
139
|
+
return /* @__PURE__ */ H(D, { children: [
|
|
139
140
|
/* @__PURE__ */ l(
|
|
140
|
-
|
|
141
|
+
R ? "span" : k,
|
|
141
142
|
{
|
|
142
143
|
ref: y,
|
|
143
|
-
className:
|
|
144
|
-
style:
|
|
145
|
-
onMouseEnter:
|
|
146
|
-
onMouseLeave:
|
|
147
|
-
onFocus:
|
|
148
|
-
onBlur:
|
|
149
|
-
children:
|
|
144
|
+
className: `relative ${R ? "inline-flex max-w-full align-middle" : "flex"} items-center`,
|
|
145
|
+
style: N,
|
|
146
|
+
onMouseEnter: Y,
|
|
147
|
+
onMouseLeave: U,
|
|
148
|
+
onFocus: q,
|
|
149
|
+
onBlur: G,
|
|
150
|
+
children: X
|
|
150
151
|
}
|
|
151
152
|
),
|
|
152
|
-
s && d &&
|
|
153
|
+
s && d && ee(
|
|
153
154
|
/* @__PURE__ */ l(
|
|
154
155
|
"div",
|
|
155
156
|
{
|
|
156
157
|
ref: v,
|
|
157
|
-
id:
|
|
158
|
+
id: I,
|
|
158
159
|
role: "tooltip",
|
|
159
|
-
"aria-hidden":
|
|
160
|
-
...
|
|
161
|
-
style:
|
|
160
|
+
"aria-hidden": T ? void 0 : !0,
|
|
161
|
+
...ne("tooltip"),
|
|
162
|
+
style: K(),
|
|
162
163
|
children: /* @__PURE__ */ l(
|
|
163
164
|
"span",
|
|
164
165
|
{
|
|
@@ -166,7 +167,7 @@ const re = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), oe = (n) => n.split(re).map((i
|
|
|
166
167
|
minWidth: 0,
|
|
167
168
|
overflowWrap: "anywhere"
|
|
168
169
|
},
|
|
169
|
-
children: typeof n == "string" ?
|
|
170
|
+
children: typeof n == "string" ? ie(n) : n
|
|
170
171
|
}
|
|
171
172
|
)
|
|
172
173
|
}
|