@omerdlw/base-framework 1.0.4 → 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,308 +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) : "global";
639
- const { actionsBySurface } = this.store.getSnapshot();
640
- return actionsBySurface[sId] ?? actionsBySurface.global ?? null;
641
- };
642
- setAction = (surfaceId, action) => {
643
- const sId = surfaceId != null ? String(surfaceId) : "global";
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) : "global";
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) : "global";
680
- if (this.cachedListBySurface.has(sId))
681
- return this.cachedListBySurface.get(sId);
682
- const globalExts = this.extensionsBySurface.get("global");
683
- const surfaceExts = this.extensionsBySurface.get(sId);
684
- if (!globalExts && !surfaceExts) {
685
- const empty = [];
686
- this.cachedListBySurface.set(sId, empty);
687
- return empty;
688
- }
689
- const merged = new Map([...globalExts || [], ...surfaceExts || []]);
690
- const result = Array.from(merged.values()).sort(
691
- (a, b) => a.order - b.order
692
- );
693
- this.cachedListBySurface.set(sId, result);
694
- return result;
695
- };
696
- setExtension = (surfaceId, extension) => {
697
- if (!extension) return;
698
- const normalized = normalizeSurfaceExtension(extension);
699
- if (!normalized) return;
700
- const sId = surfaceId != null ? String(surfaceId) : "global";
701
- let surfaceMap = this.extensionsBySurface.get(sId);
702
- if (!surfaceMap) {
703
- surfaceMap = /* @__PURE__ */ new Map();
704
- this.extensionsBySurface.set(sId, surfaceMap);
705
- }
706
- const prev = surfaceMap.get(normalized.id);
707
- 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)
708
- return;
709
- surfaceMap.set(normalized.id, normalized);
710
- this.notify();
711
- };
712
- removeExtension = (surfaceId, extensionId) => {
713
- if (!extensionId) return;
714
- const sId = surfaceId != null ? String(surfaceId) : "global";
715
- const surfaceMap = this.extensionsBySurface.get(sId);
716
- if (!surfaceMap || !surfaceMap.has(extensionId)) return;
717
- surfaceMap.delete(extensionId);
718
- if (surfaceMap.size === 0) this.extensionsBySurface.delete(sId);
719
- this.notify();
720
- };
721
- clearSurface = (surfaceId) => {
722
- const sId = surfaceId != null ? String(surfaceId) : "global";
723
- if (!this.extensionsBySurface.has(sId)) return;
724
- this.extensionsBySurface.delete(sId);
725
- this.notify();
726
- };
727
- };
728
426
 
729
427
  // src/kernel/constants.ts
730
428
  var DEFAULT_SOURCE = "dynamic";
@@ -1498,96 +1196,417 @@ function useAppliedRegistryConfig(payload, context, componentSlices) {
1498
1196
  context,
1499
1197
  payload
1500
1198
  };
