@stackone/malachite 2.55.1 → 2.57.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.
Files changed (31) hide show
  1. package/COMPONENTS.md +5 -4
  2. package/dist/components/Alert.js +77 -59
  3. package/dist/components/Alert.js.map +1 -1
  4. package/dist/components/Breadcrumbs.js.map +1 -1
  5. package/dist/components/CalloutStrip.js +7 -0
  6. package/dist/components/CalloutStrip.js.map +1 -0
  7. package/dist/components/ConfirmationDialog.js +100 -108
  8. package/dist/components/ConfirmationDialog.js.map +1 -1
  9. package/dist/components/IconBadge.js +16 -0
  10. package/dist/components/IconBadge.js.map +1 -0
  11. package/dist/components/PageLayout/index.js.map +1 -1
  12. package/dist/components/PageLayout/regularLayout.js.map +1 -1
  13. package/dist/components/SidePanel.js +99 -82
  14. package/dist/components/SidePanel.js.map +1 -1
  15. package/dist/components/Skeleton.js +45 -42
  16. package/dist/components/Skeleton.js.map +1 -1
  17. package/dist/components/Typography/MarkdownBlock.js +89 -87
  18. package/dist/components/Typography/MarkdownBlock.js.map +1 -1
  19. package/dist/components/Typography/Text.js +14 -13
  20. package/dist/components/Typography/Text.js.map +1 -1
  21. package/dist/components/Typography/index.js.map +1 -1
  22. package/dist/components/Typography/textStyles.js.map +1 -1
  23. package/dist/components/confirmationDialogVariants.js +2 -6
  24. package/dist/components/confirmationDialogVariants.js.map +1 -1
  25. package/dist/components/iconBadgeVariants.js +11 -0
  26. package/dist/components/iconBadgeVariants.js.map +1 -0
  27. package/dist/index.d.ts +39 -5
  28. package/dist/index.js +447 -445
  29. package/dist/index.js.map +1 -1
  30. package/dist/tailwind.css.js +1 -1
  31. package/package.json +1 -1
