@columenlabs/lumen-ui 0.1.291 → 0.1.292
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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lumen-bottom-sheet.d.ts +22 -0
- package/dist/lumen-bottom-sheet.js +34 -0
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export { type CalendarFact, LumenCoverageCalendarMap, type LumenCoverageCalendar
|
|
|
40
40
|
export { DetailsTable, type DetailsTableProps, FactsTable } from './details-table.js';
|
|
41
41
|
export { DrawerSection, type DrawerSectionProps } from './drawer-section.js';
|
|
42
42
|
export { type DrawerAction, LumenDrawer, type LumenDrawerProps } from './lumen-drawer.js';
|
|
43
|
+
export { LumenBottomSheet, type LumenBottomSheetProps, type SheetSnap } from './lumen-bottom-sheet.js';
|
|
43
44
|
export { LumenCode, type LumenCodeProps, langOfPath } from './lumen-code.js';
|
|
44
45
|
export { LumenCodeEditor, type LumenCodeEditorProps, type LumenCodeLang, } from './lumen-code-editor.js';
|
|
45
46
|
export { RenameField, type RenameFieldProps } from './rename-field.js';
|
package/dist/index.js
CHANGED
|
@@ -47,6 +47,7 @@ export { LumenCoverageCalendarMap, } from './coverage-calendar-map.js';
|
|
|
47
47
|
export { DetailsTable, FactsTable } from './details-table.js';
|
|
48
48
|
export { DrawerSection } from './drawer-section.js';
|
|
49
49
|
export { LumenDrawer } from './lumen-drawer.js';
|
|
50
|
+
export { LumenBottomSheet } from './lumen-bottom-sheet.js';
|
|
50
51
|
export { LumenCode, langOfPath } from './lumen-code.js';
|
|
51
52
|
export { LumenCodeEditor, } from './lumen-code-editor.js';
|
|
52
53
|
export { RenameField } from './rename-field.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/** A snap point: a share of the screen's height (0 to 1) or a height in px ("76px"). */
|
|
3
|
+
export type SheetSnap = number | string;
|
|
4
|
+
export interface LumenBottomSheetProps {
|
|
5
|
+
/** The heights it rests at, smallest first: `['76px', 0.5, 0.92]` is peek, half and full. */
|
|
6
|
+
snaps: SheetSnap[];
|
|
7
|
+
/** Where it rests now (one of `snaps`). */
|
|
8
|
+
snap: SheetSnap;
|
|
9
|
+
/** The person dragged it to another snap. */
|
|
10
|
+
onSnap: (snap: SheetSnap) => void;
|
|
11
|
+
/** Its name for screen readers. */
|
|
12
|
+
title: string;
|
|
13
|
+
/** What it holds. It stays mounted at every snap, so running work inside keeps going. */
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
className?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A bottom sheet that stays on screen and leaves the page under it live: no dim, no blur, taps and
|
|
19
|
+
* drags above it reach the page. The person drags its handle between `snaps` (peek, half, full);
|
|
20
|
+
* it never closes, so what it holds is never unmounted. Built on vaul's snap points.
|
|
21
|
+
*/
|
|
22
|
+
export declare function LumenBottomSheet({ snaps, snap, onSnap, title, children, className, }: LumenBottomSheetProps): React.JSX.Element;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Drawer } from 'vaul';
|
|
4
|
+
import { cn } from './lib/utils.js';
|
|
5
|
+
/** A snap point in px against a screen `h` px tall. */
|
|
6
|
+
function px(s, h) {
|
|
7
|
+
if (typeof s === 'number')
|
|
8
|
+
return s * h;
|
|
9
|
+
return Number.parseFloat(s);
|
|
10
|
+
}
|
|
11
|
+
/** The screen's height, kept up to date. */
|
|
12
|
+
function useScreenHeight() {
|
|
13
|
+
const [h, setH] = React.useState(() => typeof window === 'undefined' ? 800 : window.innerHeight);
|
|
14
|
+
React.useEffect(() => {
|
|
15
|
+
const on = () => setH(window.innerHeight);
|
|
16
|
+
window.addEventListener('resize', on);
|
|
17
|
+
return () => window.removeEventListener('resize', on);
|
|
18
|
+
}, []);
|
|
19
|
+
return h;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A bottom sheet that stays on screen and leaves the page under it live: no dim, no blur, taps and
|
|
23
|
+
* drags above it reach the page. The person drags its handle between `snaps` (peek, half, full);
|
|
24
|
+
* it never closes, so what it holds is never unmounted. Built on vaul's snap points.
|
|
25
|
+
*/
|
|
26
|
+
export function LumenBottomSheet({ snaps, snap, onSnap, title, children, className, }) {
|
|
27
|
+
const h = useScreenHeight();
|
|
28
|
+
// The sheet is as tall as the screen and slides down to its snap; what it holds fills only the
|
|
29
|
+
// part on screen, so a composer or footer at its bottom stays in view at every snap.
|
|
30
|
+
const shown = Math.min(h, Math.max(0, px(snap, h)));
|
|
31
|
+
return (_jsx(Drawer.Root, { open: true, modal: false, dismissible: false, handleOnly: true, snapPoints: snaps, activeSnapPoint: snap, setActiveSnapPoint: (s) => s != null && onSnap(s), children: _jsx(Drawer.Portal, { children: _jsxs(Drawer.Content, { "data-slot": "lumen-bottom-sheet", "aria-describedby": undefined,
|
|
32
|
+
// Focus stays where the person was: the sheet is always there, opening it is not a move.
|
|
33
|
+
onOpenAutoFocus: (e) => e.preventDefault(), className: cn('fixed inset-x-0 bottom-0 z-40 flex h-dvh flex-col rounded-t-2xl border-t bg-popover text-popover-foreground shadow-[0_-4px_16px_rgb(0_0_0/0.15)] outline-none', className), children: [_jsx(Drawer.Title, { className: "sr-only", children: title }), _jsxs("div", { className: "flex min-h-0 flex-col", style: { height: shown }, children: [_jsx(Drawer.Handle, { "aria-label": "Drag to resize", className: "mx-auto! my-2! h-1! w-9! shrink-0 rounded-full! bg-border! opacity-100!" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col pb-[env(safe-area-inset-bottom)]", children: children })] })] }) }) }));
|
|
34
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.292",
|
|
4
4
|
"description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@codemirror/lang-javascript": "6.2.5",
|
|
50
50
|
"@codemirror/lang-json": "6.0.2",
|
|
51
51
|
"@codemirror/lang-sql": "6.10.0",
|
|
52
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
52
|
+
"@columenlabs/lumen-ui-types": "0.1.292",
|
|
53
53
|
"@dnd-kit/core": "6.3.1",
|
|
54
54
|
"@dnd-kit/sortable": "10.0.0",
|
|
55
55
|
"@dnd-kit/utilities": "3.2.2",
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
"sonner": "^2.0.8",
|
|
83
83
|
"tailwind-merge": "^3.7.0",
|
|
84
84
|
"topojson-client": "3.1.0",
|
|
85
|
+
"vaul": "1.1.2",
|
|
85
86
|
"web-vitals": "6.2.3",
|
|
86
87
|
"world-atlas": "2.0.2"
|
|
87
88
|
},
|