@bsuite/page-builder 2.8.0-next.0 → 2.8.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/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,8 +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
|
-
/**
|
|
173
|
-
const
|
|
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
|
+
}
|
|
174
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) {
|
|
175
209
|
// Auto-height measurement (blueprint amendment A1). `measureRef` wraps
|
|
176
210
|
// `content` with NO height constraint of its own — its parent has
|
|
@@ -196,6 +230,41 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
196
230
|
const scopedContent = (_jsx(ElementScopeProvider, { scope: { pageKey, cardKey: id, cardLabel: label, isEditing }, children: _jsx(CardPaddingBoundary, { padding: cardPadding, children: content }) }));
|
|
197
231
|
const measureRef = useRef(null);
|
|
198
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]);
|
|
199
268
|
const lastReportedRowsRef = useRef(null);
|
|
200
269
|
const measureRafRef = useRef(null);
|
|
201
270
|
/**
|
|
@@ -274,7 +343,7 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
274
343
|
warnOnceAboutCollapsedContent(el);
|
|
275
344
|
// Re-measure when edit chrome mounts/unmounts so the strip is in the
|
|
276
345
|
// row count in edit mode and gone again on lossless return.
|
|
277
|
-
}, [autoHeight, onAutoHeightChange, reportRows, isEditing, cardStyleVars]);
|
|
346
|
+
}, [autoHeight, onAutoHeightChange, reportRows, isEditing, cardStyleVars, bareContent]);
|
|
278
347
|
useEffect(() => {
|
|
279
348
|
if (!autoHeight || !onAutoHeightChange)
|
|
280
349
|
return;
|
|
@@ -326,7 +395,7 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
326
395
|
const outerClass = cn('relative group overflow-visible', isEditing && 'drag-handle',
|
|
327
396
|
// Paused editing (bsuite#3277) cannot move a card, so it must not promise to.
|
|
328
397
|
isEditing && !editingPaused && 'cursor-move', injectedClassName);
|
|
329
|
-
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
|
|
330
399
|
? // ONE radius token, read by the grid item AND available to any
|
|
331
400
|
// app card that opts into the same surface. Two surfaces
|
|
332
401
|
// reading the SAME var is what makes their corners align, and
|
|
@@ -366,18 +435,9 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
366
435
|
// manually-resized slot h-full is still right: the user chose that
|
|
367
436
|
// height and the chrome should fill it.
|
|
368
437
|
autoHeight ? 'h-fit' : 'h-full',
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
|
|
372
|
-
// filter bars, plain sections, 182 slots in crm7 alone. A
|
|
373
|
-
// blanket inset is wrong, because most slots nest their own
|
|
374
|
-
// Card and would gain a gutter. So the surface pads only
|
|
375
|
-
// when nothing inside it declares its own surface or inset:
|
|
376
|
-
// `data-slot="card"` (shadcn's convention) or
|
|
377
|
-
// `data-slot="page-header"`. The value is PageHeader's own
|
|
378
|
-
// p-6 md:p-7, so a bare slot and a header line up. An
|
|
379
|
-
// operator-set --card-padding is inline style and still wins.
|
|
380
|
-
CHROME_BARE_CONTENT_INSET)
|
|
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')
|
|
381
441
|
: // Chrome OFF: layout only. Identical box, no paint.
|
|
382
442
|
cn('w-full transition-all flex flex-col', autoHeight ? 'h-fit' : 'h-full'),
|
|
383
443
|
/*
|