@columenlabs/lumen-ui 0.1.48 → 0.1.50

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.
@@ -12,8 +12,12 @@ export interface DetailsTableProps {
12
12
  }[];
13
13
  /** An optional total row, one cell per column. */
14
14
  foot?: ReactNode[];
15
+ /** The key of the row shown as picked, when rows can be picked. */
16
+ selected?: string;
17
+ /** Makes each row pickable by click or Enter/Space, for example to chart the picked row below. */
18
+ onSelect?: (key: string) => void;
15
19
  }
16
- export declare function DetailsTable({ head, rows, foot }: DetailsTableProps): import("react").JSX.Element;
20
+ export declare function DetailsTable({ head, rows, foot, selected, onSelect }: DetailsTableProps): import("react").JSX.Element;
17
21
  /** Facts as a two-row table: the labels as the header, the values under them. */
18
22
  export declare function FactsTable({ items }: {
19
23
  items: [string, ReactNode][];
@@ -1,11 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from './lib/utils.js';
3
3
  import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from './ui/table.js';
4
- export function DetailsTable({ head, rows, foot }) {
4
+ export function DetailsTable({ head, rows, foot, selected, onSelect }) {
5
5
  const marked = head.findIndex((h) => h.grow);
6
6
  const grow = marked >= 0 ? marked : head.length - 1;
7
7
  const cell = (i) => cn('num', head[i]?.right && 'text-right', i !== grow && 'w-px');
8
- return (_jsx("div", { className: "-mx-1 overflow-x-auto overflow-y-hidden rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: head.map((h, i) => (_jsx(TableHead, { className: cn(h.right && 'text-right', i !== grow && 'w-px'), children: h.label }, h.label))) }) }), _jsx(TableBody, { children: rows.map((r) => (_jsx(TableRow, { children: r.cells.map((c, i) => (_jsx(TableCell, { className: cell(i), children: c }, i))) }, r.key))) }), foot && (_jsx(TableFooter, { children: _jsx(TableRow, { children: foot.map((c, i) => (_jsx(TableCell, { className: cell(i), children: c }, i))) }) }))] }) }));
8
+ return (_jsx("div", { className: "-mx-1 overflow-x-auto overflow-y-hidden rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: head.map((h, i) => (_jsx(TableHead, { className: cn(h.right && 'text-right', i !== grow && 'w-px'), children: h.label }, h.label))) }) }), _jsx(TableBody, { children: rows.map((r) => (_jsx(TableRow, { "data-state": r.key === selected ? 'selected' : undefined, "aria-current": r.key === selected || undefined, tabIndex: onSelect ? 0 : undefined, className: cn(onSelect &&
9
+ 'cursor-pointer focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring'), onClick: onSelect && (() => onSelect(r.key)), onKeyDown: onSelect &&
10
+ ((e) => {
11
+ if (e.key !== 'Enter' && e.key !== ' ')
12
+ return;
13
+ e.preventDefault();
14
+ onSelect(r.key);
15
+ }), children: r.cells.map((c, i) => (_jsx(TableCell, { className: cell(i), children: c }, i))) }, r.key))) }), foot && (_jsx(TableFooter, { children: _jsx(TableRow, { children: foot.map((c, i) => (_jsx(TableCell, { className: cell(i), children: c }, i))) }) }))] }) }));
9
16
  }
10
17
  /** Facts as a two-row table: the labels as the header, the values under them. */