@@ -1,153 +1,170 @@
1
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
- import { createPortal as L } from "react-dom";
4
- import { ShadowRootWrapper as M } from "../ShadowRootWrapper.js";
5
- import W from "./CustomIcons/ArrowLeftIcon.js";
6
- import j from "./CustomIcons/DismissIcon.js";
7
- import w from "./Typography/EllipsisText.js";
8
- import { useOverlayBehaviour as D, OVERLAY_ICON_BUTTON_CLASSES as I } from "./overlayBehaviour.js";
9
- import { OVERLAY_ELEVATED_ATTR as F, overlayIdentity as R } from "./portalOverlay.js";
10
- const S = 200, X = (l) => typeof l == "number" ? `${l}px` : l, Z = ({
11
- open: l,
12
- onClose: n,
13
- title: i,
14
- subtitle: o,
15
- titleExtra: c,
16
- description: d,
17
- headerDivider: A = !1,
18
- icon: m,
19
- headerExtra: u,
20
- footer: p,
21
- onBack: f,
22
- maxWidth: k = 1080,
23
- "aria-label": z,
24
- "aria-labelledby": x,
25
- bodyPadding: h = !0,
26
- stacking: E = "default",
27
- children: b
2
+ import { useState as R, useRef as d, useEffect as F } from "react";
3
+ import { createPortal as X } from "react-dom";
4
+ import { ShadowRootWrapper as Y } from "../ShadowRootWrapper.js";
5
+ import q from "./CalloutStrip.js";
6
+ import U from "./CustomIcons/ArrowLeftIcon.js";
7
+ import G from "./CustomIcons/DismissIcon.js";
8
+ import A from "./Typography/EllipsisText.js";
9
+ import { useOverlayBehaviour as H, OVERLAY_ICON_BUTTON_CLASSES as k } from "./overlayBehaviour.js";
10
+ import { OVERLAY_ELEVATED_ATTR as J, overlayIdentity as z } from "./portalOverlay.js";
11
+ const E = 200, K = (t) => typeof t == "number" ? `${t}px` : t, oe = ({
12
+ open: t,
13
+ onClose: o,
14
+ title: n,
15
+ subtitle: c,
16
+ titleExtra: p,
17
+ description: u,
18
+ headerDivider: O = !1,
19
+ icon: f,
20
+ headerExtra: x,
21
+ footer: h,
22
+ onBack: b,
23
+ maxWidth: _ = 1080,
24
+ "aria-label": $,
25
+ "aria-labelledby": v,
26
+ bodyPadding: y = !0,
27
+ stacking: P = "default",
28
+ callouts: m,
29
+ renderLink: V,
30
+ children: N
28
31
  }) => {
29
- const [v, N] = g(!1), [O, y] = g(!1), t = s(null), r = s(null), T = s(null), {
30
- ref: _,
31
- isTopmost: $,
32
- zIndex: C,
33
- elevated: P
34
- } = D({
35
- open: l,
36
- onClose: n,
37
- elevated: E === "above-app-overlays",
38
- hostRef: T
32
+ const [g, T] = R(!1), [C, w] = R(!1), i = d(null), r = d(null), S = d(null), {
33
+ ref: L,
34
+ isTopmost: M,
35
+ zIndex: W,
36
+ elevated: j
37
+ } = H({
38
+ open: t,
39
+ onClose: o,
40
+ elevated: P === "above-app-overlays",
41
+ hostRef: S
39
42
  });
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);
44
- }, S)), () => {
45
- t.current !== null && (cancelAnimationFrame(t.current), t.current = null), r.current && (clearTimeout(r.current), r.current = null);
46
- }), [l]), O ? L(
43
+ if (F(() => (t ? (w(!0), r.current && (clearTimeout(r.current), r.current = null), i.current = requestAnimationFrame(() => {
44
+ i.current = null, T(!0);
45
+ })) : (T(!1), r.current = setTimeout(() => {
46
+ r.current = null, w(!1);
47
+ }, E)), () => {
48
+ i.current !== null && (cancelAnimationFrame(i.current), i.current = null), r.current && (clearTimeout(r.current), r.current = null);
49
+ }), [t]), !C)
50
+ return null;
51
+ const l = m == null ? void 0 : m.filter((s) => s.message.trim()), I = !!(l != null && l.length), B = y ? /* @__PURE__ */ e("div", { className: I ? "p-[28px]" : "py-[28px]", children: N }) : N;
52
+ return X(
47
53
  // Host carries the stacking context — ShadowRootWrapper's `isolation` would
48
54
  // otherwise flatten our z-index and let sticky page elements paint over us.
49
55
  /* @__PURE__ */ e(
50
- M,
56
+ Y,
51
57
  {
52
- hostRef: T,
53
- hostStyle: { position: "relative", zIndex: C },
54
- hostProps: P ? { ...R("sidepanel"), [F]: "" } : R("sidepanel"),
58
+ hostRef: S,
59
+ hostStyle: { position: "relative", zIndex: W },
60
+ hostProps: j ? { ...z("sidepanel"), [J]: "" } : z("sidepanel"),
55
61
  children: /* @__PURE__ */ a("div", { className: "fixed inset-0 z-[1000]", children: [
56
62
  /* @__PURE__ */ e(
57
63
  "div",
58
64
  {
59
65
  "aria-hidden": "true",
60
- onClick: n,
61
- className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${v ? "opacity-100" : "opacity-0"}`
66
+ onClick: o,
67
+ className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${g ? "opacity-100" : "opacity-0"}`
62
68
  }
63
69
  ),
64
70
  /* @__PURE__ */ a(
65
71
  "div",
66
72
  {
67
- ref: _,
73
+ ref: L,
68
74
  role: "dialog",
69
- "aria-modal": $ ? "true" : void 0,
75
+ "aria-modal": M ? "true" : void 0,
70
76
  tabIndex: -1,
71
- "aria-label": x ? void 0 : z ?? (typeof i == "string" ? i : void 0),
72
- "aria-labelledby": x,
77
+ "aria-label": v ? void 0 : $ ?? (typeof n == "string" ? n : void 0),
78
+ "aria-labelledby": v,
73
79
  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)]",
74
80
  style: {
75
- width: `min(calc(100% - 16px), ${X(k)})`,
81
+ width: `min(calc(100% - 16px), ${K(_)})`,
76
82
  // Inline: Tailwind translate utilities silently break inside
77
83
  // shadow roots (see CLAUDE.md Shadow DOM caveats).
78
- transform: v ? "translateX(0)" : "translateX(calc(100% + 16px))",
79
- transition: `transform ${S}ms ease-in-out`
84
+ transform: g ? "translateX(0)" : "translateX(calc(100% + 16px))",
85
+ transition: `transform ${E}ms ease-in-out`
80
86
  },
81
87
  children: [
82
88
  /* @__PURE__ */ a(
83
89
  "div",
84
90
  {
85
- className: `flex flex-col gap-[20px] px-[20px] py-[18px] ${A ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
91
+ className: `flex flex-col gap-[20px] px-[20px] py-[18px] ${O ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
86
92
  children: [
87
93
  /* @__PURE__ */ a("div", { className: "flex items-center gap-[12px]", children: [
88
- f ? /* @__PURE__ */ e(
94
+ b ? /* @__PURE__ */ e(
89
95
  "button",
90
96
  {
91
97
  type: "button",
92
98
  "aria-label": "Back",
93
- onClick: f,
94
- className: I,
95
- children: /* @__PURE__ */ e(W, { size: 16 })
99
+ onClick: b,
100
+ className: k,
101
+ children: /* @__PURE__ */ e(U, { size: 16 })
96
102
  }
97
103
  ) : null,
98
- m ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: m }) : null,
104
+ f ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: f }) : null,
99
105
  /* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-baseline gap-[12px]", children: [
100
106
  /* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-baseline gap-[8px]", children: [
101
107
  /* @__PURE__ */ a("div", { className: "flex min-w-0 items-baseline gap-[8px]", children: [
102
108
  /* @__PURE__ */ e("span", { className: "flex min-w-0 max-w-full shrink-0", children: /* @__PURE__ */ e(
103
- w,
109
+ A,
104
110
  {
105
- tooltip: i,
111
+ tooltip: n,
106
112
  tooltipWhenTruncated: !0,
107
113
  tooltipPlacement: "bottom",
108
114
  className: "min-w-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold",
109
- children: i
115
+ children: n
110
116
  }
111
117
  ) }),
112
- o ? /* @__PURE__ */ e(
113
- w,
118
+ c ? /* @__PURE__ */ e(
119
+ A,
114
120
  {
115
- tooltip: o,
121
+ tooltip: c,
116
122
  tooltipWhenTruncated: !0,
117
123
  tooltipPlacement: "bottom",
118
124
  color: "secondary",
119
125
  className: "min-w-0 text-[13px]",
120
- children: o
126
+ children: c
121
127
  }
122
128
  ) : null
123
129
  ] }),
124
- c ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: c }) : null
130
+ p ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: p }) : null
125
131
  ] }),
126
- u ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-baseline", children: u }) : null
132
+ x ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-baseline", children: x }) : null
127
133
  ] }),
128
134
  /* @__PURE__ */ e(
129
135
  "button",
130
136
  {
131
137
  type: "button",
132
138
  "aria-label": "Close",
133
- onClick: n,
134
- className: I,
135
- children: /* @__PURE__ */ e(j, { size: 10 })
139
+ onClick: o,
140
+ className: k,
141
+ children: /* @__PURE__ */ e(G, { size: 10 })
136
142
  }
137
143
  )
138
144
  ] }),
