@nimblebrain/synapse 0.17.1 → 0.18.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/README.md +7 -5
- package/dist/{chunk-VYR6V47N.js → chunk-3YSXPBEQ.js} +3 -3
- package/dist/{chunk-VYR6V47N.js.map → chunk-3YSXPBEQ.js.map} +1 -1
- package/dist/{chunk-FDMRJZKT.cjs → chunk-FB7GPBEM.cjs} +10 -10
- package/dist/{chunk-FDMRJZKT.cjs.map → chunk-FB7GPBEM.cjs.map} +1 -1
- package/dist/{chunk-UPDBDXQB.js → chunk-HKRTDGXN.js} +5 -2
- package/dist/chunk-HKRTDGXN.js.map +1 -0
- package/dist/{chunk-TXJMGQYF.cjs → chunk-LPWEQCZV.cjs} +5 -2
- package/dist/chunk-LPWEQCZV.cjs.map +1 -0
- package/dist/{chunk-EHLQWCYV.cjs → chunk-VDQZQDU3.cjs} +6 -6
- package/dist/{chunk-EHLQWCYV.cjs.map → chunk-VDQZQDU3.cjs.map} +1 -1
- package/dist/{chunk-SRQNQ26I.js → chunk-ZLASWV4N.js} +3 -3
- package/dist/{chunk-SRQNQ26I.js.map → chunk-ZLASWV4N.js.map} +1 -1
- package/dist/connect.iife.global.js +1 -1
- package/dist/host/index.cjs +14 -14
- package/dist/host/index.js +2 -2
- package/dist/index.cjs +14 -14
- package/dist/index.js +3 -3
- package/dist/react/index.cjs +7 -7
- package/dist/react/index.js +2 -2
- package/dist/synapse-runtime.iife.global.js +1 -1
- package/dist/synapse-ui.iife.global.js +2 -2
- package/dist/ui/index.cjs +313 -87
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +29 -2
- package/dist/ui/index.d.ts +29 -2
- package/dist/ui/index.js +314 -89
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-TXJMGQYF.cjs.map +0 -1
- package/dist/chunk-UPDBDXQB.js.map +0 -1
package/dist/ui/index.d.cts
CHANGED
|
@@ -30,7 +30,12 @@ interface BreadcrumbProps extends Omit<HTMLAttributes<HTMLElement>, "children">
|
|
|
30
30
|
}
|
|
31
31
|
declare function Breadcrumb({ crumbs, separator, style, ...rest }: BreadcrumbProps): react_jsx_runtime.JSX.Element;
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
/**
|
|
34
|
+
* `danger` is for the verb that destroys something — Delete, Remove, Forget. It is
|
|
35
|
+
* filled like `primary`, so it is never the quiet option beside one, and red so the
|
|
36
|
+
* difference reads before the label does.
|
|
37
|
+
*/
|
|
38
|
+
type Variant = "primary" | "secondary" | "ghost" | "danger";
|
|
34
39
|
type Size = "sm" | "md";
|
|
35
40
|
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
36
41
|
variant?: Variant;
|
|
@@ -55,6 +60,27 @@ interface CardProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
55
60
|
}
|
|
56
61
|
declare function Card({ padding, interactive, style, className, children, ...rest }: CardProps): react_jsx_runtime.JSX.Element;
|
|
57
62
|
|
|
63
|
+
interface ConfirmDialogProps {
|
|
64
|
+
open: boolean;
|
|
65
|
+
/** Every dismissal path — Escape, the scrim, Cancel — calls this with `false`. */
|
|
66
|
+
onOpenChange: (open: boolean) => void;
|
|
67
|
+
/** Names the dialog (`aria-labelledby`). */
|
|
68
|
+
title: ReactNode;
|
|
69
|
+
/** One line under the title. Becomes the dialog's accessible description. */
|
|
70
|
+
description?: ReactNode;
|
|
71
|
+
/** What the action will do, and any control that shapes it. */
|
|
72
|
+
children?: ReactNode;
|
|
73
|
+
confirmLabel?: string;
|
|
74
|
+
cancelLabel?: string;
|
|
75
|
+
/** Confirm's label while `onConfirm` is in flight. Defaults to `confirmLabel`. */
|
|
76
|
+
pendingLabel?: string;
|
|
77
|
+
/** Render Confirm as a `danger` button, and open with focus on Cancel. */
|
|
78
|
+
destructive?: boolean;
|
|
79
|
+
/** Resolve to close. Throw to stay open with the error's message shown. */
|
|
80
|
+
onConfirm: () => void | Promise<void>;
|
|
81
|
+
}
|
|
82
|
+
declare function ConfirmDialog({ open, onOpenChange, title, description, children, confirmLabel, cancelLabel, pendingLabel, destructive, onConfirm, }: ConfirmDialogProps): react_jsx_runtime.JSX.Element | null;
|
|
83
|
+
|
|
58
84
|
type Side$1 = "left" | "right" | "bottom";
|
|
59
85
|
interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, "onClick"> {
|
|
60
86
|
open: boolean;
|
|
@@ -446,6 +472,7 @@ declare const tokens: {
|
|
|
446
472
|
readonly borderStrong: "var(--color-border-secondary, #d1d5db)";
|
|
447
473
|
readonly ring: "var(--color-ring-primary, #2563eb)";
|
|
448
474
|
readonly danger: "var(--nb-color-danger, #dc2626)";
|
|
475
|
+
readonly dangerFg: "var(--nb-color-danger-foreground, #ffffff)";
|
|
449
476
|
readonly success: "var(--nb-color-success, #059669)";
|
|
450
477
|
readonly warning: "var(--nb-color-warning, #f59e0b)";
|
|
451
478
|
readonly processing: "var(--nb-color-processing, #7c3aed)";
|
|
@@ -534,4 +561,4 @@ interface HeadingProps extends Omit<HTMLAttributes<HTMLHeadingElement>, "color">
|
|
|
534
561
|
/** Display heading using the heading font slot. Defaults to md, semibold. */
|
|
535
562
|
declare function Heading({ size, weight, tone, as: As, style, children, ...rest }: HeadingProps): react_jsx_runtime.JSX.Element;
|
|
536
563
|
|
|
537
|
-
export { AppFrame, Avatar, Badge, type BadgeTone, Breadcrumb, Button, Card, type Column, type Crumb, Divider, Drawer, EmptyState, Heading, type HeadingSize, Inline, ListDetailLayout, ListRow, PageHeader, PageLayout, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, type Status, StatusDot, Table, Tabs, Text, TextLink, type TextSize, type Tokens, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
|
|
564
|
+
export { AppFrame, Avatar, Badge, type BadgeTone, Breadcrumb, Button, Card, type Column, ConfirmDialog, type Crumb, Divider, Drawer, EmptyState, Heading, type HeadingSize, Inline, ListDetailLayout, ListRow, PageHeader, PageLayout, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, type Status, StatusDot, Table, Tabs, Text, TextLink, type TextSize, type Tokens, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -30,7 +30,12 @@ interface BreadcrumbProps extends Omit<HTMLAttributes<HTMLElement>, "children">
|
|
|
30
30
|
}
|
|
31
31
|
declare function Breadcrumb({ crumbs, separator, style, ...rest }: BreadcrumbProps): react_jsx_runtime.JSX.Element;
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
/**
|
|
34
|
+
* `danger` is for the verb that destroys something — Delete, Remove, Forget. It is
|
|
35
|
+
* filled like `primary`, so it is never the quiet option beside one, and red so the
|
|
36
|
+
* difference reads before the label does.
|
|
37
|
+
*/
|
|
38
|
+
type Variant = "primary" | "secondary" | "ghost" | "danger";
|
|
34
39
|
type Size = "sm" | "md";
|
|
35
40
|
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
36
41
|
variant?: Variant;
|
|
@@ -55,6 +60,27 @@ interface CardProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
55
60
|
}
|
|
56
61
|
declare function Card({ padding, interactive, style, className, children, ...rest }: CardProps): react_jsx_runtime.JSX.Element;
|
|
57
62
|
|
|
63
|
+
interface ConfirmDialogProps {
|
|
64
|
+
open: boolean;
|
|
65
|
+
/** Every dismissal path — Escape, the scrim, Cancel — calls this with `false`. */
|
|
66
|
+
onOpenChange: (open: boolean) => void;
|
|
67
|
+
/** Names the dialog (`aria-labelledby`). */
|
|
68
|
+
title: ReactNode;
|
|
69
|
+
/** One line under the title. Becomes the dialog's accessible description. */
|
|
70
|
+
description?: ReactNode;
|
|
71
|
+
/** What the action will do, and any control that shapes it. */
|
|
72
|
+
children?: ReactNode;
|
|
73
|
+
confirmLabel?: string;
|
|
74
|
+
cancelLabel?: string;
|
|
75
|
+
/** Confirm's label while `onConfirm` is in flight. Defaults to `confirmLabel`. */
|
|
76
|
+
pendingLabel?: string;
|
|
77
|
+
/** Render Confirm as a `danger` button, and open with focus on Cancel. */
|
|
78
|
+
destructive?: boolean;
|
|
79
|
+
/** Resolve to close. Throw to stay open with the error's message shown. */
|
|
80
|
+
onConfirm: () => void | Promise<void>;
|
|
81
|
+
}
|
|
82
|
+
declare function ConfirmDialog({ open, onOpenChange, title, description, children, confirmLabel, cancelLabel, pendingLabel, destructive, onConfirm, }: ConfirmDialogProps): react_jsx_runtime.JSX.Element | null;
|
|
83
|
+
|
|
58
84
|
type Side$1 = "left" | "right" | "bottom";
|
|
59
85
|
interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, "onClick"> {
|
|
60
86
|
open: boolean;
|
|
@@ -446,6 +472,7 @@ declare const tokens: {
|
|
|
446
472
|
readonly borderStrong: "var(--color-border-secondary, #d1d5db)";
|
|
447
473
|
readonly ring: "var(--color-ring-primary, #2563eb)";
|
|
448
474
|
readonly danger: "var(--nb-color-danger, #dc2626)";
|
|
475
|
+
readonly dangerFg: "var(--nb-color-danger-foreground, #ffffff)";
|
|
449
476
|
readonly success: "var(--nb-color-success, #059669)";
|
|
450
477
|
readonly warning: "var(--nb-color-warning, #f59e0b)";
|
|
451
478
|
readonly processing: "var(--nb-color-processing, #7c3aed)";
|
|
@@ -534,4 +561,4 @@ interface HeadingProps extends Omit<HTMLAttributes<HTMLHeadingElement>, "color">
|
|
|
534
561
|
/** Display heading using the heading font slot. Defaults to md, semibold. */
|
|
535
562
|
declare function Heading({ size, weight, tone, as: As, style, children, ...rest }: HeadingProps): react_jsx_runtime.JSX.Element;
|
|
536
563
|
|
|
537
|
-
export { AppFrame, Avatar, Badge, type BadgeTone, Breadcrumb, Button, Card, type Column, type Crumb, Divider, Drawer, EmptyState, Heading, type HeadingSize, Inline, ListDetailLayout, ListRow, PageHeader, PageLayout, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, type Status, StatusDot, Table, Tabs, Text, TextLink, type TextSize, type Tokens, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
|
|
564
|
+
export { AppFrame, Avatar, Badge, type BadgeTone, Breadcrumb, Button, Card, type Column, ConfirmDialog, type Crumb, Divider, Drawer, EmptyState, Heading, type HeadingSize, Inline, ListDetailLayout, ListRow, PageHeader, PageLayout, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, type Status, StatusDot, Table, Tabs, Text, TextLink, type TextSize, type Tokens, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
|
package/dist/ui/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ensureStyle, injectBaseReset } from '../chunk-3HQGHPNC.js';
|
|
2
|
-
import { createContext, useRef, useId, useState,
|
|
2
|
+
import { createContext, useRef, useId, useState, useMemo, useContext, useEffect, useLayoutEffect, Fragment as Fragment$1 } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
5
|
// src/ui/tokens.ts
|
|
@@ -20,6 +20,7 @@ var tokens = {
|
|
|
20
20
|
ring: "var(--color-ring-primary, #2563eb)",
|
|
21
21
|
// ── Status / brand semantics ──
|
|
22
22
|
danger: "var(--nb-color-danger, #dc2626)",
|
|
23
|
+
dangerFg: "var(--nb-color-danger-foreground, #ffffff)",
|
|
23
24
|
success: "var(--nb-color-success, #059669)",
|
|
24
25
|
warning: "var(--nb-color-warning, #f59e0b)",
|
|
25
26
|
processing: "var(--nb-color-processing, #7c3aed)",
|
|
@@ -292,6 +293,10 @@ function Button({
|
|
|
292
293
|
vars["--nb-btn-bg"] = tokens.accent;
|
|
293
294
|
vars["--nb-btn-bg-hover"] = `color-mix(in oklab, ${tokens.accent} 88%, black)`;
|
|
294
295
|
vars["--nb-btn-fg"] = tokens.accentFg;
|
|
296
|
+
} else if (variant === "danger") {
|
|
297
|
+
vars["--nb-btn-bg"] = tokens.danger;
|
|
298
|
+
vars["--nb-btn-bg-hover"] = `color-mix(in oklab, ${tokens.danger} 88%, black)`;
|
|
299
|
+
vars["--nb-btn-fg"] = tokens.dangerFg;
|
|
295
300
|
} else if (variant === "secondary") {
|
|
296
301
|
vars["--nb-btn-bg"] = tokens.bgSubtle;
|
|
297
302
|
vars["--nb-btn-bg-hover"] = tokens.bgRaised;
|
|
@@ -410,8 +415,283 @@ function Card({
|
|
|
410
415
|
}
|
|
411
416
|
);
|
|
412
417
|
}
|
|
413
|
-
|
|
418
|
+
function inClosedDetails(el) {
|
|
419
|
+
const details = el.closest("details:not([open])");
|
|
420
|
+
if (!details) return false;
|
|
421
|
+
const summary = details.querySelector("summary");
|
|
422
|
+
return !summary || !summary.contains(el);
|
|
423
|
+
}
|
|
424
|
+
var CANDIDATES = "a[href], button, input, select, textarea, summary, [tabindex]";
|
|
425
|
+
function tabbables(panel) {
|
|
426
|
+
return Array.from(panel.querySelectorAll(CANDIDATES)).filter(
|
|
427
|
+
(el) => el.tabIndex >= 0 && !el.matches(":disabled") && !el.closest("[hidden]") && !inClosedDetails(el) && el.type !== "hidden"
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
var openOverlays = [];
|
|
431
|
+
var lockedOverflow = "";
|
|
432
|
+
var handledEscapes = /* @__PURE__ */ new WeakSet();
|
|
433
|
+
function isInnermost(self) {
|
|
434
|
+
const selfAt = openOverlays.indexOf(self);
|
|
435
|
+
return openOverlays.every((other, at) => {
|
|
436
|
+
if (other === self || !other.panel || !self.panel) return true;
|
|
437
|
+
if (self.panel.contains(other.panel)) return false;
|
|
438
|
+
if (other.panel.contains(self.panel)) return true;
|
|
439
|
+
return at < selfAt;
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
function useModal(open, panelRef, { onEscape, initialFocus }) {
|
|
443
|
+
const escapeRef = useRef(onEscape);
|
|
444
|
+
escapeRef.current = onEscape;
|
|
445
|
+
const initialFocusRef = useRef(initialFocus);
|
|
446
|
+
initialFocusRef.current = initialFocus;
|
|
447
|
+
useEffect(() => {
|
|
448
|
+
if (!open) return;
|
|
449
|
+
const panel = panelRef.current;
|
|
450
|
+
const previouslyFocused = document.activeElement;
|
|
451
|
+
const entry = { panel, restoreTo: previouslyFocused };
|
|
452
|
+
const nested = openOverlays.filter((o) => panel && o.panel && panel.contains(o.panel)).at(-1);
|
|
453
|
+
if (nested) {
|
|
454
|
+
entry.restoreTo = nested.restoreTo;
|
|
455
|
+
nested.restoreTo = panel;
|
|
456
|
+
}
|
|
457
|
+
const { body } = document;
|
|
458
|
+
if (openOverlays.length === 0) lockedOverflow = body.style.overflow;
|
|
459
|
+
openOverlays.push(entry);
|
|
460
|
+
const innermost = () => isInnermost(entry);
|
|
461
|
+
if (!(panel && previouslyFocused && panel.contains(previouslyFocused))) {
|
|
462
|
+
(initialFocusRef.current?.() ?? panel)?.focus();
|
|
463
|
+
}
|
|
464
|
+
body.style.overflow = "hidden";
|
|
465
|
+
const onWindowKeyDown = (e) => {
|
|
466
|
+
if (e.key !== "Escape" || handledEscapes.has(e) || !innermost()) return;
|
|
467
|
+
handledEscapes.add(e);
|
|
468
|
+
e.preventDefault();
|
|
469
|
+
escapeRef.current();
|
|
470
|
+
};
|
|
471
|
+
window.addEventListener("keydown", onWindowKeyDown);
|
|
472
|
+
const onPanelKeyDown = (e) => {
|
|
473
|
+
if (e.key !== "Tab" || !panel || !innermost()) return;
|
|
474
|
+
const focusables = tabbables(panel);
|
|
475
|
+
if (focusables.length === 0) {
|
|
476
|
+
e.preventDefault();
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
const first = focusables[0];
|
|
480
|
+
const last = focusables[focusables.length - 1];
|
|
481
|
+
const active = document.activeElement;
|
|
482
|
+
if (e.shiftKey && (active === first || active === panel)) {
|
|
483
|
+
e.preventDefault();
|
|
484
|
+
last.focus();
|
|
485
|
+
} else if (!e.shiftKey && active === last) {
|
|
486
|
+
e.preventDefault();
|
|
487
|
+
first.focus();
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
panel?.addEventListener("keydown", onPanelKeyDown);
|
|
491
|
+
return () => {
|
|
492
|
+
window.removeEventListener("keydown", onWindowKeyDown);
|
|
493
|
+
panel?.removeEventListener("keydown", onPanelKeyDown);
|
|
494
|
+
const at = openOverlays.indexOf(entry);
|
|
495
|
+
if (at !== -1) openOverlays.splice(at, 1);
|
|
496
|
+
if (openOverlays.length === 0) body.style.overflow = lockedOverflow;
|
|
497
|
+
entry.restoreTo?.focus?.();
|
|
498
|
+
};
|
|
499
|
+
}, [open, panelRef]);
|
|
500
|
+
}
|
|
501
|
+
var STYLE_ID3 = "nb-synapse-confirm-dialog";
|
|
414
502
|
var RULES3 = `
|
|
503
|
+
/* border-box on both, because the kit cannot assume the host resets it: under
|
|
504
|
+
content-box a full-width panel is its padding wider than a phone screen. */
|
|
505
|
+
.nb-confirm-scrim {
|
|
506
|
+
box-sizing: border-box;
|
|
507
|
+
position: fixed; inset: 0; z-index: 1010;
|
|
508
|
+
display: flex; align-items: center; justify-content: center;
|
|
509
|
+
padding: 1rem;
|
|
510
|
+
background: rgba(0, 0, 0, 0.4);
|
|
511
|
+
animation: nb-confirm-fade 160ms ease;
|
|
512
|
+
}
|
|
513
|
+
.nb-confirm {
|
|
514
|
+
box-sizing: border-box;
|
|
515
|
+
width: 100%; max-width: 28rem; max-height: 100%;
|
|
516
|
+
overflow-y: auto;
|
|
517
|
+
outline: none;
|
|
518
|
+
animation: nb-confirm-in 160ms cubic-bezier(0.2, 0, 0, 1);
|
|
519
|
+
}
|
|
520
|
+
.nb-confirm__actions {
|
|
521
|
+
display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem;
|
|
522
|
+
}
|
|
523
|
+
@keyframes nb-confirm-fade { from { opacity: 0; } }
|
|
524
|
+
@keyframes nb-confirm-in { from { opacity: 0; transform: translateY(4px); } }
|
|
525
|
+
@media (pointer: coarse) {
|
|
526
|
+
.nb-confirm__actions .nb-btn { min-height: 44px; }
|
|
527
|
+
}
|
|
528
|
+
`;
|
|
529
|
+
function ConfirmDialog({
|
|
530
|
+
open,
|
|
531
|
+
onOpenChange,
|
|
532
|
+
title,
|
|
533
|
+
description,
|
|
534
|
+
children,
|
|
535
|
+
confirmLabel = "Confirm",
|
|
536
|
+
cancelLabel = "Cancel",
|
|
537
|
+
pendingLabel,
|
|
538
|
+
destructive = false,
|
|
539
|
+
onConfirm
|
|
540
|
+
}) {
|
|
541
|
+
ensureStyle(STYLE_ID3, RULES3);
|
|
542
|
+
const panelRef = useRef(null);
|
|
543
|
+
const titleId = useId();
|
|
544
|
+
const descriptionId = useId();
|
|
545
|
+
const [pending, setPending] = useState(false);
|
|
546
|
+
const [error, setError] = useState(null);
|
|
547
|
+
useEffect(() => {
|
|
548
|
+
if (open) {
|
|
549
|
+
setError(null);
|
|
550
|
+
setPending(false);
|
|
551
|
+
}
|
|
552
|
+
}, [open]);
|
|
553
|
+
const dismiss = () => {
|
|
554
|
+
if (!pending) onOpenChange(false);
|
|
555
|
+
};
|
|
556
|
+
const focusTarget = () => panelRef.current?.querySelector(
|
|
557
|
+
destructive ? "[data-nb-confirm-cancel]" : "[data-nb-confirm-confirm]"
|
|
558
|
+
);
|
|
559
|
+
useModal(open, panelRef, { onEscape: dismiss, initialFocus: focusTarget });
|
|
560
|
+
useEffect(() => {
|
|
561
|
+
if (error) focusTarget()?.focus();
|
|
562
|
+
}, [error]);
|
|
563
|
+
const confirm = async () => {
|
|
564
|
+
if (pending) return;
|
|
565
|
+
setPending(true);
|
|
566
|
+
setError(null);
|
|
567
|
+
try {
|
|
568
|
+
await onConfirm();
|
|
569
|
+
setPending(false);
|
|
570
|
+
onOpenChange(false);
|
|
571
|
+
} catch (err) {
|
|
572
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
573
|
+
setError(message || "That didn't go through. Try again.");
|
|
574
|
+
setPending(false);
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
if (!open) return null;
|
|
578
|
+
const panelStyle = {
|
|
579
|
+
padding: "1.25rem",
|
|
580
|
+
borderRadius: tokens.radiusMd,
|
|
581
|
+
border: `${tokens.borderWidth} solid ${tokens.border}`,
|
|
582
|
+
background: tokens.bg,
|
|
583
|
+
color: tokens.fg,
|
|
584
|
+
boxShadow: tokens.shadowLg,
|
|
585
|
+
fontFamily: tokens.fontSans
|
|
586
|
+
};
|
|
587
|
+
return (
|
|
588
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: scrim click is a bonus mouse affordance; Escape and Cancel are the keyboard dismissal paths.
|
|
589
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: the scrim is a decorative dismissal backdrop; the panel below owns the alertdialog role/semantics.
|
|
590
|
+
/* @__PURE__ */ jsx(
|
|
591
|
+
"div",
|
|
592
|
+
{
|
|
593
|
+
className: "nb-confirm-scrim",
|
|
594
|
+
onClick: (e) => {
|
|
595
|
+
if (e.target === e.currentTarget) dismiss();
|
|
596
|
+
},
|
|
597
|
+
children: /* @__PURE__ */ jsxs(
|
|
598
|
+
"div",
|
|
599
|
+
{
|
|
600
|
+
ref: panelRef,
|
|
601
|
+
role: "alertdialog",
|
|
602
|
+
"aria-modal": "true",
|
|
603
|
+
"aria-labelledby": titleId,
|
|
604
|
+
"aria-describedby": description != null ? descriptionId : void 0,
|
|
605
|
+
"aria-busy": pending || void 0,
|
|
606
|
+
tabIndex: -1,
|
|
607
|
+
className: "nb-confirm",
|
|
608
|
+
style: panelStyle,
|
|
609
|
+
children: [
|
|
610
|
+
/* @__PURE__ */ jsx(
|
|
611
|
+
"h2",
|
|
612
|
+
{
|
|
613
|
+
id: titleId,
|
|
614
|
+
style: {
|
|
615
|
+
margin: 0,
|
|
616
|
+
fontFamily: tokens.fontSans,
|
|
617
|
+
fontSize: tokens.textBaseSize,
|
|
618
|
+
lineHeight: tokens.textBaseLine,
|
|
619
|
+
fontWeight: tokens.weightSemibold,
|
|
620
|
+
color: tokens.fg
|
|
621
|
+
},
|
|
622
|
+
children: title
|
|
623
|
+
}
|
|
624
|
+
),
|
|
625
|
+
description != null ? /* @__PURE__ */ jsx(
|
|
626
|
+
"p",
|
|
627
|
+
{
|
|
628
|
+
id: descriptionId,
|
|
629
|
+
style: {
|
|
630
|
+
margin: "0.25rem 0 0",
|
|
631
|
+
fontSize: tokens.textSmSize,
|
|
632
|
+
lineHeight: tokens.textSmLine,
|
|
633
|
+
color: tokens.fgMuted
|
|
634
|
+
},
|
|
635
|
+
children: description
|
|
636
|
+
}
|
|
637
|
+
) : null,
|
|
638
|
+
children != null ? /* @__PURE__ */ jsx(
|
|
639
|
+
"div",
|
|
640
|
+
{
|
|
641
|
+
style: {
|
|
642
|
+
marginTop: "1rem",
|
|
643
|
+
fontSize: tokens.textSmSize,
|
|
644
|
+
lineHeight: tokens.textSmLine
|
|
645
|
+
},
|
|
646
|
+
children
|
|
647
|
+
}
|
|
648
|
+
) : null,
|
|
649
|
+
error ? /* @__PURE__ */ jsx(
|
|
650
|
+
"p",
|
|
651
|
+
{
|
|
652
|
+
role: "alert",
|
|
653
|
+
style: {
|
|
654
|
+
margin: "0.75rem 0 0",
|
|
655
|
+
fontSize: tokens.textSmSize,
|
|
656
|
+
lineHeight: tokens.textSmLine,
|
|
657
|
+
color: tokens.danger
|
|
658
|
+
},
|
|
659
|
+
children: error
|
|
660
|
+
}
|
|
661
|
+
) : null,
|
|
662
|
+
/* @__PURE__ */ jsxs("div", { className: "nb-confirm__actions", style: { marginTop: "1.25rem" }, children: [
|
|
663
|
+
/* @__PURE__ */ jsx(
|
|
664
|
+
Button,
|
|
665
|
+
{
|
|
666
|
+
variant: "secondary",
|
|
667
|
+
size: "sm",
|
|
668
|
+
"data-nb-confirm-cancel": "",
|
|
669
|
+
disabled: pending,
|
|
670
|
+
onClick: dismiss,
|
|
671
|
+
children: cancelLabel
|
|
672
|
+
}
|
|
673
|
+
),
|
|
674
|
+
/* @__PURE__ */ jsx(
|
|
675
|
+
Button,
|
|
676
|
+
{
|
|
677
|
+
variant: destructive ? "danger" : "primary",
|
|
678
|
+
size: "sm",
|
|
679
|
+
"data-nb-confirm-confirm": "",
|
|
680
|
+
disabled: pending,
|
|
681
|
+
onClick: () => void confirm(),
|
|
682
|
+
children: pending ? pendingLabel ?? confirmLabel : confirmLabel
|
|
683
|
+
}
|
|
684
|
+
)
|
|
685
|
+
] })
|
|
686
|
+
]
|
|
687
|
+
}
|
|
688
|
+
)
|
|
689
|
+
}
|
|
690
|
+
)
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
var STYLE_ID4 = "nb-synapse-drawer";
|
|
694
|
+
var RULES4 = `
|
|
415
695
|
.nb-drawer-scrim {
|
|
416
696
|
position: fixed; inset: 0; z-index: 1000;
|
|
417
697
|
display: flex; background: rgba(0, 0, 0, 0.32);
|
|
@@ -438,18 +718,6 @@ var RULES3 = `
|
|
|
438
718
|
.nb-drawer-iconbtn { min-width: 44px; min-height: 44px; }
|
|
439
719
|
}
|
|
440
720
|
`;
|
|
441
|
-
function inClosedDetails(el) {
|
|
442
|
-
const details = el.closest("details:not([open])");
|
|
443
|
-
if (!details) return false;
|
|
444
|
-
const summary = details.querySelector("summary");
|
|
445
|
-
return !summary || !summary.contains(el);
|
|
446
|
-
}
|
|
447
|
-
var CANDIDATES = "a[href], button, input, select, textarea, summary, [tabindex]";
|
|
448
|
-
function tabbables(panel) {
|
|
449
|
-
return Array.from(panel.querySelectorAll(CANDIDATES)).filter(
|
|
450
|
-
(el) => el.tabIndex >= 0 && !el.matches(":disabled") && !el.closest("[hidden]") && !inClosedDetails(el) && el.type !== "hidden"
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
721
|
var DrawerContext = createContext(null);
|
|
454
722
|
function DrawerRoot({
|
|
455
723
|
open,
|
|
@@ -461,54 +729,11 @@ function DrawerRoot({
|
|
|
461
729
|
children,
|
|
462
730
|
...rest
|
|
463
731
|
}) {
|
|
464
|
-
ensureStyle(
|
|
732
|
+
ensureStyle(STYLE_ID4, RULES4);
|
|
465
733
|
const panelRef = useRef(null);
|
|
466
734
|
const labelId = useId();
|
|
467
735
|
const [hasTitle, setHasTitle] = useState(false);
|
|
468
|
-
|
|
469
|
-
if (!open) return;
|
|
470
|
-
const onKey = (e) => {
|
|
471
|
-
if (e.key === "Escape") {
|
|
472
|
-
e.preventDefault();
|
|
473
|
-
(onEscape ?? onClose)();
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
window.addEventListener("keydown", onKey);
|
|
477
|
-
return () => window.removeEventListener("keydown", onKey);
|
|
478
|
-
}, [open, onEscape, onClose]);
|
|
479
|
-
useEffect(() => {
|
|
480
|
-
if (!open) return;
|
|
481
|
-
const panel = panelRef.current;
|
|
482
|
-
const previouslyFocused = document.activeElement;
|
|
483
|
-
panel?.focus();
|
|
484
|
-
const { body } = document;
|
|
485
|
-
const prevOverflow = body.style.overflow;
|
|
486
|
-
body.style.overflow = "hidden";
|
|
487
|
-
const onKeyDown = (e) => {
|
|
488
|
-
if (e.key !== "Tab" || !panel) return;
|
|
489
|
-
const focusables = tabbables(panel);
|
|
490
|
-
if (focusables.length === 0) {
|
|
491
|
-
e.preventDefault();
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
const first = focusables[0];
|
|
495
|
-
const last = focusables[focusables.length - 1];
|
|
496
|
-
const active = document.activeElement;
|
|
497
|
-
if (e.shiftKey && (active === first || active === panel)) {
|
|
498
|
-
e.preventDefault();
|
|
499
|
-
last.focus();
|
|
500
|
-
} else if (!e.shiftKey && active === last) {
|
|
501
|
-
e.preventDefault();
|
|
502
|
-
first.focus();
|
|
503
|
-
}
|
|
504
|
-
};
|
|
505
|
-
panel?.addEventListener("keydown", onKeyDown);
|
|
506
|
-
return () => {
|
|
507
|
-
panel?.removeEventListener("keydown", onKeyDown);
|
|
508
|
-
body.style.overflow = prevOverflow;
|
|
509
|
-
previouslyFocused?.focus?.();
|
|
510
|
-
};
|
|
511
|
-
}, [open]);
|
|
736
|
+
useModal(open, panelRef, { onEscape: onEscape ?? onClose });
|
|
512
737
|
const ctxValue = useMemo(() => ({ labelId, setHasTitle }), [labelId]);
|
|
513
738
|
if (!open) return null;
|
|
514
739
|
const isBottom = side === "bottom";
|
|
@@ -740,8 +965,8 @@ function EmptyState({ icon, title, description, action, style, ...rest }) {
|
|
|
740
965
|
}
|
|
741
966
|
);
|
|
742
967
|
}
|
|
743
|
-
var
|
|
744
|
-
var
|
|
968
|
+
var STYLE_ID5 = "nb-synapse-listrow";
|
|
969
|
+
var RULES5 = `
|
|
745
970
|
.nb-listrow { transition: background 140ms ease; }
|
|
746
971
|
.nb-listrow--interactive { cursor: pointer; }
|
|
747
972
|
.nb-listrow--interactive:hover { background: var(--nb-listrow-hover); }
|
|
@@ -756,7 +981,7 @@ function ListRow({
|
|
|
756
981
|
className,
|
|
757
982
|
...rest
|
|
758
983
|
}) {
|
|
759
|
-
ensureStyle(
|
|
984
|
+
ensureStyle(STYLE_ID5, RULES5);
|
|
760
985
|
const rowStyle = {
|
|
761
986
|
"--nb-listrow-hover": tokens.bgSubtle,
|
|
762
987
|
display: "grid",
|
|
@@ -839,8 +1064,8 @@ function ListRow({
|
|
|
839
1064
|
}
|
|
840
1065
|
);
|
|
841
1066
|
}
|
|
842
|
-
var
|
|
843
|
-
var
|
|
1067
|
+
var STYLE_ID6 = "nb-synapse-page-header";
|
|
1068
|
+
var RULES6 = `
|
|
844
1069
|
.nb-page-header__desc {
|
|
845
1070
|
display: -webkit-box;
|
|
846
1071
|
-webkit-box-orient: vertical;
|
|
@@ -859,7 +1084,7 @@ function PageHeader({
|
|
|
859
1084
|
style,
|
|
860
1085
|
...rest
|
|
861
1086
|
}) {
|
|
862
|
-
ensureStyle(
|
|
1087
|
+
ensureStyle(STYLE_ID6, RULES6);
|
|
863
1088
|
const descVars = descriptionLines > 0 ? { "--nb-ph-desc-lines": String(descriptionLines) } : {};
|
|
864
1089
|
return /* @__PURE__ */ jsxs(
|
|
865
1090
|
"header",
|
|
@@ -945,8 +1170,8 @@ function Pagination({ page, pageCount, onChange, style, ...rest }) {
|
|
|
945
1170
|
}
|
|
946
1171
|
);
|
|
947
1172
|
}
|
|
948
|
-
var
|
|
949
|
-
var
|
|
1173
|
+
var STYLE_ID7 = "nb-synapse-prose";
|
|
1174
|
+
var RULES7 = `
|
|
950
1175
|
.nb-prose {
|
|
951
1176
|
font-family: ${tokens.fontSans};
|
|
952
1177
|
font-size: ${tokens.textBaseSize};
|
|
@@ -971,15 +1196,15 @@ var RULES6 = `
|
|
|
971
1196
|
.nb-prose strong { font-weight: ${tokens.weightSemibold}; }
|
|
972
1197
|
`;
|
|
973
1198
|
function Prose({ html, children, className, ...rest }) {
|
|
974
|
-
ensureStyle(
|
|
1199
|
+
ensureStyle(STYLE_ID7, RULES7);
|
|
975
1200
|
const cls = `nb-prose ${className ?? ""}`.trim();
|
|
976
1201
|
if (html !== void 0) {
|
|
977
1202
|
return /* @__PURE__ */ jsx("div", { className: cls, dangerouslySetInnerHTML: { __html: html }, ...rest });
|
|
978
1203
|
}
|
|
979
1204
|
return /* @__PURE__ */ jsx("div", { className: cls, ...rest, children });
|
|
980
1205
|
}
|
|
981
|
-
var
|
|
982
|
-
var
|
|
1206
|
+
var STYLE_ID8 = "nb-synapse-searchfield";
|
|
1207
|
+
var RULES8 = `
|
|
983
1208
|
.nb-search { font-family: var(--nb-search-font); color: var(--nb-search-fg); outline: none; }
|
|
984
1209
|
.nb-search::placeholder { color: var(--nb-search-placeholder); }
|
|
985
1210
|
.nb-search--underline {
|
|
@@ -1009,7 +1234,7 @@ function SearchField({
|
|
|
1009
1234
|
type = "search",
|
|
1010
1235
|
...rest
|
|
1011
1236
|
}) {
|
|
1012
|
-
ensureStyle(
|
|
1237
|
+
ensureStyle(STYLE_ID8, RULES8);
|
|
1013
1238
|
const fieldStyle = {
|
|
1014
1239
|
"--nb-search-font": tokens.fontSans,
|
|
1015
1240
|
"--nb-search-fg": tokens.fg,
|
|
@@ -1032,8 +1257,8 @@ function SearchField({
|
|
|
1032
1257
|
}
|
|
1033
1258
|
);
|
|
1034
1259
|
}
|
|
1035
|
-
var
|
|
1036
|
-
var
|
|
1260
|
+
var STYLE_ID9 = "nb-synapse-segmented";
|
|
1261
|
+
var RULES9 = `
|
|
1037
1262
|
.nb-seg {
|
|
1038
1263
|
display: inline-flex;
|
|
1039
1264
|
gap: 2px;
|
|
@@ -1068,7 +1293,7 @@ function SegmentedControl({
|
|
|
1068
1293
|
className,
|
|
1069
1294
|
...rest
|
|
1070
1295
|
}) {
|
|
1071
|
-
ensureStyle(
|
|
1296
|
+
ensureStyle(STYLE_ID9, RULES9);
|
|
1072
1297
|
const trackStyle = {
|
|
1073
1298
|
"--nb-seg-radius": tokens.radiusSm,
|
|
1074
1299
|
"--nb-seg-track": tokens.bgSubtle,
|
|
@@ -1097,14 +1322,14 @@ function SegmentedControl({
|
|
|
1097
1322
|
)) })
|
|
1098
1323
|
);
|
|
1099
1324
|
}
|
|
1100
|
-
var
|
|
1101
|
-
var
|
|
1325
|
+
var STYLE_ID10 = "nb-synapse-spinner";
|
|
1326
|
+
var RULES10 = `
|
|
1102
1327
|
@keyframes nb-spin { to { transform: rotate(360deg); } }
|
|
1103
1328
|
.nb-spinner { animation: nb-spin 0.7s linear infinite; }
|
|
1104
1329
|
@media (prefers-reduced-motion: reduce) { .nb-spinner { animation-duration: 1.6s; } }
|
|
1105
1330
|
`;
|
|
1106
1331
|
function Spinner({ size = 16, color, style, className, ...rest }) {
|
|
1107
|
-
ensureStyle(
|
|
1332
|
+
ensureStyle(STYLE_ID10, RULES10);
|
|
1108
1333
|
const spinnerStyle = {
|
|
1109
1334
|
display: "inline-block",
|
|
1110
1335
|
flexShrink: 0,
|
|
@@ -1133,7 +1358,7 @@ var COLOR = {
|
|
|
1133
1358
|
failed: tokens.danger,
|
|
1134
1359
|
idle: tokens.fgFaint
|
|
1135
1360
|
};
|
|
1136
|
-
var
|
|
1361
|
+
var STYLE_ID11 = "nb-synapse-statusdot";
|
|
1137
1362
|
var KEYFRAMES = `
|
|
1138
1363
|
@keyframes nb-statusdot-pulse {
|
|
1139
1364
|
0% { box-shadow: 0 0 0 0 var(--nb-statusdot-ring); transform: scale(1); }
|
|
@@ -1155,7 +1380,7 @@ function StatusDot({
|
|
|
1155
1380
|
className,
|
|
1156
1381
|
...rest
|
|
1157
1382
|
}) {
|
|
1158
|
-
ensureStyle(
|
|
1383
|
+
ensureStyle(STYLE_ID11, KEYFRAMES);
|
|
1159
1384
|
const dotColor = color ?? COLOR[status];
|
|
1160
1385
|
const working = status === "working";
|
|
1161
1386
|
const dotStyle = {
|
|
@@ -1178,8 +1403,8 @@ function StatusDot({
|
|
|
1178
1403
|
}
|
|
1179
1404
|
);
|
|
1180
1405
|
}
|
|
1181
|
-
var
|
|
1182
|
-
var
|
|
1406
|
+
var STYLE_ID12 = "nb-synapse-table";
|
|
1407
|
+
var RULES11 = `
|
|
1183
1408
|
.nb-table { width: 100%; border-collapse: collapse; font-family: var(--nb-table-font); }
|
|
1184
1409
|
.nb-table th, .nb-table td {
|
|
1185
1410
|
padding: 0.55rem 0.75rem;
|
|
@@ -1209,7 +1434,7 @@ function Table({
|
|
|
1209
1434
|
className,
|
|
1210
1435
|
...rest
|
|
1211
1436
|
}) {
|
|
1212
|
-
ensureStyle(
|
|
1437
|
+
ensureStyle(STYLE_ID12, RULES11);
|
|
1213
1438
|
const vars = {
|
|
1214
1439
|
"--nb-table-font": tokens.fontSans,
|
|
1215
1440
|
"--nb-table-fg": tokens.fg,
|
|
@@ -1275,8 +1500,8 @@ function Table({
|
|
|
1275
1500
|
}
|
|
1276
1501
|
);
|
|
1277
1502
|
}
|
|
1278
|
-
var
|
|
1279
|
-
var
|
|
1503
|
+
var STYLE_ID13 = "nb-synapse-tabs";
|
|
1504
|
+
var RULES12 = `
|
|
1280
1505
|
.nb-tabs {
|
|
1281
1506
|
display: flex;
|
|
1282
1507
|
align-items: stretch;
|
|
@@ -1334,7 +1559,7 @@ function Tabs({
|
|
|
1334
1559
|
onKeyDown: callerKeyDown,
|
|
1335
1560
|
...rest
|
|
1336
1561
|
}) {
|
|
1337
|
-
ensureStyle(
|
|
1562
|
+
ensureStyle(STYLE_ID13, RULES12);
|
|
1338
1563
|
const barRef = useRef(null);
|
|
1339
1564
|
const barStyle = {
|
|
1340
1565
|
"--nb-tabs-gap": "1.25rem",
|
|
@@ -1611,8 +1836,8 @@ function useSidebar() {
|
|
|
1611
1836
|
if (!ctx) throw new Error("useSidebar must be used within <SidebarLayout>");
|
|
1612
1837
|
return ctx;
|
|
1613
1838
|
}
|
|
1614
|
-
var
|
|
1615
|
-
var
|
|
1839
|
+
var STYLE_ID14 = "nb-synapse-sidebarlayout";
|
|
1840
|
+
var RULES13 = `
|
|
1616
1841
|
.nb-sidebar-drawer { transition: transform 220ms cubic-bezier(0.2, 0, 0, 1); }
|
|
1617
1842
|
.nb-sidebar-scrim { animation: nb-sidebar-fade 180ms ease; }
|
|
1618
1843
|
@keyframes nb-sidebar-fade { from { opacity: 0; } to { opacity: 1; } }
|
|
@@ -1662,7 +1887,7 @@ function SidebarLayoutRoot({
|
|
|
1662
1887
|
}
|
|
1663
1888
|
function Sidebar({ style, children, ...rest }) {
|
|
1664
1889
|
const { collapsed, mode, side, width, open, setOpen } = useSidebar();
|
|
1665
|
-
ensureStyle(
|
|
1890
|
+
ensureStyle(STYLE_ID14, RULES13);
|
|
1666
1891
|
if (!collapsed) {
|
|
1667
1892
|
const border = `${tokens.borderWidth} solid ${tokens.border}`;
|
|
1668
1893
|
return /* @__PURE__ */ jsx(
|
|
@@ -1787,6 +2012,6 @@ function Trigger({ children, style, onClick, ...rest }) {
|
|
|
1787
2012
|
}
|
|
1788
2013
|
var SidebarLayout = Object.assign(SidebarLayoutRoot, { Sidebar, Main, Trigger });
|
|
1789
2014
|
|
|
1790
|
-
export { AppFrame, Avatar, Badge, Breadcrumb, Button, Card, Divider, Drawer, EmptyState, Heading, Inline, ListDetailLayout, ListRow, PageHeader, PageLayout, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, StatusDot, Table, Tabs, Text, TextLink, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
|
|
2015
|
+
export { AppFrame, Avatar, Badge, Breadcrumb, Button, Card, ConfirmDialog, Divider, Drawer, EmptyState, Heading, Inline, ListDetailLayout, ListRow, PageHeader, PageLayout, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, StatusDot, Table, Tabs, Text, TextLink, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
|
|
1791
2016
|
//# sourceMappingURL=index.js.map
|
|
1792
2017
|
//# sourceMappingURL=index.js.map
|