@stackone/malachite 2.60.0 → 2.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENTS.md +3 -3
- package/dist/components/Modal.js +137 -112
- package/dist/components/Modal.js.map +1 -1
- package/dist/components/SidePanel.js +98 -86
- package/dist/components/SidePanel.js.map +1 -1
- package/dist/components/Surface.js +106 -87
- package/dist/components/Surface.js.map +1 -1
- package/dist/index.d.ts +20 -4
- package/dist/tailwind.css.js +1 -1
- package/package.json +1 -1
|
@@ -1,166 +1,178 @@
|
|
|
1
1
|
import { jsx as e, jsxs as a } from "react/jsx-runtime";
|
|
2
|
-
import { useState as
|
|
3
|
-
import { createPortal as
|
|
4
|
-
import { ShadowRootWrapper as
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import { useOverlayBehaviour as
|
|
10
|
-
import { OVERLAY_ELEVATED_ATTR as
|
|
11
|
-
const
|
|
2
|
+
import { useId as k, useState as _, useRef as u, useEffect as q } from "react";
|
|
3
|
+
import { createPortal as U } from "react-dom";
|
|
4
|
+
import { ShadowRootWrapper as G } from "../ShadowRootWrapper.js";
|
|
5
|
+
import H from "./CalloutStrip.js";
|
|
6
|
+
import J from "./CustomIcons/ArrowLeftIcon.js";
|
|
7
|
+
import K from "./CustomIcons/DismissIcon.js";
|
|
8
|
+
import z from "./Typography/EllipsisText.js";
|
|
9
|
+
import { useOverlayBehaviour as Q, OVERLAY_ICON_BUTTON_CLASSES as E } from "./overlayBehaviour.js";
|
|
10
|
+
import { OVERLAY_ELEVATED_ATTR as Z, overlayIdentity as O } from "./portalOverlay.js";
|
|
11
|
+
const P = 200, ee = (t) => typeof t == "number" ? `${t}px` : t, me = ({
|
|
12
12
|
open: t,
|
|
13
|
-
onClose:
|
|
14
|
-
title:
|
|
15
|
-
subtitle:
|
|
16
|
-
titleExtra:
|
|
17
|
-
description:
|
|
18
|
-
headerDivider:
|
|
19
|
-
icon:
|
|
20
|
-
headerExtra:
|
|
13
|
+
onClose: c,
|
|
14
|
+
title: o,
|
|
15
|
+
subtitle: d,
|
|
16
|
+
titleExtra: f,
|
|
17
|
+
description: m,
|
|
18
|
+
headerDivider: V = !1,
|
|
19
|
+
icon: x,
|
|
20
|
+
headerExtra: b,
|
|
21
21
|
footer: h,
|
|
22
|
-
onBack:
|
|
23
|
-
maxWidth:
|
|
24
|
-
"aria-label":
|
|
25
|
-
"aria-labelledby":
|
|
26
|
-
bodyPadding:
|
|
27
|
-
stacking:
|
|
28
|
-
callouts:
|
|
29
|
-
renderLink:
|
|
30
|
-
children:
|
|
22
|
+
onBack: v,
|
|
23
|
+
maxWidth: C = 1080,
|
|
24
|
+
"aria-label": L,
|
|
25
|
+
"aria-labelledby": y,
|
|
26
|
+
bodyPadding: N = !0,
|
|
27
|
+
stacking: j = "default",
|
|
28
|
+
callouts: p,
|
|
29
|
+
renderLink: B,
|
|
30
|
+
children: g
|
|
31
31
|
}) => {
|
|
32
|
-
const [
|
|
33
|
-
ref:
|
|
34
|
-
isTopmost:
|
|
35
|
-
zIndex:
|
|
36
|
-
elevated:
|
|
37
|
-
} =
|
|
32
|
+
const T = k(), I = k(), [w, S] = _(!1), [M, R] = _(!1), i = u(null), r = u(null), $ = u(null), {
|
|
33
|
+
ref: W,
|
|
34
|
+
isTopmost: D,
|
|
35
|
+
zIndex: F,
|
|
36
|
+
elevated: X
|
|
37
|
+
} = Q({
|
|
38
38
|
open: t,
|
|
39
|
-
onClose:
|
|
40
|
-
elevated:
|
|
41
|
-
hostRef:
|
|
39
|
+
onClose: c,
|
|
40
|
+
elevated: j === "above-app-overlays",
|
|
41
|
+
hostRef: $
|
|
42
42
|
});
|
|
43
|
-
if (
|
|
44
|
-
i.current = null,
|
|
45
|
-
})) : (
|
|
46
|
-
r.current = null,
|
|
47
|
-
},
|
|
43
|
+
if (q(() => (t ? (R(!0), r.current && (clearTimeout(r.current), r.current = null), i.current = requestAnimationFrame(() => {
|
|
44
|
+
i.current = null, S(!0);
|
|
45
|
+
})) : (S(!1), r.current = setTimeout(() => {
|
|
46
|
+
r.current = null, R(!1);
|
|
47
|
+
}, P)), () => {
|
|
48
48
|
i.current !== null && (cancelAnimationFrame(i.current), i.current = null), r.current && (clearTimeout(r.current), r.current = null);
|
|
49
|
-
}), [t]), !
|
|
49
|
+
}), [t]), !M)
|
|
50
50
|
return null;
|
|
51
|
-
const l =
|
|
52
|
-
return
|
|
51
|
+
const l = p == null ? void 0 : p.filter((n) => n.message.trim()), A = !!(l != null && l.length), Y = N ? /* @__PURE__ */ e("div", { className: A ? "p-[28px]" : "py-[28px]", children: g }) : g;
|
|
52
|
+
return U(
|
|
53
53
|
// Host carries the stacking context — ShadowRootWrapper's `isolation` would
|
|
54
54
|
// otherwise flatten our z-index and let sticky page elements paint over us.
|
|
55
55
|
/* @__PURE__ */ e(
|
|
56
|
-
|
|
56
|
+
G,
|
|
57
57
|
{
|
|
58
|
-
hostRef:
|
|
59
|
-
hostStyle: { position: "relative", zIndex:
|
|
60
|
-
hostProps:
|
|
58
|
+
hostRef: $,
|
|
59
|
+
hostStyle: { position: "relative", zIndex: F },
|
|
60
|
+
hostProps: X ? { ...O("sidepanel"), [Z]: "" } : O("sidepanel"),
|
|
61
61
|
children: /* @__PURE__ */ a("div", { className: "fixed inset-0 z-[1000]", children: [
|
|
62
62
|
/* @__PURE__ */ e(
|
|
63
63
|
"div",
|
|
64
64
|
{
|
|
65
65
|
"aria-hidden": "true",
|
|
66
|
-
onClick:
|
|
67
|
-
className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${
|
|
66
|
+
onClick: c,
|
|
67
|
+
className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${w ? "opacity-100" : "opacity-0"}`
|
|
68
68
|
}
|
|
69
69
|
),
|
|
70
70
|
/* @__PURE__ */ a(
|
|
71
71
|
"div",
|
|
72
72
|
{
|
|
73
|
-
ref:
|
|
73
|
+
ref: W,
|
|
74
74
|
role: "dialog",
|
|
75
|
-
"aria-modal":
|
|
75
|
+
"aria-modal": D ? "true" : void 0,
|
|
76
|
+
"aria-describedby": [
|
|
77
|
+
...(l ?? []).map((n, s) => `${T}-${s}`),
|
|
78
|
+
m ? I : null
|
|
79
|
+
].filter(Boolean).join(" ") || void 0,
|
|
76
80
|
tabIndex: -1,
|
|
77
|
-
"aria-label":
|
|
78
|
-
"aria-labelledby":
|
|
81
|
+
"aria-label": y ? void 0 : L ?? (typeof o == "string" ? o : void 0),
|
|
82
|
+
"aria-labelledby": y,
|
|
79
83
|
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)]",
|
|
80
84
|
style: {
|
|
81
|
-
width: `min(calc(100% - 16px), ${
|
|
85
|
+
width: `min(calc(100% - 16px), ${ee(C)})`,
|
|
82
86
|
// Inline: Tailwind translate utilities silently break inside
|
|
83
87
|
// shadow roots (see CLAUDE.md Shadow DOM caveats).
|
|
84
|
-
transform:
|
|
85
|
-
transition: `transform ${
|
|
88
|
+
transform: w ? "translateX(0)" : "translateX(calc(100% + 16px))",
|
|
89
|
+
transition: `transform ${P}ms ease-in-out`
|
|
86
90
|
},
|
|
87
91
|
children: [
|
|
88
92
|
/* @__PURE__ */ a(
|
|
89
93
|
"div",
|
|
90
94
|
{
|
|
91
|
-
className: `flex flex-col gap-[20px] px-[20px] py-[18px] ${
|
|
95
|
+
className: `flex flex-col gap-[20px] px-[20px] py-[18px] ${V ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
|
|
92
96
|
children: [
|
|
93
97
|
/* @__PURE__ */ a("div", { className: "flex items-center gap-[12px]", children: [
|
|
94
|
-
|
|
98
|
+
v ? /* @__PURE__ */ e(
|
|
95
99
|
"button",
|
|
96
100
|
{
|
|
97
101
|
type: "button",
|
|
98
102
|
"aria-label": "Back",
|
|
99
|
-
onClick:
|
|
100
|
-
className:
|
|
101
|
-
children: /* @__PURE__ */ e(
|
|
103
|
+
onClick: v,
|
|
104
|
+
className: E,
|
|
105
|
+
children: /* @__PURE__ */ e(J, { size: 16 })
|
|
102
106
|
}
|
|
103
107
|
) : null,
|
|
104
|
-
|
|
108
|
+
x ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: x }) : null,
|
|
105
109
|
/* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-baseline gap-[12px]", children: [
|
|
106
110
|
/* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-baseline gap-[8px]", children: [
|
|
107
111
|
/* @__PURE__ */ a("div", { className: "flex min-w-0 items-baseline gap-[8px]", children: [
|
|
108
112
|
/* @__PURE__ */ e("span", { className: "flex min-w-0 max-w-full shrink-0", children: /* @__PURE__ */ e(
|
|
109
|
-
|
|
113
|
+
z,
|
|
110
114
|
{
|
|
111
|
-
tooltip:
|
|
115
|
+
tooltip: o,
|
|
112
116
|
tooltipWhenTruncated: !0,
|
|
113
117
|
tooltipPlacement: "bottom",
|
|
114
118
|
className: "min-w-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold",
|
|
115
|
-
children:
|
|
119
|
+
children: o
|
|
116
120
|
}
|
|
117
121
|
) }),
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
d ? /* @__PURE__ */ e(
|
|
123
|
+
z,
|
|
120
124
|
{
|
|
121
|
-
tooltip:
|
|
125
|
+
tooltip: d,
|
|
122
126
|
tooltipWhenTruncated: !0,
|
|
123
127
|
tooltipPlacement: "bottom",
|
|
124
128
|
color: "secondary",
|
|
125
129
|
className: "min-w-0 text-[13px]",
|
|
126
|
-
children:
|
|
130
|
+
children: d
|
|
127
131
|
}
|
|
128
132
|
) : null
|
|
129
133
|
] }),
|
|
130
|
-
|
|
134
|
+
f ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: f }) : null
|
|
131
135
|
] }),
|
|
132
|
-
|
|
136
|
+
b ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-baseline", children: b }) : null
|
|
133
137
|
] }),
|
|
134
138
|
/* @__PURE__ */ e(
|
|
135
139
|
"button",
|
|
136
140
|
{
|
|
137
141
|
type: "button",
|
|
138
142
|
"aria-label": "Close",
|
|
139
|
-
onClick:
|
|
140
|
-
className:
|
|
141
|
-
children: /* @__PURE__ */ e(
|
|
143
|
+
onClick: c,
|
|
144
|
+
className: E,
|
|
145
|
+
children: /* @__PURE__ */ e(K, { size: 10 })
|
|
142
146
|
}
|
|
143
147
|
)
|
|
144
148
|
] }),
|
|
145
|
-
|
|
149
|
+
m ? /* @__PURE__ */ e(
|
|
150
|
+
"div",
|
|
151
|
+
{
|
|
152
|
+
id: I,
|
|
153
|
+
className: "text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]",
|
|
154
|
+
children: m
|
|
155
|
+
}
|
|
156
|
+
) : null
|
|
146
157
|
]
|
|
147
158
|
}
|
|
148
159
|
),
|
|
149
160
|
/* @__PURE__ */ a(
|
|
150
161
|
"div",
|
|
151
162
|
{
|
|
152
|
-
className: `min-h-0 flex-1 overflow-y-auto ${
|
|
163
|
+
className: `min-h-0 flex-1 overflow-y-auto ${N && !A ? "px-[28px]" : ""}`,
|
|
153
164
|
children: [
|
|
154
|
-
l == null ? void 0 : l.map((
|
|
155
|
-
|
|
165
|
+
l == null ? void 0 : l.map((n, s) => /* @__PURE__ */ e(
|
|
166
|
+
H,
|
|
156
167
|
{
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
id: `${T}-${s}`,
|
|
169
|
+
type: n.type,
|
|
170
|
+
message: n.message,
|
|
171
|
+
renderLink: B
|
|
160
172
|
},
|
|
161
|
-
|
|
173
|
+
s
|
|
162
174
|
)),
|
|
163
|
-
|
|
175
|
+
Y
|
|
164
176
|
]
|
|
165
177
|
}
|
|
166
178
|
),
|
|
@@ -175,7 +187,7 @@ const E = 200, K = (t) => typeof t == "number" ? `${t}px` : t, oe = ({
|
|
|
175
187
|
);
|
|
176
188
|
};
|
|
177
189
|
export {
|
|
178
|
-
|
|
179
|
-
|
|
190
|
+
me as SidePanel,
|
|
191
|
+
me as default
|
|
180
192
|
};
|
|
181
193
|
//# 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 type { AlertType } from './Alert';\nimport CalloutStrip from './CalloutStrip';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport type { RenderLink } from './PageLayout/types';\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 /** Full-width Alert bands at the top of the body, above `children`, in order. Unaffected by\n * `bodyPadding`. The message is markdown. */\n callouts?: { type?: AlertType; message: string }[];\n /** Routes root-relative links in `callouts` through the app's router; see `MarkdownBlock`. */\n renderLink?: RenderLink;\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 callouts,\n renderLink,\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 const shownCallouts = callouts?.filter((callout) => callout.message.trim());\n const hasCallouts = !!shownCallouts?.length;\n const paddedBody = bodyPadding ? (\n <div className={hasCallouts ? 'p-[28px]' : 'py-[28px]'}>{children}</div>\n ) : (\n children\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 {/* Callouts move the horizontal padding inward so their strips run full-bleed. */}\n <div\n className={`min-h-0 flex-1 overflow-y-auto ${bodyPadding && !hasCallouts ? 'px-[28px]' : ''}`}\n >\n {shownCallouts?.map((callout, index) => (\n <CalloutStrip\n key={index}\n type={callout.type}\n message={callout.message}\n renderLink={renderLink}\n />\n ))}\n {paddedBody}\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","callouts","renderLink","children","isVisible","setIsVisible","useState","isMounted","setIsMounted","frameRef","useRef","unmountTimerRef","hostRef","handlePanelRef","isTopmost","zIndex","elevated","useOverlayBehaviour","useEffect","shownCallouts","callout","hasCallouts","paddedBody","jsx","createPortal","ShadowRootWrapper","overlayIdentity","OVERLAY_ELEVATED_ATTR","jsxs","OVERLAY_ICON_BUTTON_CLASSES","ArrowLeftIcon","EllipsisText","DismissIcon","index","CalloutStrip"],"mappings":";;;;;;;;;;AAkDA,MAAMA,IAAgB,KAEhBC,IAAY,CAACC,MACf,OAAOA,KAAU,WAAW,GAAGA,CAAK,OAAOA,GASzCC,KAAsC,CAAC;AAAA,EACzC,MAAAC;AAAA,EACA,SAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC,IAAgB;AAAA,EAChB,MAAAC;AAAA,EACA,aAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,cAAcC;AAAA,EACd,mBAAmBC;AAAA,EACnB,aAAAC,IAAc;AAAA,EACd,UAAAC,IAAW;AAAA,EACX,UAAAC;AAAA,EACA,YAAAC;AAAA,EACA,UAAAC;AACJ,MAAM;AACF,QAAM,CAACC,GAAWC,CAAY,IAAIC,EAAS,EAAK,GAC1C,CAACC,GAAWC,CAAY,IAAIF,EAAS,EAAK,GAC1CG,IAAWC,EAAsB,IAAI,GACrCC,IAAkBD,EAA6C,IAAI,GACnEE,IAAUF,EAA8B,IAAI,GAC5C;AAAA,IACF,KAAKG;AAAA,IACL,WAAAC;AAAA,IACA,QAAAC;AAAA,IACA,UAAAC;AAAA,EAAA,IACAC,EAAoB;AAAA,IACpB,MAAAhC;AAAA,IACA,SAAAC;AAAA,IACA,UAAUc,MAAa;AAAA,IACvB,SAAAY;AAAA,EAAA,CACH;AAgCD,MA9BAM,EAAU,OACFjC,KACAuB,EAAa,EAAI,GACbG,EAAgB,YAChB,aAAaA,EAAgB,OAAO,GACpCA,EAAgB,UAAU,OAE9BF,EAAS,UAAU,sBAAsB,MAAM;AAC3C,IAAAA,EAAS,UAAU,MACnBJ,EAAa,EAAI;AAAA,EACrB,CAAC,MAEDA,EAAa,EAAK,GAClBM,EAAgB,UAAU,WAAW,MAAM;AACvC,IAAAA,EAAgB,UAAU,MAC1BH,EAAa,EAAK;AAAA,EACtB,GAAG3B,CAAa,IAEb,MAAM;AACT,IAAI4B,EAAS,YAAY,SACrB,qBAAqBA,EAAS,OAAO,GACrCA,EAAS,UAAU,OAEnBE,EAAgB,YAChB,aAAaA,EAAgB,OAAO,GACpCA,EAAgB,UAAU;AAAA,EAElC,IACD,CAAC1B,CAAI,CAAC,GAEL,CAACsB;AACD,WAAO;AAGX,QAAMY,IAAgBlB,KAAA,gBAAAA,EAAU,OAAO,CAACmB,MAAYA,EAAQ,QAAQ,SAC9DC,IAAc,CAAC,EAACF,KAAA,QAAAA,EAAe,SAC/BG,IAAavB,IACf,gBAAAwB,EAAC,OAAA,EAAI,WAAWF,IAAc,aAAa,aAAc,UAAAlB,EAAA,CAAS,IAElEA;AAGJ,SAAOqB;AAAA;AAAA;AAAA,IAGH,gBAAAD;AAAA,MAACE;AAAA,MAAA;AAAA,QACG,SAAAb;AAAA,QACA,WAAW,EAAE,UAAU,YAAY,QAAAG,EAAA;AAAA,QACnC,WACIC,IACM,EAAE,GAAGU,EAAgB,WAAW,GAAG,CAACC,CAAqB,GAAG,GAAA,IAC5DD,EAAgB,WAAW;AAAA,QAGrC,UAAA,gBAAAE,EAAC,OAAA,EAAI,WAAU,0BACX,UAAA;AAAA,UAAA,gBAAAL;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,eAAY;AAAA,cACZ,SAASrC;AAAA,cACT,WAAW,oGACPkB,IAAY,gBAAgB,WAChC;AAAA,YAAA;AAAA,UAAA;AAAA,UAEJ,gBAAAwB;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,KAAKf;AAAA,cACL,MAAK;AAAA,cAGL,cAAYC,IAAY,SAAS;AAAA,cACjC,UAAU;AAAA,cAEV,cACIhB,IACM,SACCD,MAAc,OAAOV,KAAU,WAAWA,IAAQ;AAAA,cAE7D,mBAAiBW;AAAA,cACjB,WAAU;AAAA,cACV,OAAO;AAAA,gBACH,OAAO,0BAA0BhB,EAAUc,CAAQ,CAAC;AAAA;AAAA;AAAA,gBAGpD,WAAWQ,IAAY,kBAAkB;AAAA,gBACzC,YAAY,aAAavB,CAAa;AAAA,cAAA;AAAA,cAG1C,UAAA;AAAA,gBAAA,gBAAA+C;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACG,WAAW,gDACPrC,IACM,yEACA,EACV;AAAA,oBAEA,UAAA;AAAA,sBAAA,gBAAAqC,EAAC,OAAA,EAAI,WAAU,gCACV,UAAA;AAAA,wBAAAjC,IACG,gBAAA4B;AAAA,0BAAC;AAAA,0BAAA;AAAA,4BACG,MAAK;AAAA,4BACL,cAAW;AAAA,4BACX,SAAS5B;AAAA,4BACT,WAAWkC;AAAA,4BAEX,UAAA,gBAAAN,EAACO,GAAA,EAAc,MAAM,GAAA,CAAI;AAAA,0BAAA;AAAA,wBAAA,IAE7B;AAAA,wBACHtC,IACG,gBAAA+B,EAAC,QAAA,EAAK,WAAU,8BAA8B,aAAK,IACnD;AAAA,wBACJ,gBAAAK,EAAC,OAAA,EAAI,WAAU,iDACX,UAAA;AAAA,0BAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gDACX,UAAA;AAAA,4BAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,yCACX,UAAA;AAAA,8BAAA,gBAAAL,EAAC,QAAA,EAAK,WAAU,oCACZ,UAAA,gBAAAA;AAAA,gCAACQ;AAAA,gCAAA;AAAA,kCACG,SAAS5C;AAAA,kCACT,sBAAoB;AAAA,kCACpB,kBAAiB;AAAA,kCACjB,WAAU;AAAA,kCAET,UAAAA;AAAA,gCAAA;AAAA,8BAAA,GAET;AAAA,8BACCC,IACG,gBAAAmC;AAAA,gCAACQ;AAAA,gCAAA;AAAA,kCACG,SAAS3C;AAAA,kCACT,sBAAoB;AAAA,kCACpB,kBAAiB;AAAA,kCACjB,OAAM;AAAA,kCACN,WAAU;AAAA,kCAET,UAAAA;AAAA,gCAAA;AAAA,8BAAA,IAEL;AAAA,4BAAA,GACR;AAAA,4BACCC,IACG,gBAAAkC,EAAC,QAAA,EAAK,WAAU,8BACX,aACL,IACA;AAAA,0BAAA,GACR;AAAA,0BACC9B,IACG,gBAAA8B,EAAC,QAAA,EAAK,WAAU,gCACX,aACL,IACA;AAAA,wBAAA,GACR;AAAA,wBACA,gBAAAA;AAAA,0BAAC;AAAA,0BAAA;AAAA,4BACG,MAAK;AAAA,4BACL,cAAW;AAAA,4BACX,SAASrC;AAAA,4BACT,WAAW2C;AAAA,4BAEX,UAAA,gBAAAN,EAACS,GAAA,EAAY,MAAM,GAAA,CAAI;AAAA,0BAAA;AAAA,wBAAA;AAAA,sBAC3B,GACJ;AAAA,sBACC1C,IACG,gBAAAiC,EAAC,OAAA,EAAI,WAAU,oEACV,aACL,IACA;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAGR,gBAAAK;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACG,WAAW,kCAAkC7B,KAAe,CAACsB,IAAc,cAAc,EAAE;AAAA,oBAE1F,UAAA;AAAA,sBAAAF,KAAA,gBAAAA,EAAe,IAAI,CAACC,GAASa,MAC1B,gBAAAV;AAAA,wBAACW;AAAA,wBAAA;AAAA,0BAEG,MAAMd,EAAQ;AAAA,0BACd,SAASA,EAAQ;AAAA,0BACjB,YAAAlB;AAAA,wBAAA;AAAA,wBAHK+B;AAAA,sBAAA;AAAA,sBAMZX;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEJ5B,IACG,gBAAA6B,EAAC,OAAA,EAAI,WAAU,4FACV,aACL,IACA;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACR,EAAA,CACJ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEJ,SAAS;AAAA,EAAA;AAEjB;"}
|
|
1
|
+
{"version":3,"file":"SidePanel.js","sources":["../../src/components/SidePanel.tsx"],"sourcesContent":["import React, { useEffect, useId, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport type { AlertType } from './Alert';\nimport CalloutStrip from './CalloutStrip';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport type { RenderLink } from './PageLayout/types';\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. Announced as the panel's description. */\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 /** Full-width Alert bands at the top of the body, above `children`, in order. Unaffected by\n * `bodyPadding`, and announced ahead of `description`. The message is markdown. */\n callouts?: { type?: AlertType; message: string }[];\n /** Routes root-relative links in `callouts` through the app's router; see `MarkdownBlock`. */\n renderLink?: RenderLink;\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 callouts,\n renderLink,\n children,\n}) => {\n const calloutId = useId();\n const descriptionId = useId();\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 const shownCallouts = callouts?.filter((callout) => callout.message.trim());\n const hasCallouts = !!shownCallouts?.length;\n const paddedBody = bodyPadding ? (\n <div className={hasCallouts ? 'p-[28px]' : 'py-[28px]'}>{children}</div>\n ) : (\n children\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 aria-describedby={\n [\n ...(shownCallouts ?? []).map((_, index) => `${calloutId}-${index}`),\n description ? descriptionId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n }\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\n id={descriptionId}\n className=\"text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]\"\n >\n {description}\n </div>\n ) : null}\n </div>\n {/* Callouts move the horizontal padding inward so their strips run full-bleed. */}\n <div\n className={`min-h-0 flex-1 overflow-y-auto ${bodyPadding && !hasCallouts ? 'px-[28px]' : ''}`}\n >\n {shownCallouts?.map((callout, index) => (\n <CalloutStrip\n key={index}\n id={`${calloutId}-${index}`}\n type={callout.type}\n message={callout.message}\n renderLink={renderLink}\n />\n ))}\n {paddedBody}\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","callouts","renderLink","children","calloutId","useId","descriptionId","isVisible","setIsVisible","useState","isMounted","setIsMounted","frameRef","useRef","unmountTimerRef","hostRef","handlePanelRef","isTopmost","zIndex","elevated","useOverlayBehaviour","useEffect","shownCallouts","callout","hasCallouts","paddedBody","jsx","createPortal","ShadowRootWrapper","overlayIdentity","OVERLAY_ELEVATED_ATTR","jsxs","_","index","OVERLAY_ICON_BUTTON_CLASSES","ArrowLeftIcon","EllipsisText","DismissIcon","CalloutStrip"],"mappings":"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"}
|