@omerdlw/base-framework 1.0.5 → 1.0.6

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.
@@ -423,329 +423,6 @@ function Button({
423
423
  );
424
424
  }
425
425
  Button.displayName = "Button";
426
- function isValidComponentType(type) {
427
- if (typeof type === "function") return true;
428
- return Boolean(
429
- type != null && typeof type === "object" && !isValidElement(type) && "$$typeof" in type
430
- );
431
- }
432
- function resolveComponentType(...candidates) {
433
- return candidates.find(isValidComponentType) ?? null;
434
- }
435
- function resolveRenderableContent(...candidates) {
436
- return candidates.find(
437
- (candidate) => candidate !== null && candidate !== void 0
438
- ) ?? null;
439
- }
440
- function collectSearchableText(value, visitedObjects) {
441
- if (typeof value === "string") return value;
442
- if (typeof value === "number" || typeof value === "boolean") {
443
- return String(value);
444
- }
445
- if (Array.isArray(value)) {
446
- if (visitedObjects.has(value)) return "";
447
- visitedObjects.add(value);
448
- const text = value.map((entry) => collectSearchableText(entry, visitedObjects)).join(" ");
449
- visitedObjects.delete(value);
450
- return text;
451
- }
452
- if (isValidElement(value)) {
453
- if (visitedObjects.has(value)) return "";
454
- visitedObjects.add(value);
455
- const text = collectSearchableText(
456
- value.props?.children,
457
- visitedObjects
458
- );
459
- visitedObjects.delete(value);
460
- return text;
461
- }
462
- if (value && typeof value === "object") {
463
- if (visitedObjects.has(value)) return "";
464
- visitedObjects.add(value);
465
- return Object.values(value).map((entry) => collectSearchableText(entry, visitedObjects)).join(" ");
466
- }
467
- return "";
468
- }
469
- function toSearchableText(value) {
470
- return collectSearchableText(value, /* @__PURE__ */ new WeakSet());
471
- }
472
- function normalizeUpper(value) {
473
- return String(value || "").trim().toUpperCase();
474
- }
475
- function formatMediaTime(seconds = 0) {
476
- const sec = Math.max(0, Math.floor(Number(seconds) || 0));
477
- const m = Math.floor(sec / 60);
478
- const s = sec % 60;
479
- return `${m}:${s < 10 ? "0" : ""}${s}`;
480
- }
481
- function isHudDescriptor(value) {
482
- return isObject(value) && !isValidElement(value) && ("component" in value || "content" in value || "node" in value || "element" in value || "isActive" in value || "id" in value);
483
- }
484
- function createDockScheduler(options = {}) {
485
- return createScheduler({
486
- defaultLabel: "dock-task",
487
- ...options
488
- });
489
- }
490
-
491
- // src/modules/dock/paths.ts
492
- function isSamePath(left, right) {
493
- const normalizedLeft = normalizePath(left);
494
- const normalizedRight = normalizePath(right);
495
- return Boolean(
496
- normalizedLeft && normalizedRight && normalizedLeft === normalizedRight
497
- );
498
- }
499
- function isPathPrefix(candidatePath, pathname) {
500
- const normalizedCandidate = normalizePath(candidatePath);
501
- const normalizedPathname = normalizePath(pathname);
502
- if (!normalizedCandidate || !normalizedPathname) return false;
503
- if (normalizedCandidate === normalizedPathname) return true;
504
- if (normalizedCandidate === "/") return normalizedPathname.startsWith("/");
505
- return normalizedPathname.startsWith(`${normalizedCandidate}/`);
506
- }
507
- function isInlineActionPathMatch(path, pathname) {
508
- return isSamePath(path, pathname) || path !== "/" && isPathPrefix(path, pathname);
509
- }
510
- function isSafeInternalHref(value) {
511
- const href = typeof value === "string" ? value.trim() : "";
512
- return href.startsWith("/") && !href.startsWith("//");
513
- }
514
- function getDockLocationKey({
515
- hash = "",
516
- pathname = "/",
517
- search = ""
518
- } = {}) {
519
- const normalizedPathname = String(pathname || "/").trim() || "/";
520
- const normalizedSearch = String(search || "").trim();
521
- const normalizedHash = String(hash || "").trim();
522
- const query = normalizedSearch ? normalizedSearch.startsWith("?") ? normalizedSearch : `?${normalizedSearch}` : "";
523
- const fragment = normalizedHash ? normalizedHash.startsWith("#") ? normalizedHash : `#${normalizedHash}` : "";
524
- return `${normalizedPathname}${query}${fragment}`;
525
- }
526
-
527
- // src/modules/dock/surface/helpers.ts
528
- function isSurfaceDescriptor(value) {
529
- return value != null && typeof value === "object" && !Array.isArray(value) && !isValidElement(value);
530
- }
531
- var generatedExtensionId = 0;
532
- function normalizeSurfaceExtension(input) {
533
- if (!input) return null;
534
- if (isValidElement(input)) {
535
- return {
536
- align: "left",
537
- className: "",
538
- component: null,
539
- content: input,
540
- id: `ext-${++generatedExtensionId}`,
541
- order: 0,
542
- props: {},
543
- unstyled: false
544
- };
545
- }
546
- if (typeof input !== "object") return null;
547
- const extension = input;
548
- const component = isValidComponentType(extension.component) ? extension.component : null;
549
- const content = isValidElement(extension.content) || typeof extension.content === "string" || typeof extension.content === "number" ? extension.content : null;
550
- if (!component && content == null) return null;
551
- const align = extension.align === "right" || extension.align === "end" ? "right" : extension.align === "center" ? "center" : "left";
552
- return {
553
- align,
554
- className: typeof extension.className === "string" ? extension.className : "",
555
- component,
556
- content,
557
- id: String(
558
- extension.id || extension.key || `ext-${++generatedExtensionId}`
559
- ),
560
- order: Number.isFinite(Number(extension.order)) ? Number(extension.order) : 0,
561
- props: isPlainObject(extension.props) ? extension.props : {},
562
- unstyled: Boolean(extension.unstyled)
563
- };
564
- }
565
- function normalizeSurfaceFlowSnapshot(value) {
566
- if (!isPlainObject(value)) return null;
567
- return { ...value };
568
- }
569
- function createSurfaceReturnHandshake(input) {
570
- const source = typeof input === "string" ? { pathname: input } : input;
571
- const pathname = typeof source?.pathname === "string" ? source.pathname.trim() : "";
572
- if (!isSafeInternalHref(pathname)) return null;
573
- return {
574
- focusKey: typeof source?.focusKey === "string" && source.focusKey.trim() ? source.focusKey.trim() : null,
575
- pathname,
576
- restoreScroll: source?.restoreScroll !== false,
577
- returnOnCancel: source?.returnOnCancel === true
578
- };
579
- }
580
- function resolveSurfaceFlowReturnHandshake(definition, input) {
581
- const flowInput = input && typeof input === "object" ? input : null;
582
- const inputHandshake = flowInput?.returnHandshake ?? (flowInput?.returnTo ? {
583
- focusKey: flowInput.returnFocusKey,
584
- pathname: flowInput.returnTo,
585
- restoreScroll: flowInput.restoreReturnScroll,
586
- returnOnCancel: flowInput.returnOnCancel
587
- } : null);
588
- const baseHandshake = definition?.returnHandshake;
589
- if (!baseHandshake && !inputHandshake) return null;
590
- return createSurfaceReturnHandshake({ ...baseHandshake, ...inputHandshake });
591
- }
592
-
593
- // src/modules/dock/surface/context.tsx
594
- var SurfaceExtensionsContext = createContext(null);
595
- var SurfaceItemContext = createContext({
596
- id: null,
597
- width: null
598
- });
599
- function useSurfaceDimensions() {
600
- const { width } = use(SurfaceItemContext);
601
- return useMemo(() => ({ width }), [width]);
602
- }
603
- function useSurfaceId() {
604
- return use(SurfaceItemContext).id;
605
- }
606
- function useSurfaceHeader() {
607
- const store = use(SurfaceExtensionsContext)?.headerActions ?? null;
608
- const surfaceId = useSurfaceId();
609
- return useCallback(
610
- (patch) => {
611
- if (!store) return;
612
- const data = typeof patch === "function" ? patch({}) : patch;
613
- if (data?.headerAction !== void 0)
614
- store.setAction(surfaceId, data.headerAction);
615
- },
616
- [store, surfaceId]
617
- );
618
- }
619
- function useSurfaceAction(action) {
620
- const store = use(SurfaceExtensionsContext)?.headerActions ?? null;
621
- const surfaceId = useSurfaceId();
622
- useEffect(() => {
623
- if (!store || action === void 0) return;
624
- store.setAction(surfaceId, action);
625
- return () => store.removeAction(surfaceId);
626
- }, [store, surfaceId, action]);
627
- }
628
- var SurfaceHeaderActionStore = class {
629
- store = createStore({
630
- actionsBySurface: {},
631
- version: 0
632
- });
633
- get version() {
634
- return this.store.getSnapshot().version;
635
- }
636
- subscribe = (listener) => this.store.subscribe(listener);
637
- getAction = (surfaceId) => {
638
- const sId = surfaceId != null ? String(surfaceId) : "active";
639
- const { actionsBySurface } = this.store.getSnapshot();
640
- return actionsBySurface[sId] ?? actionsBySurface.active ?? actionsBySurface.global ?? null;
641
- };
642
- setAction = (surfaceId, action) => {
643
- const sId = surfaceId != null ? String(surfaceId) : "active";
644
- const current = this.store.getSnapshot();
645
- if (current.actionsBySurface[sId] === action) return;
646
- this.store.setState({
647
- actionsBySurface: {
648
- ...current.actionsBySurface,
649
- [sId]: action
650
- },
651
- version: current.version + 1
652
- });
653
- };
654
- removeAction = (surfaceId) => {
655
- const sId = surfaceId != null ? String(surfaceId) : "active";
656
- const current = this.store.getSnapshot();
657
- if (!(sId in current.actionsBySurface)) return;
658
- const { [sId]: _, ...nextActions } = current.actionsBySurface;
659
- this.store.setState({
660
- actionsBySurface: nextActions,
661
- version: current.version + 1
662
- });
663
- };
664
- clearSurface = (surfaceId) => this.removeAction(surfaceId);
665
- };
666
- var SurfaceExtensionsStore = class {
667
- extensionsBySurface = /* @__PURE__ */ new Map();
668
- cachedListBySurface = /* @__PURE__ */ new Map();
669
- store = createStore({ version: 0 });
670
- get version() {
671
- return this.store.getSnapshot().version;
672
- }
673
- subscribe = (listener) => this.store.subscribe(listener);
674
- notify = () => {
675
- this.cachedListBySurface.clear();
676
- this.store.setState((prev) => ({ version: prev.version + 1 }));
677
- };
678
- getExtensionsForSurface = (surfaceId) => {
679
- const sId = surfaceId != null ? String(surfaceId) : "active";
680
- if (this.cachedListBySurface.has(sId))
681
- return this.cachedListBySurface.get(sId);
682
- const globalExts = this.extensionsBySurface.get("global");
683
- const activeExts = this.extensionsBySurface.get("active");
684
- const surfaceExts = sId !== "global" && sId !== "active" ? this.extensionsBySurface.get(sId) : void 0;
685
- let fallbackExts;
686
- if (!globalExts && !activeExts && !surfaceExts && this.extensionsBySurface.size > 0) {
687
- for (const map of this.extensionsBySurface.values()) {
688
- if (map.size > 0) {
689
- fallbackExts = map;
690
- break;
691
- }
692
- }
693
- }
694
- if (!globalExts && !activeExts && !surfaceExts && !fallbackExts) {
695
- const empty = [];
696
- this.cachedListBySurface.set(sId, empty);
697
- return empty;
698
- }
699
- const merged = new Map([
700
- ...globalExts || [],
701
- ...activeExts || [],
702
- ...surfaceExts || [],
703
- ...fallbackExts || []
704
- ]);
705
- const result = Array.from(merged.values()).sort(
706
- (a, b) => a.order - b.order
707
- );
708
- this.cachedListBySurface.set(sId, result);
709
- return result;
710
- };
711
- setExtension = (surfaceId, extension) => {
712
- if (!extension) return;
713
- const normalized = normalizeSurfaceExtension(extension);
714
- if (!normalized) return;
715
- const sId = surfaceId != null ? String(surfaceId) : "active";
716
- let surfaceMap = this.extensionsBySurface.get(sId);
717
- if (!surfaceMap) {
718
- surfaceMap = /* @__PURE__ */ new Map();
719
- this.extensionsBySurface.set(sId, surfaceMap);
720
- }
721
- const prev = surfaceMap.get(normalized.id);
722
- if (prev && prev.content === normalized.content && prev.align === normalized.align && prev.order === normalized.order && prev.className === normalized.className && prev.unstyled === normalized.unstyled && prev.component === normalized.component && prev.props === normalized.props)
723
- return;
724
- surfaceMap.set(normalized.id, normalized);
725
- this.notify();
726
- };
727
- removeExtension = (surfaceId, extensionId) => {
728
- if (!extensionId) return;
729
- const sId = surfaceId != null ? String(surfaceId) : "active";
730
- let removed = false;
731
- for (const [key, map] of this.extensionsBySurface.entries()) {
732
- if (key === sId || key === "active" || key === "global") {
733
- if (map.has(extensionId)) {
734
- map.delete(extensionId);
735
- if (map.size === 0) this.extensionsBySurface.delete(key);
736
- removed = true;
737
- }
738
- }
739
- }
740
- if (removed) this.notify();
741
- };
742
- clearSurface = (surfaceId) => {
743
- const sId = surfaceId != null ? String(surfaceId) : "active";
744
- this.extensionsBySurface.delete(sId);
745
- this.extensionsBySurface.delete("active");
746
- this.notify();
747
- };
748
- };
749
426
 
