@swiftbrowser/web 0.17.3 → 0.17.4
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/package.json +1 -1
- package/src/layout/engine.ts +26 -5
- package/src/layoutDom.ts +3 -0
package/package.json
CHANGED
package/src/layout/engine.ts
CHANGED
|
@@ -162,6 +162,10 @@ const NAV_BAR_HEIGHT = 44;
|
|
|
162
162
|
const NAV_BAR_INLINE_BOTTOM = 10;
|
|
163
163
|
// iOS 26: the large title's row is 62 (52 before).
|
|
164
164
|
const LARGE_TITLE_HEIGHT = 62;
|
|
165
|
+
// iOS 26: `.largeTitle` toolbar items take the title's place 10 below the
|
|
166
|
+
// bar's 44 row, in a row exactly their height: the content starts right
|
|
167
|
+
// under them (measured in the iOS 26 simulator, Native's LargeTitleTests).
|
|
168
|
+
const LARGE_TITLE_ITEM_TOP = 10;
|
|
165
169
|
const SHEET_GRABBER_ROW = 20;
|
|
166
170
|
const SHEET_GRABBER: Size = { width: 36, height: 5 };
|
|
167
171
|
const SHEET_GRABBER_TOP = 8;
|
|
@@ -3390,8 +3394,9 @@ export class LayoutPass {
|
|
|
3390
3394
|
|
|
3391
3395
|
/**
|
|
3392
3396
|
* The navigation bar is the status bar plus a 44 row (plus 62 for a large
|
|
3393
|
-
* title
|
|
3394
|
-
*
|
|
3397
|
+
* title, or 10 and the height of its `.largeTitle` items); a Phase 6
|
|
3398
|
+
* `searchfield` is a capsule floating above the bottom (iOS 26); `bottom`
|
|
3399
|
+
* toolbars float their items on glass in a 48 row 28
|
|
3395
3400
|
* above the bottom (`placeBottomToolbars`); the content is proposed the
|
|
3396
3401
|
* rest. Toolbar items are measured at their ideal size and laid out in iOS
|
|
3397
3402
|
* 26 glass capsules in the 44 row: adjacent `leading` (or `trailing`)
|
|
@@ -3403,6 +3408,18 @@ export class LayoutPass {
|
|
|
3403
3408
|
* inline title (`chrome.title`) is centered and truncated to the room the
|
|
3404
3409
|
* bar items leave.
|
|
3405
3410
|
*/
|
|
3411
|
+
/** The tallest `.largeTitle` toolbar item at its ideal size, or null when the screen has none (the text title shows). */
|
|
3412
|
+
private largeTitleItemsHeight(toolbars: readonly LayoutNode[], cctx: Context, width: number): number | null {
|
|
3413
|
+
let height: number | null = null;
|
|
3414
|
+
for (const toolbar of toolbars) {
|
|
3415
|
+
if (str(toolbar.props['placement']) !== 'largeTitle' || str(toolbar.props['spacer']) !== null) continue;
|
|
3416
|
+
const itemCtx = this.childContext(toolbar, cctx);
|
|
3417
|
+
const room: Proposal = { width: Math.max(0, width - 2 * NAV_ITEM_MARGIN), height: null };
|
|
3418
|
+
for (const item of toolbar.children) height = Math.max(height ?? 0, this.measure(item, itemCtx, room).height);
|
|
3419
|
+
}
|
|
3420
|
+
return height;
|
|
3421
|
+
}
|
|
3422
|
+
|
|
3406
3423
|
private placeNavScreen(node: LayoutNode, cctx: Context, x: number, y: number, size: Size): void {
|
|
3407
3424
|
const { safeArea, screen, dynamicTypeSize } = this.env;
|
|
3408
3425
|
const statusBar = y <= 0 ? safeArea.top : (cctx.barInset ?? 0);
|
|
@@ -3410,10 +3427,12 @@ export class LayoutPass {
|
|
|
3410
3427
|
const depth = num(node.props['depth']) ?? 0;
|
|
3411
3428
|
const large = displayMode === 'large' || (displayMode === 'automatic' && depth === 0);
|
|
3412
3429
|
const barHeight = statusBar + NAV_BAR_HEIGHT + (!large && y <= 0 ? NAV_BAR_INLINE_BOTTOM : 0);
|
|
3413
|
-
const largeHeight = large ? LARGE_TITLE_HEIGHT : 0;
|
|
3414
3430
|
const parts = this.navScreenParts(node);
|
|
3415
3431
|
const reachesBottom = y + size.height >= screen.height - EPSILON;
|
|
3416
3432
|
const isSpacer = (t: LayoutNode): boolean => str(t.props['spacer']) !== null;
|
|
3433
|
+
// `.largeTitle` items size the large title row; the text title is 62.
|
|
3434
|
+
const titleItemsHeight = large ? this.largeTitleItemsHeight(parts.toolbars, cctx, size.width) : null;
|
|
3435
|
+
const largeHeight = !large ? 0 : titleItemsHeight !== null ? LARGE_TITLE_ITEM_TOP + titleItemsHeight : LARGE_TITLE_HEIGHT;
|
|
3417
3436
|
const bottomToolbars = parts.toolbars.filter((t) => str(t.props['placement']) === 'bottom');
|
|
3418
3437
|
const searchMargin = reachesBottom ? SEARCH_BOTTOM_MARGIN : SEARCH_BOTTOM_MARGIN_INSET;
|
|
3419
3438
|
const bottomBarHeight = bottomToolbars.some((t) => !isSpacer(t))
|
|
@@ -3443,7 +3462,7 @@ export class LayoutPass {
|
|
|
3443
3462
|
barRow: { x, y: y + statusBar, width: size.width, height: NAV_BAR_HEIGHT },
|
|
3444
3463
|
content,
|
|
3445
3464
|
};
|
|
3446
|
-
if (large) chrome['largeTitle'] = { x, y: y + barHeight, width: size.width, height:
|
|
3465
|
+
if (large) chrome['largeTitle'] = { x, y: y + barHeight, width: size.width, height: largeHeight };
|
|
3447
3466
|
if (parts.search) {
|
|
3448
3467
|
const marginH = searchOnTop ? SEARCH_FIELD_MARGIN_H : SEARCH_BOTTOM_MARGIN_H;
|
|
3449
3468
|
chrome['searchField'] = {
|
|
@@ -3711,9 +3730,11 @@ export class LayoutPass {
|
|
|
3711
3730
|
const itemCtx = this.childContext(toolbar, cctx);
|
|
3712
3731
|
const room: Proposal = { width: Math.max(0, row.width - 2 * NAV_ITEM_MARGIN), height: null };
|
|
3713
3732
|
let cursor = row.x + NAV_ITEM_MARGIN;
|
|
3733
|
+
// The items' band: the row below its 10 top, as tall as the tallest item.
|
|
3734
|
+
const band = row.height - LARGE_TITLE_ITEM_TOP;
|
|
3714
3735
|
for (const item of toolbar.children) {
|
|
3715
3736
|
const itemSize = this.measure(item, itemCtx, room);
|
|
3716
|
-
this.place(item, itemCtx, room, cursor, row.y + (
|
|
3737
|
+
this.place(item, itemCtx, room, cursor, row.y + LARGE_TITLE_ITEM_TOP + (band - itemSize.height) / 2);
|
|
3717
3738
|
cursor += itemSize.width + NAV_ITEM_SPACING;
|
|
3718
3739
|
}
|
|
3719
3740
|
this.setFrame(toolbar, row.x, row.y, { width: row.width, height: row.height });
|
package/src/layoutDom.ts
CHANGED
|
@@ -944,6 +944,9 @@ function applyChrome(
|
|
|
944
944
|
applyChartChrome(el, node, result, box);
|
|
945
945
|
return;
|
|
946
946
|
case 'listrow':
|
|
947
|
+
// A selectable or editable row is the list's row: the engine reads a
|
|
948
|
+
// badge through it and puts the badge's rect on it, so it draws it.
|
|
949
|
+
applyBadge(result, node, el, box);
|
|
947
950
|
// Phase 8: the edit-mode control (selection circle / minus) at the
|
|
948
951
|
// engine's `editControl` rect and the reorder grip at `reorderControl`;
|
|
949
952
|
// hidden when the list is not editing.
|