@bsuite/page-builder 0.4.1 → 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.
package/dist/PageGridLayout.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import 'react-grid-layout/css/styles.css';
|
|
2
3
|
import 'react-resizable/css/styles.css';
|
|
3
4
|
import type { PageGridLayoutProps } from './types.js';
|
|
4
|
-
export declare function PageGridLayout({ pageKey, defaultLayouts, defaultCols, layoutVersion, canEditPage, editorEventNames, preferenceAdapter, widgets, widgetMeta, className, isResizable, resizeHandles, addEntityWidgetEventNames, createEntityWidget, onRegisterEntityWidget, }: PageGridLayoutProps):
|
|
5
|
+
export declare function PageGridLayout({ pageKey, defaultLayouts, defaultCols, layoutVersion, canEditPage, editorEventNames, preferenceAdapter, widgets, widgetMeta, className, isResizable, resizeHandles, addEntityWidgetEventNames, createEntityWidget, onRegisterEntityWidget, }: PageGridLayoutProps): React.JSX.Element;
|
|
5
6
|
//# sourceMappingURL=PageGridLayout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"
|
|
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"}
|
package/dist/PageGridLayout.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ArrowDown, ArrowUp, Eye, EyeOff, Layers, LayoutGrid, Lock, Plus, RotateCcw, Save, Settings2, Unlock } from 'lucide-react';
|
|
2
|
+
import { ArrowDown, ArrowUp, ChevronDown, ChevronUp, Eye, EyeOff, Layers, LayoutGrid, Lock, Plus, RotateCcw, Save, Settings2, Unlock } from 'lucide-react';
|
|
3
3
|
import React, { startTransition, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { Responsive } from 'react-grid-layout';
|
|
5
5
|
import { gridBounds, minMaxSize, minSize } from 'react-grid-layout/core';
|
|
@@ -212,6 +212,26 @@ 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. 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);
|
|
227
|
+
const editorBannerRef = useRef(null);
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
if (!isEditing)
|
|
230
|
+
return;
|
|
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);
|
|
234
|
+
}, [isEditing]);
|
|
215
235
|
useEffect(() => {
|
|
216
236
|
if (!resetConfirmOpen || typeof window === 'undefined')
|
|
217
237
|
return;
|
|
@@ -254,17 +274,21 @@ isResizable = true, resizeHandles = DEFAULT_RESIZE_HANDLES, addEntityWidgetEvent
|
|
|
254
274
|
previousActiveElement?.focus?.();
|
|
255
275
|
};
|
|
256
276
|
}, [resetConfirmOpen]);
|
|
257
|
-
return (_jsxs("div", { className: cn('relative', isEditing && 'isolate', className), children: [isEditing && (_jsxs("div", { "data-page-grid-editor-controls": true, className: cn(
|
|
277
|
+
return (_jsxs("div", { className: cn('relative', isEditing && 'isolate', className), children: [isEditing && (_jsxs("div", { ref: editorBannerRef, "data-page-grid-editor-controls": true, "data-collapsed": controlsCollapsed || undefined, className: cn(
|
|
258
278
|
// Sticky overlay banner — sits at the top of the scroll container
|
|
259
279
|
// without pushing the form down. `top-0` anchors to the nearest
|
|
260
280
|
// scrolling ancestor; `z-40` keeps it above grid items but below
|
|
261
281
|
// app-level overlays (toaster, dialogs are z-50+).
|
|
262
|
-
'sticky top-0 z-40 isolate flex flex-col gap-3
|
|
282
|
+
'sticky top-0 z-40 isolate flex flex-col gap-3 rounded-xl shadow-lg border-2 mb-4',
|
|
283
|
+
// Collapsed → thin single-row bar so the canvas below stays visible
|
|
284
|
+
// (operator-reported: expanded banner obscured most of the viewport
|
|
285
|
+
// while arranging cards). Expanded → full controls.
|
|
286
|
+
controlsCollapsed ? 'p-2' : 'p-4',
|
|
263
287
|
// Subtle translucent background so the form behind it stays
|
|
264
288
|
// partially visible — mitigates Issue 2 (banner consuming
|
|
265
289
|
// vertical space). `bg-card/95` + `backdrop-blur` keeps text
|
|
266
290
|
// legible while showing form context behind the banner.
|
|
267
|
-
'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:
|
|
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) => {
|
|
268
292
|
const meta = widgetMeta?.[key];
|
|
269
293
|
const Icon = meta?.icon;
|
|
270
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.
|
|
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",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"react": ">=18 <21",
|
|
40
40
|
"react-dom": ">=18 <21",
|
|
41
41
|
"react-grid-layout": "^2",
|
|
42
|
-
"react-resizable": "^3"
|
|
42
|
+
"react-resizable": "^3 || ^4"
|
|
43
43
|
},
|
|
44
44
|
"peerDependenciesMeta": {
|
|
45
45
|
"@dnd-kit/core": {
|
|
@@ -55,17 +55,17 @@
|
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@testing-library/jest-dom": "^6.9.1",
|
|
57
57
|
"@testing-library/react": "^16.3.2",
|
|
58
|
-
"@types/react": "^19.2.
|
|
58
|
+
"@types/react": "^19.2.17",
|
|
59
59
|
"@types/react-dom": "^19.2.3",
|
|
60
|
-
"@vitejs/plugin-react": "^6.0.
|
|
60
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
61
61
|
"jsdom": "^29.1.1",
|
|
62
|
-
"lucide-react": "^1.
|
|
63
|
-
"react": "^19.2.
|
|
64
|
-
"react-dom": "^19.2.
|
|
62
|
+
"lucide-react": "^1.17.0",
|
|
63
|
+
"react": "^19.2.7",
|
|
64
|
+
"react-dom": "^19.2.7",
|
|
65
65
|
"react-grid-layout": "^2.2.3",
|
|
66
|
-
"react-resizable": "^
|
|
66
|
+
"react-resizable": "^4.0.1",
|
|
67
67
|
"typescript": "~6.0.3",
|
|
68
|
-
"vite": "^8.0.
|
|
69
|
-
"vitest": "^4.1.
|
|
68
|
+
"vite": "^8.0.16",
|
|
69
|
+
"vitest": "^4.1.8"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
.react-grid-item.react-grid-placeholder {
|
|
38
38
|
border-radius: 1.5rem;
|
|
39
|
-
background: var(--accent-primary, var(--primary,
|
|
39
|
+
background: var(--accent-primary, var(--role-primary, var(--primary, oklch(0.546 0.215 262.9))));
|
|
40
40
|
opacity: 0.16;
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -72,12 +72,12 @@
|
|
|
72
72
|
bottom: 3px;
|
|
73
73
|
width: 6px;
|
|
74
74
|
height: 6px;
|
|
75
|
-
border-right: 2px solid var(--text-secondary,
|
|
76
|
-
border-bottom: 2px solid var(--text-secondary,
|
|
75
|
+
border-right: 2px solid var(--text-secondary, oklch(0 0 0 / 0.45));
|
|
76
|
+
border-bottom: 2px solid var(--text-secondary, oklch(0 0 0 / 0.45));
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/* Highlight the marker when hovering the handle itself. */
|
|
80
80
|
.react-grid-item > .react-resizable-handle:hover::after {
|
|
81
|
-
border-right-color: var(--accent-primary, var(--primary,
|
|
82
|
-
border-bottom-color: var(--accent-primary, var(--primary,
|
|
81
|
+
border-right-color: var(--accent-primary, var(--role-primary, var(--primary, oklch(0.546 0.215 262.9))));
|
|
82
|
+
border-bottom-color: var(--accent-primary, var(--role-primary, var(--primary, oklch(0.546 0.215 262.9))));
|
|
83
83
|
}
|