11
18
  export function FactsTable({ items }) {
@@ -24,7 +24,8 @@ export interface LumenDrawerProps {
24
24
  * edge, 320px to 60% by default. The sheet spans the screen so the resizable group has room; only
25
25
  * the handle and the drawer take the pointer, so a click beside it falls through to the overlay
26
26
  * and closes it (`!` beats the inline pointer-events Radix sets on a modal's content). Its body
27
- * holds DrawerSections; its footer is always there (actions on the right, Close by default).
27
+ * holds DrawerSections; its footer sits at the bottom (actions on the right, Close by default; on a
28
+ * phone it shows only when there are actions, as the sheet's X closes it).
28
29
  */
29
30
  export declare function LumenDrawer({ open, onClose, title, description, children, footer, footerStart, defaultSize, minSize, maxSize, }: LumenDrawerProps): import("react").JSX.Element;
30
31
  export {};
@@ -11,18 +11,19 @@ import { Sheet, SheetClose, SheetContent, SheetDescription, SheetHeader, SheetTi
11
11
  * edge, 320px to 60% by default. The sheet spans the screen so the resizable group has room; only
12
12
  * the handle and the drawer take the pointer, so a click beside it falls through to the overlay
13
13
  * and closes it (`!` beats the inline pointer-events Radix sets on a modal's content). Its body
14
- * holds DrawerSections; its footer is always there (actions on the right, Close by default).
14
+ * holds DrawerSections; its footer sits at the bottom (actions on the right, Close by default; on a
15
+ * phone it shows only when there are actions, as the sheet's X closes it).
15
16
  */
16
17
  export function LumenDrawer({ open, onClose, title, description, children, footer, footerStart, defaultSize = '32%', minSize = '320px', maxSize = '60%', }) {
17
18
  const isMobile = useIsMobile();
18
19
  const head = (_jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [_jsx(SheetTitle, { className: "truncate", children: title }), _jsx(SheetDescription, { className: description ? 'truncate text-muted-foreground text-xs' : 'sr-only', children: description ?? 'Details' })] }));
19
20
  const body = _jsx("div", { className: "flex flex-col px-4 pb-4", children: children });
20
- // Every drawer has a footer, styled like a dialog's: the body scrolls above
21
- // it and always ends on a clear edge. Without actions of its own it offers Close.
22
- // On a phone the drawer is a full screen and the footer a bar under the header, so the
23
- // keyboard never covers its actions (Dialog does the same).
24
- const foot = (_jsxs("footer", { "data-slot": "drawer-footer", className: "flex shrink-0 items-center gap-2 border-t bg-muted/50 px-4 py-2.5 max-md:order-first max-md:border-t-0 max-md:border-b", children: [footerStart && (_jsx("div", { className: "min-w-0 flex-1 truncate text-muted-foreground text-xs", children: footerStart })), _jsx("div", { className: "ml-auto flex items-center gap-2", children: footer ?? (_jsx(SheetClose, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", children: "Close" }) })) })] }));
25
- return (_jsx(Sheet, { open: open, onOpenChange: (o) => !o && onClose(), modal: isMobile, children: isMobile ? (_jsxs(SheetContent, { side: "bottom", className: "max-h-[85svh] gap-0 overflow-hidden", children: [_jsx(SheetHeader, { className: "order-first shrink-0 border-b", children: head }), _jsx("div", { className: "end-fade min-h-0 flex-1 overflow-y-auto pt-2", children: body }), foot] })) : (_jsx(SheetContent, { side: "right", showCloseButton: false,
21
+ // Every drawer ends on a footer, styled like a dialog's: the body scrolls above it and always
22
+ // ends on a clear edge. Without actions of its own it offers Close, except on a phone, where the
23
+ // sheet's X already closes it and a second Close only took room.
24
+ const plain = !footer && !footerStart;
25
+ const foot = (_jsxs("footer", { "data-slot": "drawer-footer", className: "flex shrink-0 items-center gap-2 border-t bg-muted/50 px-4 py-2.5", children: [footerStart && (_jsx("div", { className: "min-w-0 flex-1 truncate text-muted-foreground text-xs", children: footerStart })), _jsx("div", { className: "ml-auto flex items-center gap-2", children: footer ?? (_jsx(SheetClose, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", children: "Close" }) })) })] }));
26
+ return (_jsx(Sheet, { open: open, onOpenChange: (o) => !o && onClose(), modal: isMobile, children: isMobile ? (_jsxs(SheetContent, { side: "bottom", className: "max-h-[85svh] gap-0 overflow-hidden", children: [_jsx(SheetHeader, { className: "order-first shrink-0 border-b", children: head }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pt-2", children: body }), !plain && foot] })) : (_jsx(SheetContent, { side: "right", showCloseButton: false,
26
27
  // The resize handle's grab zone is wider than the handle, so a drag can start on the
27
28
  // overlay; the panels library marks that pointerdown handled, and then it doesn't close.
28
29
  onPointerDownOutside: (e) => e.detail.originalEvent.defaultPrevented && e.preventDefault(), className: "pointer-events-none! gap-0 border-0 bg-transparent shadow-none data-[side=right]:left-0 data-[side=right]:w-auto data-[side=right]:border-l-0 data-[side=right]:sm:max-w-none", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { minSize: "40%" }), _jsx(ResizableHandle, { withHandle: true, className: "pointer-events-auto" }), _jsx(ResizablePanel, { defaultSize: defaultSize, minSize: minSize, maxSize: maxSize, "data-slot": "lumen-drawer", className: "pointer-events-auto bg-popover shadow-lg", children: _jsxs("section", { className: "flex h-full flex-col overflow-hidden", children: [_jsxs("header", { className: "flex shrink-0 items-center gap-2 border-b px-4 py-3", children: [head, _jsx(SheetClose, { asChild: true, children: _jsx(IconButton, { icon: XIcon, label: "Close", className: "ml-auto" }) })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pt-2", children: body }), foot] }) })] }) })) }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@columenlabs/lumen-ui",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -41,7 +41,7 @@
41
41
  "@codemirror/lang-javascript": "6.2.5",
42
42
  "@codemirror/lang-json": "6.0.2",
43
43
  "@codemirror/lang-sql": "6.10.0",
44
- "@columenlabs/lumen-ui-types": "0.1.48",
44
+ "@columenlabs/lumen-ui-types": "0.1.50",
45
45
  "@dnd-kit/core": "6.3.1",
46
46
  "@dnd-kit/sortable": "10.0.0",
47
47
  "@dnd-kit/utilities": "3.2.2",