1501
- });
1502
- useIsomorphicLayoutEffect(
1503
- () => () => {
1504
- appliedRef.current?.cleanup();
1505
- appliedRef.current = null;
1506
- },
1507
- []
1508
- );
1509
- }
1510
- function createRegistryApplyContext(actions, {
1511
- cleanupScope = /* @__PURE__ */ new Map(),
1512
- instanceId,
1513
- modules = [],
1514
- pathname
1515
- }) {
1516
- const stamp = (queue) => ({
1517
- register: (type, key, item, sourceOrOptions, optionsArg) => queue.register(
1518
- type,
1519
- key,
1520
- item,
1521
- ...resolveRegisterArgsWithInstance(
1522
- instanceId,
1523
- sourceOrOptions,
1524
- optionsArg
1525
- )
1526
- ),
1527
- unregister: (type, key, sourceOrOptions) => queue.unregister(
1528
- type,
1529
- key,
1530
- withInstanceIdForUnregister(instanceId, sourceOrOptions)
1531
- )
1532
- });
1199
+ });
1200
+ useIsomorphicLayoutEffect(
1201
+ () => () => {
1202
+ appliedRef.current?.cleanup();
1203
+ appliedRef.current = null;
1204
+ },
1205
+ []
1206
+ );
1207
+ }
1208
+ function createRegistryApplyContext(actions, {
1209
+ cleanupScope = /* @__PURE__ */ new Map(),
1210
+ instanceId,
1211
+ modules = [],
1212
+ pathname
1213
+ }) {
1214
+ const stamp = (queue) => ({
1215
+ register: (type, key, item, sourceOrOptions, optionsArg) => queue.register(
1216
+ type,
1217
+ key,
1218
+ item,
1219
+ ...resolveRegisterArgsWithInstance(
1220
+ instanceId,
1221
+ sourceOrOptions,
1222
+ optionsArg
1223
+ )
1224
+ ),
1225
+ unregister: (type, key, sourceOrOptions) => queue.unregister(
1226
+ type,
1227
+ key,
1228
+ withInstanceIdForUnregister(instanceId, sourceOrOptions)
1229
+ )
1230
+ });
1231
+ return {
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";
1533
1413
  return {
1534
- ...stamp(actions),
1535
- batch: (executor) => typeof executor === "function" ? actions.batch((queue) => executor(stamp(queue))) : 0,
1536
- cleanupScope,
1537
- instanceId,
1538
- modules,
1539
- pathname
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)
1540
1424
  };
1541
1425
  }
1542
- function useRegistry(config, metadata) {
1543
- const { batch, register, unregister } = useRegistryActions();
1544
- const pathname = usePathname();
1545
- const modules = useInstalledModules();
1546
- const instanceId = `registry-instance-${useId()}`;
1547
- const [cleanupScope] = useState(
1548
- () => /* @__PURE__ */ new Map()
1549
- );
1550
- const context = useMemo(
1551
- () => createRegistryApplyContext(
1552
- { batch, register, unregister },
1553
- {
1554
- cleanupScope,
1555
- instanceId,
1556
- modules,
1557
- pathname
1558
- }
1559
- ),
1560
- [batch, cleanupScope, instanceId, modules, pathname, register, unregister]
1561
- );
1562
- const payload = useMemo(
1563
- () => config ? createModulePayload(modules, config, metadata) : null,
1564
- [config, metadata, modules]
1565
- );
1566
- const componentSlices = useMemo(
1567
- () => new Set(
1568
- modules.filter(
1569
- (coreModule) => coreModule.registry?.valueKind === "component"
1570
- ).map((coreModule) => coreModule.id)
1571
- ),
1572
- [modules]
1573
- );
1574
- useAppliedRegistryConfig(payload, context, componentSlices);
1426
+ function normalizeSurfaceFlowSnapshot(value) {
1427
+ if (!isPlainObject(value)) return null;
1428
+ return { ...value };
1575
1429
  }
1576
- function defineModule(coreModule) {
1577
- 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 });
1578
1452
  }
1579
- createStore(void 0);
1580
1453
 
1581
- // src/kernel/adapters.ts
1582
- function useModuleRegistration(id, value, options) {
1583
- const coreModule = useInstalledModules().find(
1584
- (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]
1585
1478
  );
1586
- const config = coreModule && options?.enabled !== false && value != null ? { [id]: value } : null;
1587
- useRegistry(config, pickRegistryMetadata(options));
1588
1479
  }
1589
-
1590
- // 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
+ };
1591
1610
  function defineThemeSpec(id) {
1592
1611
  return Object.freeze({ id });
1593
1612
  }