139
- d ? /* @__PURE__ */ e("div", { className: "text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]", children: d }) : null
145
+ u ? /* @__PURE__ */ e("div", { className: "text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]", children: u }) : null
140
146
  ]
141
147
  }
142
148
  ),
143
- /* @__PURE__ */ e(
149
+ /* @__PURE__ */ a(
144
150
  "div",
145
151
  {
146
- className: `min-h-0 flex-1 overflow-y-auto ${h ? "px-[28px]" : ""}`,
147
- children: h ? /* @__PURE__ */ e("div", { className: "py-[28px]", children: b }) : b
152
+ className: `min-h-0 flex-1 overflow-y-auto ${y && !I ? "px-[28px]" : ""}`,
153
+ children: [
154
+ l == null ? void 0 : l.map((s, D) => /* @__PURE__ */ e(
155
+ q,
156
+ {
157
+ type: s.type,
158
+ message: s.message,
159
+ renderLink: V
160
+ },
161
+ D
162
+ )),
163
+ B
164
+ ]
148
165
  }
149
166
  ),
150
- p ? /* @__PURE__ */ e("div", { className: "border-0 border-t border-solid border-[var(--malachite-card-border)] px-[24px] py-[16px]", children: p }) : null
167
+ h ? /* @__PURE__ */ e("div", { className: "border-0 border-t border-solid border-[var(--malachite-card-border)] px-[24px] py-[16px]", children: h }) : null
151
168
  ]
