@bsuite/page-builder 0.4.2 → 0.4.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"AACA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAGrF,OAAO,kCAAkC,CAAC;AAC1C,OAAO,gCAAgC,CAAC;AAIxC,OAAO,KAAK,EAAe,mBAAmB,EAAE,MAAM,YAAY,CAAC;AA+KnE,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,OAAO,EACP,UAAU,EACV,SAAS,EAMT,WAAkB,EAClB,aAAsC,EACtC,yBAAiE,EACjE,kBAAkB,EAClB,sBAAsB,GACvB,EAAE,mBAAmB,qBAwkBrB"}
1
+ {"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"AACA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAGrF,OAAO,kCAAkC,CAAC;AAC1C,OAAO,gCAAgC,CAAC;AAIxC,OAAO,KAAK,EAAe,mBAAmB,EAAE,MAAM,YAAY,CAAC;AA+KnE,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,OAAO,EACP,UAAU,EACV,SAAS,EAMT,WAAkB,EAClB,aAAsC,EACtC,yBAAiE,EACjE,kBAAkB,EAClB,sBAAsB,GACvB,EAAE,mBAAmB,qBA+iBrB"}
@@ -212,49 +212,25 @@ isResizable = true, resizeHandles = DEFAULT_RESIZE_HANDLES, addEntityWidgetEvent
212
212
  // - Focus returns to the invoking element when the dialog closes.
213
213
  const resetCancelButtonRef = useRef(null);
214
214
  const resetConfirmButtonRef = useRef(null);
215
- // Collapsed state for the sticky editor banner. On tall pages the expanded
216
- // banner (columns + full Layers list + actions) can obscure most of the
217
- // viewport while the user is arranging cards below it (operator-reported).
218
- // Collapsing reduces it to a single thin row (title + Save & Exit + expand)
219
- // so the canvas underneath stays visible. Defaults expanded; auto-collapses
220
- // once the user scrolls the banner's scroll-ancestor past a small threshold
221
- // so it stops blocking the cards being arranged.
222
- const [controlsCollapsed, setControlsCollapsed] = useState(false);
215
+ // Collapsed state for the sticky editor banner. The expanded banner
216
+ // (columns + full Layers list + actions) can obscure most of the viewport
217
+ // while the user arranges cards below it (operator-reported, twice). Two
218
+ // structural guards keep the canvas usable:
219
+ // 1. Default COLLAPSED on every open — the banner enters as a thin single
220
+ // row (icon + title + Expand + Save & Exit), so the canvas is never
221
+ // blocked on entry. The prior scroll-to-collapse heuristic failed on
222
+ // short pages: the tall banner ate the scroll room it needed to trigger.
223
+ // 2. The expanded body is height-capped and scrolls internally (see the
224
+ // controls-body className), so even expanded it can never cover more
225
+ // than part of the screen regardless of how many layers exist.
226
+ const [controlsCollapsed, setControlsCollapsed] = useState(true);
223
227
  const editorBannerRef = useRef(null);
224
- const userToggledCollapseRef = useRef(false);
225
228
  useEffect(() => {
226
- if (!isEditing || typeof window === 'undefined')
229
+ if (!isEditing)
227
230
  return;
228
- // Reset collapse state each time the editor opens (unless the user has
229
- // explicitly toggled it this session).
230
- userToggledCollapseRef.current = false;
231
- setControlsCollapsed(false);
232
- const bannerEl = editorBannerRef.current;
233
- if (!bannerEl)
234
- return;
235
- // Find the nearest scrolling ancestor so we collapse on the same scroll
236
- // the sticky banner is anchored to (may be the window or an inner pane).
237
- const findScrollParent = (node) => {
238
- let current = node?.parentElement ?? null;
239
- while (current) {
240
- const style = window.getComputedStyle(current);
241
- if (/(auto|scroll|overlay)/.test(style.overflowY))
242
- return current;
243
- current = current.parentElement;
244
- }
245
- return window;
246
- };
247
- const scrollParent = findScrollParent(bannerEl);
248
- const readScrollTop = () => scrollParent === window
249
- ? window.scrollY
250
- : scrollParent.scrollTop;
251
- const handleScroll = () => {
252
- if (userToggledCollapseRef.current)
253
- return;
254
- setControlsCollapsed(readScrollTop() > 120);
255
- };
256
- scrollParent.addEventListener('scroll', handleScroll, { passive: true });
257
- return () => scrollParent.removeEventListener('scroll', handleScroll);
231
+ // Re-collapse on each open so re-entering the editor never re-blocks the
232
+ // canvas; the user expands via the toggle to reach columns + Layers.
233
+ setControlsCollapsed(true);
258
234
  }, [isEditing]);
259
235
  useEffect(() => {
260
236
  if (!resetConfirmOpen || typeof window === 'undefined')
@@ -312,10 +288,7 @@ isResizable = true, resizeHandles = DEFAULT_RESIZE_HANDLES, addEntityWidgetEvent
312
288
  // partially visible — mitigates Issue 2 (banner consuming
313
289
  // vertical space). `bg-card/95` + `backdrop-blur` keeps text
314
290
  // legible while showing form context behind the banner.
315
- 'bg-card/95 supports-[backdrop-filter]:bg-card/80 backdrop-blur border-primary'), role: "region", "aria-label": "Canvas editor controls", children: [_jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn('rounded-full flex items-center justify-center bg-primary/10', controlsCollapsed ? 'h-8 w-8' : 'h-10 w-10 animate-pulse'), children: _jsx(Settings2, { className: cn('text-primary', controlsCollapsed ? 'h-4 w-4' : 'h-5 w-5') }) }), _jsxs("div", { children: [_jsx("h3", { className: cn('font-semibold text-foreground', controlsCollapsed ? 'text-sm' : 'text-lg'), children: "Canvas Editor Active" }), !controlsCollapsed && (_jsx("span", { className: "text-sm text-muted-foreground", children: "Drag anywhere on a card to move it. Resize with the bottom-right handle." }))] })] }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [_jsxs("button", { type: "button", className: "inline-flex items-center gap-1 rounded-md border border-border px-2 py-2 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1", "aria-expanded": !controlsCollapsed, "aria-controls": "page-grid-editor-controls-body", onClick: () => {
316
- userToggledCollapseRef.current = true;
317
- setControlsCollapsed((previous) => !previous);
318
- }, children: [controlsCollapsed ? _jsx(ChevronDown, { className: "h-4 w-4" }) : _jsx(ChevronUp, { className: "h-4 w-4" }), _jsx("span", { className: "sr-only sm:not-sr-only", children: controlsCollapsed ? 'Expand' : 'Collapse' })] }), _jsxs("button", { type: "button", className: "inline-flex items-center rounded-md px-3 py-2 text-sm font-medium bg-primary text-primary-foreground shadow transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1", onClick: () => startTransition(() => setIsEditing(false)), children: [_jsx(Save, { className: "h-4 w-4 mr-2" }), "Save & Exit"] })] })] }), _jsxs("div", { id: "page-grid-editor-controls-body", hidden: controlsCollapsed, className: "flex flex-wrap items-center gap-x-4 gap-y-2 pt-2 border-t border-border", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(LayoutGrid, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsx("span", { className: "text-sm shrink-0 text-muted-foreground", children: "Columns:" }), _jsx("input", { type: "range", min: 1, max: 24, value: layoutCols, onChange: (event) => handleColumnChange(Number(event.target.value)), className: "w-24 cursor-pointer accent-primary", "aria-label": "Column count" }), _jsx("span", { className: "text-sm font-mono w-5 text-center tabular-nums", children: layoutCols })] }), _jsx("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Column presets", children: [1, 2, 3, 4, 6, 12].map((columnCount) => (_jsx("button", { type: "button", onClick: () => handleColumnChange(columnCount), "data-active": layoutCols === columnCount || undefined, "aria-pressed": layoutCols === columnCount, className: cn('px-2 py-0.5 rounded text-xs font-medium transition-colors border', 'bg-muted text-muted-foreground border-border', 'hover:bg-muted/80 hover:text-foreground', 'data-[active]:bg-primary data-[active]:text-primary-foreground data-[active]:border-primary', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1'), children: columnCount }, columnCount))) }), hiddenWidgetKeys.length > 0 && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Eye, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsx("span", { className: "text-sm shrink-0 text-muted-foreground", children: "Add widget:" }), _jsx("div", { className: "flex flex-wrap gap-1", children: hiddenWidgetKeys.map((key) => {
291
+ 'bg-card/95 supports-[backdrop-filter]:bg-card/80 backdrop-blur border-primary'), role: "region", "aria-label": "Canvas editor controls", children: [_jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn('rounded-full flex items-center justify-center bg-primary/10', controlsCollapsed ? 'h-8 w-8' : 'h-10 w-10 animate-pulse'), children: _jsx(Settings2, { className: cn('text-primary', controlsCollapsed ? 'h-4 w-4' : 'h-5 w-5') }) }), _jsxs("div", { children: [_jsx("h3", { className: cn('font-semibold text-foreground', controlsCollapsed ? 'text-sm' : 'text-lg'), children: "Canvas Editor Active" }), !controlsCollapsed && (_jsx("span", { className: "text-sm text-muted-foreground", children: "Drag anywhere on a card to move it. Resize with the bottom-right handle." }))] })] }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [_jsxs("button", { type: "button", className: "inline-flex items-center gap-1 rounded-md border border-border px-2 py-2 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1", "aria-expanded": !controlsCollapsed, "aria-controls": "page-grid-editor-controls-body", onClick: () => setControlsCollapsed((previous) => !previous), children: [controlsCollapsed ? _jsx(ChevronDown, { className: "h-4 w-4" }) : _jsx(ChevronUp, { className: "h-4 w-4" }), _jsx("span", { className: "sr-only sm:not-sr-only", children: controlsCollapsed ? 'Expand' : 'Collapse' })] }), _jsxs("button", { type: "button", className: "inline-flex items-center rounded-md px-3 py-2 text-sm font-medium bg-primary text-primary-foreground shadow transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1", onClick: () => startTransition(() => setIsEditing(false)), children: [_jsx(Save, { className: "h-4 w-4 mr-2" }), "Save & Exit"] })] })] }), _jsxs("div", { id: "page-grid-editor-controls-body", hidden: controlsCollapsed, className: "flex flex-wrap items-center gap-x-4 gap-y-2 pt-2 border-t border-border max-h-[60vh] overflow-y-auto", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(LayoutGrid, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsx("span", { className: "text-sm shrink-0 text-muted-foreground", children: "Columns:" }), _jsx("input", { type: "range", min: 1, max: 24, value: layoutCols, onChange: (event) => handleColumnChange(Number(event.target.value)), className: "w-24 cursor-pointer accent-primary", "aria-label": "Column count" }), _jsx("span", { className: "text-sm font-mono w-5 text-center tabular-nums", children: layoutCols })] }), _jsx("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Column presets", children: [1, 2, 3, 4, 6, 12].map((columnCount) => (_jsx("button", { type: "button", onClick: () => handleColumnChange(columnCount), "data-active": layoutCols === columnCount || undefined, "aria-pressed": layoutCols === columnCount, className: cn('px-2 py-0.5 rounded text-xs font-medium transition-colors border', 'bg-muted text-muted-foreground border-border', 'hover:bg-muted/80 hover:text-foreground', 'data-[active]:bg-primary data-[active]:text-primary-foreground data-[active]:border-primary', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1'), children: columnCount }, columnCount))) }), hiddenWidgetKeys.length > 0 && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Eye, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsx("span", { className: "text-sm shrink-0 text-muted-foreground", children: "Add widget:" }), _jsx("div", { className: "flex flex-wrap gap-1", children: hiddenWidgetKeys.map((key) => {
319
292
  const meta = widgetMeta?.[key];
320
293
  const Icon = meta?.icon;
321
294
  return (_jsxs("button", { type: "button", onClick: () => showLayer(key, meta?.defaultSize), className: cn('flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium border transition-colors', 'bg-muted text-muted-foreground border-border', 'hover:bg-muted/80 hover:text-foreground hover:border-primary/60', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1'), children: [_jsx(Plus, { className: "h-3 w-3" }), Icon && _jsx(Icon, { className: "h-3 w-3" }), layerNames[key] || meta?.label || key] }, key));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsuite/page-builder",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Shared BSuite responsive page-builder grid and layout persistence primitives",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",