@@ -4304,7 +4323,7 @@ function useDockSurfaceControlsModel({
4304
4323
  const phase = propSurfacePhase ?? activeItem?.surfacePhase;
4305
4324
  const isBodyVisible = phase ? phase === DOCK_SURFACE_PHASE.EXPANDING_BODY || phase === DOCK_SURFACE_PHASE.OPEN : true;
4306
4325
  const actionStore = use(SurfaceExtensionsContext)?.headerActions ?? null;
4307
- const surfaceId = activeItem?.surfaceId || "global";
4326
+ const surfaceId = activeItem?.surfaceId || "active";
4308
4327
  const subscribeAction = useCallback(
4309
4328
  (onStoreChange) => actionStore ? actionStore.subscribe(onStoreChange) : () => {
4310
4329
  },
@@ -4334,34 +4353,47 @@ function useDockSurfaceExtension({
4334
4353
  align = "left",
4335
4354
  children,
4336
4355
  className = "",
4356
+ component,
4337
4357
  id,
4338
4358
  order = 0,
4359
+ props: extensionProps,
4339
4360
  unstyled = false
4340
4361
  }) {
4341
4362
  const store = use(SurfaceExtensionsContext)?.extensions ?? null;
4342
4363
  const surfaceId = useSurfaceId();
4343
4364
  const generatedId = useId();
4344
4365
  const effectiveId = id || `dock-surface-ext-${generatedId}`;
4345
- useEffect(() => {
4366
+ useIsomorphicLayoutEffect(() => {
4346
4367
  if (!store) return;
4347
- store.setExtension(surfaceId, {
4368
+ const extension = {
4348
4369
  align,
4349
4370
  className,
4371
+ component: component ?? null,
4350
4372
  content: children,
4351
4373
  id: effectiveId,
4352
4374
  order,
4375
+ props: extensionProps ?? {},
4353
4376
  unstyled
4354
- });
4377
+ };
4378
+ store.setExtension(surfaceId, extension);
4379
+ if (surfaceId && surfaceId !== "active") {
4380
+ store.setExtension("active", extension);
4381
+ }
4355
4382
  });
4356
- useEffect(() => {
4383
+ useIsomorphicLayoutEffect(() => {
4357
4384
  return () => {
4358
- if (store) store.removeExtension(surfaceId, effectiveId);
4385
+ if (store) {
4386
+ store.removeExtension(surfaceId, effectiveId);
4387
+ if (surfaceId && surfaceId !== "active") {
4388
+ store.removeExtension("active", effectiveId);
4389
+ }
4390
+ }
4359
4391
  };
4360
4392
  }, [store, surfaceId, effectiveId]);
4361
4393
  }
4362
4394
  function useIsSurfaceExtensionsVisible(activeItem) {
4363
4395
  const store = use(SurfaceExtensionsContext)?.extensions ?? null;
4364
- const surfaceId = activeItem?.surfaceId || "global";
4396
+ const surfaceId = activeItem?.surfaceId || "active";
4365
4397
  const isSurface = Boolean(activeItem?.isSurface);
4366
4398
  const phase = activeItem?.surfacePhase;
4367
4399
  const isBodyVisible = phase === DOCK_SURFACE_PHASE.EXPANDING_BODY || phase === DOCK_SURFACE_PHASE.OPEN;
@@ -4380,14 +4412,14 @@ function useIsSurfaceExtensionsVisible(activeItem) {
4380
4412
  return Array.isArray(raw) ? raw.length : 0;
4381
4413
  }, [activeItem?.surfaceExtensions, activeItem?.extensions]);
4382
4414
  return Boolean(
4383
- isSurface && isBodyVisible && (dynamicCount > 0 || descriptorCount > 0)
4415
+ isSurface && (isBodyVisible && dynamicCount > 0 || descriptorCount > 0)
4384
4416
  );
4385
4417
  }
4386
4418
  function useDockSurfaceExtensionsBarModel({
4387
4419
  activeItem
4388
4420
  }) {
4389
4421
  const store = use(SurfaceExtensionsContext)?.extensions ?? null;
4390
- const surfaceId = activeItem?.surfaceId || "global";
4422
+ const surfaceId = activeItem?.surfaceId || "active";
4391
4423
  const subscribe2 = useCallback(
4392
4424
  (onStoreChange) => store ? store.subscribe(onStoreChange) : () => {
4393
4425
  },