@bsuite/page-builder 2.7.0 → 2.7.1-next.0

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/README.md CHANGED
@@ -48,3 +48,19 @@ Behaviour and guarantees:
48
48
 
49
49
  When adding `autoHeight` to an existing page's layout, bump that page's
50
50
  `layoutVersion` so stale persisted layouts (without the flag) are reset.
51
+
52
+ ## Edit-mode chrome (2.7.1-next.0+)
53
+
54
+ While the canvas editor is open, each grid item renders an in-flow strip
55
+ (`[data-slot="grid-item-editor-chrome"]`) above the card content: the widget
56
+ name and a Hide control. The strip is **not** absolutely positioned over the
57
+ card heading. AutoHeight measures it with the content so the grid grows;
58
+ leaving edit mode removes it and restores the content-only measurement.
59
+ Do not restyle this in a consumer — it is the shared contract.
60
+
61
+ The label carries `min-w-0 truncate` and a `title` with the full name. That is
62
+ load-bearing on a narrow card, not decoration: without it the label's automatic
63
+ minimum size is its min-content, and a long unbroken widget name pushes the
64
+ `ml-auto` hide button outside the card box. Measured both ways in
65
+ `scripts/editor-chrome-geometry.mjs`, which reproduces the defect with the two
66
+ classes removed at run time.
@@ -1 +1 @@
1
- {"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,kCAAkC,CAAC;AAC1C,OAAO,gCAAgC,CAAC;AAsBxC,OAAO,KAAK,EAAe,mBAAmB,EAA4B,MAAM,YAAY,CAAC;AAmmB7F,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,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAKhB,UAAkB,EAClB,yBAAiE,EACjE,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,+BAA6E,EAC7E,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,GAC7B,EAAE,mBAAmB,qBAu+BrB"}
1
+ {"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,kCAAkC,CAAC;AAC1C,OAAO,gCAAgC,CAAC;AAsBxC,OAAO,KAAK,EAAe,mBAAmB,EAA4B,MAAM,YAAY,CAAC;AA2pB7F,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,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAKhB,UAAkB,EAClB,yBAAiE,EACjE,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,+BAA6E,EAC7E,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,GAC7B,EAAE,mBAAmB,qBAu+BrB"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { ElementScopeProvider } from './elementScope.js';
3
3
  import { ArrowDown, ArrowUp, ChevronDown, ChevronUp, Eye, EyeOff, Layers, LayoutGrid, Lock, Plus, RotateCcw, Save, Settings2, Unlock } from 'lucide-react';
4
4
  import React, { startTransition, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
@@ -109,6 +109,31 @@ const RGLResizeHandle = React.forwardRef(function RGLResizeHandle({ axis = 'se',
109
109
  * the silent case audible in development and leaves production untouched, which
110
110
  * is the same trade @bsuite/theme 1.3.0 made for its missing-provider warning.
111
111
  */
112
+ /**
113
+ * Edit-mode label + hide. These used to be `absolute top-2 left-2` /
114
+ * `top-2 right-2` overlays on the card (PageGridLayout GridItem, historically
115
+ * around the 407/415 marks). That painted the widget name and the hide control
116
+ * on top of the card heading — measured on the Candidates card at 1440.
117
+ *
118
+ * An earlier draft of this comment also claimed 390. Withdrawn: the instrument
119
+ * that produced that number never asserted its own `innerWidth`, and the cell
120
+ * labelled "390" reported 1560. What 390 actually looks like is now measured
121
+ * and recorded in `editor-chrome-geometry-390.json` — and it is a different
122
+ * fact: below a 480px container `buildResponsiveLayouts` stacks every card to
123
+ * full width, so 390 has no narrow card at all.
124
+ *
125
+ * In-flow, measured: the strip is a flex-none row. AutoHeight includes it in
126
+ * the unconstrained measure wrapper so the grid grows rather than overlapping.
127
+ * Fixed-height cards keep it *above* the overflow-auto body so hide cannot
128
+ * scroll away. Drag still starts from the strip (outer `.drag-handle`); hide
129
+ * is a `button` + `data-no-drag` so the existing cancel selector ignores it.
130
+ */
131
+ function GridItemEditorChrome({ id, label, onHide, }) {
132
+ return (_jsxs("div", { "data-slot": "grid-item-editor-chrome", className: "flex min-w-0 flex-none items-center gap-1 px-2 py-1 bg-muted text-muted-foreground", children: [_jsx("span", { className: "min-w-0 truncate text-[10px] px-1.5 py-0.5 rounded-md font-medium", title: label, children: label }), _jsx("button", { type: "button", className: "ml-auto h-6 w-6 shrink-0 rounded-full flex items-center justify-center bg-destructive hover:bg-destructive text-destructive-foreground shadow transition-colors", "data-no-drag": true, onPointerDown: (event) => event.stopPropagation(), onClick: (event) => {
133
+ event.stopPropagation();
134
+ onHide(id);
135
+ }, title: `Hide ${label}`, "aria-label": `Hide ${label}`, children: _jsx(EyeOff, { className: "h-3 w-3", "aria-hidden": "true" }) })] }));
136
+ }
112
137
  let warnedAboutCollapsedContent = false;
113
138
  function warnOnceAboutCollapsedContent(el) {
114
139
  if (warnedAboutCollapsedContent)
@@ -230,7 +255,9 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
230
255
  reportRows(contentPx);
231
256
  else
232
257
  warnOnceAboutCollapsedContent(el);
233
- }, [autoHeight, onAutoHeightChange, reportRows]);
258
+ // Re-measure when edit chrome mounts/unmounts so the strip is in the
259
+ // row count in edit mode and gone again on lossless return.
260
+ }, [autoHeight, onAutoHeightChange, reportRows, isEditing]);
234
261
  useEffect(() => {
235
262
  if (!autoHeight || !onAutoHeightChange)
236
263
  return;
@@ -280,10 +307,7 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
280
307
  // (buttons, inputs, textarea, select, links, [data-no-drag]) are still
281
308
  // protected via the `cancel` selector below in the <Responsive> render.
282
309
  const outerClass = cn('relative group overflow-visible', isEditing && 'drag-handle cursor-move', injectedClassName);
283
- return (_jsxs("div", { ref: ref, className: outerClass, style: injectedStyle, ...rest, children: [_jsxs("div", { className: "h-full w-full relative", children: [isEditing && (_jsx("div", { className: "absolute inset-0 z-10 pointer-events-none rounded-3xl border-2 border-transparent group-hover:border-primary/50 transition-colors bg-primary/5" })), isEditing && (_jsx("div", { className: "absolute top-2 left-2 z-30 flex items-center gap-1 pointer-events-none", children: _jsx("span", { className: "text-[10px] px-1.5 py-0.5 rounded-md opacity-80 font-medium bg-muted text-muted-foreground", children: label }) })), isEditing && (_jsx("button", { className: "absolute top-2 right-2 z-30 h-6 w-6 rounded-full flex items-center justify-center bg-destructive/80 hover:bg-destructive text-destructive-foreground shadow transition-colors", "data-no-drag": true, onPointerDown: (event) => event.stopPropagation(), onClick: (event) => {
284
- event.stopPropagation();
285
- onHide(id);
286
- }, title: `Hide ${label}`, "aria-label": `Hide ${label}`, children: _jsx(EyeOff, { className: "h-3 w-3", "aria-hidden": "true" }) })), _jsx("div", { "data-slot": "grid-item-surface", "data-chrome": chrome ? 'on' : 'off', "data-grid-slot-key": id, className: chrome
310
+ return (_jsxs("div", { ref: ref, className: outerClass, style: injectedStyle, ...rest, children: [_jsxs("div", { className: "h-full w-full relative", children: [isEditing && (_jsx("div", { className: "absolute inset-0 z-10 pointer-events-none rounded-3xl border-2 border-transparent group-hover:border-primary/50 transition-colors bg-primary/5" })), _jsx("div", { "data-slot": "grid-item-surface", "data-chrome": chrome ? 'on' : 'off', "data-grid-slot-key": id, className: chrome
287
311
  ? // ONE radius token, read by the grid item AND available to any
288
312
  // app card that opts into the same surface. Two surfaces
289
313
  // reading the SAME var is what makes their corners align, and
@@ -346,7 +370,7 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
346
370
  ...(cardStyleVars && '--card-padding' in cardStyleVars
347
371
  ? { padding: cardStyleVars['--card-padding'] }
348
372
  : null),
349
- }, children: _jsx("div", { className: cn('min-h-0', autoHeight ? 'flex-none overflow-visible' : 'flex-1 overflow-auto'), children: autoHeight ? (_jsx("div", { ref: measureRef, className: "flow-root", children: scopedContent })) : (scopedContent) }) })] }), injectedChildren] }));
373
+ }, children: autoHeight ? (_jsx("div", { "data-slot": "grid-item-body", className: "min-h-0 flex-none overflow-visible", children: _jsxs("div", { ref: measureRef, className: "flow-root", children: [isEditing ? (_jsx(GridItemEditorChrome, { id: id, label: label, onHide: onHide })) : null, scopedContent] }) })) : (_jsxs(_Fragment, { children: [isEditing ? (_jsx(GridItemEditorChrome, { id: id, label: label, onHide: onHide })) : null, _jsx("div", { "data-slot": "grid-item-body", className: "min-h-0 flex-1 overflow-auto", children: scopedContent })] })) })] }), injectedChildren] }));
350
374
  }));
351
375
  export function PageGridLayout({ pageKey, defaultLayouts, defaultCols, layoutVersion, canEditPage, editorEventNames, preferenceAdapter, widgets, widgetMeta, className,
352
376
  // Resize default flipped 2026-05-12: rgl v2 dropped auto-handle rendering
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsuite/page-builder",
3
- "version": "2.7.0",
3
+ "version": "2.7.1-next.0",
4
4
  "description": "Shared BSuite responsive page-builder grid and layout persistence primitives",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -33,6 +33,7 @@
33
33
  "build": "tsc -p tsconfig.build.json",
34
34
  "typecheck": "tsc --noEmit",
35
35
  "test": "vitest run",
36
+ "test:geometry": "node scripts/editor-chrome-geometry.mjs",
36
37
  "prepublishOnly": "pnpm build"
37
38
  },
38
39
  "peerDependencies": {