@swiftbrowser/react 0.26.10 → 0.27.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/index.js CHANGED
@@ -63,153 +63,41 @@ function usePlatform() {
63
63
  function useRedacted() {
64
64
  return useContext(ViewEnvironmentContext).redacted === true;
65
65
  }
66
- let currentUpdatePriority = 0;
67
- function detach(parent, child) {
68
- const at = parent.children.indexOf(child);
69
- if (at >= 0) parent.children.splice(at, 1);
70
- }
71
- const hostConfig = {
72
- supportsMutation: true,
73
- supportsPersistence: false,
74
- supportsHydration: false,
75
- isPrimaryRenderer: true,
76
- noTimeout: -1,
77
- scheduleTimeout: setTimeout,
78
- cancelTimeout: clearTimeout,
79
- supportsMicrotasks: true,
80
- scheduleMicrotask: queueMicrotask,
81
- getRootHostContext: () => ({}),
82
- getChildHostContext: (parent) => parent,
83
- getPublicInstance: (instance) => instance,
84
- prepareForCommit: () => null,
85
- resetAfterCommit: (tree) => tree.commit(),
86
- preparePortalMount: () => {
87
- },
88
- shouldSetTextContent: () => false,
89
- createInstance: (type, props, tree) => {
90
- if (type !== "sb") throw new Error(`Unknown host element <${type}>: only SwiftUI components render here.`);
91
- return tree.createInstance(props);
92
- },
93
- createTextInstance: (text) => {
94
- throw new Error(`Text strings must be rendered within a <Text> component (got ${JSON.stringify(text)}).`);
95
- },
96
- appendInitialChild: (parent, child) => parent.children.push(child),
97
- finalizeInitialChildren: () => false,
98
- commitMount: () => {
99
- },
100
- commitUpdate: (instance, _type, _prev, next, handle) => {
101
- const tree = treeOf(handle);
102
- if (tree) tree.updateInstance(instance, next);
103
- else {
104
- instance.props = next.props ?? {};
105
- instance.on = next.on;
106
- instance.target = next.target;
107
- }
108
- },
109
- appendChild: (parent, child) => {
110
- detach(parent, child);
111
- parent.children.push(child);
112
- },
113
- appendChildToContainer: (tree, child) => {
114
- detach(tree.root, child);
115
- tree.root.children.push(child);
116
- },
117
- insertBefore: (parent, child, before) => {
118
- detach(parent, child);
119
- const at = parent.children.indexOf(before);
120
- parent.children.splice(at < 0 ? parent.children.length : at, 0, child);
121
- },
122
- insertInContainerBefore: (tree, child, before) => {
123
- detach(tree.root, child);
124
- const at = tree.root.children.indexOf(before);
125
- tree.root.children.splice(at < 0 ? tree.root.children.length : at, 0, child);
126
- },
127
- removeChild: (parent, child) => detach(parent, child),
128
- removeChildFromContainer: (tree, child) => detach(tree.root, child),
129
- clearContainer: (tree) => {
130
- tree.root.children = [];
131
- },
132
- resetTextContent: () => {
133
- },
134
- commitTextUpdate: () => {
135
- },
136
- hideInstance: (instance) => {
137
- instance.hidden = true;
138
- },
139
- unhideInstance: (instance) => {
140
- instance.hidden = false;
141
- },
142
- hideTextInstance: () => {
143
- },
144
- unhideTextInstance: () => {
145
- },
146
- detachDeletedInstance: () => {
147
- },
148
- getInstanceFromNode: () => null,
149
- beforeActiveInstanceBlur: () => {
150
- },
151
- afterActiveInstanceBlur: () => {
152
- },
153
- prepareScopeUpdate: () => {
154
- },
155
- getInstanceFromScope: () => null,
156
- setCurrentUpdatePriority: (priority) => {
157
- currentUpdatePriority = priority;
158
- },
159
- getCurrentUpdatePriority: () => currentUpdatePriority,
160
- resolveUpdatePriority: () => currentUpdatePriority !== 0 ? currentUpdatePriority : DefaultEventPriority,
161
- resetFormInstance: () => {
162
- },
163
- requestPostPaintCallback: () => {
164
- },
165
- shouldAttemptEagerTransition: () => false,
166
- trackSchedulerEvent: () => {
167
- },
168
- resolveEventType: () => null,
169
- resolveEventTimeStamp: () => -1.1,
170
- maySuspendCommit: () => false,
171
- maySuspendCommitOnUpdate: () => false,
172
- maySuspendCommitInSyncRender: () => false,
173
- suspendOnActiveViewTransition: () => {
174
- },
175
- getSuspendedCommitReason: () => null,
176
- bindToConsole: (methodName, args) => () => console[methodName]?.(...args),
177
- preloadInstance: () => true,
178
- startSuspendingCommit: () => null,
179
- suspendInstance: () => {
180
- },
181
- waitForCommitToBeReady: () => null,
182
- NotPendingTransition: null,
183
- HostTransitionContext: createContext(null),
184
- rendererVersion: "0.3.1",
185
- rendererPackageName: "@swiftbrowser/react",
186
- extraDevToolsConfig: null
187
- };
188
- function treeOf(handle) {
189
- let fiber = handle;
190
- while (fiber) {
191
- if (fiber.tag === 3) return fiber.stateNode.containerInfo;
192
- fiber = fiber.return;
193
- }
194
- return null;
195
- }
196
- const reconciler = Reconciler(hostConfig);
197
66
  const PREF_KIND = "$pref";
198
67
  const HOIST_KIND = "$hoist";
199
- function inheritTitleModes(screens, effective) {
68
+ function inheritTitleModes(screens) {
200
69
  let below = "large";
201
70
  for (const screen of screens) {
202
- const props = screen.kind === "navscreen" ? effective.get(screen)?.props : void 0;
203
- if (!props) continue;
204
- const depth = typeof props["depth"] === "number" ? props["depth"] : 0;
205
- let mode = typeof props["displayMode"] === "string" ? props["displayMode"] : "automatic";
71
+ const entry = screen.kind === "navscreen" ? screen.entry : null;
72
+ if (!entry) continue;
73
+ const base = entry.base;
74
+ const depth = typeof base["depth"] === "number" ? base["depth"] : 0;
75
+ let mode = typeof base["displayMode"] === "string" ? base["displayMode"] : "automatic";
206
76
  if (mode === "automatic") {
207
- if (depth > 0) props["displayMode"] = below;
77
+ if (depth > 0) {
78
+ if (entry.props["displayMode"] !== below) entry.props = { ...base, displayMode: below };
79
+ } else if (entry.props !== base) entry.props = base;
208
80
  mode = depth > 0 ? below : "large";
209
- }
81
+ } else if (entry.props !== base) entry.props = base;
210
82
  below = mode === "inline" ? "inline" : "large";
211
83
  }
212
84
  }
85
+ function markStale(node) {
86
+ for (let current = node; current && !current.stale; current = current.kind === "root" ? null : current.parent) current.stale = true;
87
+ }
88
+ function attach(parent, child, index) {
89
+ detach(parent, child);
90
+ if (index === void 0 || index < 0 || index > parent.children.length) parent.children.push(child);
91
+ else parent.children.splice(index, 0, child);
92
+ child.parent = parent;
93
+ markStale(parent);
94
+ }
95
+ function detach(parent, child) {
96
+ const at = parent.children.indexOf(child);
97
+ if (at >= 0) parent.children.splice(at, 1);
98
+ if (child.parent === parent) child.parent = null;
99
+ markStale(parent);
100
+ }
213
101
  class HostTree {
214
102
  constructor(sink, options = {}) {
215
103
  this.sink = sink;
@@ -217,13 +105,14 @@ class HostTree {
217
105
  }
218
106
  sink;
219
107
  options;
220
- root = { id: 0, kind: "root", children: [], committedChildren: [] };
108
+ root = { id: 0, kind: "root", children: [], committedChildren: [], parent: null, stale: true, entry: null };
221
109
  nextId = 1;
222
110
  /** Emitted elements by id, for event dispatch. */
223
111
  live = /* @__PURE__ */ new Map();
224
- committedLive = /* @__PURE__ */ new Set();
225
112
  /** Ids whose element changed kind: removed at the end of the next flush. */
226
113
  retired = [];
114
+ /** Which flush is under way; an instance resolved in it carries the number. */
115
+ generation = 0;
227
116
  /** `withAnimation`: stamped on the next `commit`. */
228
117
  pendingAnimation;
229
118
  /** `withAnimation(_:completionCriteria:_:completion:)`: stamped on the next `commit` with its serial; the callback waits in `completions`. */
@@ -249,7 +138,13 @@ class HostTree {
249
138
  created: false,
250
139
  committedProps: null,
251
140
  committedParent: null,
252
- committedChildren: []
141
+ committedChildren: [],
142
+ parent: null,
143
+ stale: true,
144
+ entry: null,
145
+ shown: false,
146
+ effectiveParent: null,
147
+ resolvedIn: 0
253
148
  };
254
149
  }
255
150
  updateInstance(instance, next) {
@@ -268,6 +163,12 @@ class HostTree {
268
163
  instance.props = next.props ?? {};
269
164
  instance.on = next.on;
270
165
  instance.target = next.target;
166
+ markStale(instance);
167
+ }
168
+ /** `node` is hidden or shown again (Suspense): it leaves or rejoins the emitted tree. */
169
+ setHidden(instance, hidden) {
170
+ instance.hidden = hidden;
171
+ markStale(instance);
271
172
  }
272
173
  /** Emit the ops for everything that changed since the last commit. */
273
174
  commit() {
@@ -279,68 +180,134 @@ class HostTree {
279
180
  this.pendingAnimation = void 0;
280
181
  const completion = this.pendingCompletion;
281
182
  this.pendingCompletion = void 0;
282
- const effective = /* @__PURE__ */ new Map();
283
- const rootEffective = { props: {}, children: [], hoisted: [] };
284
- effective.set(this.root, rootEffective);
285
- const visit = (child, sink, ctx) => {
183
+ const generation = ++this.generation;
184
+ const root = this.root;
185
+ const rootEntry = { props: {}, base: {}, children: [], hoisted: [], escaping: [] };
186
+ const previousRoot = root.entry;
187
+ root.entry = rootEntry;
188
+ const resolved = [];
189
+ const path = [];
190
+ const targetOf = (target, ctx, hoist) => {
191
+ if (target === "root" || target === void 0) return root;
192
+ return ctx[target] ?? (hoist || this.options.remote ? root : void 0);
193
+ };
194
+ const keep = (contribution, target) => {
195
+ for (let i = path.length - 1; i >= 0; i--) {
196
+ const node = path[i];
197
+ if (node === target) return;
198
+ node.entry.escaping.push(contribution);
199
+ }
200
+ };
201
+ const assign = (target, props) => {
202
+ const entry = target.entry;
203
+ if (target.kind !== "root" && entry.props === target.props) {
204
+ entry.props = { ...entry.props };
205
+ entry.base = entry.props;
206
+ }
207
+ Object.assign(entry.props, props);
208
+ if (entry.base !== entry.props) Object.assign(entry.base, props);
209
+ };
210
+ const contribute = (contribution, ctx) => {
211
+ if (contribution.kind === "pref") {
212
+ const target = targetOf(contribution.target, ctx, false);
213
+ if (target) assign(target, contribution.props);
214
+ keep(contribution, target);
215
+ } else {
216
+ const target = targetOf(contribution.target, ctx, true);
217
+ target.entry.hoisted.push(contribution.node);
218
+ contribution.node.effectiveParent = target;
219
+ keep(contribution, target);
220
+ }
221
+ };
222
+ const visit = (child, sink, owner, ctx, hoistedTo) => {
286
223
  if (child.hidden) return;
287
224
  if (child.kind === PREF_KIND) {
288
- const target = child.target === "root" || child.target === void 0 ? this.root : ctx[child.target] ?? (this.options.remote ? this.root : void 0);
289
- const entry2 = target ? effective.get(target) : void 0;
290
- if (entry2) Object.assign(entry2.props, child.props);
225
+ contribute({ kind: "pref", target: child.target, props: child.props }, ctx);
291
226
  return;
292
227
  }
293
228
  if (child.kind === HOIST_KIND) {
294
- const target = (child.target && child.target !== "root" ? ctx[child.target] : void 0) ?? this.root;
295
- const entry2 = effective.get(target);
296
- for (const grandchild of child.children) visit(grandchild, entry2.hoisted, ctx);
229
+ const target = targetOf(child.target, ctx, true);
230
+ for (const grandchild of child.children) visit(grandchild, target.entry.hoisted, target, ctx, child.target ?? "root");
297
231
  return;
298
232
  }
299
- const entry = { props: { ...child.props }, children: [], hoisted: [] };
300
- effective.set(child, entry);
233
+ if (hoistedTo !== void 0) {
234
+ child.effectiveParent = owner;
235
+ keep({ kind: "hoist", target: hoistedTo ?? void 0, node: child }, owner);
236
+ }
301
237
  sink.push(child);
238
+ if (!child.stale && child.entry) {
239
+ child.effectiveParent = owner;
240
+ child.shown = true;
241
+ for (const contribution of child.entry.escaping) contribute(contribution, ctx);
242
+ return;
243
+ }
244
+ const entry = { props: child.props, base: child.props, children: [], hoisted: [], escaping: [] };
245
+ resolved.push([child, child.entry]);
246
+ child.entry = entry;
247
+ child.stale = false;
248
+ child.shown = true;
249
+ child.effectiveParent = owner;
250
+ child.resolvedIn = generation;
302
251
  const next = child.kind === "navscreen" ? { ...ctx, navscreen: child } : child.kind === "sheet" ? { ...ctx, sheet: child } : ctx;
303
- for (const grandchild of child.children) visit(grandchild, entry.children, next);
252
+ path.push(child);
253
+ for (const grandchild of child.children) visit(grandchild, entry.children, child, next, void 0);
254
+ path.pop();
304
255
  };
305
- for (const child of this.root.children) visit(child, rootEffective.children, {});
306
- for (const entry of effective.values()) {
256
+ for (const child of root.children) visit(child, rootEntry.children, root, {}, void 0);
257
+ root.stale = false;
258
+ if (rootEntry.hoisted.length > 0) rootEntry.children.push(...rootEntry.hoisted);
259
+ for (const [node] of resolved) {
260
+ const entry = node.entry;
307
261
  if (entry.hoisted.length > 0) entry.children.push(...entry.hoisted);
308
262
  }
309
- for (const [node, entry] of effective) {
310
- if (node !== this.root && node.kind === "navstack") inheritTitleModes(entry.children, effective);
311
- }
312
- const live = /* @__PURE__ */ new Set();
313
- const parentOf = /* @__PURE__ */ new Map();
314
- for (const [node, entry] of effective) {
315
- for (const child of entry.children) {
316
- live.add(child);
317
- parentOf.set(child, node);
318
- }
263
+ for (const [node] of resolved) {
264
+ if (node.kind === "navstack") inheritTitleModes(node.entry.children);
319
265
  }
320
266
  const ops = [];
321
- const dead = /* @__PURE__ */ new Set();
322
- for (const instance of this.committedLive) if (!live.has(instance)) dead.add(instance);
323
- for (const instance of dead) {
324
- const parent = instance.committedParent;
325
- if (parent && parent !== this.root && dead.has(parent)) continue;
326
- ops.push({ op: "remove", id: instance.id });
327
- }
328
- for (const instance of dead) {
267
+ const left = [];
268
+ const arrived = /* @__PURE__ */ new Set();
269
+ const compare = (before, after) => {
270
+ if (!before) {
271
+ for (const child of after) arrived.add(child);
272
+ return;
273
+ }
274
+ let same = before.length === after.length;
275
+ for (let i = 0; same && i < after.length; i++) if (before[i] !== after[i]) same = false;
276
+ if (same) return;
277
+ const now = new Set(after);
278
+ for (const child of before) if (!now.has(child)) left.push(child);
279
+ const then = new Set(before);
280
+ for (const child of after) if (!then.has(child)) arrived.add(child);
281
+ };
282
+ compare(previousRoot?.children, rootEntry.children);
283
+ for (const [node, previous] of resolved) compare(previous?.children, node.entry.children);
284
+ const gone = (instance) => {
329
285
  this.live.delete(instance.id);
286
+ instance.shown = false;
330
287
  instance.created = false;
331
288
  instance.committedProps = null;
332
289
  instance.committedParent = null;
333
290
  instance.committedChildren = [];
291
+ instance.stale = true;
292
+ const entry = instance.entry;
293
+ if (entry) {
294
+ for (const child of entry.children) if (child.effectiveParent === instance) gone(child);
295
+ }
296
+ };
297
+ for (const instance of left) {
298
+ if (!instance.shown || arrived.has(instance)) continue;
299
+ ops.push({ op: "remove", id: instance.id });
300
+ gone(instance);
334
301
  }
335
302
  const emit = (parent, entry) => {
336
- const current = parent.committedChildren.filter((child) => live.has(child) && parentOf.get(child) === parent);
303
+ const current = parent.committedChildren.filter((child) => child.shown && child.effectiveParent === parent);
337
304
  entry.children.forEach((child, index) => {
338
- const childEntry = effective.get(child);
305
+ const childEntry = child.entry;
339
306
  if (!child.created) {
340
307
  ops.push({ op: "create", id: child.id, kind: child.kind, props: childEntry.props });
341
308
  child.created = true;
342
309
  this.live.set(child.id, child);
343
- } else if (!deepEqual(childEntry.props, child.committedProps)) {
310
+ } else if (childEntry.props !== child.committedProps && !deepEqual(childEntry.props, child.committedProps)) {
344
311
  ops.push({ op: "update", id: child.id, props: childEntry.props });
345
312
  }
346
313
  child.committedProps = childEntry.props;
@@ -351,21 +318,20 @@ class HostTree {
351
318
  current.splice(index, 0, child);
352
319
  }
353
320
  child.committedParent = parent;
354
- emit(child, childEntry);
321
+ if (child.resolvedIn === generation) emit(child, childEntry);
355
322
  });
356
323
  parent.committedChildren = entry.children;
357
324
  };
358
- emit(this.root, rootEffective);
325
+ emit(root, rootEntry);
359
326
  for (const id of this.retired) ops.push({ op: "remove", id });
360
327
  this.retired = [];
361
- this.committedLive = live;
362
328
  if (this.options.remote) {
363
- if (!deepEqual(rootEffective.props, this.committedRootProps)) {
364
- ops.push({ op: "update", id: 0, props: rootEffective.props });
365
- this.committedRootProps = rootEffective.props;
329
+ if (!deepEqual(rootEntry.props, this.committedRootProps)) {
330
+ ops.push({ op: "update", id: 0, props: rootEntry.props });
331
+ this.committedRootProps = rootEntry.props;
366
332
  }
367
333
  } else {
368
- const scheme = rootEffective.props["colorScheme"];
334
+ const scheme = rootEntry.props["colorScheme"];
369
335
  const next = scheme === void 0 ? this.committedColorScheme === void 0 ? void 0 : null : scheme;
370
336
  if (next !== void 0 && next !== this.committedColorScheme) {
371
337
  ops.push({ op: "update", id: 0, props: { colorScheme: next } });
@@ -422,6 +388,132 @@ function deepEqual(a, b) {
422
388
  if (keys.length !== Object.keys(right).length) return false;
423
389
  return keys.every((key) => key in right && deepEqual(left[key], right[key]));
424
390
  }
391
+ let currentUpdatePriority = 0;
392
+ const hostConfig = {
393
+ supportsMutation: true,
394
+ supportsPersistence: false,
395
+ supportsHydration: false,
396
+ isPrimaryRenderer: true,
397
+ noTimeout: -1,
398
+ scheduleTimeout: setTimeout,
399
+ cancelTimeout: clearTimeout,
400
+ supportsMicrotasks: true,
401
+ scheduleMicrotask: queueMicrotask,
402
+ getRootHostContext: () => ({}),
403
+ getChildHostContext: (parent) => parent,
404
+ getPublicInstance: (instance) => instance,
405
+ prepareForCommit: () => null,
406
+ resetAfterCommit: (tree) => tree.commit(),
407
+ preparePortalMount: () => {
408
+ },
409
+ shouldSetTextContent: () => false,
410
+ createInstance: (type, props, tree) => {
411
+ if (type !== "sb") throw new Error(`Unknown host element <${type}>: only SwiftUI components render here.`);
412
+ return tree.createInstance(props);
413
+ },
414
+ createTextInstance: (text) => {
415
+ throw new Error(`Text strings must be rendered within a <Text> component (got ${JSON.stringify(text)}).`);
416
+ },
417
+ appendInitialChild: (parent, child) => attach(parent, child),
418
+ finalizeInitialChildren: () => false,
419
+ commitMount: () => {
420
+ },
421
+ commitUpdate: (instance, _type, _prev, next, handle) => {
422
+ const tree = treeOf(handle);
423
+ if (tree) tree.updateInstance(instance, next);
424
+ else {
425
+ instance.props = next.props ?? {};
426
+ instance.on = next.on;
427
+ instance.target = next.target;
428
+ markStale(instance);
429
+ }
430
+ },
431
+ appendChild: (parent, child) => attach(parent, child),
432
+ appendChildToContainer: (tree, child) => attach(tree.root, child),
433
+ insertBefore: (parent, child, before) => {
434
+ detach(parent, child);
435
+ const at = parent.children.indexOf(before);
436
+ attach(parent, child, at < 0 ? parent.children.length : at);
437
+ },
438
+ insertInContainerBefore: (tree, child, before) => {
439
+ detach(tree.root, child);
440
+ const at = tree.root.children.indexOf(before);
441
+ attach(tree.root, child, at < 0 ? tree.root.children.length : at);
442
+ },
443
+ removeChild: (parent, child) => detach(parent, child),
444
+ removeChildFromContainer: (tree, child) => detach(tree.root, child),
445
+ clearContainer: (tree) => {
446
+ for (const child of tree.root.children) child.parent = null;
447
+ tree.root.children = [];
448
+ markStale(tree.root);
449
+ },
450
+ resetTextContent: () => {
451
+ },
452
+ commitTextUpdate: () => {
453
+ },
454
+ hideInstance: (instance) => {
455
+ instance.hidden = true;
456
+ markStale(instance);
457
+ },
458
+ unhideInstance: (instance) => {
459
+ instance.hidden = false;
460
+ markStale(instance);
461
+ },
462
+ hideTextInstance: () => {
463
+ },
464
+ unhideTextInstance: () => {
465
+ },
466
+ detachDeletedInstance: () => {
467
+ },
468
+ getInstanceFromNode: () => null,
469
+ beforeActiveInstanceBlur: () => {
470
+ },
471
+ afterActiveInstanceBlur: () => {
472
+ },
473
+ prepareScopeUpdate: () => {
474
+ },
475
+ getInstanceFromScope: () => null,
476
+ setCurrentUpdatePriority: (priority) => {
477
+ currentUpdatePriority = priority;
478
+ },
479
+ getCurrentUpdatePriority: () => currentUpdatePriority,
480
+ resolveUpdatePriority: () => currentUpdatePriority !== 0 ? currentUpdatePriority : DefaultEventPriority,
481
+ resetFormInstance: () => {
482
+ },
483
+ requestPostPaintCallback: () => {
484
+ },
485
+ shouldAttemptEagerTransition: () => false,
486
+ trackSchedulerEvent: () => {
487
+ },
488
+ resolveEventType: () => null,
489
+ resolveEventTimeStamp: () => -1.1,
490
+ maySuspendCommit: () => false,
491
+ maySuspendCommitOnUpdate: () => false,
492
+ maySuspendCommitInSyncRender: () => false,
493
+ suspendOnActiveViewTransition: () => {
494
+ },
495
+ getSuspendedCommitReason: () => null,
496
+ bindToConsole: (methodName, args) => () => console[methodName]?.(...args),
497
+ preloadInstance: () => true,
498
+ startSuspendingCommit: () => null,
499
+ suspendInstance: () => {
500
+ },
501
+ waitForCommitToBeReady: () => null,
502
+ NotPendingTransition: null,
503
+ HostTransitionContext: createContext(null),
504
+ rendererVersion: "0.3.1",
505
+ rendererPackageName: "@swiftbrowser/react",
506
+ extraDevToolsConfig: null
507
+ };
508
+ function treeOf(handle) {
509
+ let fiber = handle;
510
+ while (fiber) {
511
+ if (fiber.tag === 3) return fiber.stateNode.containerInfo;
512
+ fiber = fiber.return;
513
+ }
514
+ return null;
515
+ }
516
+ const reconciler = Reconciler(hostConfig);
425
517
  const DEFAULT_ENVIRONMENT = { colorScheme: "light", dynamicTypeSize: "large", horizontalSizeClass: "compact", scenePhase: "active", platform: "ios" };
426
518
  const roots = /* @__PURE__ */ new Set();
427
519
  const HostTreeContext = createContext(null);
@@ -2196,7 +2288,7 @@ function NavigationSplitView(props) {
2196
2288
  const detail = isValidElement(own.detail) && own.detail.type === NavigationStack ? own.detail : /* @__PURE__ */ jsx(NavigationStack, { children: own.detail });
2197
2289
  const sidebar = own.sidebarWidth !== void 0 ? sb("styled", { style: { splitColumnWidth: splitColumnWidthHint(own.sidebarWidth) } }, void 0, own.sidebar) : own.sidebar;
2198
2290
  return applyModifiers(
2199
- sb("navsplit", { sidebarVisible }, { tap: toggle }, [
2291
+ sb("navsplit", { sidebarVisible }, { tap: toggle, columnwidth: (event) => own.onSidebarWidthChange?.(event.width) }, [
2200
2292
  /* @__PURE__ */ jsx(SplitColumn, { report, children: /* @__PURE__ */ jsx(NavigationStack, { children: sidebar }) }, "sidebar"),
2201
2293
  /* @__PURE__ */ jsx(SplitColumn, { report: null, children: detail }, "detail")
2202
2294
  ]),
@@ -2641,6 +2733,7 @@ const MODIFIER_KEYS = /* @__PURE__ */ new Set([
2641
2733
  "coordinateSpace",
2642
2734
  "contentTransition",
2643
2735
  "scrollDisabled",
2736
+ "defaultMinListRowHeight",
2644
2737
  "scrollEdgeEffectStyle",
2645
2738
  "scrollEdgeEffectHidden",
2646
2739
  "contentMargins",
@@ -2830,7 +2923,8 @@ const STYLED_KEYS = /* @__PURE__ */ new Set([
2830
2923
  "containerRelativeFrame",
2831
2924
  "contentTransition",
2832
2925
  "scrollDisabled",
2833
- "textSelection"
2926
+ "textSelection",
2927
+ "defaultMinListRowHeight"
2834
2928
  ]);
2835
2929
  const ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
2836
2930
  "buttonStyle",
@@ -3254,6 +3348,8 @@ function apply(key, value, node, sides) {
3254
3348
  }
3255
3349
  case "scrollDisabled":
3256
3350
  return styled({ scrollDisabled: value === true }, node);
3351
+ case "defaultMinListRowHeight":
3352
+ return typeof value === "number" && Number.isFinite(value) ? styled({ defaultMinListRowHeight: Math.max(0, value) }, node) : styled({}, node);
3257
3353
  case "textSelection":
3258
3354
  return styled({ textSelection: value === "enabled" }, node);
3259
3355
  case "contentTransition": {