@stackone/malachite 2.63.0 → 2.64.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 +1 -0
- package/dist/components/CloseButton.js +76 -0
- package/dist/components/CloseButton.js.map +1 -0
- package/dist/components/SplitScreenLayout.js +21 -38
- package/dist/components/SplitScreenLayout.js.map +1 -1
- package/dist/components/focusRing.js +4 -3
- package/dist/components/focusRing.js.map +1 -1
- package/dist/index.d.ts +29 -0
- package/dist/index.js +284 -282
- package/dist/index.js.map +1 -1
- package/dist/tailwind.css.js +1 -1
- package/dist/theme.js +175 -151
- package/dist/theme.js.map +1 -1
- package/package.json +1 -1
package/COMPONENTS.md
CHANGED
|
@@ -98,6 +98,7 @@ The catalog of components exported from `@stackone/malachite`. **Reach for one o
|
|
|
98
98
|
## Buttons & actions
|
|
99
99
|
|
|
100
100
|
- **`Button`** — Primary button. Variants: `filled`, `outline`, `surface` (outline's geometry on a ground of its own, for a control sitting on a tinted surface), `assistant` (the violet the assistant is named in — provenance, not a severity: it says who is being asked, not that anything is wrong), `destructive`, `success`, `warning`, `error`, `ghost`, `no-style`. Supports `iconOnly`, `loading`, `tooltip`. _Key props:_ `variant`, `size`, `icon`, `iconOnly`, `loading`, `disabled`, `fill`, `tooltip`.
|
|
101
|
+
- **`CloseButton`** — The bare X that dismisses a screen, panel or wizard: secondary at rest, primary on hover and keyboard focus, with no box or background at either. Use it instead of a `ghost` `Button` (which draws a hover box) or `no-style` (which has no disabled look). `surface="inverse"` is for a panel that stays dark in every theme, such as `SplitScreenLayout`’s, and reads the `closeButton` theme tokens. `loading` swaps the X for a spinner and sets `aria-busy`. Disabled and loading both use `aria-disabled` rather than `disabled`, so they ignore clicks but stay focusable and can still trigger a `Tooltip` explaining why. Named "Close" unless `aria-label` says otherwise. _Key props:_ `onClick`, `aria-label`, `size` (`small` 24px | `medium` 32px, 12px glyph), `surface` (`default` | `inverse`), `disabled`, `loading`.
|
|
101
102
|
- **`PillButton`** — Pill-shaped button, often used for filters/toggleable chips. `shape="tab"` squares the top corners so a row of them reads as attached to whatever sits above — the controls under a chat composer. Pass `href` and an interactive, non-disabled pill renders a real anchor (cmd-click, copy-link) instead of navigating from `onClick`; a disabled or `interactive={false}` pill stays static, and an unsafe scheme such as `javascript:` is dropped. `target="_blank"` always carries `noopener noreferrer`. _Key props:_ `label`, `icon`, `trailingIcon`, `selected`, `disabled`, `interactive`, `size`, `variant`, `shape` (`pill` | `tab`), `onClick`, `href`, `target`, `rel`.
|
|
102
103
|
- **`Link`** — Styled anchor/link text. _Key props:_ `LinkProps`.
|
|
103
104
|
- **`InlineConfirm`** — A confirmation asked on the control that triggered it rather than in a modal, for a reversible bulk edit where a dialog would be heavier than the change it guards. Drawn to the design's chip: 33px tall, 12px radius, its confirm cell running to the pill's own edge between two rules. Reads its own `inlineConfirm` theme tokens — a shade off the `SelectionBar` it appears beside, by design. Carries a spinning glyph by default — its own, so it takes the pill's colour rather than the sheet's dimmed grey — standing for a change waiting on an answer; pass `icon={null}` to drop it or a node to replace it. Anchored placement is in viewport coordinates, so the chip must not sit inside an ancestor carrying `transform`, `filter` or `contain`. It takes focus on open so `Enter` confirms, dismisses on `Escape` (through the shared escape-layer stack, so the topmost overlay answers) or a click outside, and returns focus to whatever opened it. `role="alertdialog"` named by the message itself, so the confirm button is never announced bare. Only one can be open at a time: opening a second dismisses the first, so it is never ambiguous what Yes answers. Pass `anchorTo` (a ref to the control it answers for) and it pins itself to that control's left, follows it while the page or a sticky header scrolls, dismisses once it scrolls out of view, and treats clicks on it as inside — without which the same click would dismiss and reopen. Left unanchored it renders in flow for the consumer to place, and must then not sit in a container that clips overflow (`Table` header cells among them). Nothing renders while `open` is false, and its listeners are attached only while it is open. _Key props:_ `open`, `message`, `confirmLabel`, `onConfirm`, `onDismiss`, `anchorTo`, `icon`, `className`, `style`.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsx as l } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as f } from "react";
|
|
3
|
+
import h from "./CustomIcons/DismissIcon.js";
|
|
4
|
+
import { FOCUS_RING_CLOSE_BUTTON_INVERSE as v, FOCUS_RING as p } from "./focusRing.js";
|
|
5
|
+
const x = {
|
|
6
|
+
small: { target: 24, glyph: 12 },
|
|
7
|
+
medium: { target: 32, glyph: 12 }
|
|
8
|
+
}, y = {
|
|
9
|
+
default: {
|
|
10
|
+
idle: "text-[var(--malachite-text-secondary,rgb(123,123,123))]",
|
|
11
|
+
interactive: "hover:text-[var(--malachite-text-primary,rgb(10,10,10))] focus-visible:text-[var(--malachite-text-primary,rgb(10,10,10))]",
|
|
12
|
+
disabled: "text-[var(--malachite-text-dimmed,rgb(161,161,161))]",
|
|
13
|
+
focusRing: p
|
|
14
|
+
},
|
|
15
|
+
inverse: {
|
|
16
|
+
idle: "text-[var(--malachite-close-button-inverse-foreground,rgba(255,255,255,0.7))]",
|
|
17
|
+
interactive: "hover:text-[var(--malachite-close-button-inverse-hover-foreground,rgb(255,255,255))] focus-visible:text-[var(--malachite-close-button-inverse-hover-foreground,rgb(255,255,255))]",
|
|
18
|
+
disabled: "text-[var(--malachite-close-button-inverse-disabled-foreground,rgba(255,255,255,0.35))]",
|
|
19
|
+
focusRing: v
|
|
20
|
+
}
|
|
21
|
+
}, S = (e, a) => {
|
|
22
|
+
const { idle: r, interactive: o, disabled: t, focusRing: i } = y[e];
|
|
23
|
+
return `${{
|
|
24
|
+
enabled: `${r} ${o} cursor-pointer`,
|
|
25
|
+
disabled: `${t} cursor-not-allowed`,
|
|
26
|
+
loading: `${r} cursor-progress`
|
|
27
|
+
}[a]} ${i}`;
|
|
28
|
+
}, C = "flex shrink-0 items-center justify-center rounded-md border-0 bg-transparent p-0 transition-colors", $ = (e) => {
|
|
29
|
+
e.preventDefault(), e.stopPropagation();
|
|
30
|
+
}, E = f(
|
|
31
|
+
({
|
|
32
|
+
onClick: e,
|
|
33
|
+
"aria-label": a = "Close",
|
|
34
|
+
"aria-labelledby": r,
|
|
35
|
+
disabled: o = !1,
|
|
36
|
+
loading: t = !1,
|
|
37
|
+
size: i = "small",
|
|
38
|
+
surface: n = "default",
|
|
39
|
+
className: u = "",
|
|
40
|
+
...m
|
|
41
|
+
}, g) => {
|
|
42
|
+
const { target: d, glyph: s } = x[i], c = o && "disabled" || t && "loading" || "enabled", b = c !== "enabled";
|
|
43
|
+
return /* @__PURE__ */ l(
|
|
44
|
+
"button",
|
|
45
|
+
{
|
|
46
|
+
...m,
|
|
47
|
+
ref: g,
|
|
48
|
+
type: "button",
|
|
49
|
+
"aria-label": a,
|
|
50
|
+
"aria-labelledby": r,
|
|
51
|
+
"aria-disabled": b ? !0 : void 0,
|
|
52
|
+
"aria-busy": t ? !0 : void 0,
|
|
53
|
+
onClick: b ? $ : e,
|
|
54
|
+
className: `${C} ${S(n, c)} ${u}`,
|
|
55
|
+
style: { width: d, height: d },
|
|
56
|
+
children: t ? (
|
|
57
|
+
// Not `Spinner`: its smallest step is 14px inside a min-height wrapper.
|
|
58
|
+
/* @__PURE__ */ l(
|
|
59
|
+
"span",
|
|
60
|
+
{
|
|
61
|
+
"aria-hidden": !0,
|
|
62
|
+
className: "box-border shrink-0 animate-spin rounded-full border-2 border-solid border-current border-t-transparent motion-reduce:animate-none motion-reduce:border-t-current",
|
|
63
|
+
style: { width: s, height: s }
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
) : /* @__PURE__ */ l(h, { size: s })
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
E.displayName = "CloseButton";
|
|
72
|
+
export {
|
|
73
|
+
E as CloseButton,
|
|
74
|
+
E as default
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=CloseButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloseButton.js","sources":["../../src/components/CloseButton.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport { FOCUS_RING, FOCUS_RING_CLOSE_BUTTON_INVERSE } from './focusRing';\n\nexport type CloseButtonSize = 'small' | 'medium';\n\n/** `inverse` is for a surface that stays dark in every theme, e.g. `SplitScreenLayout`'s panel. */\nexport type CloseButtonSurface = 'default' | 'inverse';\n\nexport interface CloseButtonProps\n extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n | 'children'\n | 'className'\n | 'style'\n | 'color'\n | 'type'\n | 'disabled'\n | 'onClick'\n | 'aria-label'\n | 'aria-disabled'\n | 'aria-busy'\n > {\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n /** Accessible name. Defaults to \"Close\"; name what closes when there are several. */\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n disabled?: boolean;\n /** Shows a spinner in place of the X, sets `aria-busy` and ignores clicks. */\n loading?: boolean;\n /** `small` is a 24px target, `medium` a 32px one. The glyph is 12px in both. */\n size?: CloseButtonSize;\n surface?: CloseButtonSurface;\n className?: string;\n}\n\nconst SIZE_PX: Record<CloseButtonSize, { target: number; glyph: number }> = {\n small: { target: 24, glyph: 12 },\n medium: { target: 32, glyph: 12 },\n};\n\nconst SURFACE_CLASSES: Record<\n CloseButtonSurface,\n { idle: string; interactive: string; disabled: string; focusRing: string }\n> = {\n default: {\n idle: 'text-[var(--malachite-text-secondary,rgb(123,123,123))]',\n interactive:\n 'hover:text-[var(--malachite-text-primary,rgb(10,10,10))] focus-visible:text-[var(--malachite-text-primary,rgb(10,10,10))]',\n disabled: 'text-[var(--malachite-text-dimmed,rgb(161,161,161))]',\n focusRing: FOCUS_RING,\n },\n inverse: {\n idle: 'text-[var(--malachite-close-button-inverse-foreground,rgba(255,255,255,0.7))]',\n interactive:\n 'hover:text-[var(--malachite-close-button-inverse-hover-foreground,rgb(255,255,255))] focus-visible:text-[var(--malachite-close-button-inverse-hover-foreground,rgb(255,255,255))]',\n disabled:\n 'text-[var(--malachite-close-button-inverse-disabled-foreground,rgba(255,255,255,0.35))]',\n focusRing: FOCUS_RING_CLOSE_BUTTON_INVERSE,\n },\n};\n\ntype CloseButtonState = 'enabled' | 'disabled' | 'loading';\n\nconst stateClassesOf = (surface: CloseButtonSurface, state: CloseButtonState): string => {\n const { idle, interactive, disabled, focusRing } = SURFACE_CLASSES[surface];\n const byState: Record<CloseButtonState, string> = {\n enabled: `${idle} ${interactive} cursor-pointer`,\n disabled: `${disabled} cursor-not-allowed`,\n loading: `${idle} cursor-progress`,\n };\n return `${byState[state]} ${focusRing}`;\n};\n\nconst BASE_CLASSES =\n 'flex shrink-0 items-center justify-center rounded-md border-0 bg-transparent p-0 transition-colors';\n\n// A click on an aria-disabled button still dispatches, so stop it before an ancestor's handler runs.\nconst swallowClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n};\n\n/** The bare X that dismisses a screen or panel: no box at rest or on hover. */\nconst CloseButton = forwardRef<HTMLButtonElement, CloseButtonProps>(\n (\n {\n onClick,\n 'aria-label': ariaLabel = 'Close',\n 'aria-labelledby': ariaLabelledBy,\n disabled = false,\n loading = false,\n size = 'small',\n surface = 'default',\n className = '',\n ...rest\n },\n ref,\n ) => {\n const { target, glyph } = SIZE_PX[size];\n const state: CloseButtonState =\n (disabled && 'disabled') || (loading && 'loading') || 'enabled';\n const inactive = state !== 'enabled';\n\n return (\n <button\n {...rest}\n ref={ref}\n type=\"button\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n // aria-disabled, not `disabled`: a disabled element gets no pointer events, so a\n // wrapping Tooltip could never explain it, and focus would drop to <body> mid-request.\n aria-disabled={inactive ? true : undefined}\n aria-busy={loading ? true : undefined}\n onClick={inactive ? swallowClick : onClick}\n className={`${BASE_CLASSES} ${stateClassesOf(surface, state)} ${className}`}\n style={{ width: target, height: target }}\n >\n {loading ? (\n // Not `Spinner`: its smallest step is 14px inside a min-height wrapper.\n <span\n aria-hidden\n className=\"box-border shrink-0 animate-spin rounded-full border-2 border-solid border-current border-t-transparent motion-reduce:animate-none motion-reduce:border-t-current\"\n style={{ width: glyph, height: glyph }}\n />\n ) : (\n <DismissIcon size={glyph} />\n )}\n </button>\n );\n },\n);\n\nCloseButton.displayName = 'CloseButton';\n\nexport default CloseButton;\nexport { CloseButton };\n"],"names":["SIZE_PX","SURFACE_CLASSES","FOCUS_RING","FOCUS_RING_CLOSE_BUTTON_INVERSE","stateClassesOf","surface","state","idle","interactive","disabled","focusRing","BASE_CLASSES","swallowClick","event","CloseButton","forwardRef","onClick","ariaLabel","ariaLabelledBy","loading","size","className","rest","ref","target","glyph","inactive","jsx","DismissIcon"],"mappings":";;;;AAoCA,MAAMA,IAAsE;AAAA,EACxE,OAAO,EAAE,QAAQ,IAAI,OAAO,GAAA;AAAA,EAC5B,QAAQ,EAAE,QAAQ,IAAI,OAAO,GAAA;AACjC,GAEMC,IAGF;AAAA,EACA,SAAS;AAAA,IACL,MAAM;AAAA,IACN,aACI;AAAA,IACJ,UAAU;AAAA,IACV,WAAWC;AAAA,EAAA;AAAA,EAEf,SAAS;AAAA,IACL,MAAM;AAAA,IACN,aACI;AAAA,IACJ,UACI;AAAA,IACJ,WAAWC;AAAA,EAAA;AAEnB,GAIMC,IAAiB,CAACC,GAA6BC,MAAoC;AACrF,QAAM,EAAE,MAAAC,GAAM,aAAAC,GAAa,UAAAC,GAAU,WAAAC,EAAA,IAAcT,EAAgBI,CAAO;AAM1E,SAAO,GAL2C;AAAA,IAC9C,SAAS,GAAGE,CAAI,IAAIC,CAAW;AAAA,IAC/B,UAAU,GAAGC,CAAQ;AAAA,IACrB,SAAS,GAAGF,CAAI;AAAA,EAAA,EAEFD,CAAK,CAAC,IAAII,CAAS;AACzC,GAEMC,IACF,sGAGEC,IAAe,CAACC,MAA+C;AACjE,EAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AACV,GAGMC,IAAcC;AAAA,EAChB,CACI;AAAA,IACI,SAAAC;AAAA,IACA,cAAcC,IAAY;AAAA,IAC1B,mBAAmBC;AAAA,IACnB,UAAAT,IAAW;AAAA,IACX,SAAAU,IAAU;AAAA,IACV,MAAAC,IAAO;AAAA,IACP,SAAAf,IAAU;AAAA,IACV,WAAAgB,IAAY;AAAA,IACZ,GAAGC;AAAA,EAAA,GAEPC,MACC;AACD,UAAM,EAAE,QAAAC,GAAQ,OAAAC,MAAUzB,EAAQoB,CAAI,GAChCd,IACDG,KAAY,cAAgBU,KAAW,aAAc,WACpDO,IAAWpB,MAAU;AAE3B,WACI,gBAAAqB;AAAA,MAAC;AAAA,MAAA;AAAA,QACI,GAAGL;AAAA,QACJ,KAAAC;AAAA,QACA,MAAK;AAAA,QACL,cAAYN;AAAA,QACZ,mBAAiBC;AAAA,QAGjB,iBAAeQ,IAAW,KAAO;AAAA,QACjC,aAAWP,IAAU,KAAO;AAAA,QAC5B,SAASO,IAAWd,IAAeI;AAAA,QACnC,WAAW,GAAGL,CAAY,IAAIP,EAAeC,GAASC,CAAK,CAAC,IAAIe,CAAS;AAAA,QACzE,OAAO,EAAE,OAAOG,GAAQ,QAAQA,EAAA;AAAA,QAE/B,UAAAL;AAAA;AAAA,UAEG,gBAAAQ;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,eAAW;AAAA,cACX,WAAU;AAAA,cACV,OAAO,EAAE,OAAOF,GAAO,QAAQA,EAAA;AAAA,YAAM;AAAA,UAAA;AAAA,YAGzC,gBAAAE,EAACC,GAAA,EAAY,MAAMH,EAAA,CAAO;AAAA,MAAA;AAAA,IAAA;AAAA,EAI1C;AACJ;AAEAX,EAAY,cAAc;"}
|
|
@@ -1,51 +1,34 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"button",
|
|
8
|
-
{
|
|
9
|
-
type: "button",
|
|
10
|
-
"aria-label": "Close",
|
|
11
|
-
onClick: i,
|
|
12
|
-
className: `flex cursor-pointer items-center justify-center border-0 bg-transparent p-0 transition-colors ${s}`,
|
|
13
|
-
children: /* @__PURE__ */ e(c, { size: 12 })
|
|
14
|
-
}
|
|
15
|
-
), x = ({
|
|
16
|
-
left: i,
|
|
17
|
-
right: s,
|
|
18
|
-
logo: a,
|
|
1
|
+
import { jsxs as i, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { CloseButton as s } from "./CloseButton.js";
|
|
3
|
+
const f = ({
|
|
4
|
+
left: a,
|
|
5
|
+
right: n,
|
|
6
|
+
logo: r,
|
|
19
7
|
onClose: l,
|
|
20
|
-
footer:
|
|
21
|
-
}) => /* @__PURE__ */
|
|
22
|
-
/* @__PURE__ */
|
|
23
|
-
/* @__PURE__ */
|
|
8
|
+
footer: c
|
|
9
|
+
}) => /* @__PURE__ */ i("div", { className: "flex h-screen w-full overflow-hidden gap-3 bg-[var(--malachite-card-sunken-background)] p-3", children: [
|
|
10
|
+
/* @__PURE__ */ i("div", { className: "flex min-w-0 flex-1 flex-col items-center px-[60px] py-[40px]", children: [
|
|
11
|
+
/* @__PURE__ */ i("div", { className: "flex h-6 w-full shrink-0 items-center justify-between", children: [
|
|
24
12
|
/* @__PURE__ */ e("span", { className: "size-6 shrink-0", "aria-hidden": !0 }),
|
|
25
|
-
|
|
26
|
-
/* @__PURE__ */ e("span", { className: "flex size-6 shrink-0 items-center justify-center", children: l ? /* @__PURE__ */ e(
|
|
27
|
-
r,
|
|
28
|
-
{
|
|
29
|
-
onClose: l,
|
|
30
|
-
className: "text-[var(--malachite-text-secondary)] hover:text-[var(--malachite-text-primary)] lg:hidden"
|
|
31
|
-
}
|
|
32
|
-
) : null })
|
|
13
|
+
r ?? /* @__PURE__ */ e("span", { className: "size-6 shrink-0", "aria-hidden": !0 }),
|
|
14
|
+
/* @__PURE__ */ e("span", { className: "flex size-6 shrink-0 items-center justify-center", children: l ? /* @__PURE__ */ e(s, { onClick: l, className: "lg:hidden" }) : null })
|
|
33
15
|
] }),
|
|
34
|
-
/* @__PURE__ */ e("div", { className: "flex w-full min-h-0 flex-1 flex-col overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ e("div", { className: "m-auto flex w-full max-w-[380px] flex-col items-center py-10", children:
|
|
35
|
-
/* @__PURE__ */ e("div", { className: "flex h-6 shrink-0 items-center justify-center", children:
|
|
16
|
+
/* @__PURE__ */ e("div", { className: "flex w-full min-h-0 flex-1 flex-col overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ e("div", { className: "m-auto flex w-full max-w-[380px] flex-col items-center py-10", children: a }) }),
|
|
17
|
+
/* @__PURE__ */ e("div", { className: "flex h-6 shrink-0 items-center justify-center", children: c })
|
|
36
18
|
] }),
|
|
37
|
-
/* @__PURE__ */
|
|
19
|
+
/* @__PURE__ */ i("div", { className: "relative hidden min-w-0 flex-1 flex-col items-center justify-center overflow-hidden rounded-[28px] bg-[#2b2b2b] px-[60px] py-[40px] lg:flex", children: [
|
|
38
20
|
l ? /* @__PURE__ */ e(
|
|
39
|
-
|
|
21
|
+
s,
|
|
40
22
|
{
|
|
41
|
-
|
|
42
|
-
|
|
23
|
+
onClick: l,
|
|
24
|
+
surface: "inverse",
|
|
25
|
+
className: "absolute top-[34px] right-[54px] z-10"
|
|
43
26
|
}
|
|
44
27
|
) : null,
|
|
45
|
-
|
|
28
|
+
n
|
|
46
29
|
] })
|
|
47
30
|
] });
|
|
48
31
|
export {
|
|
49
|
-
|
|
32
|
+
f as default
|
|
50
33
|
};
|
|
51
34
|
//# sourceMappingURL=SplitScreenLayout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SplitScreenLayout.js","sources":["../../src/components/SplitScreenLayout.tsx"],"sourcesContent":["import React from 'react';\nimport
|
|
1
|
+
{"version":3,"file":"SplitScreenLayout.js","sources":["../../src/components/SplitScreenLayout.tsx"],"sourcesContent":["import React from 'react';\nimport CloseButton from './CloseButton';\n\ninterface SplitScreenLayoutProps {\n left: React.ReactNode;\n right: React.ReactNode;\n logo?: React.ReactNode;\n onClose?: () => void;\n footer?: React.ReactNode;\n}\n\nconst SplitScreenLayout: React.FC<SplitScreenLayoutProps> = ({\n left,\n right,\n logo,\n onClose,\n footer,\n}) => (\n <div className=\"flex h-screen w-full overflow-hidden gap-3 bg-[var(--malachite-card-sunken-background)] p-3\">\n <div className=\"flex min-w-0 flex-1 flex-col items-center px-[60px] py-[40px]\">\n <div className=\"flex h-6 w-full shrink-0 items-center justify-between\">\n <span className=\"size-6 shrink-0\" aria-hidden />\n {logo ?? <span className=\"size-6 shrink-0\" aria-hidden />}\n <span className=\"flex size-6 shrink-0 items-center justify-center\">\n {onClose ? <CloseButton onClick={onClose} className=\"lg:hidden\" /> : null}\n </span>\n </div>\n <div className=\"flex w-full min-h-0 flex-1 flex-col overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\">\n <div className=\"m-auto flex w-full max-w-[380px] flex-col items-center py-10\">\n {left}\n </div>\n </div>\n <div className=\"flex h-6 shrink-0 items-center justify-center\">{footer}</div>\n </div>\n <div className=\"relative hidden min-w-0 flex-1 flex-col items-center justify-center overflow-hidden rounded-[28px] bg-[#2b2b2b] px-[60px] py-[40px] lg:flex\">\n {/* 6px in from 40/60: the 24px target is 12px wider than the glyph, which stays put. */}\n {onClose ? (\n <CloseButton\n onClick={onClose}\n surface=\"inverse\"\n className=\"absolute top-[34px] right-[54px] z-10\"\n />\n ) : null}\n {right}\n </div>\n </div>\n);\n\nexport default SplitScreenLayout;\n"],"names":["SplitScreenLayout","left","right","logo","onClose","footer","jsxs","jsx","CloseButton"],"mappings":";;AAWA,MAAMA,IAAsD,CAAC;AAAA,EACzD,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,MAAAC;AAAA,EACA,SAAAC;AAAA,EACA,QAAAC;AACJ,MACI,gBAAAC,EAAC,OAAA,EAAI,WAAU,+FACX,UAAA;AAAA,EAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,iEACX,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,yDACX,UAAA;AAAA,MAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,mBAAkB,eAAW,IAAC;AAAA,MAC7CJ,KAAQ,gBAAAI,EAAC,QAAA,EAAK,WAAU,mBAAkB,eAAW,IAAC;AAAA,MACvD,gBAAAA,EAAC,QAAA,EAAK,WAAU,oDACX,UAAAH,IAAU,gBAAAG,EAACC,GAAA,EAAY,SAASJ,GAAS,WAAU,YAAA,CAAY,IAAK,KAAA,CACzE;AAAA,IAAA,GACJ;AAAA,IACA,gBAAAG,EAAC,SAAI,WAAU,4GACX,4BAAC,OAAA,EAAI,WAAU,gEACV,UAAAN,EAAA,CACL,EAAA,CACJ;AAAA,IACA,gBAAAM,EAAC,OAAA,EAAI,WAAU,iDAAiD,UAAAF,EAAA,CAAO;AAAA,EAAA,GAC3E;AAAA,EACA,gBAAAC,EAAC,OAAA,EAAI,WAAU,+IAEV,UAAA;AAAA,IAAAF,IACG,gBAAAG;AAAA,MAACC;AAAA,MAAA;AAAA,QACG,SAASJ;AAAA,QACT,SAAQ;AAAA,QACR,WAAU;AAAA,MAAA;AAAA,IAAA,IAEd;AAAA,IACHF;AAAA,EAAA,EAAA,CACL;AAAA,EAAA,CACJ;"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
const o = "outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-text-primary)]", e = "outline-none focus-visible:[outline:2px_solid_var(--malachite-text-primary)] focus-visible:[outline-offset:-2px]", i = "pointer-events-none absolute inset-0 z-[2] hidden group-focus-visible:block [outline:2px_solid_var(--malachite-text-primary)] [outline-offset:-2px]", t = "outline-none has-[[role=radio]:focus-visible]:outline-offset-2 has-[[role=radio]:focus-visible]:[outline:2px_solid_var(--malachite-text-primary)]",
|
|
1
|
+
const o = "outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-text-primary)]", e = "outline-none focus-visible:[outline:2px_solid_var(--malachite-text-primary)] focus-visible:[outline-offset:-2px]", i = "pointer-events-none absolute inset-0 z-[2] hidden group-focus-visible:block [outline:2px_solid_var(--malachite-text-primary)] [outline-offset:-2px]", t = "outline-none has-[[role=radio]:focus-visible]:outline-offset-2 has-[[role=radio]:focus-visible]:[outline:2px_solid_var(--malachite-text-primary)]", s = "outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-selection-bar-foreground)]", l = "outline-none focus-visible:[outline:2px_solid_var(--malachite-inline-confirm-foreground)] focus-visible:[outline-offset:-2px]", n = "outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-close-button-inverse-hover-foreground,rgb(255,255,255))]";
|
|
2
2
|
export {
|
|
3
3
|
o as FOCUS_RING,
|
|
4
|
-
|
|
4
|
+
n as FOCUS_RING_CLOSE_BUTTON_INVERSE,
|
|
5
|
+
l as FOCUS_RING_INLINE_CONFIRM_INSET,
|
|
5
6
|
e as FOCUS_RING_INSET,
|
|
6
7
|
i as FOCUS_RING_INSET_OVERLAY,
|
|
7
|
-
|
|
8
|
+
s as FOCUS_RING_SELECTION_BAR,
|
|
8
9
|
t as FOCUS_RING_WITHIN_RADIO
|
|
9
10
|
};
|
|
10
11
|
//# sourceMappingURL=focusRing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focusRing.js","sources":["../../src/components/focusRing.ts"],"sourcesContent":["// Shared keyboard focus indicator for interactive components.\n\n/** Standard focus ring — sits 2px outside the control. */\nexport const FOCUS_RING =\n 'outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-text-primary)]';\n\n/**\n * Inset focus ring — drawn 2px inside the element edge. Use for full-bleed elements\n * inside an `overflow-hidden` container (e.g. Surface.Row) where an outset outline\n * would be clipped.\n */\nexport const FOCUS_RING_INSET =\n 'outline-none focus-visible:[outline:2px_solid_var(--malachite-text-primary)] focus-visible:[outline-offset:-2px]';\n\n/** `FOCUS_RING_INSET` drawn by an overlay while its `group` ancestor has keyboard focus. */\nexport const FOCUS_RING_INSET_OVERLAY =\n 'pointer-events-none absolute inset-0 z-[2] hidden group-focus-visible:block [outline:2px_solid_var(--malachite-text-primary)] [outline-offset:-2px]';\n\n/** Ring drawn on a wrapper when a control *inside* it takes focus. */\nexport const FOCUS_RING_WITHIN =\n 'outline-none has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:[outline:2px_solid_var(--malachite-text-primary)]';\n\n/**\n * As `FOCUS_RING_WITHIN`, for a card whose control is a `role=\"radio\"` beside its links:\n * `:has(:focus-visible)` would also match a focused link and draw a second ring.\n */\nexport const FOCUS_RING_WITHIN_RADIO =\n 'outline-none has-[[role=radio]:focus-visible]:outline-offset-2 has-[[role=radio]:focus-visible]:[outline:2px_solid_var(--malachite-text-primary)]';\n\n/** Ring for a control on the SelectionBar, where `FOCUS_RING` would be invisible. */\nexport const FOCUS_RING_SELECTION_BAR =\n 'outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-selection-bar-foreground)]';\n\n/** Inset ring for a control on the InlineConfirm chip. */\nexport const FOCUS_RING_INLINE_CONFIRM_INSET =\n 'outline-none focus-visible:[outline:2px_solid_var(--malachite-inline-confirm-foreground)] focus-visible:[outline-offset:-2px]';\n"],"names":["FOCUS_RING","FOCUS_RING_INSET","FOCUS_RING_INSET_OVERLAY","FOCUS_RING_WITHIN_RADIO","FOCUS_RING_SELECTION_BAR","FOCUS_RING_INLINE_CONFIRM_INSET"],"mappings":"AAGO,MAAMA,IACT,+GAOSC,IACT,oHAGSC,IACT,uJAUSC,IACT,qJAGSC,IACT,2HAGSC,IACT;"}
|
|
1
|
+
{"version":3,"file":"focusRing.js","sources":["../../src/components/focusRing.ts"],"sourcesContent":["// Shared keyboard focus indicator for interactive components.\n\n/** Standard focus ring — sits 2px outside the control. */\nexport const FOCUS_RING =\n 'outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-text-primary)]';\n\n/**\n * Inset focus ring — drawn 2px inside the element edge. Use for full-bleed elements\n * inside an `overflow-hidden` container (e.g. Surface.Row) where an outset outline\n * would be clipped.\n */\nexport const FOCUS_RING_INSET =\n 'outline-none focus-visible:[outline:2px_solid_var(--malachite-text-primary)] focus-visible:[outline-offset:-2px]';\n\n/** `FOCUS_RING_INSET` drawn by an overlay while its `group` ancestor has keyboard focus. */\nexport const FOCUS_RING_INSET_OVERLAY =\n 'pointer-events-none absolute inset-0 z-[2] hidden group-focus-visible:block [outline:2px_solid_var(--malachite-text-primary)] [outline-offset:-2px]';\n\n/** Ring drawn on a wrapper when a control *inside* it takes focus. */\nexport const FOCUS_RING_WITHIN =\n 'outline-none has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:[outline:2px_solid_var(--malachite-text-primary)]';\n\n/**\n * As `FOCUS_RING_WITHIN`, for a card whose control is a `role=\"radio\"` beside its links:\n * `:has(:focus-visible)` would also match a focused link and draw a second ring.\n */\nexport const FOCUS_RING_WITHIN_RADIO =\n 'outline-none has-[[role=radio]:focus-visible]:outline-offset-2 has-[[role=radio]:focus-visible]:[outline:2px_solid_var(--malachite-text-primary)]';\n\n/** Ring for a control on the SelectionBar, where `FOCUS_RING` would be invisible. */\nexport const FOCUS_RING_SELECTION_BAR =\n 'outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-selection-bar-foreground)]';\n\n/** Inset ring for a control on the InlineConfirm chip. */\nexport const FOCUS_RING_INLINE_CONFIRM_INSET =\n 'outline-none focus-visible:[outline:2px_solid_var(--malachite-inline-confirm-foreground)] focus-visible:[outline-offset:-2px]';\n\n/** Ring for `CloseButton surface=\"inverse\"`, where `FOCUS_RING` would be invisible on the dark panel. */\nexport const FOCUS_RING_CLOSE_BUTTON_INVERSE =\n 'outline-none focus-visible:outline-offset-2 focus-visible:[outline:2px_solid_var(--malachite-close-button-inverse-hover-foreground,rgb(255,255,255))]';\n"],"names":["FOCUS_RING","FOCUS_RING_INSET","FOCUS_RING_INSET_OVERLAY","FOCUS_RING_WITHIN_RADIO","FOCUS_RING_SELECTION_BAR","FOCUS_RING_INLINE_CONFIRM_INSET","FOCUS_RING_CLOSE_BUTTON_INVERSE"],"mappings":"AAGO,MAAMA,IACT,+GAOSC,IACT,oHAGSC,IACT,uJAUSC,IACT,qJAGSC,IACT,2HAGSC,IACT,iIAGSC,IACT;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -927,6 +927,28 @@ export declare interface ClampTextProps {
|
|
|
927
927
|
|
|
928
928
|
export declare const ClearIcon: React.FC<IconProps_27>;
|
|
929
929
|
|
|
930
|
+
/** The bare X that dismisses a screen or panel: no box at rest or on hover. */
|
|
931
|
+
export declare const CloseButton: default_2.ForwardRefExoticComponent<CloseButtonProps & default_2.RefAttributes<HTMLButtonElement>>;
|
|
932
|
+
|
|
933
|
+
export declare interface CloseButtonProps extends Omit<default_2.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'className' | 'style' | 'color' | 'type' | 'disabled' | 'onClick' | 'aria-label' | 'aria-disabled' | 'aria-busy'> {
|
|
934
|
+
onClick?: default_2.MouseEventHandler<HTMLButtonElement>;
|
|
935
|
+
/** Accessible name. Defaults to "Close"; name what closes when there are several. */
|
|
936
|
+
'aria-label'?: string;
|
|
937
|
+
'aria-labelledby'?: string;
|
|
938
|
+
disabled?: boolean;
|
|
939
|
+
/** Shows a spinner in place of the X, sets `aria-busy` and ignores clicks. */
|
|
940
|
+
loading?: boolean;
|
|
941
|
+
/** `small` is a 24px target, `medium` a 32px one. The glyph is 12px in both. */
|
|
942
|
+
size?: CloseButtonSize;
|
|
943
|
+
surface?: CloseButtonSurface;
|
|
944
|
+
className?: string;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
export declare type CloseButtonSize = 'small' | 'medium';
|
|
948
|
+
|
|
949
|
+
/** `inverse` is for a surface that stays dark in every theme, e.g. `SplitScreenLayout`'s panel. */
|
|
950
|
+
export declare type CloseButtonSurface = 'default' | 'inverse';
|
|
951
|
+
|
|
930
952
|
export declare const CloseIcon: React.FC<IconProps_28>;
|
|
931
953
|
|
|
932
954
|
export declare const CodeBlock: default_2.FC<CodeBlockProps>;
|
|
@@ -3258,6 +3280,12 @@ export declare interface MalachiteTheme {
|
|
|
3258
3280
|
divider: string;
|
|
3259
3281
|
shadow: string;
|
|
3260
3282
|
};
|
|
3283
|
+
/** `CloseButton surface="inverse"`: the X on a panel that is dark in every theme. */
|
|
3284
|
+
closeButton: {
|
|
3285
|
+
inverseForeground: string;
|
|
3286
|
+
inverseHoverForeground: string;
|
|
3287
|
+
inverseDisabledForeground: string;
|
|
3288
|
+
};
|
|
3261
3289
|
dropdown: {
|
|
3262
3290
|
border: string;
|
|
3263
3291
|
borderActive: string;
|
|
@@ -3803,6 +3831,7 @@ export declare interface PartialMalachiteTheme {
|
|
|
3803
3831
|
cardStrip?: Partial<MalachiteTheme['colors']['cardStrip']>;
|
|
3804
3832
|
selectionBar?: Partial<MalachiteTheme['colors']['selectionBar']>;
|
|
3805
3833
|
inlineConfirm?: Partial<MalachiteTheme['colors']['inlineConfirm']>;
|
|
3834
|
+
closeButton?: Partial<MalachiteTheme['colors']['closeButton']>;
|
|
3806
3835
|
dropdown?: Partial<MalachiteTheme['colors']['dropdown']>;
|
|
3807
3836
|
tag?: {
|
|
3808
3837
|
[K in keyof MalachiteTheme['colors']['tag']]?: Partial<MalachiteTheme['colors']['tag'][K]>;
|