@columenlabs/lumen-ui 0.1.305 → 0.1.306

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.
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Dialog } from 'radix-ui';
3
3
  import * as React from 'react';
4
4
  import { Drawer } from 'vaul';
5
+ import { useKeyboardFit } from './hooks/use-keyboard-fit.js';
5
6
  import { cn } from './lib/utils.js';
6
7
  /** A snap point in px against a screen `h` px tall. */
7
8
  function px(s, h) {
@@ -27,11 +28,14 @@ function useSafeBottom() {
27
28
  }, []);
28
29
  return inset;
29
30
  }
30
- /** The screen's height, kept up to date. */
31
+ /**
32
+ * The screen's height, kept up to date: the layout viewport, which a phone's keyboard leaves alone
33
+ * (iOS shrinks `innerHeight` with the keyboard, which would shrink the sheet with it).
34
+ */
31
35
  function useScreenHeight() {
32
- const [h, setH] = React.useState(() => typeof window === 'undefined' ? 800 : window.innerHeight);
36
+ const [h, setH] = React.useState(() => typeof window === 'undefined' ? 800 : document.documentElement.clientHeight);
33
37
  React.useEffect(() => {
34
- const on = () => setH(window.innerHeight);
38
+ const on = () => setH(document.documentElement.clientHeight);
35
39
  window.addEventListener('resize', on);
36
40
  return () => window.removeEventListener('resize', on);
37
41
  }, []);
@@ -51,7 +55,14 @@ export function LumenBottomSheet({ snaps, snap, onSnap, title, children, classNa
51
55
  const at = snaps.indexOf(snap);
52
56
  // The sheet is as tall as the screen and slides down to its snap; what it holds fills only the
53
57
  // part on screen, so a composer or footer at its bottom stays in view at every snap.
54
- const shown = Math.min(h, Math.max(0, px(rest(snap), h)));
58
+ const rested = Math.min(h, Math.max(0, px(rest(snap), h)));
59
+ // Typing in the sheet with the keyboard up: the sheet ends at the keyboard, as tall as its snap or
60
+ // what is visible, so the field and the composer sit just above the keys (theme.css holds vaul's
61
+ // slide off while it does). A field above the sheet leaves the sheet where it rests.
62
+ const kb = useKeyboardFit();
63
+ const [typing, setTyping] = React.useState(false);
64
+ const lifted = typing && kb ? Math.min(rested, kb.height) : undefined;
65
+ const shown = lifted ?? rested;
55
66
  return (_jsx(Drawer.Root, { open: true, modal: false, dismissible: false, handleOnly: true, snapPoints: rests, activeSnapPoint: rests[at] ?? rest(snap), setActiveSnapPoint: (s) => {
56
67
  const i = s == null ? -1 : rests.indexOf(s);
57
68
  const next = snaps[i];
@@ -59,5 +70,10 @@ export function LumenBottomSheet({ snaps, snap, onSnap, title, children, classNa
59
70
  onSnap(next);
60
71
  }, children: _jsx(Dialog.Root, { open: true, modal: false, onOpenChange: () => { }, children: _jsx(Drawer.Portal, { children: _jsxs(Drawer.Content, { "data-slot": "lumen-bottom-sheet", "aria-describedby": undefined,
61
72
  // Focus stays where the person was: the sheet is always there, opening it is not a move.
62
- 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 overflow-hidden", 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 })] })] }) }) }) }));
73
+ onOpenAutoFocus: (e) => e.preventDefault(), onFocus: () => setTyping(true), onBlur: (e) => {
74
+ if (!e.currentTarget.contains(e.relatedTarget))
75
+ setTyping(false);
76
+ }, "data-lifted": lifted === undefined ? undefined : '', style: lifted === undefined || !kb
77
+ ? undefined
78
+ : { top: kb.top + kb.height - lifted, bottom: 'auto', height: lifted }, 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 overflow-hidden", 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: cn('flex min-h-0 flex-1 flex-col', lifted === undefined && 'pb-[env(safe-area-inset-bottom)]'), children: children })] })] }) }) }) }));
63
79
  }
package/dist/theme.css CHANGED
@@ -974,3 +974,10 @@ body[data-spotlight="nav"] [data-spotlit] {
974
974
  display: none;
975
975
  }
976
976
  }
977
+
978
+ /* LumenBottomSheet while the person types in it with the keyboard up: it is placed at the keyboard
979
+ (lumen-bottom-sheet.tsx), so vaul's slide to its snap, set inline, stays off until the keys go. */
980
+ [data-slot="lumen-bottom-sheet"][data-lifted] {
981
+ transform: none !important;
982
+ transition: none !important;
983
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@columenlabs/lumen-ui",
3
- "version": "0.1.305",
3
+ "version": "0.1.306",
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.305",
52
+ "@columenlabs/lumen-ui-types": "0.1.306",
53
53
  "@dnd-kit/core": "6.3.1",
54
54
  "@dnd-kit/sortable": "10.0.0",
55
55
  "@dnd-kit/utilities": "3.2.2",