152
169
  }
153
170
  )
@@ -155,10 +172,10 @@ const S = 200, X = (l) => typeof l == "number" ? `${l}px` : l, Z = ({
155
172
  }
156
173
  ),
157
174
  document.body
158
- ) : null;
175
+ );
159
176
  };
160
177
  export {
161
- Z as SidePanel,
162
- Z as default
178
+ oe as SidePanel,
179
+ oe as default
163
180
  };
164
181
  //# 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 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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"}
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":"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"}
@@ -1,7 +1,9 @@
1
- import { jsx as i } from "react/jsx-runtime";
1
+ import { jsx as c } from "react/jsx-runtime";
2
2
  import { useRef as d } from "react";
3
- import { useAdoptedStyleSheet as c } from "./useAdoptedStyleSheet.js";
4
- const k = { small: 24, default: 32, large: 40 }, S = { small: 64, default: 96, large: 128 }, E = { small: 24, default: 32, large: 40 }, b = { small: 24, default: 32, large: 40 }, g = "malachite-skeleton-loading", u = "rgba(190, 190, 190, 0.2)", p = "rgba(129, 129, 129, 0.24)", y = `linear-gradient(90deg, ${u} 25%, ${p} 37%, ${u} 63%)`, f = `@keyframes ${g} { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }`, T = (e) => {
3
+ import { useAdoptedStyleSheet as u } from "./useAdoptedStyleSheet.js";
4
+ const E = { small: 24, default: 32, large: 40 }, S = { small: 64, default: 96, large: 128 }, T = { small: 24, default: 32, large: 40 }, b = { small: 24, default: 32, large: 40 }, g = "malachite-skeleton-loading", s = "rgba(190, 190, 190, 0.2)", p = "rgba(129, 129, 129, 0.24)", A = `linear-gradient(90deg, ${s} 25%, ${p} 37%, ${s} 63%)`, k = "data-malachite-skeleton-active", m = `@keyframes ${g} { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
5
+ [${k}] { background-image: ${A}; background-size: 400% 100%; animation: ${g} 1.4s ease infinite; }
6
+ @media (prefers-reduced-motion: reduce) { [${k}] { animation: none; background-image: none; } }`, _ = (e) => {
5
7
  switch (e) {
6
8
  case "round":
7
9
  case "circle":
@@ -11,93 +13,94 @@ const k = { small: 24, default: 32, large: 40 }, S = { small: 64, default: 96, l
11
13
  default:
12
14
  return 6;
13
15
  }
14
- }, m = (e) => ({
16
+ }, f = {
15
17
  display: "inline-block",
16
18
  verticalAlign: "middle",
17
- background: e ? y : u,
18
- backgroundSize: e ? "400% 100%" : void 0,
19
- animation: e ? `${g} 1.4s ease infinite` : void 0,
19
+ backgroundColor: s,
20
20
  flexShrink: 0
21
- }), A = ({
21
+ }, v = ({
22
22
  size: e = "default",
23
- shape: r = "default",
24
- block: n = !1,
25
- active: l = !0,
23
+ shape: n = "default",
24
+ block: r = !1,
25
+ active: o = !0,
26
26
  className: t,
27
27
  width: a,
28
- height: o,
29
- minWidth: s
28
+ height: i,
29
+ minWidth: l
30
30
  }) => {
31
31
  const h = d(null);
32
- return c(h, f, "malachite-skeleton-keyframes"), /* @__PURE__ */ i(
32
+ return u(h, m, "malachite-skeleton"), /* @__PURE__ */ c(
33
33
  "span",
34
34
  {
35
35
  ref: h,
36
36
  className: t,
37
+ "data-malachite-skeleton-active": o ? "" : void 0,
37
38
  "aria-busy": "true",
38
39
  "aria-hidden": "true",
39
40
  style: {
40
- ...m(l),
41
- width: n ? "100%" : a ?? S[e],
42
- height: o ?? k[e],
43
- minWidth: s,
44
- borderRadius: T(r)
41
+ ...f,
42
+ width: r ? "100%" : a ?? S[e],
43
+ height: i ?? E[e],
44
+ minWidth: l,
45
+ borderRadius: _(n)
45
46
  }
46
47
  }
47
48
  );
48
- }, R = ({
49
+ }, y = ({
49
50
  size: e = "default",
50
- block: r = !1,
51
- active: n = !0,
52
- className: l,
51
+ block: n = !1,
52
+ active: r = !0,
53
+ className: o,
53
54
  width: t,
54
55
  height: a,
55
- minWidth: o
56
+ minWidth: i
56
57
  }) => {
57
- const s = d(null);
58
- return c(s, f, "malachite-skeleton-keyframes"), /* @__PURE__ */ i(
58
+ const l = d(null);
59
+ return u(l, m, "malachite-skeleton"), /* @__PURE__ */ c(
59
60
  "span",
60
61
  {
61
- ref: s,
62
- className: l,
62
+ ref: l,
63
+ className: o,
64
+ "data-malachite-skeleton-active": r ? "" : void 0,
63
65
  "aria-busy": "true",
64
66
  "aria-hidden": "true",
65
67
  style: {
66
- ...m(n),
67
- width: r ? "100%" : t ?? 160,
68
- height: a ?? E[e],
69
- minWidth: o,
68
+ ...f,
69
+ width: n ? "100%" : t ?? 160,
70
+ height: a ?? T[e],
71
+ minWidth: i,
70
72
  borderRadius: 6
71
73
  }
72
74
  }
73
75
  );
74
76
  }, I = ({
75
77
  size: e = "default",
76
- shape: r = "circle",
77
- active: n = !0,
78
- className: l
78
+ shape: n = "circle",
79
+ active: r = !0,
80
+ className: o
79
81
  }) => {
80
82
  const t = d(null);
81
- c(t, f, "malachite-skeleton-keyframes");
83
+ u(t, m, "malachite-skeleton");
82
84
  const a = typeof e == "number" ? e : b[e];
83
- return /* @__PURE__ */ i(
85
+ return /* @__PURE__ */ c(
84
86
  "span",
85
87
  {
86
88
  ref: t,
87
- className: l,
89
+ className: o,
90
+ "data-malachite-skeleton-active": r ? "" : void 0,
88
91
  "aria-busy": "true",
89
92
  "aria-hidden": "true",
90
93
  style: {
91
- ...m(n),
94
+ ...f,
92
95
  width: a,
93
96
  height: a,
94
- borderRadius: r === "circle" ? 9999 : 6
97
+ borderRadius: n === "circle" ? 9999 : 6
95
98
  }
96
99
  }
97
100
  );
98
101
  }, B = {
99
- Button: A,
100
- Input: R,
102
+ Button: v,
103
+ Input: y,
101
104
  Avatar: I
102
105
  };
103
106
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"Skeleton.js","sources":["../../src/components/Skeleton.tsx"],"sourcesContent":["import React, { useRef } from 'react';\nimport { useAdoptedStyleSheet } from './useAdoptedStyleSheet';\n\ntype SkeletonSize = 'small' | 'default' | 'large';\ntype SkeletonShape = 'default' | 'round' | 'circle' | 'square';\n\ninterface BaseSkeletonProps {\n active?: boolean;\n className?: string;\n}\n\ninterface SkeletonButtonProps extends BaseSkeletonProps {\n size?: SkeletonSize;\n shape?: SkeletonShape;\n block?: boolean;\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n}\n\ninterface SkeletonInputProps extends BaseSkeletonProps {\n size?: SkeletonSize;\n block?: boolean;\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n}\n\ninterface SkeletonAvatarProps extends BaseSkeletonProps {\n size?: SkeletonSize | number;\n shape?: 'circle' | 'square';\n}\n\nconst BUTTON_HEIGHT: Record<SkeletonSize, number> = { small: 24, default: 32, large: 40 };\nconst BUTTON_WIDTH: Record<SkeletonSize, number> = { small: 64, default: 96, large: 128 };\nconst INPUT_HEIGHT: Record<SkeletonSize, number> = { small: 24, default: 32, large: 40 };\nconst AVATAR_SIZE: Record<SkeletonSize, number> = { small: 24, default: 32, large: 40 };\n\nconst KEYFRAME_NAME = 'malachite-skeleton-loading';\nconst SKELETON_BASE = 'rgba(190, 190, 190, 0.2)';\nconst SKELETON_SHIMMER = 'rgba(129, 129, 129, 0.24)';\nconst SKELETON_GRADIENT = `linear-gradient(90deg, ${SKELETON_BASE} 25%, ${SKELETON_SHIMMER} 37%, ${SKELETON_BASE} 63%)`;\nconst KEYFRAMES_CSS = `@keyframes ${KEYFRAME_NAME} { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }`;\n\nconst getRadius = (shape: SkeletonShape): string | number => {\n switch (shape) {\n case 'round':\n case 'circle':\n return 9999;\n case 'square':\n return 0;\n default:\n return 6;\n }\n};\n\nconst baseStyle = (active: boolean): React.CSSProperties => ({\n display: 'inline-block',\n verticalAlign: 'middle',\n background: active ? SKELETON_GRADIENT : SKELETON_BASE,\n backgroundSize: active ? '400% 100%' : undefined,\n animation: active ? `${KEYFRAME_NAME} 1.4s ease infinite` : undefined,\n flexShrink: 0,\n});\n\nconst SkeletonButton: React.FC<SkeletonButtonProps> = ({\n size = 'default',\n shape = 'default',\n block = false,\n active = true,\n className,\n width,\n height,\n minWidth,\n}) => {\n const ref = useRef<HTMLSpanElement>(null);\n useAdoptedStyleSheet(ref, KEYFRAMES_CSS, 'malachite-skeleton-keyframes');\n return (\n <span\n ref={ref}\n className={className}\n aria-busy=\"true\"\n aria-hidden=\"true\"\n style={{\n ...baseStyle(active),\n width: block ? '100%' : (width ?? BUTTON_WIDTH[size]),\n height: height ?? BUTTON_HEIGHT[size],\n minWidth,\n borderRadius: getRadius(shape),\n }}\n />\n );\n};\n\nconst SkeletonInput: React.FC<SkeletonInputProps> = ({\n size = 'default',\n block = false,\n active = true,\n className,\n width,\n height,\n minWidth,\n}) => {\n const ref = useRef<HTMLSpanElement>(null);\n useAdoptedStyleSheet(ref, KEYFRAMES_CSS, 'malachite-skeleton-keyframes');\n return (\n <span\n ref={ref}\n className={className}\n aria-busy=\"true\"\n aria-hidden=\"true\"\n style={{\n ...baseStyle(active),\n width: block ? '100%' : (width ?? 160),\n height: height ?? INPUT_HEIGHT[size],\n minWidth,\n borderRadius: 6,\n }}\n />\n );\n};\n\nconst SkeletonAvatar: React.FC<SkeletonAvatarProps> = ({\n size = 'default',\n shape = 'circle',\n active = true,\n className,\n}) => {\n const ref = useRef<HTMLSpanElement>(null);\n useAdoptedStyleSheet(ref, KEYFRAMES_CSS, 'malachite-skeleton-keyframes');\n const px = typeof size === 'number' ? size : AVATAR_SIZE[size];\n return (\n <span\n ref={ref}\n className={className}\n aria-busy=\"true\"\n aria-hidden=\"true\"\n style={{\n ...baseStyle(active),\n width: px,\n height: px,\n borderRadius: shape === 'circle' ? 9999 : 6,\n }}\n />\n );\n};\n\nconst Skeleton = {\n Button: SkeletonButton,\n Input: SkeletonInput,\n Avatar: SkeletonAvatar,\n};\n\nexport default Skeleton;\n"],"names":["BUTTON_HEIGHT","BUTTON_WIDTH","INPUT_HEIGHT","AVATAR_SIZE","KEYFRAME_NAME","SKELETON_BASE","SKELETON_SHIMMER","SKELETON_GRADIENT","KEYFRAMES_CSS","getRadius","shape","baseStyle","active","SkeletonButton","size","block","className","width","height","minWidth","ref","useRef","useAdoptedStyleSheet","jsx","SkeletonInput","SkeletonAvatar","px","Skeleton"],"mappings":"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"}
1
+ {"version":3,"file":"Skeleton.js","sources":["../../src/components/Skeleton.tsx"],"sourcesContent":["import React, { useRef } from 'react';\nimport { useAdoptedStyleSheet } from './useAdoptedStyleSheet';\n\ntype SkeletonSize = 'small' | 'default' | 'large';\ntype SkeletonShape = 'default' | 'round' | 'circle' | 'square';\n\ninterface BaseSkeletonProps {\n active?: boolean;\n className?: string;\n}\n\ninterface SkeletonButtonProps extends BaseSkeletonProps {\n size?: SkeletonSize;\n shape?: SkeletonShape;\n block?: boolean;\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n}\n\ninterface SkeletonInputProps extends BaseSkeletonProps {\n size?: SkeletonSize;\n block?: boolean;\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n}\n\ninterface SkeletonAvatarProps extends BaseSkeletonProps {\n size?: SkeletonSize | number;\n shape?: 'circle' | 'square';\n}\n\nconst BUTTON_HEIGHT: Record<SkeletonSize, number> = { small: 24, default: 32, large: 40 };\nconst BUTTON_WIDTH: Record<SkeletonSize, number> = { small: 64, default: 96, large: 128 };\nconst INPUT_HEIGHT: Record<SkeletonSize, number> = { small: 24, default: 32, large: 40 };\nconst AVATAR_SIZE: Record<SkeletonSize, number> = { small: 24, default: 32, large: 40 };\n\nconst KEYFRAME_NAME = 'malachite-skeleton-loading';\nconst SKELETON_BASE = 'rgba(190, 190, 190, 0.2)';\nconst SKELETON_SHIMMER = 'rgba(129, 129, 129, 0.24)';\nconst SKELETON_GRADIENT = `linear-gradient(90deg, ${SKELETON_BASE} 25%, ${SKELETON_SHIMMER} 37%, ${SKELETON_BASE} 63%)`;\nconst ACTIVE_ATTR = 'data-malachite-skeleton-active';\n// The shimmer lives in the sheet, not inline, so the reduced-motion query can switch it off.\nconst SKELETON_CSS = `@keyframes ${KEYFRAME_NAME} { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }\n[${ACTIVE_ATTR}] { background-image: ${SKELETON_GRADIENT}; background-size: 400% 100%; animation: ${KEYFRAME_NAME} 1.4s ease infinite; }\n@media (prefers-reduced-motion: reduce) { [${ACTIVE_ATTR}] { animation: none; background-image: none; } }`;\n\nconst getRadius = (shape: SkeletonShape): string | number => {\n switch (shape) {\n case 'round':\n case 'circle':\n return 9999;\n case 'square':\n return 0;\n default:\n return 6;\n }\n};\n\nconst BASE_STYLE: React.CSSProperties = {\n display: 'inline-block',\n verticalAlign: 'middle',\n backgroundColor: SKELETON_BASE,\n flexShrink: 0,\n};\n\nconst SkeletonButton: React.FC<SkeletonButtonProps> = ({\n size = 'default',\n shape = 'default',\n block = false,\n active = true,\n className,\n width,\n height,\n minWidth,\n}) => {\n const ref = useRef<HTMLSpanElement>(null);\n useAdoptedStyleSheet(ref, SKELETON_CSS, 'malachite-skeleton');\n return (\n <span\n ref={ref}\n className={className}\n data-malachite-skeleton-active={active ? '' : undefined}\n aria-busy=\"true\"\n aria-hidden=\"true\"\n style={{\n ...BASE_STYLE,\n width: block ? '100%' : (width ?? BUTTON_WIDTH[size]),\n height: height ?? BUTTON_HEIGHT[size],\n minWidth,\n borderRadius: getRadius(shape),\n }}\n />\n );\n};\n\nconst SkeletonInput: React.FC<SkeletonInputProps> = ({\n size = 'default',\n block = false,\n active = true,\n className,\n width,\n height,\n minWidth,\n}) => {\n const ref = useRef<HTMLSpanElement>(null);\n useAdoptedStyleSheet(ref, SKELETON_CSS, 'malachite-skeleton');\n return (\n <span\n ref={ref}\n className={className}\n data-malachite-skeleton-active={active ? '' : undefined}\n aria-busy=\"true\"\n aria-hidden=\"true\"\n style={{\n ...BASE_STYLE,\n width: block ? '100%' : (width ?? 160),\n height: height ?? INPUT_HEIGHT[size],\n minWidth,\n borderRadius: 6,\n }}\n />\n );\n};\n\nconst SkeletonAvatar: React.FC<SkeletonAvatarProps> = ({\n size = 'default',\n shape = 'circle',\n active = true,\n className,\n}) => {\n const ref = useRef<HTMLSpanElement>(null);\n useAdoptedStyleSheet(ref, SKELETON_CSS, 'malachite-skeleton');\n const px = typeof size === 'number' ? size : AVATAR_SIZE[size];\n return (\n <span\n ref={ref}\n className={className}\n data-malachite-skeleton-active={active ? '' : undefined}\n aria-busy=\"true\"\n aria-hidden=\"true\"\n style={{\n ...BASE_STYLE,\n width: px,\n height: px,\n borderRadius: shape === 'circle' ? 9999 : 6,\n }}\n />\n );\n};\n\nconst Skeleton = {\n Button: SkeletonButton,\n Input: SkeletonInput,\n Avatar: SkeletonAvatar,\n};\n\nexport default Skeleton;\n"],"names":["BUTTON_HEIGHT","BUTTON_WIDTH","INPUT_HEIGHT","AVATAR_SIZE","KEYFRAME_NAME","SKELETON_BASE","SKELETON_SHIMMER","SKELETON_GRADIENT","ACTIVE_ATTR","SKELETON_CSS","getRadius","shape","BASE_STYLE","SkeletonButton","size","block","active","className","width","height","minWidth","ref","useRef","useAdoptedStyleSheet","jsx","SkeletonInput","SkeletonAvatar","px","Skeleton"],"mappings":"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"}