@bsuite/page-builder 2.7.1 → 2.8.0-next.1
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 +9 -0
- package/dist/PageGridLayout.d.ts.map +1 -1
- package/dist/PageGridLayout.js +77 -3
- package/package.json +10 -10
package/dist/PageGridLayout.d.ts
CHANGED
|
@@ -7,5 +7,14 @@ export declare const PAGE_GRID_SAVE_EVENT = "bsuite-page-grid-save";
|
|
|
7
7
|
export interface PageGridSaveEventDetail {
|
|
8
8
|
pageKey: string;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* True when a chrome-on surface's content brings no inset of its own.
|
|
12
|
+
*
|
|
13
|
+
* Walk down pure wrappers (no padding, exactly one element child) to the
|
|
14
|
+
* first element that does layout work, then call it bare only if it has no
|
|
15
|
+
* left and no top padding. A slot is never bare while anything inside it is a
|
|
16
|
+
* Card or a PageHeader. The in-edit label strip is skipped, not measured.
|
|
17
|
+
*/
|
|
18
|
+
export declare function hasBareContent(surface: HTMLElement): boolean;
|
|
10
19
|
export declare function PageGridLayout({ pageKey, defaultLayouts, defaultCols, layoutVersion, canEditPage, editorEventNames, preferenceAdapter, widgets, widgetMeta, className, isResizable, resizeHandles, tenantId, defaultAutoHeight, layoutMigrations, itemChrome, addEntityWidgetEventNames, createEntityWidget, onRegisterEntityWidget, relationshipCatalog, addRelationshipWidgetEventNames, createRelationshipWidget, onRegisterRelationshipWidget, onRelationshipWidgetRejected, }: PageGridLayoutProps): React.JSX.Element;
|
|
11
20
|
//# sourceMappingURL=PageGridLayout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"AAGA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,kCAAkC,CAAC;AAC1C,OAAO,gCAAgC,CAAC;AAsBxC,OAAO,KAAK,EAAe,mBAAmB,EAA4B,MAAM,YAAY,CAAC;AAE7F,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAC5D,MAAM,WAAW,uBAAuB;IAAG,OAAO,EAAE,MAAM,CAAA;CAAE;
|
|
1
|
+
{"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"AAGA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,kCAAkC,CAAC;AAC1C,OAAO,gCAAgC,CAAC;AAsBxC,OAAO,KAAK,EAAe,mBAAmB,EAA4B,MAAM,YAAY,CAAC;AAE7F,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAC5D,MAAM,WAAW,uBAAuB;IAAG,OAAO,EAAE,MAAM,CAAA;CAAE;AAyR5D;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAoB5D;AAscD,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,qBAoqCrB"}
|
package/dist/PageGridLayout.js
CHANGED
|
@@ -169,6 +169,42 @@ function warnOnceAboutCollapsedContent(el) {
|
|
|
169
169
|
+ '(an aspect ratio, a px/rem height, or min-height), or pass autoHeight={false} on '
|
|
170
170
|
+ 'this card so it renders into the constrained scrollable wrapper instead.');
|
|
171
171
|
}
|
|
172
|
+
/** Content elements that declare a surface, and therefore an inset, of their own. */
|
|
173
|
+
const SELF_SURFACED = '[data-slot="card"], [data-slot="page-header"]';
|
|
174
|
+
/**
|
|
175
|
+
* True when a chrome-on surface's content brings no inset of its own.
|
|
176
|
+
*
|
|
177
|
+
* Walk down pure wrappers (no padding, exactly one element child) to the
|
|
178
|
+
* first element that does layout work, then call it bare only if it has no
|
|
179
|
+
* left and no top padding. A slot is never bare while anything inside it is a
|
|
180
|
+
* Card or a PageHeader. The in-edit label strip is skipped, not measured.
|
|
181
|
+
*/
|
|
182
|
+
export function hasBareContent(surface) {
|
|
183
|
+
if (surface.querySelector(SELF_SURFACED))
|
|
184
|
+
return false;
|
|
185
|
+
const root = surface.querySelector('[data-slot="grid-item-body"]') ?? surface;
|
|
186
|
+
const firstContent = (el) => {
|
|
187
|
+
for (const child of Array.from(el.children)) {
|
|
188
|
+
if (child.getAttribute('data-slot') === 'grid-item-editor-chrome')
|
|
189
|
+
continue;
|
|
190
|
+
// The autoHeight measure wrapper is structure, not content.
|
|
191
|
+
if (child.classList.contains('flow-root') && el === root)
|
|
192
|
+
return firstContent(child);
|
|
193
|
+
return child;
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
};
|
|
197
|
+
let el = firstContent(root);
|
|
198
|
+
if (!el)
|
|
199
|
+
return false;
|
|
200
|
+
const padded = (node) => {
|
|
201
|
+
const cs = getComputedStyle(node);
|
|
202
|
+
return (Number.parseFloat(cs.paddingLeft) || 0) > 0 || (Number.parseFloat(cs.paddingTop) || 0) > 0;
|
|
203
|
+
};
|
|
204
|
+
while (!padded(el) && el.children.length === 1)
|
|
205
|
+
el = el.children[0];
|
|
206
|
+
return !padded(el);
|
|
207
|
+
}
|
|
172
208
|
const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, isEditing, label, pageKey, onHide, editingPaused = false, autoHeight, onAutoHeightChange, chrome = false, cardStyleVars, children: injectedChildren, className: injectedClassName, style: injectedStyle, ...rest }, ref) {
|
|
173
209
|
// Auto-height measurement (blueprint amendment A1). `measureRef` wraps
|
|
174
210
|
// `content` with NO height constraint of its own — its parent has
|
|
@@ -194,6 +230,41 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
194
230
|
const scopedContent = (_jsx(ElementScopeProvider, { scope: { pageKey, cardKey: id, cardLabel: label, isEditing }, children: _jsx(CardPaddingBoundary, { padding: cardPadding, children: content }) }));
|
|
195
231
|
const measureRef = useRef(null);
|
|
196
232
|
const surfaceRef = useRef(null);
|
|
233
|
+
/**
|
|
234
|
+
* Does this chrome-on slot hold content that brings no inset of its own?
|
|
235
|
+
* (crm7#2734). The chrome surface paints a border and no padding, so a bare
|
|
236
|
+
* filter bar or hand-rolled header sat on the border. A blanket inset is
|
|
237
|
+
* wrong twice over: most slots nest their own Card, and many widgets pad
|
|
238
|
+
* themselves (`p-6`) without declaring any marker. The first release used
|
|
239
|
+
* a CSS `:has()` guard and double-padded exactly those widgets, which CSS
|
|
240
|
+
* cannot see. So the decision is MEASURED: see `hasBareContent`.
|
|
241
|
+
*/
|
|
242
|
+
const [bareContent, setBareContent] = useState(false);
|
|
243
|
+
useLayoutEffect(() => {
|
|
244
|
+
const surface = surfaceRef.current;
|
|
245
|
+
if (!chrome || !surface) {
|
|
246
|
+
setBareContent(false);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const detect = () => setBareContent(hasBareContent(surface));
|
|
250
|
+
detect();
|
|
251
|
+
if (typeof MutationObserver === 'undefined')
|
|
252
|
+
return;
|
|
253
|
+
let frame = null;
|
|
254
|
+
const schedule = typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function'
|
|
255
|
+
? window.requestAnimationFrame.bind(window)
|
|
256
|
+
: (cb) => setTimeout(cb, 0);
|
|
257
|
+
const mo = new MutationObserver(() => {
|
|
258
|
+
if (frame !== null)
|
|
259
|
+
return;
|
|
260
|
+
frame = schedule(() => {
|
|
261
|
+
frame = null;
|
|
262
|
+
detect();
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
mo.observe(surface, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'data-slot', 'style'] });
|
|
266
|
+
return () => mo.disconnect();
|
|
267
|
+
}, [chrome]);
|
|
197
268
|
const lastReportedRowsRef = useRef(null);
|
|
198
269
|
const measureRafRef = useRef(null);
|
|
199
270
|
/**
|
|
@@ -272,7 +343,7 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
272
343
|
warnOnceAboutCollapsedContent(el);
|
|
273
344
|
// Re-measure when edit chrome mounts/unmounts so the strip is in the
|
|
274
345
|
// row count in edit mode and gone again on lossless return.
|
|
275
|
-
}, [autoHeight, onAutoHeightChange, reportRows, isEditing, cardStyleVars]);
|
|
346
|
+
}, [autoHeight, onAutoHeightChange, reportRows, isEditing, cardStyleVars, bareContent]);
|
|
276
347
|
useEffect(() => {
|
|
277
348
|
if (!autoHeight || !onAutoHeightChange)
|
|
278
349
|
return;
|
|
@@ -324,7 +395,7 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
324
395
|
const outerClass = cn('relative group overflow-visible', isEditing && 'drag-handle',
|
|
325
396
|
// Paused editing (bsuite#3277) cannot move a card, so it must not promise to.
|
|
326
397
|
isEditing && !editingPaused && 'cursor-move', injectedClassName);
|
|
327
|
-
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, ref: surfaceRef, "data-card-padding": !chrome && cardStyleVars && '--card-padding' in cardStyleVars ? '' : undefined, className: chrome
|
|
398
|
+
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-bare-content": chrome && bareContent ? '' : undefined, "data-grid-slot-key": id, ref: surfaceRef, "data-card-padding": !chrome && cardStyleVars && '--card-padding' in cardStyleVars ? '' : undefined, className: chrome
|
|
328
399
|
? // ONE radius token, read by the grid item AND available to any
|
|
329
400
|
// app card that opts into the same surface. Two surfaces
|
|
330
401
|
// reading the SAME var is what makes their corners align, and
|
|
@@ -363,7 +434,10 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
363
434
|
// becomes transparent space below the card, which nobody can see. For a
|
|
364
435
|
// manually-resized slot h-full is still right: the user chose that
|
|
365
436
|
// height and the chrome should fill it.
|
|
366
|
-
autoHeight ? 'h-fit' : 'h-full'
|
|
437
|
+
autoHeight ? 'h-fit' : 'h-full',
|
|
438
|
+
// PageHeader's own inset, so a bare slot and a header line up.
|
|
439
|
+
// An operator --card-padding is inline style and still wins.
|
|
440
|
+
bareContent && 'p-6 md:p-7')
|
|
367
441
|
: // Chrome OFF: layout only. Identical box, no paint.
|
|
368
442
|
cn('w-full transition-all flex flex-col', autoHeight ? 'h-fit' : 'h-full'),
|
|
369
443
|
/*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsuite/page-builder",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0-next.1",
|
|
4
4
|
"description": "Shared BSuite responsive page-builder grid and layout persistence primitives",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/
|
|
12
|
+
"url": "git+https://github.com/Arcane-Fly/bsuite.git",
|
|
13
13
|
"directory": "packages/page-builder"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
@@ -70,18 +70,18 @@
|
|
|
70
70
|
"@bsuite/theme": "workspace:^",
|
|
71
71
|
"@testing-library/jest-dom": "^7.0.1",
|
|
72
72
|
"@testing-library/react": "^16.3.3",
|
|
73
|
-
"@types/node": "^26.
|
|
74
|
-
"@types/react": "^19.
|
|
75
|
-
"@types/react-dom": "^19.
|
|
73
|
+
"@types/node": "^26.6.2",
|
|
74
|
+
"@types/react": "^19.3.0",
|
|
75
|
+
"@types/react-dom": "^19.3.0",
|
|
76
76
|
"@vitejs/plugin-react": "^6.1.1",
|
|
77
|
-
"jsdom": "^30.0
|
|
78
|
-
"lucide-react": "^1.
|
|
79
|
-
"react": "^19.
|
|
80
|
-
"react-dom": "^19.
|
|
77
|
+
"jsdom": "^30.1.0",
|
|
78
|
+
"lucide-react": "^1.47.0",
|
|
79
|
+
"react": "^19.3.0",
|
|
80
|
+
"react-dom": "^19.3.0",
|
|
81
81
|
"react-grid-layout": "^2.2.4",
|
|
82
82
|
"react-resizable": "^4.0.2",
|
|
83
83
|
"typescript": "^6.0.3",
|
|
84
|
-
"vite": "^8.
|
|
84
|
+
"vite": "^8.3.0",
|
|
85
85
|
"vitest": "^4.1.11"
|
|
86
86
|
},
|
|
87
87
|
"packageManager": "pnpm@10.33.3"
|