@dimina-kit/electron-deck 0.1.0-dev.20260630123203 → 0.1.0-dev.20260701155140
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/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +92 -12
- package/dist/client/index.js.map +1 -1
- package/dist/client/layout-client.d.ts +35 -14
- package/dist/client/layout-client.d.ts.map +1 -1
- package/dist/client/placement-publisher.d.ts +14 -0
- package/dist/client/placement-publisher.d.ts.map +1 -0
- package/dist/dock-react/dock-view.d.ts +6 -0
- package/dist/dock-react/dock-view.d.ts.map +1 -1
- package/dist/dock-react/index.js +4 -2
- package/dist/dock-react/index.js.map +1 -1
- package/dist/{electron-deck-C9_Yu3fd.js → electron-deck-B9fun93z.js} +105 -78
- package/dist/electron-deck-B9fun93z.js.map +1 -0
- package/dist/host/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/deck-app.d.ts +43 -11
- package/dist/internal/deck-app.d.ts.map +1 -1
- package/dist/internal/wire-transport.d.ts +17 -14
- package/dist/internal/wire-transport.d.ts.map +1 -1
- package/dist/layout/index.d.ts +4 -0
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +2 -2
- package/dist/layout/placement-reconcile.d.ts +50 -0
- package/dist/layout/placement-reconcile.d.ts.map +1 -0
- package/dist/layout/snapshot-reconcile.d.ts +28 -0
- package/dist/layout/snapshot-reconcile.d.ts.map +1 -0
- package/dist/{layout-B1t15b_q.js → layout-ByOiOdnc.js} +267 -2
- package/dist/layout-ByOiOdnc.js.map +1 -0
- package/dist/main/index.js +1 -1
- package/dist/main/view-handle.d.ts.map +1 -1
- package/dist/preload/index.cjs +4 -4
- package/dist/preload/index.cjs.map +1 -1
- package/dist/preload/index.d.ts +1 -1
- package/dist/preload/index.js +4 -4
- package/dist/preload/index.js.map +1 -1
- package/dist/{protocol-BJqo-vP2.js → protocol-B6TOT9AP.js} +2 -2
- package/dist/protocol-B6TOT9AP.js.map +1 -0
- package/dist/shared/protocol.d.ts +1 -1
- package/dist/{view-handle-CR-yWNfr.js → view-handle-DDhpBuW-.js} +2 -2
- package/dist/{view-handle-CR-yWNfr.js.map → view-handle-DDhpBuW-.js.map} +1 -1
- package/package.json +4 -4
- package/dist/electron-deck-C9_Yu3fd.js.map +0 -1
- package/dist/layout-B1t15b_q.js.map +0 -1
- package/dist/protocol-BJqo-vP2.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"layout-B1t15b_q.js","names":[],"sources":["../src/layout/registry.ts","../src/layout/serialize.ts","../src/layout/sanitize.ts","../src/layout/mutations.ts","../src/layout/model.ts","../src/layout/user-actions.ts"],"sourcesContent":["/**\n * Panel registry — pure in-memory map of panel descriptors. Pure TS.\n */\nimport type { Disposable, PanelDescriptor, PanelRegistry } from './types.js'\n\nexport function createPanelRegistry(): PanelRegistry {\n\tconst map = new Map<string, PanelDescriptor>()\n\treturn {\n\t\tregister(p: PanelDescriptor): Disposable {\n\t\t\tmap.set(p.id, p)\n\t\t\treturn {\n\t\t\t\tdispose(): void {\n\t\t\t\t\t// Only drop if this exact descriptor is still registered, so a\n\t\t\t\t\t// re-register under the same id isn't undone by a stale handle.\n\t\t\t\t\tif (map.get(p.id) === p) map.delete(p.id)\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t\tget(id: string): PanelDescriptor | undefined {\n\t\t\treturn map.get(id)\n\t\t},\n\t\tlist(): readonly PanelDescriptor[] {\n\t\t\treturn [...map.values()]\n\t\t},\n\t}\n}\n","/**\n * Serialize / parse / validate — structural integrity + acyclicity. Pure TS.\n *\n * Default-DENY: parseLayout throws on any tree validateTree would flag.\n */\nimport type { LayoutNode, LayoutTree } from './types.js'\n\nconst MAX_DEPTH = 64\n\nexport function serializeLayout(t: LayoutTree): string {\n\treturn JSON.stringify(t)\n}\n\n/** Mutable cross-node state threaded through the whole walk. */\ninterface WalkState {\n\treadonly seenIds: Set<string>\n\treadonly seenObjects: Set<object>\n\treadonly panelOwners: Map<string, string>\n\treadonly knownPanelIds: ReadonlySet<string> | null\n}\n\n/** Report missing / duplicate node id, registering the id when first seen. */\nfunction checkNodeId(id: string | undefined, kind: unknown, state: WalkState, problems: string[]): void {\n\tif (id === undefined) {\n\t\tproblems.push(`node missing string id (kind=${String(kind)})`)\n\t}\n\telse if (state.seenIds.has(id)) {\n\t\tproblems.push(`duplicate node id: ${id}`)\n\t}\n\telse {\n\t\tstate.seenIds.add(id)\n\t}\n}\n\n/** Validate a single panel id within a tabgroup: type, cross-group ownership, orphan. */\nfunction checkPanel(p: unknown, id: string | undefined, state: WalkState, problems: string[]): void {\n\tif (typeof p !== 'string') {\n\t\tproblems.push(`tabs ${id ?? '?'}: non-string panel id`)\n\t\treturn\n\t}\n\tconst owner = state.panelOwners.get(p)\n\tif (owner !== undefined) {\n\t\tproblems.push(`duplicate panel id across groups: ${p}`)\n\t}\n\telse {\n\t\tstate.panelOwners.set(p, id ?? '?')\n\t}\n\tif (state.knownPanelIds && !state.knownPanelIds.has(p)) {\n\t\tproblems.push(`orphan panel not in known panel ids: ${p}`)\n\t}\n}\n\n/** Validate a `tabs` node: panels array, per-panel rules, active membership. */\nfunction checkTabs(node: unknown, id: string | undefined, state: WalkState, problems: string[]): void {\n\tconst tg = node as { panels?: unknown; active?: unknown }\n\tconst panels = Array.isArray(tg.panels) ? (tg.panels as unknown[]) : null\n\tif (!panels) {\n\t\tproblems.push(`tabs ${id ?? '?'}: panels is not an array`)\n\t\treturn\n\t}\n\tif (panels.length === 0) {\n\t\tproblems.push(`tabs ${id ?? '?'}: empty tabgroup`)\n\t}\n\tfor (const p of panels) {\n\t\tcheckPanel(p, id, state, problems)\n\t}\n\tconst active = tg.active\n\tif (typeof active !== 'string' || !panels.includes(active)) {\n\t\tproblems.push(`tabs ${id ?? '?'}: active ${String(active)} not in panels`)\n\t}\n}\n\n/** Validate one constraint entry. Returns true if it is PX-SIZED (non-null). */\nfunction checkConstraintEntry(c: unknown, id: string | undefined, problems: string[]): boolean {\n\tif (c === null) {\n\t\treturn false\n\t}\n\tif (typeof c !== 'object') {\n\t\tproblems.push(`split ${id ?? '?'}: constraint is not null nor an object: ${String(c)}`)\n\t\treturn false\n\t}\n\t// Exactly ONE of `fixedPx` / `minPx`, value finite > 0.\n\tconst keys = Object.keys(c as object)\n\tconst hasFixed = keys.includes('fixedPx')\n\tconst hasMin = keys.includes('minPx')\n\tif (keys.length !== 1 || !(hasFixed || hasMin)) {\n\t\tproblems.push(`split ${id ?? '?'}: constraint must have exactly one of 'fixedPx' or 'minPx', got [${keys.join(', ')}]`)\n\t}\n\tconst cKey = hasFixed ? 'fixedPx' : 'minPx'\n\tconst cVal = hasFixed ? (c as { fixedPx?: unknown }).fixedPx : (c as { minPx?: unknown }).minPx\n\tif (typeof cVal !== 'number' || !Number.isFinite(cVal) || cVal <= 0) {\n\t\tproblems.push(`split ${id ?? '?'}: constraint ${cKey} must be a finite number > 0, got ${String(cVal)}`)\n\t}\n\treturn true\n}\n\n/**\n * Validate the OPTIONAL `constraints` field's INTRINSIC format (array shape +\n * per-entry rules + exactly-one-of fixedPx/minPx + all-px guard), INDEPENDENTLY\n * of `children` validity. The LENGTH-vs-children comparison lives elsewhere.\n */\nfunction checkConstraints(raw: unknown, id: string | undefined, problems: string[]): void {\n\tconst constraints = Array.isArray(raw) ? (raw as unknown[]) : null\n\tif (!constraints) {\n\t\tproblems.push(`split ${id ?? '?'}: constraints is not an array`)\n\t\treturn\n\t}\n\t// Tracks whether EVERY child is PX-SIZED (a non-null constraint — `fixedPx`\n\t// OR `minPx`). Both are sized in px and excluded from the weight pool, so an\n\t// all-constrained split trips the rrp footgun (needs >= 1 weight-sized\n\t// child); only a `null` child clears it.\n\tlet everyConstrained = constraints.length > 0\n\tfor (const c of constraints) {\n\t\tif (!checkConstraintEntry(c, id, problems)) {\n\t\t\teveryConstrained = false\n\t\t}\n\t}\n\t// Guard the rrp footgun: an all-px-sized split has no weight-sized child to\n\t// absorb leftover space (rrp v4.10 requires >= 1).\n\tif (everyConstrained) {\n\t\tproblems.push(`split ${id ?? '?'}: all children are px-sized constraints; at least one must be weight-sized`)\n\t}\n}\n\n/** Validate the `sizes` field against a valid `children` array. */\nfunction checkSizes(sizes: unknown[] | null, children: unknown[], id: string | undefined, problems: string[]): void {\n\tif (!sizes || sizes.length !== children.length) {\n\t\tproblems.push(\n\t\t\t`split ${id ?? '?'}: sizes ${sizes ? sizes.length : 'missing'} != children ${children.length}`,\n\t\t)\n\t\treturn\n\t}\n\tfor (const s of sizes) {\n\t\tif (typeof s !== 'number' || !Number.isFinite(s)) {\n\t\t\tproblems.push(`split ${id ?? '?'}: non-finite size ${String(s)}`)\n\t\t}\n\t}\n}\n\n/**\n * Walk an arbitrary (possibly malformed / cyclic / shared-ref) node graph and\n * collect structural problems. Never recurses infinitely: a node already on the\n * current path (cycle) or already visited elsewhere (shared ref) is reported and\n * not descended into.\n */\nfunction collectProblems(\n\troot: unknown,\n\tknownPanelIds: ReadonlySet<string> | null,\n): string[] {\n\tconst problems: string[] = []\n\tconst state: WalkState = {\n\t\tseenIds: new Set<string>(),\n\t\tseenObjects: new Set<object>(),\n\t\tpanelOwners: new Map<string, string>(),\n\t\tknownPanelIds,\n\t}\n\n\tconst visit = (node: unknown, depth: number, path: Set<object>): void => {\n\t\tif (depth > MAX_DEPTH) {\n\t\t\tproblems.push(`depth exceeds ${MAX_DEPTH}`)\n\t\t\treturn\n\t\t}\n\t\tif (node === null || typeof node !== 'object') {\n\t\t\tproblems.push(`node is not an object: ${String(node)}`)\n\t\t\treturn\n\t\t}\n\t\tconst obj = node as object\n\t\tif (path.has(obj)) {\n\t\t\tproblems.push('cycle detected: node reachable from itself')\n\t\t\treturn\n\t\t}\n\t\tif (state.seenObjects.has(obj)) {\n\t\t\tproblems.push('shared node reference: same object appears twice')\n\t\t\treturn\n\t\t}\n\t\tstate.seenObjects.add(obj)\n\n\t\tconst n = node as { kind?: unknown; id?: unknown }\n\t\tconst kind = n.kind\n\t\tconst id = typeof n.id === 'string' ? n.id : undefined\n\n\t\tcheckNodeId(id, kind, state, problems)\n\n\t\tif (kind === 'tabs') {\n\t\t\tcheckTabs(node, id, state, problems)\n\t\t}\n\t\telse if (kind === 'split') {\n\t\t\tvisitSplit(node, id, depth, path, obj, state, problems, visit)\n\t\t}\n\t\telse {\n\t\t\tproblems.push(`unknown node kind: ${String(kind)}`)\n\t\t}\n\t}\n\n\tvisit(root, 0, new Set())\n\treturn problems\n}\n\n/** Validate a `split` node and recurse into its children. */\nfunction visitSplit(\n\tnode: unknown,\n\tid: string | undefined,\n\tdepth: number,\n\tpath: Set<object>,\n\tobj: object,\n\tstate: WalkState,\n\tproblems: string[],\n\tvisit: (node: unknown, depth: number, path: Set<object>) => void,\n): void {\n\tconst sp = node as { children?: unknown; sizes?: unknown; orientation?: unknown; constraints?: unknown }\n\tconst children = Array.isArray(sp.children) ? (sp.children as unknown[]) : null\n\tconst sizes = Array.isArray(sp.sizes) ? (sp.sizes as unknown[]) : null\n\tconst orientation = sp.orientation\n\tif (orientation !== 'row' && orientation !== 'column') {\n\t\tproblems.push(`split ${id ?? '?'}: invalid orientation ${String(orientation)}`)\n\t}\n\tif (sp.constraints !== undefined) {\n\t\tcheckConstraints(sp.constraints, id, problems)\n\t}\n\n\tif (!children) {\n\t\tproblems.push(`split ${id ?? '?'}: children is not an array`)\n\t\treturn\n\t}\n\tif (children.length < 2) {\n\t\tproblems.push(`split ${id ?? '?'}: must have >= 2 children, has ${children.length}`)\n\t}\n\tcheckSizes(sizes, children, id, problems)\n\t// LENGTH-vs-children comparison (gated on a valid children array).\n\tif (sp.constraints !== undefined && Array.isArray(sp.constraints)) {\n\t\tconst constraints = sp.constraints as unknown[]\n\t\tif (constraints.length !== children.length) {\n\t\t\tproblems.push(\n\t\t\t\t`split ${id ?? '?'}: constraints ${constraints.length} != children ${children.length}`,\n\t\t\t)\n\t\t}\n\t}\n\tconst nextPath = new Set(path)\n\tnextPath.add(obj)\n\tfor (const child of children) {\n\t\tvisit(child, depth + 1, nextPath)\n\t}\n}\n\nexport function validateTree(t: LayoutTree, knownPanelIds: ReadonlySet<string>): string[] {\n\tif (t === null || typeof t !== 'object') return ['tree is not an object']\n\tif ((t as { version?: unknown }).version !== 1) {\n\t\treturn [`unsupported version: ${String((t as { version?: unknown }).version)}`]\n\t}\n\treturn collectProblems((t as { root?: unknown }).root, knownPanelIds)\n}\n\nexport function parseLayout(json: string): LayoutTree {\n\tlet raw: unknown\n\ttry {\n\t\traw = JSON.parse(json)\n\t}\n\tcatch {\n\t\tthrow new Error('parseLayout: input is not valid JSON')\n\t}\n\tif (raw === null || typeof raw !== 'object') {\n\t\tthrow new Error('parseLayout: top-level value is not an object')\n\t}\n\tconst obj = raw as { version?: unknown; root?: unknown }\n\tif (obj.version !== 1) {\n\t\tthrow new Error(`parseLayout: unsupported version ${String(obj.version)}`)\n\t}\n\tif (obj.root === undefined || obj.root === null) {\n\t\tthrow new Error('parseLayout: missing root')\n\t}\n\t// Validate structure with no knownPanelIds constraint (orphan check N/A on\n\t// pure deserialize — caller pairs with their own registry).\n\tconst problems = collectProblems(obj.root, null)\n\tif (problems.length > 0) {\n\t\tthrow new Error(`parseLayout: illegal layout — ${problems.join('; ')}`)\n\t}\n\treturn { version: 1, root: obj.root as LayoutNode }\n}\n","/**\n * Self-healing for persisted layout trees — pure TS (no react/electron).\n *\n * A FLEXIBLE child (`constraints[i]` null / no constraints) has no enforced\n * lower weight bound in the serialized tree: `validateTree` only rejects\n * NON-FINITE sizes, not non-positive ones. A user who dragged a flexible panel\n * to ~0 width writes a ~0 (or 0, or negative) weight into the tree; on the next\n * restore that panel comes back at 0 width, invisible and effectively stuck.\n *\n * `sanitizeFlexibleWeights` heals such a tree: every flexible child whose weight\n * is NON-POSITIVE (≤ 0 or non-finite) is lifted to a minimum positive weight, so\n * a restored panel is always visible. A small-but-POSITIVE weight is left as-is\n * — weights are a relative ratio (any positive scale is valid), so a tiny\n * positive weight is healthy, not collapsed. PX-SIZED children\n * (`fixedPx`/`minPx`) are sized in pixels, NOT weights — their `sizes[i]` entry\n * is a preserved-but-unused placeholder — so they are left untouched. The\n * function is pure (clone-on-write, never mutates the input).\n */\nimport type { LayoutNode, LayoutTree, SizeConstraint, SplitNode } from './types.js'\n\n/** The healed-up value for a collapsed flexible child. A small positive weight:\n * enough to make the panel visible without stealing meaningful space from its\n * healthy siblings (the user can re-drag afterwards). */\nconst HEALED_FLEX_WEIGHT = 1\n\n/** Is child `i` of `node` flexible (weight-sized) — i.e. has no px constraint? */\nfunction isFlexibleAt(node: SplitNode, i: number): boolean {\n\treturn (node.constraints?.[i] ?? null) === null\n}\n\nfunction sanitizeNode(node: LayoutNode): LayoutNode {\n\tif (node.kind === 'tabs') return node\n\n\t// Recurse first so nested splits are healed regardless of this level.\n\tconst children = node.children.map(sanitizeNode)\n\n\t// Heal this split's FLEXIBLE child weights. ONLY a NON-POSITIVE weight (≤ 0 or\n\t// non-finite — the \"dragged to 0 / negative\" collapse) is healed; every\n\t// POSITIVE weight is kept verbatim, however small. Weights are a RELATIVE ratio\n\t// (any positive scale is valid — `[0.001, 0.006]` is the same layout as\n\t// `[1, 6]`), so a small-but-positive weight is healthy and must not be rewritten\n\t// (that would crush the ratio). Px children are never touched.\n\tlet changed = children.some((c, i) => c !== node.children[i])\n\tconst sizes = node.sizes.map((w, i) => {\n\t\tif (!isFlexibleAt(node, i)) return w\n\t\tif (typeof w === 'number' && Number.isFinite(w) && w > 0) return w\n\t\tchanged = true\n\t\treturn HEALED_FLEX_WEIGHT\n\t})\n\n\tif (!changed) return node\n\tconst rebuilt: SplitNode = {\n\t\tkind: 'split',\n\t\tid: node.id,\n\t\torientation: node.orientation,\n\t\tchildren,\n\t\tsizes,\n\t}\n\t// Preserve the constraints array verbatim (only weights are touched).\n\treturn node.constraints !== undefined\n\t\t? { ...rebuilt, constraints: node.constraints as readonly (SizeConstraint | null)[] }\n\t\t: rebuilt\n}\n\n/**\n * Return a tree in which every FLEXIBLE child with a non-positive (≤ tiny\n * threshold) weight is healed to a minimum positive weight, recursively. Px\n * children are untouched. Pure: the input is never mutated; a fully-healthy tree\n * is returned structurally unchanged (same weights).\n */\nexport function sanitizeFlexibleWeights(tree: LayoutTree): LayoutTree {\n\tconst root = sanitizeNode(tree.root)\n\treturn root === tree.root ? tree : { version: 1, root }\n}\n","/**\n * Pure tree mutations. Every function returns a NEW tree and never mutates its\n * input (clone-on-write). All structural invariants (#1) are funnelled through\n * `normalizeRoot`, which collapses empty tabgroups + single-child splits,\n * cascading upward, while keeping the root a LayoutNode.\n */\nimport type { LayoutNode, LayoutTree, Orientation, SizeConstraint, SplitNode, TabGroupNode } from './types.js'\n\n// ───────────────────────── helpers ─────────────────────────\n\nfunction tg(id: string, panels: string[], active: string): TabGroupNode {\n\treturn { kind: 'tabs', id, panels, active }\n}\n\n/** Re-derive active after panels changed: keep current active if still present,\n * else select panels[min(removedIndex, len-1)] (clamp to last). */\nfunction deriveActive(panels: string[], prevActive: string, removedIndex: number): string {\n\tif (panels.length === 0) return ''\n\tif (panels.includes(prevActive)) return prevActive\n\tconst idx = Math.min(removedIndex, panels.length - 1)\n\treturn panels[Math.max(0, idx)]!\n}\n\n/**\n * Collapse a (already child-normalized) node:\n * - tabgroup with 0 panels => null (drop)\n * - split: drop null children; if 0 left => null; if 1 left => that child;\n * else rebuild with repaired sizes.\n */\nfunction normalize(node: LayoutNode): LayoutNode | null {\n\tif (node.kind === 'tabs') {\n\t\treturn node.panels.length === 0 ? null : node\n\t}\n\t// split: normalize children first.\n\tconst kept: LayoutNode[] = []\n\tconst keptSizes: number[] = []\n\tconst keptConstraints: (SizeConstraint | null)[] = []\n\tconst hadConstraints = node.constraints !== undefined\n\tnode.children.forEach((child, i) => {\n\t\tconst n = normalize(child)\n\t\tif (n !== null) {\n\t\t\tkept.push(n)\n\t\t\tkeptSizes.push(node.sizes[i] ?? 1)\n\t\t\tif (hadConstraints) keptConstraints.push(node.constraints![i] ?? null)\n\t\t}\n\t})\n\tif (kept.length === 0) return null\n\tif (kept.length === 1) return kept[0]!\n\tconst rebuilt: SplitNode = { kind: 'split', id: node.id, orientation: node.orientation, children: kept, sizes: keptSizes }\n\tif (!hadConstraints) return rebuilt\n\t// M3 repair: dropping children can leave a multi-child split whose survivors\n\t// are ALL fixed-px (the sole flexible child was the one removed). That tree is\n\t// rejected by validateTree (rrp needs >= 1 weight-sized child). Deterministically\n\t// clear the LAST survivor's constraint so >= 1 flexible child remains.\n\tconst allFixed = keptConstraints.length > 0 && !keptConstraints.some(c => c === null)\n\tif (allFixed) {\n\t\tkeptConstraints[keptConstraints.length - 1] = null\n\t}\n\treturn { ...rebuilt, constraints: keptConstraints }\n}\n\n/** Apply collapse to the root, guaranteeing the result is a LayoutNode. A root\n * that collapses to nothing is illegal upstream (we never empty the last group\n * without a replacement), so we only reach here with a survivor. */\nfunction normalizeRoot(root: LayoutNode): LayoutNode {\n\tconst n = normalize(root)\n\tif (n === null) {\n\t\tthrow new Error('mutation would empty the entire layout')\n\t}\n\treturn n\n}\n\ninterface Located {\n\tgroup: TabGroupNode\n}\n\nfunction findGroupContaining(root: LayoutNode, panelId: string): Located | null {\n\tlet found: TabGroupNode | null = null\n\tconst walk = (n: LayoutNode): void => {\n\t\tif (found) return\n\t\tif (n.kind === 'tabs') {\n\t\t\tif (n.panels.includes(panelId)) found = n\n\t\t}\n\t\telse {\n\t\t\tn.children.forEach(walk)\n\t\t}\n\t}\n\twalk(root)\n\treturn found ? { group: found } : null\n}\n\nfunction findGroupById(root: LayoutNode, groupId: string): TabGroupNode | null {\n\tlet found: TabGroupNode | null = null\n\tconst walk = (n: LayoutNode): void => {\n\t\tif (found) return\n\t\tif (n.kind === 'tabs') {\n\t\t\tif (n.id === groupId) found = n\n\t\t}\n\t\telse {\n\t\t\tn.children.forEach(walk)\n\t\t}\n\t}\n\twalk(root)\n\treturn found\n}\n\n/** Collect every panelId present anywhere in the tree. */\nfunction collectPanelIds(root: LayoutNode): Set<string> {\n\tconst out = new Set<string>()\n\tconst walk = (n: LayoutNode): void => {\n\t\tif (n.kind === 'tabs') {\n\t\t\tfor (const p of n.panels) out.add(p)\n\t\t}\n\t\telse {\n\t\t\tn.children.forEach(walk)\n\t\t}\n\t}\n\twalk(root)\n\treturn out\n}\n\n/** True if `panelId` exists in any tabgroup of the tree. */\nfunction hasPanel(root: LayoutNode, id: string): boolean {\n\treturn collectPanelIds(root).has(id)\n}\n\n/** Collect every node id present anywhere in the tree (splits + tabgroups). */\nfunction collectNodeIds(root: LayoutNode): Set<string> {\n\tconst out = new Set<string>()\n\tconst walk = (n: LayoutNode): void => {\n\t\tout.add(n.id)\n\t\tif (n.kind === 'split') n.children.forEach(walk)\n\t}\n\twalk(root)\n\treturn out\n}\n\n/**\n * Mint an id from `base` that is not already in `taken`. If `base` is free,\n * return it; otherwise append an incrementing `#N` suffix until free. Mutates\n * `taken` so successive calls in the same mutation can't collide with each other.\n */\nfunction freshId(taken: Set<string>, base: string): string {\n\tlet candidate = base\n\tlet n = 2\n\twhile (taken.has(candidate)) {\n\t\tcandidate = `${base}#${n}`\n\t\tn += 1\n\t}\n\ttaken.add(candidate)\n\treturn candidate\n}\n\nfunction findSplitById(root: LayoutNode, splitId: string): SplitNode | null {\n\tlet found: SplitNode | null = null\n\tconst walk = (n: LayoutNode): void => {\n\t\tif (found) return\n\t\tif (n.kind === 'split') {\n\t\t\tif (n.id === splitId) found = n\n\t\t\tn.children.forEach(walk)\n\t\t}\n\t}\n\twalk(root)\n\treturn found\n}\n\n/**\n * Rebuild the tree, replacing the node with matching id by `replacement`\n * (which may be null to delete — handled by collapse). This produces a fresh\n * object graph (clone-on-write); untouched branches are still rebuilt so the\n * input is never shared.\n */\nfunction replaceNode(node: LayoutNode, targetId: string, replacement: LayoutNode): LayoutNode {\n\tif (node.id === targetId) return replacement\n\tif (node.kind === 'tabs') return tg(node.id, [...node.panels], node.active)\n\tconst out: SplitNode = {\n\t\tkind: 'split',\n\t\tid: node.id,\n\t\torientation: node.orientation,\n\t\tchildren: node.children.map(c => replaceNode(c, targetId, replacement)),\n\t\tsizes: [...node.sizes],\n\t}\n\treturn node.constraints !== undefined ? { ...out, constraints: [...node.constraints] } : out\n}\n\nfunction cloneNode(node: LayoutNode): LayoutNode {\n\tif (node.kind === 'tabs') return tg(node.id, [...node.panels], node.active)\n\tconst out: SplitNode = {\n\t\tkind: 'split',\n\t\tid: node.id,\n\t\torientation: node.orientation,\n\t\tchildren: node.children.map(cloneNode),\n\t\tsizes: [...node.sizes],\n\t}\n\treturn node.constraints !== undefined ? { ...out, constraints: [...node.constraints] } : out\n}\n\nfunction wrap(root: LayoutNode): LayoutTree {\n\treturn { version: 1, root }\n}\n\n// ───────────────────────── mutations ─────────────────────────\n\nexport function setSizes(t: LayoutTree, splitId: string, sizes: readonly number[]): LayoutTree {\n\tconst target = findSplitById(t.root, splitId)\n\tif (!target) throw new Error(`setSizes: split not found: ${splitId}`)\n\tif (sizes.length !== target.children.length) {\n\t\tthrow new Error(\n\t\t\t`setSizes: sizes length ${sizes.length} != children length ${target.children.length}`,\n\t\t)\n\t}\n\tif (!sizes.every(s => Number.isFinite(s))) {\n\t\tthrow new Error(`setSizes: every size must be a finite number, got [${sizes.join(', ')}]`)\n\t}\n\tconst replacement: SplitNode = {\n\t\tkind: 'split',\n\t\tid: target.id,\n\t\torientation: target.orientation,\n\t\tchildren: target.children.map(cloneNode),\n\t\tsizes: [...sizes],\n\t}\n\t// setSizes must NOT touch constraints — carry them through unchanged.\n\tconst withConstraints: SplitNode = target.constraints !== undefined\n\t\t? { ...replacement, constraints: [...target.constraints] }\n\t\t: replacement\n\treturn wrap(replaceNode(t.root, splitId, withConstraints))\n}\n\n/**\n * Set (or clear) the fixed-px constraint on child `childIndex` of split\n * `splitId`. Pure (clone-on-write). Lazily materializes an all-null constraints\n * array aligned with `children` when absent, then writes the slot. Clearing\n * (`constraint === null`) keeps the array even if all entries become null.\n */\nexport function setConstraint(\n\tt: LayoutTree,\n\tsplitId: string,\n\tchildIndex: number,\n\tconstraint: SizeConstraint | null,\n): LayoutTree {\n\tconst target = findSplitById(t.root, splitId)\n\tif (!target) throw new Error(`setConstraint: split not found: ${splitId}`)\n\tif (!Number.isInteger(childIndex)) {\n\t\tthrow new Error(`setConstraint: childIndex must be an integer, got ${childIndex}`)\n\t}\n\tif (childIndex < 0 || childIndex >= target.children.length) {\n\t\tthrow new Error(\n\t\t\t`setConstraint: childIndex ${childIndex} out of range [0, ${target.children.length})`,\n\t\t)\n\t}\n\tconst base: (SizeConstraint | null)[] = target.constraints !== undefined\n\t\t? [...target.constraints]\n\t\t: target.children.map(() => null)\n\tbase[childIndex] = constraint\n\t// M3 guard: never produce an all-FIXED-px split. If applying this constraint\n\t// would leave EVERY child `fixedPx`-locked (0 weight-sized children),\n\t// `validateTree`/`parseLayout` would later reject the serialized tree (rrp\n\t// requires >= 1 weight-sized child). You cannot fixedPx-pin the LAST flexible\n\t// child — treat it as a NO-OP. A `minPx` child is FLEXIBLE (weight-sized with a\n\t// floor), so it does NOT count toward \"all fixed\" — pinning a `minPx` floor is\n\t// always allowed.\n\tif (base.length > 0 && base.every(c => c !== null)) {\n\t\treturn t\n\t}\n\tconst replacement: SplitNode = {\n\t\tkind: 'split',\n\t\tid: target.id,\n\t\torientation: target.orientation,\n\t\tchildren: target.children.map(cloneNode),\n\t\tsizes: [...target.sizes],\n\t\tconstraints: base,\n\t}\n\treturn wrap(replaceNode(t.root, splitId, replacement))\n}\n\nexport function setActive(t: LayoutTree, groupId: string, panelId: string): LayoutTree {\n\tconst group = findGroupById(t.root, groupId)\n\tif (!group) throw new Error(`setActive: group not found: ${groupId}`)\n\tif (!group.panels.includes(panelId)) {\n\t\tthrow new Error(`setActive: panel ${panelId} not in group ${groupId}`)\n\t}\n\tconst replacement = tg(group.id, [...group.panels], panelId)\n\treturn wrap(replaceNode(t.root, groupId, replacement))\n}\n\n/** Remove a panel from whichever group holds it; collapse. */\nfunction removePanel(root: LayoutNode, panelId: string): LayoutNode {\n\tconst located = findGroupContaining(root, panelId)\n\tif (!located) throw new Error(`panel not found: ${panelId}`)\n\tconst { group } = located\n\tconst removedIndex = group.panels.indexOf(panelId)\n\tconst panels = group.panels.filter(p => p !== panelId)\n\tconst replacement = tg(group.id, panels, deriveActive(panels, group.active, removedIndex))\n\tconst replaced = replaceNode(root, group.id, replacement)\n\treturn normalizeRoot(replaced)\n}\n\nexport function closePanel(t: LayoutTree, panelId: string): LayoutTree {\n\t// Last-panel no-op guard: closing the SOLE panel in the whole tree would\n\t// empty the layout (normalizeRoot throws). Instead return the tree unchanged\n\t// so hosts can wire a close button without special-casing the final panel.\n\t// An UNKNOWN id is NOT \"the last panel\" — only short-circuit when the panel\n\t// actually EXISTS and is the only one; otherwise fall through to removePanel,\n\t// which throws \"panel not found\" for an unknown id (behavior preserved).\n\tconst ids = collectPanelIds(t.root)\n\tif (ids.size === 1 && ids.has(panelId)) return t\n\treturn wrap(removePanel(t.root, panelId))\n}\n\nexport function extractPanel(\n\tt: LayoutTree,\n\tpanelId: string,\n): { tree: LayoutTree; extracted: string } {\n\tconst located = findGroupContaining(t.root, panelId)\n\tif (!located) throw new Error(`extractPanel: panel not found: ${panelId}`)\n\treturn { tree: wrap(removePanel(t.root, panelId)), extracted: panelId }\n}\n\nexport function insertPanel(\n\tt: LayoutTree,\n\tpanelId: string,\n\tdest: { groupId: string; index?: number },\n): LayoutTree {\n\tif (hasPanel(t.root, panelId)) {\n\t\tthrow new Error(`insertPanel: panel already exists in the tree: ${panelId}`)\n\t}\n\tconst group = findGroupById(t.root, dest.groupId)\n\tif (!group) throw new Error(`insertPanel: dest group not found: ${dest.groupId}`)\n\tconst panels = [...group.panels]\n\tconst idx = clampInsertIndex(dest.index, panels.length)\n\tpanels.splice(idx, 0, panelId)\n\tconst replacement = tg(group.id, panels, group.active)\n\treturn wrap(normalizeRoot(replaceNode(t.root, group.id, replacement)))\n}\n\nfunction clampInsertIndex(index: number | undefined, len: number): number {\n\tif (index === undefined) return len\n\tif (index < 0) return 0\n\tif (index > len) return len\n\treturn index\n}\n\nexport function movePanel(\n\tt: LayoutTree,\n\tpanelId: string,\n\tdest: { groupId: string; index?: number },\n): LayoutTree {\n\tconst src = findGroupContaining(t.root, panelId)\n\tif (!src) throw new Error(`movePanel: panel not found: ${panelId}`)\n\tconst destGroup = findGroupById(t.root, dest.groupId)\n\tif (!destGroup) throw new Error(`movePanel: dest group not found: ${dest.groupId}`)\n\n\tif (src.group.id === destGroup.id) {\n\t\t// Same-group reorder: remove then re-insert at the clamped index.\n\t\tconst without = src.group.panels.filter(p => p !== panelId)\n\t\tconst idx = clampInsertIndex(dest.index, without.length)\n\t\tconst panels = [...without]\n\t\tpanels.splice(idx, 0, panelId)\n\t\tconst replacement = tg(src.group.id, panels, src.group.active)\n\t\treturn wrap(normalizeRoot(replaceNode(t.root, src.group.id, replacement)))\n\t}\n\n\t// Cross-group: remove from source (re-derive active + maybe collapse), then\n\t// insert into dest. Compute the destination panels against the ORIGINAL dest\n\t// group so the clamp matches its pre-move length.\n\tconst removedIndex = src.group.panels.indexOf(panelId)\n\tconst srcPanels = src.group.panels.filter(p => p !== panelId)\n\tconst srcReplacement = tg(src.group.id, srcPanels, deriveActive(srcPanels, src.group.active, removedIndex))\n\n\tconst destPanels = [...destGroup.panels]\n\tconst idx = clampInsertIndex(dest.index, destPanels.length)\n\tdestPanels.splice(idx, 0, panelId)\n\tconst destReplacement = tg(destGroup.id, destPanels, destGroup.active)\n\n\tlet root = replaceNode(t.root, src.group.id, srcReplacement)\n\troot = replaceNode(root, destGroup.id, destReplacement)\n\treturn wrap(normalizeRoot(root))\n}\n\nexport function splitPanel(\n\tt: LayoutTree,\n\tatPanelId: string,\n\tdir: Orientation,\n\tnewPanelId: string,\n\tside: 'before' | 'after',\n): LayoutTree {\n\tif (hasPanel(t.root, newPanelId)) {\n\t\tthrow new Error(`splitPanel: new panel already exists in the tree: ${newPanelId}`)\n\t}\n\tconst located = findGroupContaining(t.root, atPanelId)\n\tif (!located) throw new Error(`splitPanel: panel not found: ${atPanelId}`)\n\tconst { group } = located\n\n\t// Generated node ids must be unique within the current tree: a node literally\n\t// named `${origGroupId}__sp` could already exist and produce a duplicate-id\n\t// tree. Mint collision-free ids off the deterministic bases.\n\tconst taken = collectNodeIds(t.root)\n\n\t// Extract atPanelId into its own new group.\n\tconst origGroupId = group.id\n\tconst extractedGroup = tg(freshId(taken, `${origGroupId}__split`), [atPanelId], atPanelId)\n\tconst newGroup = tg(freshId(taken, `${origGroupId}__new`), [newPanelId], newPanelId)\n\n\tconst children: LayoutNode[] = side === 'after'\n\t\t? [extractedGroup, newGroup]\n\t\t: [newGroup, extractedGroup]\n\tconst newSplit: SplitNode = {\n\t\tkind: 'split',\n\t\tid: freshId(taken, `${origGroupId}__sp`),\n\t\torientation: dir,\n\t\tchildren,\n\t\tsizes: [1, 1],\n\t}\n\n\tif (group.panels.length === 1) {\n\t\t// Replace the whole group with the new split.\n\t\treturn wrap(normalizeRoot(replaceNode(t.root, origGroupId, newSplit)))\n\t}\n\n\t// Multi-panel group: pull atPanelId out, keep the rest in the orig group,\n\t// and place the new split where the orig group was... but the orig group must\n\t// survive too. So: replace orig group with a split [remainingGroup, newSplit]?\n\t// The contract only requires: atPanel + newPanel live in different groups, and\n\t// the orig group keeps the remaining panels. Replace orig group with a split\n\t// of [origRemaining, newSplit] using `dir` orientation.\n\tconst removedIndex = group.panels.indexOf(atPanelId)\n\tconst remaining = group.panels.filter(p => p !== atPanelId)\n\tconst origRemainingGroup = tg(origGroupId, remaining, deriveActive(remaining, group.active, removedIndex))\n\n\tconst outerChildren: LayoutNode[] = side === 'after'\n\t\t? [origRemainingGroup, newSplit]\n\t\t: [newSplit, origRemainingGroup]\n\tconst outerSplit: SplitNode = {\n\t\tkind: 'split',\n\t\tid: freshId(taken, `${origGroupId}__outer`),\n\t\torientation: dir,\n\t\tchildren: outerChildren,\n\t\tsizes: [1, 1],\n\t}\n\treturn wrap(normalizeRoot(replaceNode(t.root, origGroupId, outerSplit)))\n}\n","/**\n * Observable layout model — single-writer, synchronous, call-ordered.\n *\n * INV-3: mutations assume an already-validated (acyclic, integrity-checked) tree\n * — callers feeding hand-built trees should parseLayout/validateTree first.\n *\n * Conventions (pinned by model.test.ts):\n * - revision starts at 0 for the initial tree.\n * - subscribe() does NOT replay; first emission is on the first successful\n * apply, carrying revision 1.\n * - +1 per successful apply; a throwing mutation does NOT advance revision and\n * does NOT notify (the throw propagates to the caller).\n */\nimport type { LayoutModel, LayoutSnapshot, LayoutTree } from './types.js'\n\nexport function createLayoutModel(initial: LayoutTree): LayoutModel {\n\t// Own the initial tree: take a structural snapshot so a later external mutation\n\t// of the caller's `initial` object can't leak into model state. The tree is\n\t// readonly-typed / treated as immutable, so a deep clone is the cheapest\n\t// correct ownership stance. (The `next` from each apply is already a fresh tree\n\t// produced by the pure mutations, so it needs no further clone.)\n\tlet current: LayoutTree = structuredClone(initial)\n\tlet revision = 0\n\tconst subscribers = new Set<(snap: LayoutSnapshot) => void>()\n\n\t// Re-entrancy guard: a subscriber may call apply() during notification. We\n\t// must not re-enter and bump `revision` mid-delivery (subscribers would then\n\t// observe a non-monotonic sequence). Instead, enqueue and drain FIFO so each\n\t// apply fully commits + notifies before the next begins.\n\tlet applying = false\n\tconst queue: ((t: LayoutTree) => LayoutTree)[] = []\n\n\tconst commitAndNotify = (mut: (t: LayoutTree) => LayoutTree): void => {\n\t\t// Compute first; if it throws, nothing below runs — revision stays put\n\t\t// and no subscriber is notified.\n\t\tconst next = mut(current)\n\t\tcurrent = next\n\t\trevision += 1\n\t\tconst snap: LayoutSnapshot = { tree: current, revision }\n\t\t// Snapshot the subscriber set so unsubscribe during delivery is safe.\n\t\t// Isolate subscriber errors: a throw from one must not abort delivery to\n\t\t// the rest, nor make apply() throw after a committed state. The model's\n\t\t// job is delivery, not subscriber correctness — swallow and continue.\n\t\tfor (const fn of [...subscribers]) {\n\t\t\ttry {\n\t\t\t\tfn(snap)\n\t\t\t}\n\t\t\tcatch {\n\t\t\t\t// intentionally swallowed — see above.\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tget(): LayoutTree {\n\t\t\treturn current\n\t\t},\n\t\t/**\n\t\t * `mut` MUST be pure (clone-on-write); the built-in mutations satisfy this.\n\t\t */\n\t\tapply(mut: (t: LayoutTree) => LayoutTree): void {\n\t\t\tif (applying) {\n\t\t\t\t// Re-entrant call (a subscriber applied during notification): queue it\n\t\t\t\t// and let the in-flight drain pass process it after the current pass.\n\t\t\t\tqueue.push(mut)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tapplying = true\n\t\t\ttry {\n\t\t\t\t// Top-level (non-re-entrant) apply: a throw here propagates to the\n\t\t\t\t// caller and does NOT advance revision / notify. (`finally` below\n\t\t\t\t// still resets `applying`, so a throw can't wedge the model.)\n\t\t\t\tcommitAndNotify(mut)\n\t\t\t\t// Drain re-entrant mutations enqueued during notification. Each queued\n\t\t\t\t// apply was deferred and is therefore fire-and-forget: its original\n\t\t\t\t// caller already returned, so it cannot deliver a synchronous throw\n\t\t\t\t// back. Run each as an INDEPENDENT transaction — a throw skips that\n\t\t\t\t// item (no revision bump, no notify) and we continue draining the rest\n\t\t\t\t// in FIFO order. This keeps a thrown queued mut from bubbling into the\n\t\t\t\t// already-committed outer apply() and from disrupting the order /\n\t\t\t\t// processing of later queued items.\n\t\t\t\twhile (queue.length > 0) {\n\t\t\t\t\tconst queuedMut = queue.shift()!\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcommitAndNotify(queuedMut)\n\t\t\t\t\t}\n\t\t\t\t\tcatch {\n\t\t\t\t\t\t// Deferred apply: swallow + continue — see above.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfinally {\n\t\t\t\tapplying = false\n\t\t\t}\n\t\t},\n\t\tsubscribe(fn: (snap: LayoutSnapshot) => void): () => void {\n\t\t\tsubscribers.add(fn)\n\t\t\treturn (): void => {\n\t\t\t\tsubscribers.delete(fn)\n\t\t\t}\n\t\t},\n\t}\n}\n","/**\n * Capability-aware layout operations for user-triggered interactions.\n *\n * Keep these separate from the pure mutations: callers may still use\n * `closePanel` for restore/migration/programmatic layout transforms, while UI\n * entry points consistently honor registry capabilities.\n */\nimport { closePanel } from './mutations.js'\nimport type { LayoutTree, PanelRegistry } from './types.js'\n\n/**\n * Close a panel only when its descriptor permits user closure.\n *\n * Missing descriptors and an omitted `closable` capability retain the historic\n * close behavior. Only an explicit `closable:false` blocks the operation.\n */\nexport function closePanelForUser(\n\ttree: LayoutTree,\n\tpanelId: string,\n\tregistry: PanelRegistry,\n): LayoutTree {\n\treturn registry.get(panelId)?.closable === false ? tree : closePanel(tree, panelId)\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-BJqo-vP2.js","names":[],"sources":["../src/shared/protocol.ts"],"sourcesContent":["/**\n * Deck framework wire protocol —— main ↔ webview 之间的 channel 名 + 帧\n * 形态。SoT 在此,preload / client / main runtime 都从这里 import。\n *\n * 设计:把 declared `hostServices` / `simulatorApis` / `events` 三类全部走\n * **两个** 统一 channel,避免 channel name 爆炸 / 难以加 senderPolicy 白名单。\n * - `__electron-deck:invoke` — webview → main RPC (ipcRenderer.invoke)\n * - `__electron-deck:event` — main → webview event push (webContents.send)\n * - `__electron-deck:probe` — webview → main 探活,bridge ready 检查\n *\n * 帧用 JSON 对象一层 envelope,便于扩展 + 校验。\n *\n * @internal\n */\n\nimport type { JsonValue } from '../types.js'\n\n/** Bridge global 默认挂的全局名(contextBridge.exposeInMainWorld) */\nexport const DEFAULT_BRIDGE_GLOBAL = '__electronDeckBridge'\n\n/**\n * Slot-token LAYOUT bridge 默认挂的全局名。`exposeDeckLayoutBridge()` 默认暴露到\n * 此名,renderer 的 `createDeckLayoutClient({ bridge: window.__electronDeckLayoutBridge })`\n * 读取同名。单一来源避免 preload helper 与 client 之间字符串漂移。\n */\nexport const DEFAULT_LAYOUT_BRIDGE_GLOBAL = '__electronDeckLayoutBridge'\n\n/** Bridge protocol semver;client 在 ready() 时校验 major 一致 */\nexport const BRIDGE_PROTOCOL_VERSION = '1.0.0'\n\nexport const DeckChannel = {\n\tInvoke: '__electron-deck:invoke',\n\tEvent: '__electron-deck:event',\n\tProbe: '__electron-deck:probe',\n\tPlace: '__electron-deck:place',\n\tSlotGrant: '__electron-deck:slot-grant',\n\tLayoutSubscribe: '__electron-deck:layout-subscribe',\n} as const\n\nexport type InvokeKind = 'host' | 'simulator'\n\nexport interface InvokeRequest {\n\treadonly kind: InvokeKind\n\treadonly name: string\n\treadonly args: readonly JsonValue[]\n}\n\nexport interface InvokeSuccess<R extends JsonValue = JsonValue> {\n\treadonly ok: true\n\treadonly result: R\n}\n\nexport interface InvokeFailure {\n\treadonly ok: false\n\treadonly error: {\n\t\treadonly remoteName: string\n\t\treadonly message: string\n\t\treadonly code?: string\n\t}\n}\n\nexport type InvokeResponse<R extends JsonValue = JsonValue> =\n\t| InvokeSuccess<R>\n\t| InvokeFailure\n\nexport interface EventEnvelope<P extends JsonValue = JsonValue> {\n\treadonly name: string\n\treadonly payload: P\n}\n\nexport interface ProbeResponse {\n\treadonly ready: true\n\treadonly version: typeof BRIDGE_PROTOCOL_VERSION\n}\n\n/**\n * Bridge global 暴露到 webview window 的 shape。preload 把它通过\n * `contextBridge.exposeInMainWorld(globalName, bridge)` 注入;webview-side\n * `createDeckClient()` 通过 `globalThis[globalName]` 读取。\n *\n * 注意所有方法必须是 contextBridge-friendly(plain values + serializable\n * arguments),不要把 Map / Set / Date / Promise.race 等 leak 进 bridge 接口。\n */\nexport interface DeckBridge {\n\treadonly version: typeof BRIDGE_PROTOCOL_VERSION\n\tprobe(): Promise<ProbeResponse>\n\tinvoke(req: InvokeRequest): Promise<InvokeResponse>\n\t/** 订阅 event channel;返回 unsubscribe 函数(不是 Disposable,因为要跨 contextBridge) */\n\tonEvent(listener: (env: EventEnvelope) => void): () => void\n}\n"],"mappings":";;AAkBA,IAAa,wBAAwB;;;;;;AAOrC,IAAa,+BAA+B;;AAG5C,IAAa,0BAA0B;AAEvC,IAAa,cAAc;CAC1B,QAAQ;CACR,OAAO;CACP,OAAO;CACP,OAAO;CACP,WAAW;CACX,iBAAiB;AAClB"}
|