@stackone/malachite 2.70.0 → 2.72.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 (34) hide show
  1. package/COMPONENTS.md +12 -11
  2. package/dist/components/Accordion.js +59 -53
  3. package/dist/components/Accordion.js.map +1 -1
  4. package/dist/components/Alert.js +100 -75
  5. package/dist/components/Alert.js.map +1 -1
  6. package/dist/components/Button.js +89 -82
  7. package/dist/components/Button.js.map +1 -1
  8. package/dist/components/Modal.js +75 -74
  9. package/dist/components/Modal.js.map +1 -1
  10. package/dist/components/PopoverParts.js +35 -35
  11. package/dist/components/PopoverParts.js.map +1 -1
  12. package/dist/components/Search.js +30 -29
  13. package/dist/components/Search.js.map +1 -1
  14. package/dist/components/SidePanel.js +124 -106
  15. package/dist/components/SidePanel.js.map +1 -1
  16. package/dist/components/StatusPill.js +61 -0
  17. package/dist/components/StatusPill.js.map +1 -0
  18. package/dist/components/Surface.js +138 -133
  19. package/dist/components/Surface.js.map +1 -1
  20. package/dist/components/Toolbar.js +40 -33
  21. package/dist/components/Toolbar.js.map +1 -1
  22. package/dist/components/Typography/EllipsisText.js +27 -25
  23. package/dist/components/Typography/EllipsisText.js.map +1 -1
  24. package/dist/components/Typography/MarkdownBlock.js +36 -28
  25. package/dist/components/Typography/MarkdownBlock.js.map +1 -1
  26. package/dist/components/Typography/Text.js +24 -22
  27. package/dist/components/Typography/Text.js.map +1 -1
  28. package/dist/components/WizardLayout.js +81 -67
  29. package/dist/components/WizardLayout.js.map +1 -1
  30. package/dist/index.d.ts +65 -2
  31. package/dist/index.js +356 -354
  32. package/dist/index.js.map +1 -1
  33. package/dist/tailwind.css.js +1 -1
  34. package/package.json +1 -1