750
427
  // src/kernel/constants.ts
751
428
  var DEFAULT_SOURCE = "dynamic";
@@ -1552,63 +1229,384 @@ function createRegistryApplyContext(actions, {
1552
1229
  )
1553
1230
  });
1554
1231
  return {
1555
- ...stamp(actions),
1556
- batch: (executor) => typeof executor === "function" ? actions.batch((queue) => executor(stamp(queue))) : 0,
1557
- cleanupScope,
1558
- instanceId,
1559
- modules,
1560
- pathname
1232
+ ...stamp(actions),
1233
+ batch: (executor) => typeof executor === "function" ? actions.batch((queue) => executor(stamp(queue))) : 0,
1234
+ cleanupScope,
1235
+ instanceId,
1236
+ modules,
1237
+ pathname
1238
+ };
1239
+ }
1240
+ function useRegistry(config, metadata) {
1241
+ const { batch, register, unregister } = useRegistryActions();
1242
+ const pathname = usePathname();
1243
+ const modules = useInstalledModules();
1244
+ const instanceId = `registry-instance-${useId()}`;
1245
+ const [cleanupScope] = useState(
1246
+ () => /* @__PURE__ */ new Map()
1247
+ );
1248
+ const context = useMemo(
1249
+ () => createRegistryApplyContext(
1250
+ { batch, register, unregister },
1251
+ {
1252
+ cleanupScope,
1253
+ instanceId,
1254
+ modules,
1255
+ pathname
1256
+ }
1257
+ ),
1258
+ [batch, cleanupScope, instanceId, modules, pathname, register, unregister]
1259
+ );
1260
+ const payload = useMemo(
1261
+ () => config ? createModulePayload(modules, config, metadata) : null,
1262
+ [config, metadata, modules]
1263
+ );
1264
+ const componentSlices = useMemo(
1265
+ () => new Set(
1266
+ modules.filter(
1267
+ (coreModule) => coreModule.registry?.valueKind === "component"
1268
+ ).map((coreModule) => coreModule.id)
1269
+ ),
1270
+ [modules]
1271
+ );
1272
+ useAppliedRegistryConfig(payload, context, componentSlices);
1273
+ }
1274
+ function defineModule(coreModule) {
1275
+ return Object.freeze({ ...coreModule });
1276
+ }
1277
+ createStore(void 0);
1278
+
1279
+ // src/kernel/adapters.ts
1280
+ function useModuleRegistration(id, value, options) {
1281
+ const coreModule = useInstalledModules().find(
1282
+ (candidate) => candidate.id === id
1283
+ );
1284
+ const config = coreModule && options?.enabled !== false && value != null ? { [id]: value } : null;
1285
+ useRegistry(config, pickRegistryMetadata(options));
1286
+ }
1287
+ function isValidComponentType(type) {
1288
+ if (typeof type === "function") return true;
1289
+ return Boolean(
1290
+ type != null && typeof type === "object" && !isValidElement(type) && "$$typeof" in type
1291
+ );
1292
+ }
1293
+ function resolveComponentType(...candidates) {
1294
+ return candidates.find(isValidComponentType) ?? null;
1295
+ }
1296
+ function resolveRenderableContent(...candidates) {
1297
+ return candidates.find(
1298
+ (candidate) => candidate !== null && candidate !== void 0
1299
+ ) ?? null;
1300
+ }
1301
+ function collectSearchableText(value, visitedObjects) {
1302
+ if (typeof value === "string") return value;
1303
+ if (typeof value === "number" || typeof value === "boolean") {
1304
+ return String(value);
1305
+ }
1306
+ if (Array.isArray(value)) {
1307
+ if (visitedObjects.has(value)) return "";
1308
+ visitedObjects.add(value);
1309
+ const text = value.map((entry) => collectSearchableText(entry, visitedObjects)).join(" ");
1310
+ visitedObjects.delete(value);
1311
+ return text;
1312
+ }
1313
+ if (isValidElement(value)) {
1314
+ if (visitedObjects.has(value)) return "";
1315
+ visitedObjects.add(value);
1316
+ const text = collectSearchableText(
1317
+ value.props?.children,
1318
+ visitedObjects
1319
+ );
1320
+ visitedObjects.delete(value);
1321
+ return text;
1322
+ }
1323
+ if (value && typeof value === "object") {
1324
+ if (visitedObjects.has(value)) return "";
1325
+ visitedObjects.add(value);
1326
+ return Object.values(value).map((entry) => collectSearchableText(entry, visitedObjects)).join(" ");
1327
+ }
1328
+ return "";
1329
+ }
1330
+ function toSearchableText(value) {
1331
+ return collectSearchableText(value, /* @__PURE__ */ new WeakSet());
1332
+ }
1333
+ function normalizeUpper(value) {
1334
+ return String(value || "").trim().toUpperCase();
1335
+ }
1336
+ function formatMediaTime(seconds = 0) {
1337
+ const sec = Math.max(0, Math.floor(Number(seconds) || 0));
1338
+ const m = Math.floor(sec / 60);
1339
+ const s = sec % 60;
1340
+ return `${m}:${s < 10 ? "0" : ""}${s}`;
1341
+ }
1342
+ function isHudDescriptor(value) {
1343
+ return isObject(value) && !isValidElement(value) && ("component" in value || "content" in value || "node" in value || "element" in value || "isActive" in value || "id" in value);
1344
+ }
1345
+ function createDockScheduler(options = {}) {
1346
+ return createScheduler({
1347
+ defaultLabel: "dock-task",
1348
+ ...options
1349
+ });
1350
+ }
1351
+
1352
+ // src/modules/dock/paths.ts
1353
+ function isSamePath(left, right) {
1354
+ const normalizedLeft = normalizePath(left);
1355
+ const normalizedRight = normalizePath(right);
1356
+ return Boolean(
1357
+ normalizedLeft && normalizedRight && normalizedLeft === normalizedRight
1358
+ );
1359
+ }
1360
+ function isPathPrefix(candidatePath, pathname) {
1361
+ const normalizedCandidate = normalizePath(candidatePath);
1362
+ const normalizedPathname = normalizePath(pathname);
1363
+ if (!normalizedCandidate || !normalizedPathname) return false;
1364
+ if (normalizedCandidate === normalizedPathname) return true;
1365
+ if (normalizedCandidate === "/") return normalizedPathname.startsWith("/");
1366
+ return normalizedPathname.startsWith(`${normalizedCandidate}/`);
1367
+ }
1368
+ function isInlineActionPathMatch(path, pathname) {
1369
+ return isSamePath(path, pathname) || path !== "/" && isPathPrefix(path, pathname);
1370
+ }
1371
+ function isSafeInternalHref(value) {
1372
+ const href = typeof value === "string" ? value.trim() : "";
1373
+ return href.startsWith("/") && !href.startsWith("//");
1374
+ }
1375
+ function getDockLocationKey({
1376
+ hash = "",
1377
+ pathname = "/",
1378
+ search = ""
1379
+ } = {}) {
1380
+ const normalizedPathname = String(pathname || "/").trim() || "/";
1381
+ const normalizedSearch = String(search || "").trim();
1382
+ const normalizedHash = String(hash || "").trim();
1383
+ const query = normalizedSearch ? normalizedSearch.startsWith("?") ? normalizedSearch : `?${normalizedSearch}` : "";
1384
+ const fragment = normalizedHash ? normalizedHash.startsWith("#") ? normalizedHash : `#${normalizedHash}` : "";
1385
+ return `${normalizedPathname}${query}${fragment}`;
1386
+ }
1387
+
1388
+ // src/modules/dock/surface/helpers.ts
1389
+ function isSurfaceDescriptor(value) {
1390
+ return value != null && typeof value === "object" && !Array.isArray(value) && !isValidElement(value);
1391
+ }
1392
+ var generatedExtensionId = 0;
1393
+ function normalizeSurfaceExtension(input) {
1394
+ if (!input) return null;
1395
+ if (isValidElement(input)) {
1396
+ return {
1397
+ align: "left",
1398
+ className: "",
1399
+ component: null,
1400
+ content: input,
1401
+ id: `ext-${++generatedExtensionId}`,
1402
+ order: 0,
1403
+ props: {},
1404
+ unstyled: false
1405
+ };
1406
+ }
1407
+ if (typeof input !== "object") return null;
1408
+ const extension = input;
1409
+ const component = isValidComponentType(extension.component) ? extension.component : null;
1410
+ const content = isValidElement(extension.content) || typeof extension.content === "string" && extension.content !== "" || typeof extension.content === "number" ? extension.content : null;
1411
+ if (!component && content == null) return null;
1412
+ const align = extension.align === "right" || extension.align === "end" ? "right" : extension.align === "center" ? "center" : "left";
1413
+ return {
1414
+ align,
1415
+ className: typeof extension.className === "string" ? extension.className : "",
1416
+ component,
1417
+ content,
1418
+ id: String(
1419
+ extension.id || extension.key || `ext-${++generatedExtensionId}`
1420
+ ),
1421
+ order: Number.isFinite(Number(extension.order)) ? Number(extension.order) : 0,
1422
+ props: isPlainObject(extension.props) ? extension.props : {},
1423
+ unstyled: Boolean(extension.unstyled)
1561
1424
  };
1562
1425
  }