@@ -1,104 +1,118 @@
1
- import { jsxs as l, jsx as e } from "react/jsx-runtime";
2
- import { useRef as b, useState as k, useLayoutEffect as $ } from "react";
3
- import { Button as j } from "./Button.js";
4
- import z from "./CustomIcons/ArrowLeftIcon.js";
5
- import { GLASS_SURFACE_STYLE as L } from "./glassSurface.js";
6
- const H = ({
7
- showBack: f = !1,
8
- onBack: x,
1
+ import { jsxs as s, jsx as e } from "react/jsx-runtime";
2
+ import { useRef as j, useState as L, useLayoutEffect as z } from "react";
3
+ import { Button as A } from "./Button.js";
4
+ import R from "./CustomIcons/ArrowLeftIcon.js";
5
+ import { GLASS_SURFACE_STYLE as B } from "./glassSurface.js";
6
+ const E = {
7
+ default: "px-6 pt-4 min-h-[var(--malachite-control-height-small,28px)]",
8
+ large: "h-[60px] px-[28px] max-sm:h-[52px] max-sm:px-[16px]"
9
+ }, F = ({
10
+ showBack: p = !1,
11
+ onBack: f,
9
12
  backDisabled: h = !1,
10
- leading: p,
11
- stepper: d,
12
- trailing: u,
13
- header: s,
14
- footer: t,
15
- footerGlass: v = !1,
16
- center: g = !1,
17
- contentWidth: i = 480,
18
- minWidth: r,
19
- children: w,
20
- className: y = ""
13
+ reserveBack: d = !0,
14
+ topBarSize: u = "default",
15
+ leading: v,
16
+ stepper: g,
17
+ trailing: w,
18
+ banner: r,
19
+ header: t,
20
+ footer: l,
21
+ footerGlass: N = !1,
22
+ footerAlign: y = "full",
23
+ center: b = !1,
24
+ contentWidth: a = 480,
25
+ minWidth: c,
26
+ children: k,
27
+ className: S = ""
21
28
  }) => {
22
- const n = b(null), [N, c] = k(0);
23
- return $(() => {
24
- const a = n.current;
25
- if (!a) {
26
- c(0);
29
+ const n = j(null), [$, o] = L(0);
30
+ return z(() => {
31
+ const i = n.current;
32
+ if (!i) {
33
+ o(0);
27
34
  return;
28
35
  }
29
- const o = () => c(a.offsetHeight);
30
- o();
31
- const m = new ResizeObserver(o);
32
- return m.observe(a), () => m.disconnect();
33
- }, [t]), /* @__PURE__ */ l(
36
+ const m = () => o(i.offsetHeight);
37
+ m();
38
+ const x = new ResizeObserver(m);
39
+ return x.observe(i), () => x.disconnect();
40
+ }, [l]), /* @__PURE__ */ s(
34
41
  "div",
35
42
  {
36
- className: `w-full h-screen flex flex-col overflow-hidden bg-[var(--malachite-card-sunken-background)] ${y}`,
37
- style: r ? { minWidth: `${r}px` } : void 0,
43
+ className: `w-full h-screen flex flex-col overflow-hidden bg-[var(--malachite-card-sunken-background)] ${S}`,
44
+ style: c ? { minWidth: `${c}px` } : void 0,
38
45
  children: [
39
- /* @__PURE__ */ l("div", { className: "w-full shrink-0 flex items-center justify-between px-6 pt-4 min-h-[var(--malachite-control-height-small,28px)]", children: [
40
- /* @__PURE__ */ l("div", { className: "flex items-center gap-[16px] min-w-0", children: [
41
- f ? /* @__PURE__ */ e(
42
- j,
43
- {
44
- variant: "outline",
45
- size: "small",
46
- iconOnly: !0,
47
- icon: /* @__PURE__ */ e(z, { size: 14 }),
48
- disabled: h,
49
- onClick: x,
50
- "aria-label": "Back",
51
- className: "w-[var(--malachite-control-height-small,28px)] h-[var(--malachite-control-height-small,28px)] shrink-0"
52
- }
53
- ) : /* @__PURE__ */ e("span", { className: "w-[var(--malachite-control-height-small,28px)] h-[var(--malachite-control-height-small,28px)] shrink-0" }),
54
- p
55
- ] }),
56
- /* @__PURE__ */ l("div", { className: "flex items-center gap-[16px]", children: [
57
- u ?? null,
58
- d ?? null
59
- ] })
60
- ] }),
61
- s ? /* @__PURE__ */ e("div", { className: "w-full shrink-0 flex flex-col items-center px-6 pt-8", children: /* @__PURE__ */ e(
46
+ /* @__PURE__ */ s(
47
+ "div",
48
+ {
49
+ className: `w-full shrink-0 flex items-center justify-between ${E[u]}`,
50
+ children: [
51
+ /* @__PURE__ */ s("div", { className: "flex items-center gap-[16px] min-w-0", children: [
52
+ p ? /* @__PURE__ */ e(
53
+ A,
54
+ {
55
+ variant: "outline",
56
+ size: "small",
57
+ iconOnly: !0,
58
+ icon: /* @__PURE__ */ e(R, { size: 14 }),
59
+ disabled: h,
60
+ onClick: f,
61
+ "aria-label": "Back",
62
+ className: "w-[var(--malachite-control-height-small,28px)] h-[var(--malachite-control-height-small,28px)] shrink-0"
63
+ }
64
+ ) : d ? /* @__PURE__ */ e("span", { className: "w-[var(--malachite-control-height-small,28px)] h-[var(--malachite-control-height-small,28px)] shrink-0" }) : null,
65
+ v
66
+ ] }),
67
+ /* @__PURE__ */ s("div", { className: "flex items-center gap-[16px]", children: [
68
+ w ?? null,
69
+ g ?? null
70
+ ] })
71
+ ]
72
+ }
73
+ ),
74
+ r ? /* @__PURE__ */ e("div", { className: "w-full shrink-0 px-[12px] pt-[12px]", children: r }) : null,
75
+ t ? /* @__PURE__ */ e("div", { className: "w-full shrink-0 flex flex-col items-center px-6 pt-8", children: /* @__PURE__ */ e(
62
76
  "div",
63
77
  {
64
78
  className: "w-full flex flex-col items-center gap-[24px]",
65
- style: { maxWidth: `${i}px` },
66
- children: s
79
+ style: { maxWidth: `${a}px` },
80
+ children: t
67
81
  }
68
82
  ) }) : null,
69
- /* @__PURE__ */ l("div", { className: "relative flex-1 min-h-0", children: [
83
+ /* @__PURE__ */ s("div", { className: "relative flex-1 min-h-0", children: [
70
84
  /* @__PURE__ */ e(
71
85
  "div",
72
86
  {
73
- className: `absolute inset-0 overflow-y-auto flex flex-col items-center px-6 ${g ? "justify-center" : "justify-start"}`,
87
+ className: `absolute inset-0 overflow-y-auto flex flex-col items-center px-6 ${b ? "justify-center" : "justify-start"}`,
74
88
  style: {
75
89
  // Reserve the overlaid footer's height plus a gap, so the last item
76
90
  // clears the footer with breathing room (not flush against it, which
77
91
  // reads as hidden content continuing underneath).
78
- paddingBottom: t ? `${N + 24}px` : "48px"
92
+ paddingBottom: l ? `${$ + 24}px` : "48px"
79
93
  },
80
94
  children: /* @__PURE__ */ e(
81
95
  "div",
82
96
  {
83
97
  className: "w-full flex flex-col items-center gap-[40px]",
84
98
  style: {
85
- maxWidth: `${i}px`,
99
+ maxWidth: `${a}px`,
86
100
  // Top padding lives on the scrolling content — NOT the scrollport —
87
101
  // so a `position: sticky` child pins flush to the top with no gap.
88
- paddingTop: s ? "32px" : "48px"
102
+ paddingTop: t ? "32px" : "48px"
89
103
  },
90
- children: w
104
+ children: k
91
105
  }
92
106
  )
93
107
  }
94
108
  ),
95
- t ? /* @__PURE__ */ e(
109
+ l ? /* @__PURE__ */ e(
96
110
  "div",
97
111
  {
98
112
  ref: n,
99
113
  className: "absolute inset-x-0 bottom-0 z-20",
100
- style: v ? L : void 0,
101
- children: t
114
+ style: N ? B : void 0,
115
+ children: y === "content" ? /* @__PURE__ */ e("div", { className: "flex justify-center px-6 pt-4 pb-3", children: /* @__PURE__ */ e("div", { className: "w-full", style: { maxWidth: `${a}px` }, children: l }) }) : l
102
116
  }
103
117
  ) : null
104
118
  ] })
@@ -107,7 +121,7 @@ const H = ({
107
121
  );
108
122
  };
109
123
  export {
110
- H as WizardLayout,
111
- H as default
124
+ F as WizardLayout,
125
+ F as default
112
126
  };
113
127
  //# sourceMappingURL=WizardLayout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WizardLayout.js","sources":["../../src/components/WizardLayout.tsx"],"sourcesContent":["import React, { useLayoutEffect, useRef, useState } from 'react';\nimport Button from './Button';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport { GLASS_SURFACE_STYLE } from './glassSurface';\n\nexport interface WizardLayoutProps {\n /** Renders the outline back button in the top-left slot. */\n showBack?: boolean;\n onBack?: () => void;\n backDisabled?: boolean;\n /** Top-left slot beside the back button — e.g. a user avatar menu. */\n leading?: React.ReactNode;\n /** Right top-bar slot (sits just before `stepper`) — e.g. a theme toggle. */\n stepper?: React.ReactNode;\n /** Far-right top-bar slot — e.g. a theme toggle. */\n trailing?: React.ReactNode;\n /**\n * Pinned below the top bar and always visible while the content scrolls —\n * e.g. connection logos + a step title. Rendered in the same centred column\n * as the content (`contentWidth`).\n */\n header?: React.ReactNode;\n /** Pinned to the bottom of the screen — typically a <FooterNav /> or a primary CTA. */\n footer?: React.ReactNode;\n /**\n * Give the pinned footer a frosted-glass treatment (translucent background +\n * backdrop blur) so scrolling content shows through it. The footer already sits\n * above sticky body content, so it reads as glass over the scrolling list.\n */\n footerGlass?: boolean;\n /** Vertically centre the content (used for terminal/success screens). */\n center?: boolean;\n /** Max width of the centered content column. */\n contentWidth?: number;\n /** Minimum width of the whole layout, below which it scrolls horizontally. */\n minWidth?: number;\n children?: React.ReactNode;\n className?: string;\n}\n\nconst WizardLayout: React.FC<WizardLayoutProps> = ({\n showBack = false,\n onBack,\n backDisabled = false,\n leading,\n stepper,\n trailing,\n header,\n footer,\n footerGlass = false,\n center = false,\n contentWidth = 480,\n minWidth,\n children,\n className = '',\n}) => {\n // The footer overlays the bottom of the scroll area (so content can glass under\n // it). Measure it so the scroll content reserves matching bottom space and the\n // last item is never hidden behind it.\n const footerRef = useRef<HTMLDivElement>(null);\n const [footerHeight, setFooterHeight] = useState(0);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: re-run when the footer node mounts/unmounts so the observer attaches to the current element.\n useLayoutEffect(() => {\n const el = footerRef.current;\n if (!el) {\n setFooterHeight(0);\n return;\n }\n const update = () => setFooterHeight(el.offsetHeight);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(el);\n return () => observer.disconnect();\n }, [footer]);\n\n return (\n <div\n className={`w-full h-screen flex flex-col overflow-hidden bg-[var(--malachite-card-sunken-background)] ${className}`}\n style={minWidth ? { minWidth: `${minWidth}px` } : undefined}\n >\n <div className=\"w-full shrink-0 flex items-center justify-between px-6 pt-4 min-h-[var(--malachite-control-height-small,28px)]\">\n <div className=\"flex items-center gap-[16px] min-w-0\">\n {showBack ? (\n <Button\n variant=\"outline\"\n size=\"small\"\n iconOnly\n icon={<ArrowLeftIcon size={14} />}\n disabled={backDisabled}\n onClick={onBack}\n aria-label=\"Back\"\n className=\"w-[var(--malachite-control-height-small,28px)] h-[var(--malachite-control-height-small,28px)] shrink-0\"\n />\n ) : (\n <span className=\"w-[var(--malachite-control-height-small,28px)] h-[var(--malachite-control-height-small,28px)] shrink-0\" />\n )}\n {leading}\n </div>\n <div className=\"flex items-center gap-[16px]\">\n {trailing ?? null}\n {stepper ?? null}\n </div>\n </div>\n\n {header ? (\n <div className=\"w-full shrink-0 flex flex-col items-center px-6 pt-8\">\n <div\n className=\"w-full flex flex-col items-center gap-[24px]\"\n style={{ maxWidth: `${contentWidth}px` }}\n >\n {header}\n </div>\n </div>\n ) : null}\n\n <div className=\"relative flex-1 min-h-0\">\n <div\n className={`absolute inset-0 overflow-y-auto flex flex-col items-center px-6 ${\n center ? 'justify-center' : 'justify-start'\n }`}\n style={{\n // Reserve the overlaid footer's height plus a gap, so the last item\n // clears the footer with breathing room (not flush against it, which\n // reads as hidden content continuing underneath).\n paddingBottom: footer ? `${footerHeight + 24}px` : '48px',\n }}\n >\n <div\n className=\"w-full flex flex-col items-center gap-[40px]\"\n style={{\n maxWidth: `${contentWidth}px`,\n // Top padding lives on the scrolling content — NOT the scrollport —\n // so a `position: sticky` child pins flush to the top with no gap.\n paddingTop: header ? '32px' : '48px',\n }}\n >\n {children}\n </div>\n </div>\n\n {footer ? (\n <div\n ref={footerRef}\n // z-20 keeps the pinned footer above sticky body content (e.g. a\n // sticky Accordion header at z-10) so it can't paint over the footer.\n className=\"absolute inset-x-0 bottom-0 z-20\"\n style={footerGlass ? GLASS_SURFACE_STYLE : undefined}\n >\n {footer}\n </div>\n ) : null}\n </div>\n </div>\n );\n};\n\nexport default WizardLayout;\nexport { WizardLayout };\n"],"names":["WizardLayout","showBack","onBack","backDisabled","leading","stepper","trailing","header","footer","footerGlass","center","contentWidth","minWidth","children","className","footerRef","useRef","footerHeight","setFooterHeight","useState","useLayoutEffect","el","update","observer","jsxs","jsx","Button","ArrowLeftIcon","GLASS_SURFACE_STYLE"],"mappings":"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"}
1
+ {"version":3,"file":"WizardLayout.js","sources":["../../src/components/WizardLayout.tsx"],"sourcesContent":["import React, { useLayoutEffect, useRef, useState } from 'react';\nimport Button from './Button';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport { GLASS_SURFACE_STYLE } from './glassSurface';\n\nexport interface WizardLayoutProps {\n /** Renders the outline back button in the top-left slot. */\n showBack?: boolean;\n onBack?: () => void;\n backDisabled?: boolean;\n /** `false` drops the hidden back button's square, so `leading` sits at the same inset as `trailing`. */\n reserveBack?: boolean;\n /** `large`: a 60px bar with 28px insets (52px and 16px below 640px), items centred. */\n topBarSize?: 'default' | 'large';\n /** Top-left slot beside the back button — e.g. a user avatar menu. */\n leading?: React.ReactNode;\n /** Right top-bar slot (sits just before `stepper`) — e.g. a theme toggle. */\n stepper?: React.ReactNode;\n /** Far-right top-bar slot — e.g. a theme toggle. */\n trailing?: React.ReactNode;\n /** A page-wide notice under the top bar, above `header`. */\n banner?: React.ReactNode;\n /**\n * Pinned below the top bar and always visible while the content scrolls —\n * e.g. connection logos + a step title. Rendered in the same centred column\n * as the content (`contentWidth`).\n */\n header?: React.ReactNode;\n /** Pinned to the bottom of the screen — typically a <FooterNav /> or a primary CTA. */\n footer?: React.ReactNode;\n /**\n * Give the pinned footer a frosted-glass treatment (translucent background +\n * backdrop blur) so scrolling content shows through it. The footer already sits\n * above sticky body content, so it reads as glass over the scrolling list.\n */\n footerGlass?: boolean;\n /** `content` holds the footer to the content column, so a full-width action lines up with the list. */\n footerAlign?: 'full' | 'content';\n /** Vertically centre the content (used for terminal/success screens). */\n center?: boolean;\n /** Max width of the centered content column. */\n contentWidth?: number;\n /** Minimum width of the whole layout, below which it scrolls horizontally. */\n minWidth?: number;\n children?: React.ReactNode;\n className?: string;\n}\n\nconst TOP_BAR_CLASSES: Record<NonNullable<WizardLayoutProps['topBarSize']>, string> = {\n default: 'px-6 pt-4 min-h-[var(--malachite-control-height-small,28px)]',\n large: 'h-[60px] px-[28px] max-sm:h-[52px] max-sm:px-[16px]',\n};\n\nconst WizardLayout: React.FC<WizardLayoutProps> = ({\n showBack = false,\n onBack,\n backDisabled = false,\n reserveBack = true,\n topBarSize = 'default',\n leading,\n stepper,\n trailing,\n banner,\n header,\n footer,\n footerGlass = false,\n footerAlign = 'full',\n center = false,\n contentWidth = 480,\n minWidth,\n children,\n className = '',\n}) => {\n // The footer overlays the bottom of the scroll area (so content can glass under\n // it). Measure it so the scroll content reserves matching bottom space and the\n // last item is never hidden behind it.\n const footerRef = useRef<HTMLDivElement>(null);\n const [footerHeight, setFooterHeight] = useState(0);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: re-run when the footer node mounts/unmounts so the observer attaches to the current element.\n useLayoutEffect(() => {\n const el = footerRef.current;\n if (!el) {\n setFooterHeight(0);\n return;\n }\n const update = () => setFooterHeight(el.offsetHeight);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(el);\n return () => observer.disconnect();\n }, [footer]);\n\n return (\n <div\n className={`w-full h-screen flex flex-col overflow-hidden bg-[var(--malachite-card-sunken-background)] ${className}`}\n style={minWidth ? { minWidth: `${minWidth}px` } : undefined}\n >\n <div\n className={`w-full shrink-0 flex items-center justify-between ${TOP_BAR_CLASSES[topBarSize]}`}\n >\n <div className=\"flex items-center gap-[16px] min-w-0\">\n {showBack ? (\n <Button\n variant=\"outline\"\n size=\"small\"\n iconOnly\n icon={<ArrowLeftIcon size={14} />}\n disabled={backDisabled}\n onClick={onBack}\n aria-label=\"Back\"\n className=\"w-[var(--malachite-control-height-small,28px)] h-[var(--malachite-control-height-small,28px)] shrink-0\"\n />\n ) : reserveBack ? (\n <span className=\"w-[var(--malachite-control-height-small,28px)] h-[var(--malachite-control-height-small,28px)] shrink-0\" />\n ) : null}\n {leading}\n </div>\n <div className=\"flex items-center gap-[16px]\">\n {trailing ?? null}\n {stepper ?? null}\n </div>\n </div>\n\n {banner ? <div className=\"w-full shrink-0 px-[12px] pt-[12px]\">{banner}</div> : null}\n\n {header ? (\n <div className=\"w-full shrink-0 flex flex-col items-center px-6 pt-8\">\n <div\n className=\"w-full flex flex-col items-center gap-[24px]\"\n style={{ maxWidth: `${contentWidth}px` }}\n >\n {header}\n </div>\n </div>\n ) : null}\n\n <div className=\"relative flex-1 min-h-0\">\n <div\n className={`absolute inset-0 overflow-y-auto flex flex-col items-center px-6 ${\n center ? 'justify-center' : 'justify-start'\n }`}\n style={{\n // Reserve the overlaid footer's height plus a gap, so the last item\n // clears the footer with breathing room (not flush against it, which\n // reads as hidden content continuing underneath).\n paddingBottom: footer ? `${footerHeight + 24}px` : '48px',\n }}\n >\n <div\n className=\"w-full flex flex-col items-center gap-[40px]\"\n style={{\n maxWidth: `${contentWidth}px`,\n // Top padding lives on the scrolling content — NOT the scrollport —\n // so a `position: sticky` child pins flush to the top with no gap.\n paddingTop: header ? '32px' : '48px',\n }}\n >\n {children}\n </div>\n </div>\n\n {footer ? (\n <div\n ref={footerRef}\n // z-20 keeps the pinned footer above sticky body content (e.g. a\n // sticky Accordion header at z-10) so it can't paint over the footer.\n className=\"absolute inset-x-0 bottom-0 z-20\"\n style={footerGlass ? GLASS_SURFACE_STYLE : undefined}\n >\n {footerAlign === 'content' ? (\n <div className=\"flex justify-center px-6 pt-4 pb-3\">\n <div className=\"w-full\" style={{ maxWidth: `${contentWidth}px` }}>\n {footer}\n </div>\n </div>\n ) : (\n footer\n )}\n </div>\n ) : null}\n </div>\n </div>\n );\n};\n\nexport default WizardLayout;\nexport { WizardLayout };\n"],"names":["TOP_BAR_CLASSES","WizardLayout","showBack","onBack","backDisabled","reserveBack","topBarSize","leading","stepper","trailing","banner","header","footer","footerGlass","footerAlign","center","contentWidth","minWidth","children","className","footerRef","useRef","footerHeight","setFooterHeight","useState","useLayoutEffect","el","update","observer","jsxs","jsx","Button","ArrowLeftIcon","GLASS_SURFACE_STYLE"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -51,6 +51,11 @@ declare interface AccordionBaseProps {
51
51
  * be interactive (e.g. a Checkbox) without nesting a button inside a button.
52
52
  */
53
53
  trailing?: default_2.ReactNode;
54
+ /** Before the title, outside the toggle button. */
55
+ leading?: default_2.ReactNode;
56
+ arrowPosition?: 'start' | 'end';
57
+ /** `false` keeps an open row on the card ground. */
58
+ highlightExpanded?: boolean;
54
59
  defaultExpanded?: boolean;
55
60
  isExpanded?: boolean;
56
61
  onToggle?: (expanded: boolean) => void;
@@ -180,6 +185,8 @@ export declare const AdvancedLogsIcon: React.FC<IconProps_4>;
180
185
 
181
186
  export declare const Alert: default_2.FC<AlertProps>;
182
187
 
188
+ export declare type AlertLayout = 'inline' | 'banner';
189
+
183
190
  declare interface AlertProps {
184
191
  type?: AlertType;
185
192
  message: string;
@@ -199,6 +206,10 @@ declare interface AlertProps {
199
206
  live?: boolean;
200
207
  /** Routes root-relative links in `message` through the app's router; see `MarkdownBlock`. */
201
208
  renderLink?: RenderLink;
209
+ /** `banner`: a 48px page-wide band. Applies only without `children`. */
210
+ layout?: AlertLayout;
211
+ /** A bold sentence the message runs on from. Plain text, not markdown. */
212
+ lead?: string;
202
213
  }
203
214
 
204
215
  export declare type AlertType = 'info' | 'success' | 'error' | 'warning' | 'assistant';
@@ -402,10 +413,14 @@ declare interface ButtonProps extends default_2.ButtonHTMLAttributes<HTMLButtonE
402
413
  contentAlign?: 'center' | 'start';
403
414
  /** Fills the container's width. */
404
415
  flexGrow?: boolean;
416
+ /** `wide` holds a 120px floor for a primary action. */
417
+ width?: 'auto' | 'wide';
405
418
  fill?: boolean;
406
419
  tooltip?: string;
407
420
  tooltipPlacement?: 'top' | 'bottom' | 'left' | 'right';
408
421
  iconOnly?: boolean;
422
+ /** Pulls a borderless button out by its own padding, so its label lines up with the text around it. */
423
+ flush?: boolean;
409
424
  children?: default_2.ReactNode;
410
425
  onClick?: default_2.MouseEventHandler<HTMLButtonElement & HTMLAnchorElement>;
411
426
  /** Renders the button as a real anchor, so a link action is never an <a> nested in a <button>. */
@@ -430,7 +445,9 @@ export declare type ButtonVariant = 'filled' | 'outline'
430
445
  * acts on what it produced. Provenance, not a severity: it says who is being asked, not
431
446
  * that anything is wrong.
432
447
  */
433
- | 'assistant' | 'destructive' | 'success' | 'warning' | 'error' | 'ghost' | 'no-style';
448
+ | 'assistant' | 'destructive' | 'success' | 'warning' | 'error' | 'ghost'
449
+ /** Text only, in the accent colour, for a secondary action beside a primary one. */
450
+ | 'quiet' | 'no-style';
434
451
 
435
452
  export declare const Card: default_2.FC<CardProps>;
436
453
 
@@ -1650,6 +1667,7 @@ declare interface EllipsisTextProps {
1650
1667
  maxWidth?: string;
1651
1668
  color?: TextColor;
1652
1669
  size?: FontSize;
1670
+ fontWeight?: FontWeight;
1653
1671
  /**
1654
1672
  * Show `tooltip` only when the text is actually cut off. Opt-in, because `tooltip` is any
1655
1673
  * node: a caller repeating the label wants this, and one supplying something the label does
@@ -3565,6 +3583,8 @@ export declare interface ModalProps {
3565
3583
  closeOnOverlayClick?: boolean;
3566
3584
  /** Whether the body gets default padding. Default: true. */
3567
3585
  bodyPadding?: boolean;
3586
+ /** `tall`: 600px, or the viewport less 160px, for content that sizes to its box. */
3587
+ bodyHeight?: 'auto' | 'tall';
3568
3588
  /** Full-width Alert bands at the top of the body, above `children`, in order. Unaffected by
3569
3589
  * `bodyPadding`, and announced ahead of the dialog's description. The message is markdown. */
3570
3590
  callouts?: {
@@ -4027,6 +4047,8 @@ declare type PopoverFocusSource = {
4027
4047
  export declare interface PopoverHeaderProps {
4028
4048
  title: string;
4029
4049
  action?: default_2.ReactNode;
4050
+ /** `false` drops the rule and sits the header 4px over the list. */
4051
+ divider?: boolean;
4030
4052
  }
4031
4053
 
4032
4054
  export declare type PopoverInitialFocus = default_2.RefObject<HTMLElement | null> | (() => HTMLElement | null | undefined);
@@ -4310,6 +4332,7 @@ export declare interface SearchProps {
4310
4332
  /** 'large' (42px) for form inputs; 'medium' (32px) for toolbars; 'small' (28px) in a table. */
4311
4333
  size?: SearchSize;
4312
4334
  variant?: SearchVariant;
4335
+ textSize?: SearchTextSize;
4313
4336
  disabled?: boolean;
4314
4337
  autoFocus?: boolean;
4315
4338
  className?: string;
@@ -4331,6 +4354,9 @@ export declare interface SearchProps {
4331
4354
 
4332
4355
  export declare type SearchSize = 'small' | 'medium' | 'large';
4333
4356
 
4357
+ /** `body` is the 14px body step at any size. */
4358
+ export declare type SearchTextSize = 'control' | 'body';
4359
+
4334
4360
  export declare const SearchTrigger: default_2.ForwardRefExoticComponent<SearchTriggerProps & default_2.RefAttributes<HTMLButtonElement>>;
4335
4361
 
4336
4362
  export declare interface SearchTriggerProps extends Omit<default_2.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'className' | 'style' | 'color' | 'type'> {
@@ -4663,12 +4689,15 @@ export declare interface SidePanelProps {
4663
4689
  /** Dismiss handler — close button, ESC, or overlay click. */
4664
4690
  onClose: () => void;
4665
4691
  title: default_2.ReactNode;
4666
- /** Secondary text, inline after the title. */
4667
4692
  subtitle?: default_2.ReactNode;
4693
+ /** `below` stacks the subtitle under the title, so neither truncates the other. */
4694
+ subtitlePlacement?: 'inline' | 'below';
4668
4695
  /** Content at the end of the title row, after the subtitle (e.g. a status tag). */
4669
4696
  titleExtra?: default_2.ReactNode;
4670
4697
  /** Block paragraph below the title row, spanning the header width. Announced as the panel's description. */
4671
4698
  description?: default_2.ReactNode;
4699
+ /** Pinned between the header and the scrolling body. */
4700
+ toolbar?: default_2.ReactNode;
4672
4701
  /** Divider under the header. Default: false. */
4673
4702
  headerDivider?: boolean;
4674
4703
  /** Leading header slot, typically a logo or icon. */
@@ -4853,6 +4882,26 @@ export declare interface StatusBadgeProps {
4853
4882
 
4854
4883
  export declare type StatusBadgeType = 'success' | 'error' | 'warning' | 'info';
4855
4884
 
4885
+ export declare const StatusPill: default_2.FC<StatusPillProps>;
4886
+
4887
+ export declare interface StatusPillProps {
4888
+ label: string;
4889
+ /** Set in the mono face after a `·`. */
4890
+ detail?: string;
4891
+ tone?: StatusPillTone;
4892
+ icon?: default_2.ReactNode;
4893
+ busy?: boolean;
4894
+ /** Makes it a `status` live region. Off by default, as on `Alert`. */
4895
+ live?: boolean;
4896
+ /** Names the live region; only applies with `live`. */
4897
+ 'aria-label'?: string;
4898
+ /** Only applies with `live`. */
4899
+ 'aria-labelledby'?: string;
4900
+ className?: string;
4901
+ }
4902
+
4903
+ export declare type StatusPillTone = 'success' | 'neutral' | 'warning' | 'error';
4904
+
4856
4905
  export declare const StepCurrentIcon: React.FC<IconProps_104>;
4857
4906
 
4858
4907
  export declare const Stepper: default_2.FC<StepperProps>;
@@ -4985,6 +5034,8 @@ declare interface SurfaceRowChromeProps {
4985
5034
  * an outcome, where the result belongs to the whole line rather than to one cell in it.
4986
5035
  */
4987
5036
  tone?: 'default' | 'muted' | 'success' | 'error';
5037
+ /** `compact` is an 8px by 16px inset the row owns. */
5038
+ inset?: 'none' | 'compact';
4988
5039
  className?: string;
4989
5040
  style?: default_2.CSSProperties;
4990
5041
  }
@@ -5323,6 +5374,7 @@ export declare interface TextProps {
5323
5374
  children: default_2.ReactNode;
5324
5375
  tooltip?: string;
5325
5376
  textAlign?: 'left' | 'center' | 'right' | 'justify';
5377
+ wrap?: boolean;
5326
5378
  /** The element it renders, for a heading or paragraph that keeps Text's look. */
5327
5379
  as?: TextElement;
5328
5380
  className?: string;
@@ -5454,6 +5506,9 @@ export declare interface ToolbarProps {
5454
5506
  * the content it pins over — the consumer then owns the gutter. */
5455
5507
  padding?: 'none' | 'compact' | 'default';
5456
5508
  layout?: 'plain' | 'filters';
5509
+ /** `page` paints the sunken page ground, for a bar that sits above a card. */
5510
+ surface?: 'card' | 'page';
5511
+ sticky?: boolean;
5457
5512
  className?: string;
5458
5513
  style?: default_2.CSSProperties;
5459
5514
  }
@@ -5583,12 +5638,18 @@ export declare interface WizardLayoutProps {
5583
5638
  showBack?: boolean;
5584
5639
  onBack?: () => void;
5585
5640
  backDisabled?: boolean;
5641
+ /** `false` drops the hidden back button's square, so `leading` sits at the same inset as `trailing`. */
5642
+ reserveBack?: boolean;
5643
+ /** `large`: a 60px bar with 28px insets (52px and 16px below 640px), items centred. */
5644
+ topBarSize?: 'default' | 'large';
5586
5645
  /** Top-left slot beside the back button — e.g. a user avatar menu. */
5587
5646
  leading?: default_2.ReactNode;
5588
5647
  /** Right top-bar slot (sits just before `stepper`) — e.g. a theme toggle. */
5589
5648
  stepper?: default_2.ReactNode;
5590
5649
  /** Far-right top-bar slot — e.g. a theme toggle. */
5591
5650
  trailing?: default_2.ReactNode;
5651
+ /** A page-wide notice under the top bar, above `header`. */
5652
+ banner?: default_2.ReactNode;
5592
5653
  /**
5593
5654
  * Pinned below the top bar and always visible while the content scrolls —
5594
5655
  * e.g. connection logos + a step title. Rendered in the same centred column
@@ -5603,6 +5664,8 @@ export declare interface WizardLayoutProps {
5603
5664
  * above sticky body content, so it reads as glass over the scrolling list.
5604
5665
  */
5605
5666
  footerGlass?: boolean;
5667
+ /** `content` holds the footer to the content column, so a full-width action lines up with the list. */
5668
+ footerAlign?: 'full' | 'content';
5606
5669
  /** Vertically centre the content (used for terminal/success screens). */
5607
5670
  center?: boolean;
5608
5671
  /** Max width of the centered content column. */