1563
- function useRegistry(config, metadata) {
1564
- const { batch, register, unregister } = useRegistryActions();
1565
- const pathname = usePathname();
1566
- const modules = useInstalledModules();
1567
- const instanceId = `registry-instance-${useId()}`;
1568
- const [cleanupScope] = useState(
1569
- () => /* @__PURE__ */ new Map()
1570
- );
1571
- const context = useMemo(
1572
- () => createRegistryApplyContext(
1573
- { batch, register, unregister },
1574
- {
1575
- cleanupScope,
1576
- instanceId,
1577
- modules,
1578
- pathname
1579
- }
1580
- ),
1581
- [batch, cleanupScope, instanceId, modules, pathname, register, unregister]
1582
- );
1583
- const payload = useMemo(
1584
- () => config ? createModulePayload(modules, config, metadata) : null,
1585
- [config, metadata, modules]
1586
- );
1587
- const componentSlices = useMemo(
1588
- () => new Set(
1589
- modules.filter(
1590
- (coreModule) => coreModule.registry?.valueKind === "component"
1591
- ).map((coreModule) => coreModule.id)
1592
- ),
1593
- [modules]
1594
- );
1595
- useAppliedRegistryConfig(payload, context, componentSlices);
1426
+ function normalizeSurfaceFlowSnapshot(value) {
1427
+ if (!isPlainObject(value)) return null;
1428
+ return { ...value };
1596
1429
  }
1597
- function defineModule(coreModule) {
1598
- return Object.freeze({ ...coreModule });
1430
+ function createSurfaceReturnHandshake(input) {
1431
+ const source = typeof input === "string" ? { pathname: input } : input;
1432
+ const pathname = typeof source?.pathname === "string" ? source.pathname.trim() : "";
1433
+ if (!isSafeInternalHref(pathname)) return null;
1434
+ return {
1435
+ focusKey: typeof source?.focusKey === "string" && source.focusKey.trim() ? source.focusKey.trim() : null,
1436
+ pathname,
1437
+ restoreScroll: source?.restoreScroll !== false,
1438
+ returnOnCancel: source?.returnOnCancel === true
1439
+ };
1440
+ }
1441
+ function resolveSurfaceFlowReturnHandshake(definition, input) {
1442
+ const flowInput = input && typeof input === "object" ? input : null;
1443
+ const inputHandshake = flowInput?.returnHandshake ?? (flowInput?.returnTo ? {
1444
+ focusKey: flowInput.returnFocusKey,
1445
+ pathname: flowInput.returnTo,
1446
+ restoreScroll: flowInput.restoreReturnScroll,
1447
+ returnOnCancel: flowInput.returnOnCancel
1448
+ } : null);
1449
+ const baseHandshake = definition?.returnHandshake;
1450
+ if (!baseHandshake && !inputHandshake) return null;
1451
+ return createSurfaceReturnHandshake({ ...baseHandshake, ...inputHandshake });
1599
1452
  }
1600
- createStore(void 0);
1601
1453
 
1602
- // src/kernel/adapters.ts
1603
- function useModuleRegistration(id, value, options) {
1604
- const coreModule = useInstalledModules().find(
1605
- (candidate) => candidate.id === id
1454
+ // src/modules/dock/surface/context.tsx
1455
+ var SurfaceExtensionsContext = getOrCreateGlobalContext("SurfaceExtensionsContext", null);
1456
+ var SurfaceItemContext = getOrCreateGlobalContext("SurfaceItemContext", {
1457
+ id: null,
1458
+ width: null
1459
+ });
1460
+ function useSurfaceDimensions() {
1461
+ const { width } = use(SurfaceItemContext);
1462
+ return useMemo(() => ({ width }), [width]);
1463
+ }
1464
+ function useSurfaceId() {
1465
+ return use(SurfaceItemContext).id;
1466
+ }
1467
+ function useSurfaceHeader() {
1468
+ const store = use(SurfaceExtensionsContext)?.headerActions ?? null;
1469
+ const surfaceId = useSurfaceId();
1470
+ return useCallback(
1471
+ (patch) => {
1472
+ if (!store) return;
1473
+ const data = typeof patch === "function" ? patch({}) : patch;
1474
+ if (data?.headerAction !== void 0)
1475
+ store.setAction(surfaceId, data.headerAction);
1476
+ },
1477
+ [store, surfaceId]
1606
1478
  );
1607
- const config = coreModule && options?.enabled !== false && value != null ? { [id]: value } : null;
1608
- useRegistry(config, pickRegistryMetadata(options));
1609
1479
  }
1610
-
1611
- // src/theme.tsx
1480
+ function useSurfaceAction(action) {
1481
+ const store = use(SurfaceExtensionsContext)?.headerActions ?? null;
1482
+ const surfaceId = useSurfaceId();
1483
+ useEffect(() => {
1484
+ if (!store || action === void 0) return;
1485
+ store.setAction(surfaceId, action);
1486
+ return () => store.removeAction(surfaceId);
1487
+ }, [store, surfaceId, action]);
1488
+ }
1489
+ var SurfaceHeaderActionStore = class {
1490
+ store = createStore({
1491
+ actionsBySurface: {},
1492
+ version: 0
1493
+ });
1494
+ get version() {
1495
+ return this.store.getSnapshot().version;
1496
+ }
1497
+ subscribe = (listener) => this.store.subscribe(listener);
1498
+ getAction = (surfaceId) => {
1499
+ const sId = surfaceId != null ? String(surfaceId) : "active";
1500
+ const { actionsBySurface } = this.store.getSnapshot();
1501
+ return actionsBySurface[sId] ?? actionsBySurface.active ?? actionsBySurface.global ?? null;
1502
+ };
1503
+ setAction = (surfaceId, action) => {
1504
+ const sId = surfaceId != null ? String(surfaceId) : "active";
1505
+ const current = this.store.getSnapshot();
1506
+ if (current.actionsBySurface[sId] === action) return;
1507
+ this.store.setState({
1508
+ actionsBySurface: {
1509
+ ...current.actionsBySurface,
1510
+ [sId]: action
1511
+ },
1512
+ version: current.version + 1
1513
+ });
1514
+ };
1515
+ removeAction = (surfaceId) => {
1516
+ const sId = surfaceId != null ? String(surfaceId) : "active";
1517
+ const current = this.store.getSnapshot();
1518
+ if (!(sId in current.actionsBySurface)) return;
1519
+ const { [sId]: _, ...nextActions } = current.actionsBySurface;
1520
+ this.store.setState({
1521
+ actionsBySurface: nextActions,
1522
+ version: current.version + 1
1523
+ });
1524
+ };
1525
+ clearSurface = (surfaceId) => this.removeAction(surfaceId);
1526
+ };
1527
+ var SurfaceExtensionsStore = class {
1528
+ extensionsBySurface = /* @__PURE__ */ new Map();
1529
+ cachedListBySurface = /* @__PURE__ */ new Map();
1530
+ store = createStore({ version: 0 });
1531
+ get version() {
1532
+ return this.store.getSnapshot().version;
1533
+ }
1534
+ subscribe = (listener) => this.store.subscribe(listener);
1535
+ notify = () => {
1536
+ this.cachedListBySurface.clear();
1537
+ this.store.setState((prev) => ({ version: prev.version + 1 }));
1538
+ };
1539
+ getExtensionsForSurface = (surfaceId) => {
1540
+ const sId = surfaceId != null ? String(surfaceId) : "active";
1541
+ if (this.cachedListBySurface.has(sId))
1542
+ return this.cachedListBySurface.get(sId);
1543
+ const globalExts = this.extensionsBySurface.get("global");
1544
+ const activeExts = this.extensionsBySurface.get("active");
1545
+ const surfaceExts = sId !== "global" && sId !== "active" ? this.extensionsBySurface.get(sId) : void 0;
1546
+ let fallbackExts;
1547
+ if (!globalExts && !activeExts && !surfaceExts && this.extensionsBySurface.size > 0) {
1548
+ for (const map of this.extensionsBySurface.values()) {
1549
+ if (map.size > 0) {
1550
+ fallbackExts = map;
1551
+ break;
1552
+ }
1553
+ }
1554
+ }
1555
+ if (!globalExts && !activeExts && !surfaceExts && !fallbackExts) {
1556
+ const empty = [];
1557
+ this.cachedListBySurface.set(sId, empty);
1558
+ return empty;
1559
+ }
1560
+ const merged = new Map([
1561
+ ...globalExts || [],
1562
+ ...activeExts || [],
1563
+ ...surfaceExts || [],
1564
+ ...fallbackExts || []
1565
+ ]);
1566
+ const result = Array.from(merged.values()).sort(
1567
+ (a, b) => a.order - b.order
1568
+ );
1569
+ this.cachedListBySurface.set(sId, result);
1570
+ return result;
1571
+ };
1572
+ setExtension = (surfaceId, extension) => {
1573
+ if (!extension) return;
1574
+ const normalized = normalizeSurfaceExtension(extension);
1575
+ if (!normalized) return;
1576
+ const sId = surfaceId != null ? String(surfaceId) : "active";
1577
+ let surfaceMap = this.extensionsBySurface.get(sId);
1578
+ if (!surfaceMap) {
1579
+ surfaceMap = /* @__PURE__ */ new Map();
1580
+ this.extensionsBySurface.set(sId, surfaceMap);
1581
+ }
1582
+ const prev = surfaceMap.get(normalized.id);
1583
+ if (prev && prev.content === normalized.content && prev.align === normalized.align && prev.order === normalized.order && prev.className === normalized.className && prev.unstyled === normalized.unstyled && prev.component === normalized.component && prev.props === normalized.props)
1584
+ return;
1585
+ surfaceMap.set(normalized.id, normalized);
1586
+ this.notify();
1587
+ };
1588
+ removeExtension = (surfaceId, extensionId) => {
1589
+ if (!extensionId) return;
1590
+ const sId = surfaceId != null ? String(surfaceId) : "active";
1591
+ let removed = false;
1592
+ for (const [key, map] of this.extensionsBySurface.entries()) {
1593
+ if (key === sId || key === "active" || key === "global") {
1594
+ if (map.has(extensionId)) {
1595
+ map.delete(extensionId);
1596
+ if (map.size === 0) this.extensionsBySurface.delete(key);
1597
+ removed = true;
1598
+ }
1599
+ }
1600
+ }
1601
+ if (removed) this.notify();
1602
+ };
1603
+ clearSurface = (surfaceId) => {
1604
+ const sId = surfaceId != null ? String(surfaceId) : "active";
1605
+ this.extensionsBySurface.delete(sId);
1606
+ this.extensionsBySurface.delete("active");
1607
+ this.notify();
1608
+ };
1609
+ };
1612
1610
  function defineThemeSpec(id) {
1613
1611
  return Object.freeze({ id });
1614
1612
  }
@@ -4355,8 +4353,10 @@ function useDockSurfaceExtension({
4355
4353
  align = "left",
4356
4354
  children,
4357
4355
  className = "",
4356
+ component,
4358
4357
  id,
4359
4358
  order = 0,
4359
+ props: extensionProps,
4360
4360
  unstyled = false
4361
4361
  }) {
4362
4362
  const store = use(SurfaceExtensionsContext)?.extensions ?? null;
@@ -4368,9 +4368,11 @@ function useDockSurfaceExtension({
4368
4368
  const extension = {
4369
4369
  align,
4370
4370
  className,
4371
+ component: component ?? null,
4371
4372
  content: children,
4372
4373
  id: effectiveId,
4373
4374
  order,
4375
+ props: extensionProps ?? {},
4374
4376
  unstyled
4375
4377
  };
4376
4378
  store.setExtension(surfaceId, extension);
@@ -4378,7 +4380,7 @@ function useDockSurfaceExtension({
4378
4380
  store.setExtension("active", extension);
4379
4381
  }
4380
4382
  });
4381
- useEffect(() => {
4383
+ useIsomorphicLayoutEffect(() => {
4382
4384
  return () => {
4383
4385
  if (store) {
4384
4386
  store.removeExtension(surfaceId, effectiveId);
@@ -4410,7 +4412,7 @@ function useIsSurfaceExtensionsVisible(activeItem) {
4410
4412
  return Array.isArray(raw) ? raw.length : 0;
4411
4413
  }, [activeItem?.surfaceExtensions, activeItem?.extensions]);
4412
4414
  return Boolean(
4413
- isSurface && isBodyVisible && (dynamicCount > 0 || descriptorCount > 0)
4415
+ isSurface && (isBodyVisible && dynamicCount > 0 || descriptorCount > 0)
4414
4416
  );
4415
4417
  }
4416
4418
  function useDockSurfaceExtensionsBarModel({