@dreamboard-games/sdk 0.5.0-alpha.5 → 0.5.0-alpha.7
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/README.md +16 -6
- package/dist/{chunk-7RGMPJQG.js → chunk-HZPKKBEG.js} +81 -5
- package/dist/chunk-HZPKKBEG.js.map +1 -0
- package/dist/index.d.ts +121 -4
- package/dist/index.js +189 -8
- package/dist/index.js.map +1 -1
- package/dist/{model-BCl8WsB6.d.ts → model-D2Z9j0Yi.d.ts} +18 -3
- package/dist/react.d.ts +43 -28
- package/dist/react.js +333 -133
- package/dist/react.js.map +1 -1
- package/dist/reducer.js +4 -0
- package/dist/reducer.js.map +1 -1
- package/package.json +1 -4
- package/dist/chunk-7RGMPJQG.js.map +0 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ pnpm add @dreamboard-games/sdk
|
|
|
13
13
|
The package declarations and export map are the API authority. There are four entry points:
|
|
14
14
|
|
|
15
15
|
- `@dreamboard-games/sdk`: framework-free instances, sources, features and canonical host protocol schemas.
|
|
16
|
-
- `@dreamboard-games/sdk/react`: typed React provider, selectors, subscriptions, and
|
|
16
|
+
- `@dreamboard-games/sdk/react`: typed React provider, selectors, subscriptions, and card gesture and drop-area hooks.
|
|
17
17
|
- `@dreamboard-games/sdk/reducer`: game authoring, manifest compilation, execution and trusted worker admission.
|
|
18
18
|
- `@dreamboard-games/sdk/testing`: browser-safe local/scenario sources, replay, inspection and bounded exploration.
|
|
19
19
|
|
|
@@ -221,7 +221,8 @@ cards: [
|
|
|
221
221
|
```
|
|
222
222
|
|
|
223
223
|
These definitions create runtime IDs `ace-1`, `ace-2`, and `king`, all in the
|
|
224
|
-
`ranked` category.
|
|
224
|
+
`ranked` category. Card IDs cannot start with `hidden:`; that prefix is reserved
|
|
225
|
+
for the positions a seat uses to address concealed cards. When the card schema has `variants`, every `cardType` must
|
|
225
226
|
name one of them; `compileManifest` and `createGame` reject unknown categories.
|
|
226
227
|
The inferred table narrows a card lookup by its runtime ID to that definition's
|
|
227
228
|
card set, category, and properties. A variant property overrides a shared
|
|
@@ -297,10 +298,13 @@ pnpm add @dreamboard-games/sdk react@^19 react-dom@^19 @tanstack/react-store@0.1
|
|
|
297
298
|
install the React adapter. The `/react` entry delegates selectors to that package;
|
|
298
299
|
the application bundler resolves its supported React subscription dependencies.
|
|
299
300
|
|
|
300
|
-
|
|
301
|
-
`
|
|
302
|
-
BoardTargets components or your own renderer.
|
|
303
|
-
Headless `game.drag` remains browser-free and handles
|
|
301
|
+
`/react` classifies each card press as a tap, hold, drag or browse. Enable
|
|
302
|
+
`dragFeature`, export `useCardGesture`, `useDropArea` and `useDragOverlay` from the
|
|
303
|
+
binding, and use the copied Hand and BoardTargets components or your own renderer.
|
|
304
|
+
The SDK prescribes no layout. Headless `game.drag` remains browser-free and handles
|
|
305
|
+
atomic domain routing. `fanLayout` computes arc positions for a hand, and
|
|
306
|
+
`originsFeature` adds `card.getOrigin()` so a newly shown card can animate from
|
|
307
|
+
the zone or player it came from.
|
|
304
308
|
|
|
305
309
|
## Local development and tests
|
|
306
310
|
|
|
@@ -324,3 +328,9 @@ sources publish the canonical seat view and keep command bases private.
|
|
|
324
328
|
Card sets contain their authored `cards`, `cardSchema`, and `defaultHome` directly.
|
|
325
329
|
Standard playing cards are game-owned definitions with ordinary suit/rank
|
|
326
330
|
properties; the SDK does not synthesize inventories or assign built-in rules.
|
|
331
|
+
|
|
332
|
+
The exported `createGestureRecognizer(down, callbacks, options)` defaults to
|
|
333
|
+
upward touch dragging so hands retain sideways scrolling. Pile controls can use
|
|
334
|
+
`{ dragDirection: "any" }` with `touch-action: none` to drag toward a hand below
|
|
335
|
+
or beside them. This classifies pointer intent only; submit an authored interaction
|
|
336
|
+
through the bound game to enforce its rules, without selecting a hidden card ID.
|
|
@@ -1184,10 +1184,17 @@ var Controller = class {
|
|
|
1184
1184
|
if (!interaction?.currentLifetime() || !interaction.getIsAvailable())
|
|
1185
1185
|
return;
|
|
1186
1186
|
const cardInput = interaction.findInput(target.cardInputKey);
|
|
1187
|
-
|
|
1188
|
-
|
|
1187
|
+
if (!cardInput || cardInput.descriptor.domain.type !== "cardTarget" || !cardInput.getIsEligible(cardId))
|
|
1188
|
+
return;
|
|
1189
|
+
const input = target.kind === "interaction" ? void 0 : interaction.findInput(target.inputKey);
|
|
1190
|
+
if (target.kind !== "interaction" && (!input || !matchesBoardTarget(input.descriptor, target) || !input.getIsEligible(target.value)))
|
|
1189
1191
|
return;
|
|
1190
1192
|
let next = { ...this.drafts()[interaction.key] };
|
|
1193
|
+
const chosen = next[cardInput.key];
|
|
1194
|
+
if (!input && isManyInput(cardInput.descriptor) && Array.isArray(chosen) && chosen.includes(cardId)) {
|
|
1195
|
+
this.activate(interaction.key);
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1191
1198
|
routeCardInputIntent(
|
|
1192
1199
|
{
|
|
1193
1200
|
getDraft: () => next,
|
|
@@ -1202,7 +1209,7 @@ var Controller = class {
|
|
|
1202
1209
|
{
|
|
1203
1210
|
cardId,
|
|
1204
1211
|
cardInputKey: cardInput.key,
|
|
1205
|
-
dropTarget: { inputKey: input.key, value: target.value }
|
|
1212
|
+
dropTarget: input && target.kind !== "interaction" ? { inputKey: input.key, value: target.value } : void 0
|
|
1206
1213
|
}
|
|
1207
1214
|
);
|
|
1208
1215
|
this.writeDraft(interaction.key, next);
|
|
@@ -1447,9 +1454,78 @@ function createGameInstance() {
|
|
|
1447
1454
|
};
|
|
1448
1455
|
}
|
|
1449
1456
|
|
|
1457
|
+
// src/headless/gesture.ts
|
|
1458
|
+
var GESTURE_THRESHOLDS = Object.freeze({
|
|
1459
|
+
/** Movement, in CSS pixels, before a press becomes a drag or a browse. */
|
|
1460
|
+
slop: 8,
|
|
1461
|
+
/** A touch or pen held this long without moving inspects the card. */
|
|
1462
|
+
holdMs: 350,
|
|
1463
|
+
/** A mouse resting on a card this long inspects it. */
|
|
1464
|
+
hoverMs: 250,
|
|
1465
|
+
/** A finger drags when upward travel exceeds this multiple of sideways travel. */
|
|
1466
|
+
axisBias: 1.25
|
|
1467
|
+
});
|
|
1468
|
+
function createGestureRecognizer(down, callbacks, options = {}) {
|
|
1469
|
+
const origin = { x: down.clientX, y: down.clientY };
|
|
1470
|
+
const mouse = down.pointerType === "mouse";
|
|
1471
|
+
let kind = "tap";
|
|
1472
|
+
let finished = false;
|
|
1473
|
+
const holdTimer = mouse ? void 0 : setTimeout(() => {
|
|
1474
|
+
kind = "hold";
|
|
1475
|
+
callbacks.hold();
|
|
1476
|
+
}, GESTURE_THRESHOLDS.holdMs);
|
|
1477
|
+
const point = (event) => ({
|
|
1478
|
+
x: event.clientX,
|
|
1479
|
+
y: event.clientY
|
|
1480
|
+
});
|
|
1481
|
+
const ours = (event) => !finished && (!event || event.pointerId === down.pointerId);
|
|
1482
|
+
function finish() {
|
|
1483
|
+
finished = true;
|
|
1484
|
+
clearTimeout(holdTimer);
|
|
1485
|
+
}
|
|
1486
|
+
return {
|
|
1487
|
+
move(event) {
|
|
1488
|
+
if (!ours(event)) return;
|
|
1489
|
+
if (kind === "drag") return callbacks.dragMove(point(event));
|
|
1490
|
+
const dx = event.clientX - origin.x;
|
|
1491
|
+
const dy = event.clientY - origin.y;
|
|
1492
|
+
if (kind !== "tap" || Math.hypot(dx, dy) < GESTURE_THRESHOLDS.slop)
|
|
1493
|
+
return;
|
|
1494
|
+
clearTimeout(holdTimer);
|
|
1495
|
+
const lifts = mouse || options.dragDirection === "any" || -dy > GESTURE_THRESHOLDS.axisBias * Math.abs(dx);
|
|
1496
|
+
if (lifts && callbacks.dragStart(origin)) {
|
|
1497
|
+
kind = "drag";
|
|
1498
|
+
callbacks.dragMove(point(event));
|
|
1499
|
+
} else kind = "browse";
|
|
1500
|
+
},
|
|
1501
|
+
up(event) {
|
|
1502
|
+
if (!ours(event)) return;
|
|
1503
|
+
finish();
|
|
1504
|
+
callbacks.end(kind, point(event));
|
|
1505
|
+
},
|
|
1506
|
+
cancel(event) {
|
|
1507
|
+
if (!ours(event)) return;
|
|
1508
|
+
finish();
|
|
1509
|
+
callbacks.cancel(kind);
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
// src/headless/drop-targets.ts
|
|
1515
|
+
function isSameDropTarget(left, right) {
|
|
1516
|
+
if (left.interactionKey !== right.interactionKey || left.cardInputKey !== right.cardInputKey)
|
|
1517
|
+
return false;
|
|
1518
|
+
if (left.kind === "interaction" || right.kind === "interaction")
|
|
1519
|
+
return left.kind === right.kind;
|
|
1520
|
+
return left.kind === right.kind && left.valueKind === right.valueKind && inputValueKey(left.value) === inputValueKey(right.value) && (left.valueKind !== "board-id" || right.valueKind === "board-id" && left.boardId === right.boardId) && left.inputKey === right.inputKey;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1450
1523
|
export {
|
|
1451
1524
|
runtimeFeatures,
|
|
1452
1525
|
AmbiguousTargetError,
|
|
1453
|
-
createGameInstance
|
|
1526
|
+
createGameInstance,
|
|
1527
|
+
isSameDropTarget,
|
|
1528
|
+
GESTURE_THRESHOLDS,
|
|
1529
|
+
createGestureRecognizer
|
|
1454
1530
|
};
|
|
1455
|
-
//# sourceMappingURL=chunk-
|
|
1531
|
+
//# sourceMappingURL=chunk-HZPKKBEG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/headless/runtime-features.ts","../src/headless/input-control.ts","../src/headless/instance.ts","../src/headless/interaction-inputs.ts","../src/headless/interaction-router.ts","../src/headless/gesture.ts","../src/headless/drop-targets.ts"],"sourcesContent":["import type {\n RuntimeBoardState,\n RuntimeBoardCollections,\n} from \"../reducer/model/table.js\";\nimport type { ActionProps, ReadonlyData } from \"./model.js\";\nimport type { InputDomain } from \"../shared/protocol/frame.js\";\nimport type { RuntimeJson } from \"../shared/runtime-json.js\";\nimport type {\n GameSource,\n SourceSnapshot,\n SourceState,\n} from \"./sources/types.js\";\nimport type {\n RuntimeSelectionTarget,\n RuntimeDropTarget,\n RuntimeTargetOptions,\n} from \"./targets.js\";\n\n/** Internal operations over admitted projections; never a game facade widened to unknown. */\nexport const runtimeFeatures = Symbol(\"runtimeFeatures\");\nexport interface RuntimeInput {\n readonly key: string;\n getDomain(): InputDomain;\n getIsEligible(value: RuntimeJson): boolean;\n getIsSelected(value: RuntimeJson): boolean;\n getTargetProps(value: RuntimeJson): ActionProps;\n}\nexport interface RuntimeInteraction {\n readonly key: string;\n getIsAvailable(): boolean;\n getInputs(): readonly RuntimeInput[];\n}\nexport interface RuntimeFeatureSnapshot {\n readonly view: unknown;\n readonly snapshot: SourceSnapshot | null;\n readonly connection: SourceState[\"connection\"];\n readonly interactions: { list(): readonly RuntimeInteraction[] };\n readonly cards: {\n find(\n id: string,\n ): { getInteractions(): readonly RuntimeInteraction[] } | undefined;\n };\n}\nexport interface RuntimeFeatureGame extends RuntimeFeatureSnapshot {\n getSnapshot(): RuntimeFeatureSnapshot;\n getOptions(): { readonly source: GameSource };\n subscribe(listener: () => void): () => void;\n}\nexport interface RuntimeBoard {\n readonly id: string;\n readonly data: ReadonlyData<RuntimeBoardState>;\n readonly game: RuntimeFeatureGame;\n}\nexport interface RuntimeCollection<Value> {\n get(id: string): Value;\n find(id: string): Value | undefined;\n getAll(): readonly Value[];\n}\nexport interface RuntimeFeatureContext {\n readonly game: RuntimeFeatureGame;\n getBoards(): ReadonlyData<RuntimeBoardCollections[\"byId\"]>;\n createBoard(data: ReadonlyData<RuntimeBoardState>): RuntimeBoard;\n routeTarget(\n target: RuntimeSelectionTarget,\n options?: RuntimeTargetOptions,\n ): void;\n routeCardDrop(cardId: string, target: RuntimeDropTarget): void;\n invalidate(): void;\n}\n","import type { ActionProps } from \"./model.js\";\nimport type { InputDomain } from \"../shared/protocol/frame.js\";\nimport type { RuntimeJson } from \"../shared/runtime-json.js\";\n\ntype Domain<Type extends InputDomain[\"type\"]> = Extract<\n InputDomain,\n { type: Type }\n>;\ntype Editable<Value> = {\n readonly value: Value;\n readonly setValue: (value: Value) => void;\n};\ntype Control<Type extends \"boundedNumber\" | \"resourceMap\", Value> = {\n readonly type: Type;\n readonly domain: Domain<Type>;\n} & (\n | ({ readonly mode: \"single\" } & Editable<Value | undefined>)\n | ({ readonly mode: \"many\" } & Editable<Value[]>)\n);\nexport interface InputTargetOption<Value = RuntimeJson> {\n readonly value: Value;\n readonly label: string;\n readonly selected: boolean;\n readonly props: ActionProps;\n}\n/** A captured, descriptor-driven editor. Its handlers retain the input's lifetime. */\nexport type InputControl = {\n readonly key: string;\n readonly disabled: boolean;\n readonly props: {\n readonly disabled: boolean;\n readonly [key: `data-${string}`]: string | number | boolean | undefined;\n };\n} & (\n | Control<\"boundedNumber\", number>\n | Control<\"resourceMap\", Record<string, number>>\n | { readonly type: \"targets\"; readonly options: readonly InputTargetOption[] }\n);\n\ninterface ControlInput {\n readonly key: string;\n getDomain(): InputDomain;\n getValue(): RuntimeJson | undefined;\n setValue(value: RuntimeJson): void;\n clear(): void;\n getTargetOptions(): readonly InputTargetOption[];\n}\n/** Drafts can contain incomplete edits, so normalize only the displayed field values. */\nfunction resourceValue(\n domain: Domain<\"resourceMap\">,\n value: RuntimeJson | undefined,\n): Record<string, number> {\n const record =\n value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value\n : {};\n return Object.fromEntries(\n domain.resources.map((resource) => {\n const amount = record[resource.resourceId];\n return [resource.resourceId, typeof amount === \"number\" ? amount : 0];\n }),\n );\n}\nexport function createInputControl(\n input: ControlInput,\n props: InputControl[\"props\"],\n): InputControl {\n const domain = input.getDomain();\n const current = input.getValue();\n const common = { key: input.key, disabled: props.disabled, props };\n if (domain.type === \"boundedNumber\") {\n if (domain.selection?.mode === \"many\")\n return {\n ...common,\n type: \"boundedNumber\",\n domain,\n mode: \"many\",\n value: Array.isArray(current)\n ? current.filter(\n (value): value is number => typeof value === \"number\",\n )\n : [],\n setValue: (value) => input.setValue(value),\n };\n return {\n ...common,\n type: \"boundedNumber\",\n domain,\n mode: \"single\",\n value: typeof current === \"number\" ? current : undefined,\n setValue: (value) =>\n value === undefined ? input.clear() : input.setValue(value),\n };\n }\n if (domain.type === \"resourceMap\") {\n if (domain.selection?.mode === \"many\")\n return {\n ...common,\n type: \"resourceMap\",\n domain,\n mode: \"many\",\n value: Array.isArray(current)\n ? current.map((value) => resourceValue(domain, value))\n : [],\n setValue: (value) => input.setValue(value),\n };\n return {\n ...common,\n type: \"resourceMap\",\n domain,\n mode: \"single\",\n value: current === undefined ? undefined : resourceValue(domain, current),\n setValue: (value) =>\n value === undefined ? input.clear() : input.setValue(value),\n };\n }\n return { ...common, type: \"targets\", options: input.getTargetOptions() };\n}\n","import {\n runtimeFeatures,\n type RuntimeFeatureContext,\n type RuntimeCollection,\n} from \"./runtime-features.js\";\nimport type {\n RuntimeBoardCollections,\n RuntimeBoardState,\n} from \"../reducer/model/table.js\";\nimport type { ReadonlyData } from \"./model.js\";\nimport { createInputControl } from \"./input-control.js\";\nimport { requireLookup } from \"../shared/lookup.js\";\nimport type {\n RuntimeBoardTarget,\n RuntimeSelectionTarget,\n RuntimeTargetOptions,\n RuntimeDropTarget,\n} from \"./targets.js\";\nimport { immutableCopy } from \"./sources/immutable.js\";\nimport { createStore } from \"@tanstack/store\";\nimport {\n inputTargetInDomain,\n inputValueKey,\n inputValueInDomain,\n} from \"../shared/input-domain.js\";\nimport {\n getInteractionDraftReadiness,\n routeInteractionTarget,\n routeCardInputIntent,\n shouldAutoSubmitInteraction,\n} from \"./interaction-router.js\";\nimport {\n inputSelection,\n isManyInput,\n isManyTargetSelectable,\n} from \"./interaction-inputs.js\";\nimport type { RuntimeJson } from \"../shared/runtime-json.js\";\nimport type {\n Features,\n FeatureContext,\n GameInstance,\n CoreInstance,\n InstanceOptions,\n GameSource,\n SourceState,\n SourceSnapshot,\n SubmitResult,\n InteractionDescriptor,\n InteractionInputDescriptor,\n NativeEvent,\n} from \"./model.js\";\n\ntype Values = Readonly<Record<string, RuntimeJson>>;\ntype DraftMap = Readonly<Record<string, Values | undefined>>;\ntype RuntimeLocalState = { drafts: DraftMap; activeInteraction: string | null };\n/** Concrete controller options; game-specific keys are bound by createGameInstance. */\ntype RuntimeOptions = {\n readonly source: GameSource;\n readonly initialState?: Partial<RuntimeLocalState>;\n readonly state?: Partial<RuntimeLocalState>;\n readonly onDraftsChange?: (drafts: DraftMap) => void;\n readonly onActiveInteractionChange?: (key: string | null) => void;\n readonly onError?: (error: unknown) => void;\n readonly coverage?: Readonly<Record<string, unknown>>;\n readonly debug?: boolean;\n};\nconst EMPTY: Values = Object.freeze({});\nconst EMPTY_DRAFTS: DraftMap = Object.freeze({});\nconst equalValue = (a: unknown, b: unknown) =>\n Object.is(a, b) ||\n (typeof a === \"object\" &&\n typeof b === \"object\" &&\n inputValueKey(a) === inputValueKey(b));\nfunction inDomain(\n input: InteractionInputDescriptor,\n value: unknown,\n partial = false,\n) {\n return inputValueInDomain(input.domain, value, input.domain.selection, {\n ignoreMinimum: partial,\n });\n}\nfunction matchesBoardTarget(\n input: InteractionInputDescriptor,\n target: RuntimeBoardTarget,\n) {\n const domain = input.domain;\n return (\n domain.type === \"boardTarget\" &&\n domain.valueKind === target.valueKind &&\n (domain.targetKind === target.kind ||\n (target.kind === \"space\" && domain.targetKind === \"tile\")) &&\n domain.boardId ===\n (target.valueKind === \"board-id\" ? target.boardId : target.value.boardId)\n );\n}\nfunction immutableValues(value: Values): Values {\n return immutableCopy(value);\n}\nfunction data(\n action: string,\n interaction: string,\n input?: string,\n value?: RuntimeJson,\n) {\n return {\n \"data-action\": action,\n \"data-interaction\": interaction,\n ...(input ? { \"data-input\": input } : {}),\n ...(value === undefined\n ? {}\n : {\n \"data-value\":\n typeof value === \"string\" ? value : JSON.stringify(value),\n }),\n };\n}\nexport class AmbiguousTargetError extends Error {\n constructor(id: string) {\n super(\n `Target '${id}' belongs to more than one eligible input. Choose an interaction and input explicitly.`,\n );\n this.name = \"AmbiguousTargetError\";\n }\n}\n\nclass InteractionObject {\n readonly key: string;\n readonly id: string;\n readonly phase: string;\n readonly label: string;\n readonly help?: string;\n readonly kind: \"inputs\" | \"steps\";\n readonly inputObjects: readonly InputObject[];\n readonly seat: number;\n readonly draft: Values;\n readonly draftIdentity: Values;\n readonly source: GameSource;\n readonly epoch: number;\n constructor(\n readonly owner: Controller,\n readonly descriptor: InteractionDescriptor,\n draft: Values,\n readonly status: \"open\" | \"submitting\" | \"submitted\",\n readonly connected: boolean,\n ) {\n this.seat =\n descriptor.actorSeat ??\n owner.sourceState.snapshot?.players.findIndex(\n (player) => player.playerId === owner.sourceState.snapshot?.me,\n ) ??\n -1;\n this.draftIdentity = draft;\n this.draft = immutableValues(draft);\n this.source = owner.options.source;\n this.epoch = owner.epoch;\n this.key = descriptor.interactionKey;\n this.id = descriptor.interactionId;\n this.phase = descriptor.phaseName;\n this.label = descriptor.label;\n this.help = descriptor.help;\n this.kind = descriptor.step ? \"steps\" : \"inputs\";\n this.inputObjects = Object.freeze(\n descriptor.inputs.map((input) =>\n owner.object(\"input\", new InputObject(this, input)),\n ),\n );\n }\n get game() {\n return this.owner.instance;\n }\n getAvailability() {\n return this.descriptor.availability;\n }\n getIsAvailable() {\n return this.descriptor.availability.status === \"available\";\n }\n getUnavailableReason() {\n return this.descriptor.availability.status === \"available\"\n ? null\n : this.descriptor.availability.reason;\n }\n getStep() {\n return this.descriptor.step ?? null;\n }\n getStepIndex() {\n return this.descriptor.step?.index ?? null;\n }\n getInput(key: string) {\n return requireLookup(\n this.findInput(key),\n `Input in interaction ${this.key}`,\n key,\n );\n }\n findInput(key: string) {\n return this.inputObjects.find((input) => input.key === key);\n }\n getInputs() {\n return this.inputObjects;\n }\n readiness() {\n return getInteractionDraftReadiness(this.descriptor, this.draft);\n }\n getIsReady() {\n return this.readiness().ready;\n }\n getMissingInputs() {\n return this.readiness().missingInputs;\n }\n getStatus() {\n return this.status;\n }\n currentLifetime() {\n return (\n this.source === this.owner.options.source &&\n this.epoch === this.owner.epoch &&\n !this.owner.disposed\n );\n }\n submit() {\n return this.currentLifetime()\n ? this.owner.submit(this.key, false)\n : Promise.resolve({ accepted: false as const, errorCode: \"CLOSED\" });\n }\n cancel() {\n return this.currentLifetime()\n ? this.owner.submit(this.key, true)\n : Promise.resolve({ accepted: false as const, errorCode: \"CLOSED\" });\n }\n reset() {\n if (this.currentLifetime()) this.owner.reset(this.key);\n }\n activate() {\n if (this.currentLifetime()) this.owner.activate(this.key);\n }\n getSubmitHandler() {\n return (event?: NativeEvent) => {\n event?.preventDefault();\n this.owner.handle(() => this.submit());\n };\n }\n getSubmitProps() {\n const disabled =\n !this.getIsAvailable() ||\n !this.getIsReady() ||\n this.status !== \"open\" ||\n !this.connected;\n return {\n ...data(\"submit\", this.key),\n \"data-seat\": this.seat,\n type: \"button\" as const,\n disabled,\n \"data-ready\": this.getIsReady(),\n \"data-disabled\": disabled,\n onClick: this.getSubmitHandler(),\n };\n }\n}\nclass InputObject {\n readonly key: string;\n readonly kind: InteractionInputDescriptor[\"kind\"];\n constructor(\n readonly interaction: InteractionObject,\n readonly descriptor: InteractionInputDescriptor,\n ) {\n this.key = descriptor.key;\n this.kind = descriptor.kind;\n }\n get game() {\n return this.interaction.game;\n }\n get domainType() {\n return this.descriptor.domain.type;\n }\n get selectionMode() {\n return isManyInput(this.descriptor) ? \"many\" : \"single\";\n }\n getTargetOptions() {\n const domain = this.getDomain();\n return this.getEligibleTargets().map((value) => ({\n value,\n label:\n (domain.type === \"choice\" || domain.type === \"choiceList\"\n ? domain.choices.find((choice) => Object.is(choice.value, value))\n ?.label\n : undefined) ??\n (value === null\n ? \"None\"\n : typeof value === \"object\"\n ? JSON.stringify(value)\n : String(value)),\n selected: this.getIsSelected(value),\n props: this.getTargetProps(value),\n }));\n }\n getDomain() {\n return this.descriptor.domain;\n }\n getValue(): RuntimeJson | undefined {\n return (\n this.interaction.draft[this.key] ??\n (Object.hasOwn(this.interaction.draft, this.key)\n ? null\n : this.descriptor.defaultValue)\n );\n }\n setValue(value: RuntimeJson) {\n if (!this.interaction.currentLifetime()) return;\n this.interaction.owner.setInput(this.interaction.key, this.key, value);\n }\n clear() {\n if (!this.interaction.currentLifetime()) return;\n this.interaction.owner.clearInput(this.interaction.key, this.key);\n }\n getIsReady() {\n const descriptor = {\n ...this.interaction.descriptor,\n inputs: [this.descriptor],\n };\n return getInteractionDraftReadiness(descriptor, {\n [this.key]: this.getValue(),\n }).ready;\n }\n getEligibleTargets(): readonly RuntimeJson[] {\n const domain = this.descriptor.domain;\n if (domain.type === \"cardTarget\" || domain.type === \"boardTarget\")\n return domain.eligibleTargets;\n if (domain.type === \"choice\" || domain.type === \"choiceList\")\n return domain.choices\n .filter((choice) => !choice.disabled)\n .map((choice) => choice.value);\n return [];\n }\n getIsEligible(value: RuntimeJson) {\n const input = this.descriptor;\n return (\n inputTargetInDomain(input.domain, value) &&\n isManyTargetSelectable(input, this.getValue(), value)\n );\n }\n getIsSelected(value: RuntimeJson) {\n const current = this.getValue();\n return isManyInput(this.descriptor) && Array.isArray(current)\n ? current.some((item) => equalValue(item, value))\n : equalValue(current, value);\n }\n getSelectHandler(value: RuntimeJson) {\n return () => {\n if (this.interaction.currentLifetime())\n this.interaction.owner.select(this.interaction.key, this.key, value);\n };\n }\n getTargetProps(value: RuntimeJson) {\n const eligible = this.getIsEligible(value);\n const disabled =\n !eligible ||\n !this.interaction.getIsAvailable() ||\n this.interaction.status !== \"open\" ||\n !this.interaction.connected;\n return {\n ...data(\"select\", this.interaction.key, this.key, value),\n \"data-seat\": this.interaction.seat,\n type: \"button\" as const,\n disabled,\n \"data-eligible\": eligible,\n \"data-selected\": this.getIsSelected(value),\n \"data-disabled\": disabled,\n onClick: () => this.getSelectHandler(value)(),\n };\n }\n getControl() {\n const disabled =\n !this.interaction.getIsAvailable() ||\n this.interaction.status !== \"open\" ||\n !this.interaction.connected;\n return createInputControl(this, {\n ...data(\"option\", this.interaction.key, this.key),\n \"data-seat\": this.interaction.seat,\n disabled,\n \"data-disabled\": disabled,\n });\n }\n}\nclass CardObject {\n readonly epoch: number;\n readonly seat: number;\n readonly view: Readonly<Record<string, RuntimeJson>> | null;\n readonly hidden: boolean;\n readonly backImage: string | null;\n constructor(\n readonly owner: Controller,\n readonly id: string,\n readonly zone: string,\n readonly index: number,\n encoded: string | undefined,\n backImage: string | undefined,\n readonly routes: readonly InteractionObject[],\n ) {\n this.epoch = owner.epoch;\n this.seat =\n owner.sourceState.snapshot?.players.findIndex(\n (player) => player.playerId === owner.sourceState.snapshot?.me,\n ) ?? -1;\n this.view = encoded\n ? immutableCopy(JSON.parse(encoded) as Record<string, RuntimeJson>)\n : null;\n this.hidden = this.view === null;\n this.backImage = backImage ?? null;\n }\n get game() {\n return this.owner.instance;\n }\n getInteractions() {\n return this.routes;\n }\n getIsEligible() {\n return this.routes.some((route) => route.getIsAvailable());\n }\n getIsSelected() {\n return this.routes.some((route) =>\n route\n .getInputs()\n .some(\n (input) =>\n input.descriptor.domain.type === \"cardTarget\" &&\n input.getIsSelected(this.id),\n ),\n );\n }\n getCanSelect(options?: RuntimeTargetOptions) {\n return this.routes.some(\n (route) =>\n route.getIsAvailable() &&\n (!options?.interaction || route.key === options.interaction) &&\n route.status === \"open\" &&\n route.connected &&\n route\n .getInputs()\n .some(\n (input) =>\n input.descriptor.domain.type === \"cardTarget\" &&\n (!options?.input || input.key === options.input) &&\n input.getIsEligible(this.id),\n ),\n );\n }\n select(options?: RuntimeTargetOptions) {\n if (this.epoch !== this.owner.epoch || this.owner.disposed) return;\n this.owner.selectCard(this.id, options);\n }\n getSelectHandler(options?: RuntimeTargetOptions) {\n return () => this.select(options);\n }\n getProps(options?: RuntimeTargetOptions) {\n return {\n type: \"button\" as const,\n disabled: !this.getCanSelect(options),\n \"data-action\": \"select\",\n \"data-value\": this.id,\n \"data-interaction\": options?.interaction,\n \"data-input\": options?.input,\n \"data-eligible\": this.getIsEligible(),\n \"data-selected\": this.getIsSelected(),\n \"data-disabled\": !this.getCanSelect(options),\n \"data-hidden\": this.hidden,\n \"data-seat\": this.seat,\n onClick: this.getSelectHandler(options),\n };\n }\n}\nclass ZoneObject {\n constructor(\n readonly owner: Controller,\n readonly id: string,\n readonly cards: readonly CardObject[],\n ) {}\n get game() {\n return this.owner.instance;\n }\n get count() {\n return this.cards.length;\n }\n getIsEmpty() {\n return this.count === 0;\n }\n getCard(id: string) {\n return requireLookup(this.findCard(id), `Card in zone ${this.id}`, id);\n }\n findCard(id: string) {\n return this.cards.find((card) => card.id === id);\n }\n getCards(options?: { sort?: (a: CardObject, b: CardObject) => number }) {\n return options?.sort ? [...this.cards].sort(options.sort) : this.cards;\n }\n}\nclass PlayerObject {\n readonly id: string;\n readonly name: string;\n readonly color?: string;\n constructor(\n readonly owner: Controller,\n summary: SourceSnapshot[\"players\"][number],\n readonly index: number,\n readonly isMe: boolean,\n readonly active: boolean,\n ) {\n this.id = summary.playerId;\n this.name = summary.displayName;\n this.color = summary.color;\n }\n get game() {\n return this.owner.instance;\n }\n}\nclass PhaseObject {\n constructor(readonly current: string | null) {}\n is(name: string) {\n return this.current === name;\n }\n switch<R>(routes: Record<string, () => R>): R | null {\n return this.current === null ? null : routes[this.current]();\n }\n}\n\ninterface RuntimeModel {\n readonly snapshot: SourceSnapshot | null;\n readonly view: SourceSnapshot[\"frame\"][\"view\"] | null;\n readonly version: number | null;\n readonly connection: SourceState[\"connection\"];\n readonly request: SourceState[\"request\"];\n readonly failure: SourceState[\"failure\"];\n readonly state: {\n readonly drafts: DraftMap;\n readonly activeInteraction: string | null;\n };\n readonly phase: PhaseObject;\n readonly turn: {\n readonly activePlayerIds: readonly string[];\n readonly currentPlayerId: string | null;\n readonly order: readonly string[];\n readonly isMine: boolean;\n };\n readonly me: {\n readonly id: string;\n readonly player: PlayerObject;\n getCanAct(): boolean;\n } | null;\n readonly players: RuntimeCollection<PlayerObject> & {\n readonly order: readonly string[];\n next(id: string): PlayerObject;\n };\n readonly interactions: {\n get(key: string): InteractionObject;\n find(key: string): InteractionObject | undefined;\n list(): readonly InteractionObject[];\n listAvailable(): readonly InteractionObject[];\n };\n readonly inputs: {\n get(key: string, name: string): InputObject;\n find(key: string, name: string): InputObject | undefined;\n };\n readonly zones: RuntimeCollection<ZoneObject>;\n readonly cards: Pick<RuntimeCollection<CardObject>, \"get\" | \"find\">;\n readonly events: { readonly recent: SourceSnapshot[\"frame\"][\"events\"] };\n}\ninterface RuntimeCore extends RuntimeModel {\n readonly store: Pick<\n ReturnType<typeof createStore<RuntimeModel>>,\n \"get\" | \"subscribe\"\n >;\n getSnapshot(): RuntimeModel;\n getOptions(): RuntimeOptions;\n setOptions(options: RuntimeOptions): void;\n subscribe(listener: () => void): () => void;\n dispose(): void;\n assertCoverage(): void;\n inspect(): RuntimeModel;\n}\ninterface RuntimeContext extends Omit<\n RuntimeFeatureContext,\n \"game\" | \"getBoards\"\n> {\n readonly [runtimeFeatures]: RuntimeFeatureContext;\n}\n\nclass Controller {\n epoch = 0;\n options: RuntimeOptions;\n localDrafts: DraftMap;\n localActive: string | null;\n disposed = false;\n readonly instance: RuntimeCore;\n readonly store: ReturnType<typeof createStore<RuntimeModel>>;\n readonly prototypes = {\n interaction: Object.create(InteractionObject.prototype) as object,\n input: Object.create(InputObject.prototype) as object,\n card: Object.create(CardObject.prototype) as object,\n zone: Object.create(ZoneObject.prototype) as object,\n board: {},\n };\n subscription: { unsubscribe(): void } | undefined;\n sourceState: SourceState;\n reportedFailures = new WeakMap<GameSource, Readonly<Error>>();\n pending: {\n source: GameSource;\n key: string;\n draft: Values;\n revision: number;\n version: number;\n epoch: number;\n accepted: boolean;\n cancel: boolean;\n } | null = null;\n building: RuntimeModel | undefined;\n rootProperties = new Map<PropertyKey, PropertyDescriptor>();\n featureDisposals: (() => void)[] = [];\n warned = new Set<string>();\n invalidControlledState: RuntimeOptions[\"state\"] | undefined;\n observed = new Set<string>();\n revisions = new Map<string, number>();\n lastDrafts: DraftMap = EMPTY_DRAFTS;\n lastInteractions: readonly InteractionObject[] = [];\n lastSnapshotDrafts: DraftMap | undefined;\n trackDrafts() {\n const drafts = this.drafts();\n for (const key of new Set([\n ...Object.keys(this.lastDrafts),\n ...Object.keys(drafts),\n ]))\n if (this.lastDrafts[key] !== drafts[key])\n this.revisions.set(key, (this.revisions.get(key) ?? 0) + 1);\n this.lastDrafts = drafts;\n }\n constructor(\n options: RuntimeOptions,\n features?: (core: RuntimeCore, context: RuntimeContext) => Features,\n ) {\n this.options = options;\n this.localDrafts = options.initialState?.drafts ?? EMPTY_DRAFTS;\n this.localActive = options.initialState?.activeInteraction ?? null;\n this.sourceState = options.source.store.get();\n const current = () => this.building ?? this.store.get();\n const root: RuntimeCore = {\n get snapshot() {\n return current().snapshot;\n },\n get view() {\n return current().view;\n },\n get version() {\n return current().version;\n },\n get connection() {\n return current().connection;\n },\n get failure() {\n return current().failure;\n },\n get request() {\n return current().request;\n },\n get state() {\n return current().state;\n },\n get phase() {\n return current().phase;\n },\n get turn() {\n return current().turn;\n },\n get me() {\n return current().me;\n },\n get players() {\n return current().players;\n },\n get interactions() {\n return current().interactions;\n },\n get inputs() {\n return current().inputs;\n },\n get zones() {\n return current().zones;\n },\n get cards() {\n return current().cards;\n },\n get events() {\n return current().events;\n },\n store: {\n get: () => this.store.get(),\n subscribe: (listener: () => void) => this.store.subscribe(listener),\n },\n getSnapshot: () => this.building ?? this.store.get(),\n getOptions: () => this.options,\n setOptions: (next: RuntimeOptions) => this.setOptions(next),\n subscribe: (listener: () => void) => {\n const sub = this.store.subscribe(listener);\n return () => sub.unsubscribe();\n },\n dispose: () => this.dispose(),\n assertCoverage: () => this.assertCoverage(),\n inspect: () => this.store.get(),\n };\n // Keep live projections out of enumeration, spreads, and serialization.\n for (const [key, descriptor] of Object.entries(\n Object.getOwnPropertyDescriptors(root),\n )) {\n if (descriptor.get) {\n Object.defineProperty(root, key, {\n enumerable: false,\n configurable: false,\n });\n }\n }\n Object.defineProperty(root, \"store\", {\n enumerable: false,\n configurable: false,\n writable: false,\n });\n this.instance = root;\n this.store = createStore(Object.freeze(this.build()));\n if (\"apply\" in options.source)\n Object.defineProperty(root, \"apply\", {\n value: (action: unknown) =>\n (\n this.options.source as GameSource & {\n apply(action: unknown): unknown;\n }\n ).apply(action),\n });\n if (\"explore\" in options.source)\n Object.defineProperty(root, \"explore\", {\n value: (...args: unknown[]) =>\n (\n this.options.source as GameSource & {\n explore(...args: unknown[]): unknown;\n }\n ).explore(...args),\n });\n const runtime: RuntimeFeatureContext = {\n game: this.instance,\n getBoards: () => {\n // The materializer owns the reserved boards projection. Source/game binding\n // admits that projection once; feature algorithms never cast facade values.\n const view = this.instance.view as {\n boards?: Pick<RuntimeBoardCollections, \"byId\">;\n } | null;\n return view?.boards?.byId ?? {};\n },\n createBoard: (data: ReadonlyData<RuntimeBoardState>) =>\n this.object(\"board\", {\n id: data.id,\n data: immutableCopy(data),\n game: this.instance,\n }),\n routeTarget: (target, options) => this.routeTarget(target, options),\n routeCardDrop: (cardId, target) => this.routeCardDrop(cardId, target),\n invalidate: () => {\n if (!this.disposed) this.refresh();\n },\n };\n const context: RuntimeContext = { ...runtime, [runtimeFeatures]: runtime };\n for (const feature of Object.values(\n features?.(this.instance, context) ?? {},\n )) {\n if (feature.root)\n for (const key of Reflect.ownKeys(feature.root)) {\n if (key in root || this.rootProperties.has(key))\n throw new Error(`Overlapping feature property '${String(key)}'.`);\n this.rootProperties.set(\n key,\n Object.getOwnPropertyDescriptor(feature.root, key)!,\n );\n Object.defineProperty(root, key, {\n get: (): unknown =>\n Reflect.get(this.building ?? this.store.get(), key),\n });\n }\n for (const hook of [\n \"interaction\",\n \"input\",\n \"zone\",\n \"card\",\n \"board\",\n ] as const)\n this.install(this.prototypes[hook], feature[hook]);\n if (feature.dispose) this.featureDisposals.push(feature.dispose);\n }\n this.refresh();\n this.subscribeSource();\n this.reportSourceFailure();\n }\n install(target: object, extension: object | undefined) {\n if (!extension) return;\n for (const key of Reflect.ownKeys(extension)) {\n if (\n key in target ||\n [\n \"game\",\n \"owner\",\n \"descriptor\",\n \"draft\",\n \"inputObjects\",\n \"status\",\n \"connected\",\n \"key\",\n \"id\",\n \"phase\",\n \"label\",\n \"help\",\n \"kind\",\n \"interaction\",\n \"view\",\n \"hidden\",\n \"zone\",\n \"index\",\n \"routes\",\n \"cards\",\n ].includes(String(key))\n )\n throw new Error(`Overlapping feature property '${String(key)}'.`);\n }\n Object.defineProperties(\n target,\n Object.getOwnPropertyDescriptors(extension),\n );\n }\n object<T extends object>(hook: keyof Controller[\"prototypes\"], value: T): T {\n Object.setPrototypeOf(value, this.prototypes[hook]);\n return Object.freeze(value);\n }\n drafts() {\n if (\n this.options.state &&\n this.options.state === this.invalidControlledState\n )\n return EMPTY_DRAFTS;\n return this.options.state?.drafts ?? this.localDrafts;\n }\n active() {\n if (\n this.options.state &&\n this.options.state === this.invalidControlledState\n )\n return null;\n return this.options.state?.activeInteraction !== undefined\n ? this.options.state.activeInteraction\n : this.localActive;\n }\n writeDrafts(next: DraftMap) {\n if (this.options.state?.drafts === undefined) this.localDrafts = next;\n this.options.onDraftsChange?.(next);\n this.refresh();\n }\n writeDraft(key: string, value: Values | undefined) {\n const drafts = this.drafts();\n const next = { ...drafts };\n if (value === undefined) delete next[key];\n else next[key] = immutableValues(value);\n this.writeDrafts(Object.freeze(next));\n }\n activate(key: string | null) {\n if (this.disposed || (key !== null && !this.current(key))) return;\n if (this.options.state?.activeInteraction === undefined)\n this.localActive = key;\n this.options.onActiveInteractionChange?.(key);\n this.refresh();\n }\n descriptorFor(base: InteractionDescriptor, draft: Values) {\n const zones = this.sourceState.snapshot?.frame.zones ?? {};\n for (const input of base.inputs) {\n const card = draft[input.key];\n if (input.domain.type !== \"cardTarget\" || typeof card !== \"string\")\n continue;\n for (const zone of Object.values(zones)) {\n const route = zone.playableByCardId[card]?.find(\n (value) => value.interactionKey === base.interactionKey,\n );\n if (route) return route;\n }\n }\n return base;\n }\n current(key: string) {\n return this.store.get().interactions.find(key);\n }\n editable(key: string) {\n const interaction = this.current(key);\n return !this.disposed &&\n this.sourceState.connection === \"ready\" &&\n !this.sourceState.request &&\n interaction?.getIsAvailable()\n ? interaction\n : undefined;\n }\n setInput(key: string, inputKey: string, value: RuntimeJson) {\n const interaction = this.editable(key);\n if (!interaction?.findInput(inputKey)) return;\n this.writeDraft(key, { ...this.drafts()[key], [inputKey]: value });\n }\n clearInput(key: string, inputKey: string) {\n if (!this.editable(key)?.findInput(inputKey)) return;\n const value = { ...this.drafts()[key] };\n delete value[inputKey];\n this.writeDraft(key, value);\n }\n reset(key: string) {\n if (this.disposed) return;\n this.writeDraft(key, undefined);\n if (this.active() === key) this.activate(null);\n }\n select(\n key: string,\n inputKey: string,\n value: RuntimeJson,\n route?: InteractionObject,\n ) {\n const interaction = route ?? this.editable(key);\n if (\n route &&\n (!route.currentLifetime() ||\n !route.getIsAvailable() ||\n this.sourceState.connection !== \"ready\" ||\n this.sourceState.request ||\n this.pending)\n )\n return;\n const input = interaction?.findInput(inputKey);\n if (!interaction || !input?.getIsEligible(value)) return;\n if (\n isManyInput(input.descriptor) ||\n (typeof value === \"string\" &&\n (input.descriptor.domain.type === \"cardTarget\" ||\n input.descriptor.domain.type === \"boardTarget\"))\n ) {\n let next: Record<string, unknown> = { ...this.drafts()[key] };\n routeInteractionTarget(\n {\n getDraft: () => next,\n setInput: (_key, k, v) => {\n next = { ...next, [k]: v };\n },\n clearInput: (_key, k) => {\n if (k) delete next[k];\n },\n },\n interaction.descriptor,\n { inputKey, value },\n );\n this.writeDraft(key, next as Values);\n } else this.setInput(key, inputKey, value);\n this.activate(key);\n const current = this.current(key);\n if (\n current &&\n Object.hasOwn(this.drafts()[key] ?? EMPTY, inputKey) &&\n shouldAutoSubmitInteraction(current.descriptor) &&\n current.getIsReady()\n )\n this.handle(() => this.submit(key, false));\n }\n selectCard(id: string, options?: RuntimeTargetOptions) {\n const card = this.store.get().cards.find(id);\n if (\n !card ||\n this.sourceState.request ||\n this.sourceState.connection !== \"ready\"\n )\n return;\n const candidates = card.routes.flatMap((interaction) => {\n if (\n !interaction.getIsAvailable() ||\n !interaction.currentLifetime() ||\n (options?.interaction && interaction.key !== options.interaction)\n )\n return [];\n return interaction\n .getInputs()\n .filter(\n (input) =>\n input.descriptor.domain.type === \"cardTarget\" &&\n (!options?.input || input.key === options.input) &&\n input.getIsEligible(id),\n )\n .map((input) => ({ interaction, input }));\n });\n if (candidates.length > 1) throw new AmbiguousTargetError(id);\n const candidate = candidates[0];\n if (candidate)\n this.select(\n candidate.interaction.key,\n candidate.input.key,\n id,\n candidate.interaction,\n );\n }\n handle(submit: () => Promise<SubmitResult>) {\n const source = this.options.source;\n const active = () => !this.disposed && this.options.source === source;\n void submit().then(\n (result) => {\n if (active() && !result.accepted)\n this.options.onError?.(\n new Error(result.message ?? result.errorCode, { cause: result }),\n );\n },\n (error) => {\n if (!active()) return;\n const state = source.store.get();\n if (state.failure === error || state.connection === \"closed\") return;\n this.options.onError?.(error);\n },\n );\n }\n async submit(key: string, cancel: boolean): Promise<SubmitResult> {\n const source = this.options.source;\n const interaction = this.current(key);\n if (\n this.disposed ||\n this.sourceState.connection !== \"ready\" ||\n this.sourceState.request ||\n this.pending\n )\n return { accepted: false, errorCode: \"BUSY\" };\n if (!interaction) return { accepted: false, errorCode: \"UNAVAILABLE\" };\n if (\n cancel\n ? !interaction.getStep()?.canCancel\n : !interaction.getIsAvailable() || !interaction.getIsReady()\n )\n return { accepted: false, errorCode: \"UNAVAILABLE\" };\n if (!(\"submit\" in source) || !(\"cancel\" in source))\n return { accepted: false, errorCode: \"READ_ONLY\" };\n const commandSource = source as GameSource & {\n submit(id: string, params: RuntimeJson): Promise<SubmitResult>;\n cancel(id: string): Promise<SubmitResult>;\n };\n const operation = {\n source,\n key,\n draft: this.drafts()[key] ?? EMPTY,\n revision: this.revisions.get(key) ?? 0,\n version: this.sourceState.snapshot.version,\n epoch: this.epoch,\n accepted: false,\n cancel,\n };\n this.pending = operation;\n try {\n const result = await (cancel\n ? commandSource.cancel(interaction.id)\n : commandSource.submit(\n interaction.id,\n interaction.readiness().values as RuntimeJson,\n ));\n if (this.pending !== operation) return result;\n if (!result.accepted) {\n this.pending = null;\n this.refresh();\n return result;\n }\n operation.accepted = true;\n this.finishBarrier();\n return result;\n } catch (error) {\n if (this.pending === operation) {\n this.pending = null;\n this.refresh();\n }\n throw error;\n }\n }\n finishBarrier() {\n const operation = this.pending;\n if (\n !operation?.accepted ||\n this.sourceState.request ||\n operation.source !== this.options.source ||\n operation.epoch !== this.epoch\n )\n return;\n if (\n this.sourceState.connection === \"closed\" ||\n this.sourceState.connection === \"failed\"\n ) {\n this.pending = null;\n this.refresh();\n return;\n }\n if (\n this.sourceState.connection !== \"ready\" ||\n (this.sourceState.snapshot?.version ?? -1) <= operation.version\n )\n return;\n this.pending = null;\n if ((this.revisions.get(operation.key) ?? 0) === operation.revision)\n this.reset(operation.key);\n else this.refresh();\n }\n reportSourceFailure() {\n const failure = this.sourceState.failure;\n if (\n !failure ||\n !this.options.onError ||\n this.reportedFailures.get(this.options.source) === failure\n )\n return;\n this.reportedFailures.set(this.options.source, failure);\n this.options.onError?.(failure);\n }\n subscribeSource() {\n const source = this.options.source;\n this.subscription = source.store.subscribe(() => {\n if (this.disposed || this.options.source !== source) return;\n const next = source.store.get();\n const previousSnapshot = this.sourceState.snapshot;\n this.sourceState = next;\n if (\n previousSnapshot &&\n next.snapshot &&\n previousSnapshot.me !== next.snapshot.me\n ) {\n this.epoch++;\n this.invalidControlledState = this.options.state;\n this.pending = null;\n this.localDrafts = EMPTY_DRAFTS;\n this.localActive = null;\n this.options.onDraftsChange?.({});\n this.options.onActiveInteractionChange?.(null);\n }\n this.reconcile();\n this.refresh();\n this.finishBarrier();\n this.reportSourceFailure();\n });\n }\n setOptions(next: RuntimeOptions) {\n if (this.disposed) throw new Error(\"Game instance is disposed.\");\n const changed = next.source !== this.options.source;\n if (changed) {\n this.epoch++;\n this.subscription?.unsubscribe();\n this.options.source.dispose();\n this.pending = null;\n }\n this.options = next;\n if (changed) {\n this.invalidControlledState = next.state;\n this.localDrafts = EMPTY_DRAFTS;\n this.localActive = null;\n this.sourceState = next.source.store.get();\n this.options.onDraftsChange?.({});\n this.options.onActiveInteractionChange?.(null);\n this.subscribeSource();\n }\n this.reconcile();\n this.refresh();\n this.reportSourceFailure();\n }\n reconcile() {\n const snapshot = this.sourceState.snapshot;\n if (!snapshot) return;\n const drafts = this.drafts();\n let changed = false;\n const next: Record<string, Values | undefined> = { ...drafts };\n for (const [key, values] of Object.entries(drafts)) {\n if (!values) continue;\n const base = snapshot.frame.availableInteractions.find(\n (value) => value.interactionKey === key,\n );\n if (!base) {\n if (this.pending?.key !== key) {\n delete next[key];\n changed = true;\n }\n continue;\n }\n const descriptor = this.descriptorFor(base, values);\n const kept = { ...values };\n let fieldChanged = false;\n for (const [name, value] of Object.entries(values)) {\n const input = descriptor.inputs.find((input) => input.key === name);\n if (!input && this.pending?.key === key) continue;\n const selection = input && inputSelection(input);\n if (input && selection?.mode === \"many\" && Array.isArray(value)) {\n const eligible = value.filter((item) =>\n inputTargetInDomain(input.domain, item),\n );\n const max = selection.max;\n const retained =\n max === undefined ? eligible : eligible.slice(0, max);\n if (retained.length !== value.length) {\n kept[name] = retained;\n changed = true;\n fieldChanged = true;\n }\n continue;\n }\n if (!input || !inDomain(input, value, true)) {\n delete kept[name];\n changed = true;\n fieldChanged = true;\n }\n }\n if (fieldChanged) next[key] = immutableValues(kept);\n }\n if (changed) this.writeDrafts(Object.freeze(next));\n const active = this.active();\n if (\n active &&\n !snapshot.frame.availableInteractions.some(\n (value) => value.interactionKey === active,\n )\n )\n this.activate(null);\n }\n dispose() {\n if (this.disposed) return;\n this.disposed = true;\n this.featureDisposals.forEach((dispose) => dispose());\n this.subscription?.unsubscribe();\n this.pending = null;\n this.options.source.dispose();\n this.sourceState = this.options.source.store.get();\n this.refresh();\n }\n assertCoverage() {\n const missing =\n this.sourceState.snapshot?.frame.availableInteractions\n .filter(\n (d) =>\n d.availability.status === \"available\" &&\n !this.observed.has(d.interactionKey),\n )\n .map((d) => d.interactionKey) ?? [];\n if (missing.length)\n throw new Error(`Interactions not read: ${missing.join(\", \")}`);\n }\n routeTarget(target: RuntimeSelectionTarget, options?: RuntimeTargetOptions) {\n if (target.kind === \"card\") {\n this.selectCard(target.value, options);\n return;\n }\n const candidates = this.lastInteractions.flatMap((interaction) =>\n interaction\n .getInputs()\n .filter(\n (input) =>\n matchesBoardTarget(input.descriptor, target) &&\n input.getIsEligible(target.value) &&\n interaction.getIsAvailable() &&\n (!options?.interaction ||\n interaction.key === options.interaction) &&\n (!options?.input || input.key === options.input),\n )\n .map((input) => ({ interaction, input })),\n );\n if (candidates.length > 1)\n throw new AmbiguousTargetError(JSON.stringify(target.value));\n const match = candidates[0];\n if (match)\n this.select(match.interaction.key, match.input.key, target.value);\n }\n routeCardDrop(cardId: string, target: RuntimeDropTarget) {\n if (\n this.disposed ||\n this.sourceState.request ||\n this.pending ||\n this.sourceState.connection !== \"ready\"\n )\n return;\n const card = this.store.get().cards.find(cardId);\n const interaction = card?.routes.find(\n (route) => route.key === target.interactionKey,\n );\n if (!interaction?.currentLifetime() || !interaction.getIsAvailable())\n return;\n const cardInput = interaction.findInput(target.cardInputKey);\n if (\n !cardInput ||\n cardInput.descriptor.domain.type !== \"cardTarget\" ||\n !cardInput.getIsEligible(cardId)\n )\n return;\n const input =\n target.kind === \"interaction\"\n ? undefined\n : interaction.findInput(target.inputKey);\n if (\n target.kind !== \"interaction\" &&\n (!input ||\n !matchesBoardTarget(input.descriptor, target) ||\n !input.getIsEligible(target.value))\n )\n return;\n let next: Record<string, unknown> = { ...this.drafts()[interaction.key] };\n const chosen = next[cardInput.key];\n // Dropping adds a card; it never toggles an already chosen card back out.\n if (\n !input &&\n isManyInput(cardInput.descriptor) &&\n Array.isArray(chosen) &&\n chosen.includes(cardId)\n ) {\n this.activate(interaction.key);\n return;\n }\n routeCardInputIntent(\n {\n getDraft: () => next,\n setInput: (_key, key, value) => {\n next = { ...next, [key]: value };\n },\n clearInput: (_key, key) => {\n if (key) delete next[key];\n },\n },\n interaction.descriptor,\n {\n cardId,\n cardInputKey: cardInput.key,\n dropTarget:\n input && target.kind !== \"interaction\"\n ? { inputKey: input.key, value: target.value }\n : undefined,\n },\n );\n this.writeDraft(interaction.key, next as Values);\n this.activate(interaction.key);\n const current = this.current(interaction.key);\n if (\n current &&\n shouldAutoSubmitInteraction(current.descriptor) &&\n current.getIsReady()\n )\n this.handle(() => current.submit());\n }\n warnUnread() {\n const environment =\n (import.meta as { env?: { DEV?: boolean } }).env?.DEV ??\n (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env\n ?.NODE_ENV === \"development\";\n if (!(this.options.debug ?? environment)) return;\n queueMicrotask(() => {\n if (this.disposed) return;\n for (const descriptor of this.sourceState.snapshot?.frame\n .availableInteractions ?? []) {\n const key = descriptor.interactionKey;\n if (\n descriptor.availability.status === \"available\" &&\n !this.observed.has(key) &&\n !this.warned.has(key)\n ) {\n this.warned.add(key);\n console.warn(`Available interaction '${key}' has not been read.`);\n }\n }\n });\n }\n build(previous?: RuntimeModel): RuntimeModel {\n this.trackDrafts();\n const { snapshot, connection, request, failure } = this.sourceState;\n const old = previous?.snapshot;\n const drafts = this.drafts();\n const active = this.active();\n const sameSnapshot = snapshot === old;\n const sameActors = sameSnapshot;\n const summaries = snapshot?.players ?? [];\n const activeIds = snapshot?.frame.flow.activePlayers ?? [];\n const playerObjects =\n sameActors && previous\n ? previous.players.getAll()\n : Object.freeze(\n summaries.map((player, index) =>\n Object.freeze(\n new PlayerObject(\n this,\n player,\n index,\n player.playerId === snapshot?.me,\n activeIds.includes(player.playerId),\n ),\n ),\n ),\n );\n const players =\n sameActors && previous\n ? previous.players\n : {\n order: Object.freeze(playerObjects.map((p) => p.id)),\n get: (id: string) =>\n requireLookup(\n playerObjects.find((p) => p.id === id),\n \"Player\",\n id,\n ),\n find: (id: string) => playerObjects.find((p) => p.id === id),\n getAll: () => playerObjects,\n next: (id: string) => {\n const index = playerObjects.findIndex((p) => p.id === id);\n return requireLookup(\n index < 0\n ? undefined\n : playerObjects[(index + 1) % playerObjects.length],\n \"Next player after\",\n id,\n );\n },\n };\n const me =\n sameActors && previous\n ? previous.me\n : snapshot\n ? {\n id: snapshot.me,\n player: players.get(snapshot.me),\n getCanAct: () =>\n snapshot.frame.availableInteractions.some(\n (value) => value.availability.status === \"available\",\n ),\n }\n : null;\n const descriptors = snapshot?.frame.availableInteractions ?? [];\n const interactionObjects = descriptors.map((base) => {\n const key = base.interactionKey;\n const draft = drafts[key] ?? EMPTY;\n const descriptor = this.descriptorFor(base, draft);\n const status =\n request || this.pending\n ? request?.interactionId === descriptor.interactionId &&\n request.phase === \"awaiting-frame\"\n ? \"submitted\"\n : \"submitting\"\n : \"open\";\n const oldObject = this.lastInteractions.find(\n (value) => value.key === key,\n );\n return oldObject?.descriptor === descriptor &&\n oldObject.epoch === this.epoch &&\n oldObject.source === this.options.source &&\n oldObject.draftIdentity === draft &&\n oldObject.status === status &&\n oldObject.connected === (connection === \"ready\")\n ? oldObject\n : this.object(\n \"interaction\",\n new InteractionObject(\n this,\n descriptor,\n draft,\n status,\n connection === \"ready\",\n ),\n );\n });\n const interactionsSame =\n previous &&\n interactionObjects.length === this.lastInteractions.length &&\n interactionObjects.every(\n (value, index) => value === this.lastInteractions[index],\n );\n this.lastInteractions = Object.freeze(interactionObjects);\n const interactions = interactionsSame\n ? previous.interactions\n : {\n get: (key: string) => {\n this.observed.add(key);\n return requireLookup(\n interactionObjects.find((value) => value.key === key),\n \"Interaction\",\n key,\n );\n },\n find: (key: string) => {\n this.observed.add(key);\n return interactionObjects.find((value) => value.key === key);\n },\n list: () => {\n interactionObjects.forEach((value) => this.observed.add(value.key));\n return Object.freeze(interactionObjects);\n },\n listAvailable: () => {\n const available = interactionObjects.filter((value) =>\n value.getIsAvailable(),\n );\n available.forEach((value) => this.observed.add(value.key));\n return Object.freeze(available);\n },\n };\n const inputs =\n interactionsSame && previous\n ? previous.inputs\n : {\n get: (key: string, name: string) =>\n requireLookup(\n interactions.find(key)?.findInput(name),\n `Input in interaction ${key}`,\n name,\n ),\n find: (key: string, name: string) =>\n interactions.find(key)?.findInput(name),\n };\n const zonesSame = sameSnapshot && interactionsSame && previous;\n const zones = zonesSame\n ? previous.zones\n : (() => {\n const objects = Object.entries(snapshot?.frame.zones ?? {}).map(\n ([id, zone]) =>\n this.object(\n \"zone\",\n new ZoneObject(\n this,\n id,\n Object.freeze(\n zone.cardIds.map((cardId, index) =>\n this.object(\n \"card\",\n new CardObject(\n this,\n cardId,\n id,\n index,\n zone.cardViewsById[cardId],\n zone.cardBacksById[cardId],\n Object.freeze(\n (zone.playableByCardId[cardId] ?? []).map(\n (descriptor) =>\n this.object(\n \"interaction\",\n new InteractionObject(\n this,\n descriptor,\n drafts[descriptor.interactionKey] ?? EMPTY,\n request || this.pending\n ? \"submitting\"\n : \"open\",\n connection === \"ready\",\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n );\n return {\n get: (id: string) =>\n requireLookup(\n objects.find((zone) => zone.id === id),\n \"Zone\",\n id,\n ),\n find: (id: string) => objects.find((zone) => zone.id === id),\n getAll: () => Object.freeze(objects),\n };\n })();\n const cards = zonesSame\n ? previous.cards\n : {\n get: (id: string) =>\n requireLookup(\n zones\n .getAll()\n .map((zone) => zone.findCard(id))\n .find((card) => card !== undefined),\n \"Card\",\n id,\n ),\n find: (id: string) =>\n zones\n .getAll()\n .map((zone) => zone.findCard(id))\n .find((card) => card !== undefined),\n };\n const capturedState =\n this.lastSnapshotDrafts === drafts &&\n previous?.state.activeInteraction === active\n ? previous.state\n : immutableCopy({ drafts, activeInteraction: active });\n this.lastSnapshotDrafts = drafts;\n for (const value of [players, me, interactions, inputs, zones, cards])\n if (value) Object.freeze(value);\n const model: RuntimeModel = {\n snapshot,\n view: snapshot?.frame.view ?? null,\n version: snapshot?.version ?? null,\n connection,\n request,\n failure,\n state: capturedState,\n phase:\n sameSnapshot && previous\n ? previous.phase\n : Object.freeze(\n new PhaseObject(snapshot?.frame.flow.currentPhase ?? null),\n ),\n turn:\n sameSnapshot && previous\n ? previous.turn\n : Object.freeze({\n activePlayerIds: activeIds,\n currentPlayerId: activeIds.length === 1 ? activeIds[0] : null,\n order: players.order,\n isMine: snapshot ? activeIds.includes(snapshot.me) : false,\n }),\n me,\n players,\n interactions,\n inputs,\n zones,\n cards,\n events:\n sameSnapshot && previous\n ? previous.events\n : Object.freeze({\n recent: snapshot?.frame.events ?? Object.freeze([]),\n }),\n };\n this.building = model;\n try {\n for (const [key, descriptor] of this.rootProperties)\n Object.defineProperty(model, key, {\n value: descriptor.get\n ? descriptor.get.call(this.instance)\n : descriptor.value,\n enumerable: true,\n });\n } finally {\n this.building = undefined;\n }\n return model;\n }\n refresh() {\n if (!this.store) return;\n this.store.setState((previous) => Object.freeze(this.build(previous)));\n this.warnUnread();\n }\n}\nexport function createGameInstance<G>() {\n return function <\n const F extends Features = Record<never, never>,\n S extends GameSource = GameSource,\n >(\n options: InstanceOptions<G, S> & {\n features?: (core: CoreInstance<G>, context: FeatureContext<G>) => F;\n },\n ): GameInstance<G, F, S> {\n // Composition boundary: callers bind this source and feature callbacks to G.\n // Runtime classes keep concrete descriptor contracts; only this facade exposes G/F.\n const controller = new Controller(\n options as RuntimeOptions,\n options.features as\n ((core: RuntimeCore, context: RuntimeContext) => Features) | undefined,\n );\n // eslint-disable-next-line no-restricted-syntax -- Controller construction binds this source and feature map to the public G/F/S facade.\n return controller.instance as unknown as GameInstance<G, F, S>;\n };\n}\n","import type {\n InteractionDescriptor,\n InteractionInputDescriptor,\n InputSelection,\n} from \"../shared/protocol/frame.js\";\nimport { inputDomainErrors, inputValueKey } from \"../shared/input-domain.js\";\nimport type { RuntimeJson } from \"../shared/runtime-json.js\";\n\nexport function interactionInputKeys(\n descriptor: Pick<InteractionDescriptor, \"inputs\">,\n): string[] {\n return descriptor.inputs.map((input) => input.key);\n}\n\nexport function applyInteractionInputDefaults<\n Params extends Record<string, unknown>,\n>(\n descriptor: Pick<InteractionDescriptor, \"inputs\" | \"step\">,\n params: Readonly<Partial<Params>>,\n): Partial<Params> {\n const next: Record<string, unknown> = descriptor.step\n ? Object.fromEntries(\n Object.entries(params).filter(([key]) =>\n descriptor.inputs.some((input) => input.key === key),\n ),\n )\n : { ...params };\n for (const input of descriptor.inputs) {\n if (next[input.key] !== undefined) continue;\n if (!(\"defaultValue\" in input)) continue;\n next[input.key] = input.defaultValue;\n }\n return next as Partial<Params>;\n}\n\nexport function validateInteractionInputDomains(\n descriptor: Pick<InteractionDescriptor, \"inputs\">,\n params: Readonly<Record<string, unknown>>,\n): Partial<Record<string, readonly string[]>> {\n const fieldErrors: Record<string, string[]> = {};\n\n for (const rawInput of descriptor.inputs) {\n const input = rawInput;\n const value = params[input.key];\n if (value === undefined) continue;\n for (const error of inputDomainErrors(\n input.domain,\n value,\n input.domain.selection,\n ))\n pushFieldError(fieldErrors, input.key, error);\n }\n\n return fieldErrors;\n}\n\nexport function isInputValueReady(\n input: InteractionInputDescriptor,\n value: unknown,\n): boolean {\n if (value === undefined) return false;\n if (value === null)\n return (\n input.domain.type === \"choice\" &&\n (input.domain.choices ?? []).some(\n (choice) => choice.value === null && !choice.disabled,\n )\n );\n const selection = inputSelection(input);\n if (selection?.mode !== \"many\") return true;\n return Array.isArray(value) && value.length >= selection.min;\n}\n\nexport function isManyInput(input: InteractionInputDescriptor): boolean {\n return inputSelection(input)?.mode === \"many\";\n}\n\nexport function toggleManyValue(\n current: unknown,\n value: RuntimeJson,\n selection: InputSelection,\n): RuntimeJson[] {\n if (selection.mode !== \"many\") return [value];\n const previous = Array.isArray(current) ? (current as RuntimeJson[]) : [];\n const existing = previous.findIndex((item) => sameValue(item, value));\n if (existing >= 0) {\n return previous.filter((item) => !sameValue(item, value));\n }\n if (selection.max !== undefined && previous.length >= selection.max) {\n return previous;\n }\n return [...previous, value];\n}\n\nexport function isManyTargetSelectable(\n input: InteractionInputDescriptor,\n current: unknown,\n targetId: RuntimeJson,\n): boolean {\n const selection = inputSelection(input);\n if (selection?.mode !== \"many\") return true;\n const currentValues = Array.isArray(current)\n ? (current as RuntimeJson[])\n : [];\n if (currentValues.some((item) => sameValue(item, targetId))) return true;\n return selection.max === undefined || currentValues.length < selection.max;\n}\n\nexport function hasInteractionFieldErrors(\n fieldErrors: Partial<Record<string, readonly string[]>>,\n): boolean {\n return Object.values(fieldErrors).some(\n (messages) => (messages?.length ?? 0) > 0,\n );\n}\n\nexport function inputByKey(\n descriptor: Pick<InteractionDescriptor, \"inputs\">,\n key: string,\n): InteractionInputDescriptor | undefined {\n return descriptor.inputs.find((input) => input.key === key);\n}\n\nexport function inputSelection(\n input: InteractionInputDescriptor,\n): InputSelection | undefined {\n if (input.domain.selection) return input.domain.selection;\n // choiceList is already an array domain; expose its selection bounds for toggling and reconciliation.\n if (input.domain.type === \"choiceList\")\n return {\n mode: \"many\",\n min: input.domain.min ?? 0,\n max: input.domain.max ?? input.domain.choices.length,\n };\n return undefined;\n}\n\nfunction pushFieldError(\n fieldErrors: Record<string, string[]>,\n key: string,\n message: string,\n): void {\n fieldErrors[key] = [...(fieldErrors[key] ?? []), message];\n}\n\nfunction sameValue(left: RuntimeJson, right: RuntimeJson): boolean {\n return inputValueKey(left) === inputValueKey(right);\n}\n","import type { InteractionDescriptor } from \"../shared/protocol/frame.js\";\nimport {\n applyInteractionInputDefaults,\n hasInteractionFieldErrors,\n inputByKey,\n interactionInputKeys,\n inputSelection,\n isInputValueReady,\n toggleManyValue,\n validateInteractionInputDomains,\n} from \"./interaction-inputs.js\";\nimport type { RuntimeJson } from \"../shared/runtime-json.js\";\n\nexport interface InteractionDraftMutation {\n key: string;\n value: unknown;\n}\n\nexport interface InteractionDraftReadiness {\n values: Record<string, unknown>;\n missingInputs: readonly string[];\n fieldErrors: Partial<Record<string, readonly string[]>>;\n ready: boolean;\n}\n\nexport interface RoutedInteractionTarget {\n inputKey: string;\n value: RuntimeJson;\n extraInputs?: Record<string, unknown>;\n}\n\nexport interface RoutedCardInputIntent {\n cardInputKey: string;\n cardId: string;\n dropTarget?: {\n inputKey: string;\n value: RuntimeJson;\n };\n}\n\nexport interface RoutedInteractionTargetResult {\n params: Record<string, unknown>;\n readiness: InteractionDraftReadiness;\n}\n\nexport function applyInteractionDraftMutation(\n store: DraftStore,\n descriptor: InteractionDescriptor,\n mutations: readonly InteractionDraftMutation[],\n): Record<string, unknown> {\n const originalDraft: Record<string, unknown> = {\n ...store.getDraft(descriptor.interactionKey),\n };\n const nextDraft: Record<string, unknown> = {\n ...originalDraft,\n };\n\n const currentKeys = new Set(interactionInputKeys(descriptor));\n for (const { key, value } of mutations) {\n if (!descriptor.step || currentKeys.has(key)) nextDraft[key] = value;\n }\n if (descriptor.step) {\n for (const key of Object.keys(nextDraft))\n if (!currentKeys.has(key)) delete nextDraft[key];\n }\n\n const allKeys = new Set([\n ...Object.keys(originalDraft),\n ...Object.keys(nextDraft),\n ]);\n for (const key of allKeys) {\n if (!(key in nextDraft)) {\n store.clearInput(descriptor.interactionKey, key);\n continue;\n }\n if (originalDraft[key] !== nextDraft[key]) {\n store.setInput(descriptor.interactionKey, key, nextDraft[key]);\n }\n }\n\n return nextDraft;\n}\n\nexport function getInteractionDraftReadiness(\n descriptor: InteractionDescriptor,\n draft: Readonly<Record<string, unknown>>,\n): InteractionDraftReadiness {\n const values = applyInteractionInputDefaults<Record<string, unknown>>(\n descriptor,\n draft,\n ) as Record<string, unknown>;\n const missingInputs = interactionInputKeys(descriptor).filter((key) => {\n const input = inputByKey(descriptor, key);\n const value = values[key];\n return input\n ? !isInputValueReady(input, value)\n : value === null || value === undefined;\n });\n const fieldErrors = validateInteractionInputDomains(descriptor, values);\n return {\n values,\n missingInputs,\n fieldErrors,\n ready:\n missingInputs.length === 0 && !hasInteractionFieldErrors(fieldErrors),\n };\n}\n\nexport function routeInteractionTarget(\n store: DraftStore,\n descriptor: InteractionDescriptor,\n target: RoutedInteractionTarget,\n): RoutedInteractionTargetResult {\n const input = inputByKey(descriptor, target.inputKey);\n const currentDraft = store.getDraft(descriptor.interactionKey);\n const selection = input ? inputSelection(input) : undefined;\n const targetValue =\n selection?.mode === \"many\"\n ? toggleManyValue(\n currentDraft[target.inputKey] ?? input?.defaultValue,\n target.value,\n selection,\n )\n : target.value;\n const params = applyInteractionDraftMutation(store, descriptor, [\n ...Object.entries(target.extraInputs ?? {}).map(([key, value]) => ({\n key,\n value,\n })),\n { key: target.inputKey, value: targetValue },\n ]);\n return {\n params,\n readiness: getInteractionDraftReadiness(descriptor, params),\n };\n}\n\nexport function routeCardInputIntent(\n store: DraftStore,\n descriptor: InteractionDescriptor,\n intent: RoutedCardInputIntent,\n): RoutedInteractionTargetResult {\n return routeInteractionTarget(store, descriptor, {\n inputKey: intent.cardInputKey,\n value: intent.cardId,\n extraInputs: intent.dropTarget\n ? { [intent.dropTarget.inputKey]: intent.dropTarget.value }\n : undefined,\n });\n}\n\nexport function shouldAutoSubmitInteraction(\n descriptor: InteractionDescriptor,\n): boolean {\n return (\n descriptor.commit.mode === \"autoWhenReady\" &&\n !descriptor.inputs.some((input) => input.domain.selection?.mode === \"many\")\n );\n}\n\ninterface DraftStore {\n getDraft(key: string): Record<string, unknown>;\n setInput(interaction: string, key: string, value: unknown): void;\n clearInput(interaction: string, key: string): void;\n}\n","import type { Point } from \"./features/pointer-session.js\";\n\n/** Measured with emulated touch; confirm on physical devices before changing. */\nexport const GESTURE_THRESHOLDS = Object.freeze({\n /** Movement, in CSS pixels, before a press becomes a drag or a browse. */\n slop: 8,\n /** A touch or pen held this long without moving inspects the card. */\n holdMs: 350,\n /** A mouse resting on a card this long inspects it. */\n hoverMs: 250,\n /** A finger drags when upward travel exceeds this multiple of sideways travel. */\n axisBias: 1.25,\n});\n\nexport interface GesturePointer {\n readonly pointerId: number;\n readonly pointerType: string;\n readonly clientX: number;\n readonly clientY: number;\n}\n\n/**\n * How a press ended. A tap leaves selection to the native click; a hold\n * inspected the card; a browse handed sideways movement to native scrolling.\n */\nexport type GestureKind = \"tap\" | \"hold\" | \"drag\" | \"browse\";\n\nexport interface GestureCallbacks {\n /** A touch or pen stayed still for `holdMs`. */\n hold(): void;\n /** Return false when the card cannot be dragged; the press then browses. */\n dragStart(origin: Point): boolean;\n dragMove(point: Point): void;\n /** The pointer lifted. */\n end(kind: GestureKind, point: Point): void;\n /** The browser or the caller cancelled. A cancelled drag never drops. */\n cancel(kind: GestureKind): void;\n}\n\nexport interface GestureRecognizer {\n move(event: GesturePointer): void;\n up(event: GesturePointer): void;\n cancel(event?: Pick<GesturePointer, \"pointerId\">): void;\n}\n\nexport interface GestureOptions {\n /** Hands keep sideways scrolling; piles can be dragged toward any destination. */\n readonly dragDirection?: \"up\" | \"any\";\n}\n\n/**\n * Classifies one press. A mouse drags in any direction and never holds. A\n * finger drags upward, browses sideways and holds when still, so cards can use\n * `touch-action: pan-x` and keep native sideways scrolling.\n */\nexport function createGestureRecognizer(\n down: GesturePointer,\n callbacks: GestureCallbacks,\n options: GestureOptions = {},\n): GestureRecognizer {\n const origin = { x: down.clientX, y: down.clientY };\n const mouse = down.pointerType === \"mouse\";\n let kind: GestureKind = \"tap\";\n let finished = false;\n const holdTimer = mouse\n ? undefined\n : setTimeout(() => {\n kind = \"hold\";\n callbacks.hold();\n }, GESTURE_THRESHOLDS.holdMs);\n const point = (event: GesturePointer) => ({\n x: event.clientX,\n y: event.clientY,\n });\n const ours = (event?: Pick<GesturePointer, \"pointerId\">) =>\n !finished && (!event || event.pointerId === down.pointerId);\n function finish() {\n finished = true;\n clearTimeout(holdTimer);\n }\n return {\n move(event) {\n if (!ours(event)) return;\n if (kind === \"drag\") return callbacks.dragMove(point(event));\n const dx = event.clientX - origin.x;\n const dy = event.clientY - origin.y;\n if (kind !== \"tap\" || Math.hypot(dx, dy) < GESTURE_THRESHOLDS.slop)\n return;\n clearTimeout(holdTimer);\n const lifts =\n mouse ||\n options.dragDirection === \"any\" ||\n -dy > GESTURE_THRESHOLDS.axisBias * Math.abs(dx);\n if (lifts && callbacks.dragStart(origin)) {\n kind = \"drag\";\n callbacks.dragMove(point(event));\n } else kind = \"browse\";\n },\n up(event) {\n if (!ours(event)) return;\n finish();\n callbacks.end(kind, point(event));\n },\n cancel(event) {\n if (!ours(event)) return;\n finish();\n callbacks.cancel(kind);\n },\n };\n}\n","import { inputValueKey } from \"../shared/input-domain.js\";\nimport type { RuntimeDropTarget } from \"./targets.js\";\n\n/** Targets are rebuilt with every frame; compare their route and destination. */\nexport function isSameDropTarget(\n left: RuntimeDropTarget,\n right: RuntimeDropTarget,\n): boolean {\n if (\n left.interactionKey !== right.interactionKey ||\n left.cardInputKey !== right.cardInputKey\n )\n return false;\n if (left.kind === \"interaction\" || right.kind === \"interaction\")\n return left.kind === right.kind;\n return (\n left.kind === right.kind &&\n left.valueKind === right.valueKind &&\n inputValueKey(left.value) === inputValueKey(right.value) &&\n (left.valueKind !== \"board-id\" ||\n (right.valueKind === \"board-id\" && left.boardId === right.boardId)) &&\n left.inputKey === right.inputKey\n );\n}\n"],"mappings":";;;;;;;;;;;;AAmBO,IAAM,kBAAkB,uBAAO,iBAAiB;;;AC6BvD,SAAS,cACP,QACA,OACwB;AACxB,QAAM,SACJ,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC/D,QACA,CAAC;AACP,SAAO,OAAO;AAAA,IACZ,OAAO,UAAU,IAAI,CAAC,aAAa;AACjC,YAAM,SAAS,OAAO,SAAS,UAAU;AACzC,aAAO,CAAC,SAAS,YAAY,OAAO,WAAW,WAAW,SAAS,CAAC;AAAA,IACtE,CAAC;AAAA,EACH;AACF;AACO,SAAS,mBACd,OACA,OACc;AACd,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,UAAU,MAAM,SAAS;AAC/B,QAAM,SAAS,EAAE,KAAK,MAAM,KAAK,UAAU,MAAM,UAAU,MAAM;AACjE,MAAI,OAAO,SAAS,iBAAiB;AACnC,QAAI,OAAO,WAAW,SAAS;AAC7B,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM;AAAA,QACN;AAAA,QACA,MAAM;AAAA,QACN,OAAO,MAAM,QAAQ,OAAO,IACxB,QAAQ;AAAA,UACN,CAAC,UAA2B,OAAO,UAAU;AAAA,QAC/C,IACA,CAAC;AAAA,QACL,UAAU,CAAC,UAAU,MAAM,SAAS,KAAK;AAAA,MAC3C;AACF,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,OAAO,OAAO,YAAY,WAAW,UAAU;AAAA,MAC/C,UAAU,CAAC,UACT,UAAU,SAAY,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK;AAAA,IAC9D;AAAA,EACF;AACA,MAAI,OAAO,SAAS,eAAe;AACjC,QAAI,OAAO,WAAW,SAAS;AAC7B,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM;AAAA,QACN;AAAA,QACA,MAAM;AAAA,QACN,OAAO,MAAM,QAAQ,OAAO,IACxB,QAAQ,IAAI,CAAC,UAAU,cAAc,QAAQ,KAAK,CAAC,IACnD,CAAC;AAAA,QACL,UAAU,CAAC,UAAU,MAAM,SAAS,KAAK;AAAA,MAC3C;AACF,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,OAAO,YAAY,SAAY,SAAY,cAAc,QAAQ,OAAO;AAAA,MACxE,UAAU,CAAC,UACT,UAAU,SAAY,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK;AAAA,IAC9D;AAAA,EACF;AACA,SAAO,EAAE,GAAG,QAAQ,MAAM,WAAW,SAAS,MAAM,iBAAiB,EAAE;AACzE;;;AClGA,SAAS,mBAAmB;;;ACXrB,SAAS,qBACd,YACU;AACV,SAAO,WAAW,OAAO,IAAI,CAAC,UAAU,MAAM,GAAG;AACnD;AAEO,SAAS,8BAGd,YACA,QACiB;AACjB,QAAM,OAAgC,WAAW,OAC7C,OAAO;AAAA,IACL,OAAO,QAAQ,MAAM,EAAE;AAAA,MAAO,CAAC,CAAC,GAAG,MACjC,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,QAAQ,GAAG;AAAA,IACrD;AAAA,EACF,IACA,EAAE,GAAG,OAAO;AAChB,aAAW,SAAS,WAAW,QAAQ;AACrC,QAAI,KAAK,MAAM,GAAG,MAAM,OAAW;AACnC,QAAI,EAAE,kBAAkB,OAAQ;AAChC,SAAK,MAAM,GAAG,IAAI,MAAM;AAAA,EAC1B;AACA,SAAO;AACT;AAEO,SAAS,gCACd,YACA,QAC4C;AAC5C,QAAM,cAAwC,CAAC;AAE/C,aAAW,YAAY,WAAW,QAAQ;AACxC,UAAM,QAAQ;AACd,UAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,QAAI,UAAU,OAAW;AACzB,eAAW,SAAS;AAAA,MAClB,MAAM;AAAA,MACN;AAAA,MACA,MAAM,OAAO;AAAA,IACf;AACE,qBAAe,aAAa,MAAM,KAAK,KAAK;AAAA,EAChD;AAEA,SAAO;AACT;AAEO,SAAS,kBACd,OACA,OACS;AACT,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,UAAU;AACZ,WACE,MAAM,OAAO,SAAS,aACrB,MAAM,OAAO,WAAW,CAAC,GAAG;AAAA,MAC3B,CAAC,WAAW,OAAO,UAAU,QAAQ,CAAC,OAAO;AAAA,IAC/C;AAEJ,QAAM,YAAY,eAAe,KAAK;AACtC,MAAI,WAAW,SAAS,OAAQ,QAAO;AACvC,SAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,UAAU,UAAU;AAC3D;AAEO,SAAS,YAAY,OAA4C;AACtE,SAAO,eAAe,KAAK,GAAG,SAAS;AACzC;AAEO,SAAS,gBACd,SACA,OACA,WACe;AACf,MAAI,UAAU,SAAS,OAAQ,QAAO,CAAC,KAAK;AAC5C,QAAM,WAAW,MAAM,QAAQ,OAAO,IAAK,UAA4B,CAAC;AACxE,QAAM,WAAW,SAAS,UAAU,CAAC,SAAS,UAAU,MAAM,KAAK,CAAC;AACpE,MAAI,YAAY,GAAG;AACjB,WAAO,SAAS,OAAO,CAAC,SAAS,CAAC,UAAU,MAAM,KAAK,CAAC;AAAA,EAC1D;AACA,MAAI,UAAU,QAAQ,UAAa,SAAS,UAAU,UAAU,KAAK;AACnE,WAAO;AAAA,EACT;AACA,SAAO,CAAC,GAAG,UAAU,KAAK;AAC5B;AAEO,SAAS,uBACd,OACA,SACA,UACS;AACT,QAAM,YAAY,eAAe,KAAK;AACtC,MAAI,WAAW,SAAS,OAAQ,QAAO;AACvC,QAAM,gBAAgB,MAAM,QAAQ,OAAO,IACtC,UACD,CAAC;AACL,MAAI,cAAc,KAAK,CAAC,SAAS,UAAU,MAAM,QAAQ,CAAC,EAAG,QAAO;AACpE,SAAO,UAAU,QAAQ,UAAa,cAAc,SAAS,UAAU;AACzE;AAEO,SAAS,0BACd,aACS;AACT,SAAO,OAAO,OAAO,WAAW,EAAE;AAAA,IAChC,CAAC,cAAc,UAAU,UAAU,KAAK;AAAA,EAC1C;AACF;AAEO,SAAS,WACd,YACA,KACwC;AACxC,SAAO,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,QAAQ,GAAG;AAC5D;AAEO,SAAS,eACd,OAC4B;AAC5B,MAAI,MAAM,OAAO,UAAW,QAAO,MAAM,OAAO;AAEhD,MAAI,MAAM,OAAO,SAAS;AACxB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,MAAM,OAAO,OAAO;AAAA,MACzB,KAAK,MAAM,OAAO,OAAO,MAAM,OAAO,QAAQ;AAAA,IAChD;AACF,SAAO;AACT;AAEA,SAAS,eACP,aACA,KACA,SACM;AACN,cAAY,GAAG,IAAI,CAAC,GAAI,YAAY,GAAG,KAAK,CAAC,GAAI,OAAO;AAC1D;AAEA,SAAS,UAAU,MAAmB,OAA6B;AACjE,SAAO,cAAc,IAAI,MAAM,cAAc,KAAK;AACpD;;;ACtGO,SAAS,8BACd,OACA,YACA,WACyB;AACzB,QAAM,gBAAyC;AAAA,IAC7C,GAAG,MAAM,SAAS,WAAW,cAAc;AAAA,EAC7C;AACA,QAAM,YAAqC;AAAA,IACzC,GAAG;AAAA,EACL;AAEA,QAAM,cAAc,IAAI,IAAI,qBAAqB,UAAU,CAAC;AAC5D,aAAW,EAAE,KAAK,MAAM,KAAK,WAAW;AACtC,QAAI,CAAC,WAAW,QAAQ,YAAY,IAAI,GAAG,EAAG,WAAU,GAAG,IAAI;AAAA,EACjE;AACA,MAAI,WAAW,MAAM;AACnB,eAAW,OAAO,OAAO,KAAK,SAAS;AACrC,UAAI,CAAC,YAAY,IAAI,GAAG,EAAG,QAAO,UAAU,GAAG;AAAA,EACnD;AAEA,QAAM,UAAU,oBAAI,IAAI;AAAA,IACtB,GAAG,OAAO,KAAK,aAAa;AAAA,IAC5B,GAAG,OAAO,KAAK,SAAS;AAAA,EAC1B,CAAC;AACD,aAAW,OAAO,SAAS;AACzB,QAAI,EAAE,OAAO,YAAY;AACvB,YAAM,WAAW,WAAW,gBAAgB,GAAG;AAC/C;AAAA,IACF;AACA,QAAI,cAAc,GAAG,MAAM,UAAU,GAAG,GAAG;AACzC,YAAM,SAAS,WAAW,gBAAgB,KAAK,UAAU,GAAG,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,6BACd,YACA,OAC2B;AAC3B,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,EACF;AACA,QAAM,gBAAgB,qBAAqB,UAAU,EAAE,OAAO,CAAC,QAAQ;AACrE,UAAM,QAAQ,WAAW,YAAY,GAAG;AACxC,UAAM,QAAQ,OAAO,GAAG;AACxB,WAAO,QACH,CAAC,kBAAkB,OAAO,KAAK,IAC/B,UAAU,QAAQ,UAAU;AAAA,EAClC,CAAC;AACD,QAAM,cAAc,gCAAgC,YAAY,MAAM;AACtE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,OACE,cAAc,WAAW,KAAK,CAAC,0BAA0B,WAAW;AAAA,EACxE;AACF;AAEO,SAAS,uBACd,OACA,YACA,QAC+B;AAC/B,QAAM,QAAQ,WAAW,YAAY,OAAO,QAAQ;AACpD,QAAM,eAAe,MAAM,SAAS,WAAW,cAAc;AAC7D,QAAM,YAAY,QAAQ,eAAe,KAAK,IAAI;AAClD,QAAM,cACJ,WAAW,SAAS,SAChB;AAAA,IACE,aAAa,OAAO,QAAQ,KAAK,OAAO;AAAA,IACxC,OAAO;AAAA,IACP;AAAA,EACF,IACA,OAAO;AACb,QAAM,SAAS,8BAA8B,OAAO,YAAY;AAAA,IAC9D,GAAG,OAAO,QAAQ,OAAO,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,MACjE;AAAA,MACA;AAAA,IACF,EAAE;AAAA,IACF,EAAE,KAAK,OAAO,UAAU,OAAO,YAAY;AAAA,EAC7C,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA,WAAW,6BAA6B,YAAY,MAAM;AAAA,EAC5D;AACF;AAEO,SAAS,qBACd,OACA,YACA,QAC+B;AAC/B,SAAO,uBAAuB,OAAO,YAAY;AAAA,IAC/C,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,aAAa,OAAO,aAChB,EAAE,CAAC,OAAO,WAAW,QAAQ,GAAG,OAAO,WAAW,MAAM,IACxD;AAAA,EACN,CAAC;AACH;AAEO,SAAS,4BACd,YACS;AACT,SACE,WAAW,OAAO,SAAS,mBAC3B,CAAC,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,WAAW,SAAS,MAAM;AAE9E;;;AF5FA,IAAM,QAAgB,OAAO,OAAO,CAAC,CAAC;AACtC,IAAM,eAAyB,OAAO,OAAO,CAAC,CAAC;AAC/C,IAAM,aAAa,CAAC,GAAY,MAC9B,OAAO,GAAG,GAAG,CAAC,KACb,OAAO,MAAM,YACZ,OAAO,MAAM,YACb,cAAc,CAAC,MAAM,cAAc,CAAC;AACxC,SAAS,SACP,OACA,OACA,UAAU,OACV;AACA,SAAO,mBAAmB,MAAM,QAAQ,OAAO,MAAM,OAAO,WAAW;AAAA,IACrE,eAAe;AAAA,EACjB,CAAC;AACH;AACA,SAAS,mBACP,OACA,QACA;AACA,QAAM,SAAS,MAAM;AACrB,SACE,OAAO,SAAS,iBAChB,OAAO,cAAc,OAAO,cAC3B,OAAO,eAAe,OAAO,QAC3B,OAAO,SAAS,WAAW,OAAO,eAAe,WACpD,OAAO,aACJ,OAAO,cAAc,aAAa,OAAO,UAAU,OAAO,MAAM;AAEvE;AACA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,cAAc,KAAK;AAC5B;AACA,SAAS,KACP,QACA,aACA,OACA,OACA;AACA,SAAO;AAAA,IACL,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,GAAI,QAAQ,EAAE,cAAc,MAAM,IAAI,CAAC;AAAA,IACvC,GAAI,UAAU,SACV,CAAC,IACD;AAAA,MACE,cACE,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AAAA,IAC5D;AAAA,EACN;AACF;AACO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,IAAY;AACtB;AAAA,MACE,WAAW,EAAE;AAAA,IACf;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,oBAAN,MAAwB;AAAA,EAatB,YACW,OACA,YACT,OACS,QACA,WACT;AALS;AACA;AAEA;AACA;AAET,SAAK,OACH,WAAW,aACX,MAAM,YAAY,UAAU,QAAQ;AAAA,MAClC,CAAC,WAAW,OAAO,aAAa,MAAM,YAAY,UAAU;AAAA,IAC9D,KACA;AACF,SAAK,gBAAgB;AACrB,SAAK,QAAQ,gBAAgB,KAAK;AAClC,SAAK,SAAS,MAAM,QAAQ;AAC5B,SAAK,QAAQ,MAAM;AACnB,SAAK,MAAM,WAAW;AACtB,SAAK,KAAK,WAAW;AACrB,SAAK,QAAQ,WAAW;AACxB,SAAK,QAAQ,WAAW;AACxB,SAAK,OAAO,WAAW;AACvB,SAAK,OAAO,WAAW,OAAO,UAAU;AACxC,SAAK,eAAe,OAAO;AAAA,MACzB,WAAW,OAAO;AAAA,QAAI,CAAC,UACrB,MAAM,OAAO,SAAS,IAAI,YAAY,MAAM,KAAK,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAAA,EA3BW;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAjBF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EA8BT,IAAI,OAAO;AACT,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EACA,kBAAkB;AAChB,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EACA,iBAAiB;AACf,WAAO,KAAK,WAAW,aAAa,WAAW;AAAA,EACjD;AAAA,EACA,uBAAuB;AACrB,WAAO,KAAK,WAAW,aAAa,WAAW,cAC3C,OACA,KAAK,WAAW,aAAa;AAAA,EACnC;AAAA,EACA,UAAU;AACR,WAAO,KAAK,WAAW,QAAQ;AAAA,EACjC;AAAA,EACA,eAAe;AACb,WAAO,KAAK,WAAW,MAAM,SAAS;AAAA,EACxC;AAAA,EACA,SAAS,KAAa;AACpB,WAAO;AAAA,MACL,KAAK,UAAU,GAAG;AAAA,MAClB,wBAAwB,KAAK,GAAG;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EACA,UAAU,KAAa;AACrB,WAAO,KAAK,aAAa,KAAK,CAAC,UAAU,MAAM,QAAQ,GAAG;AAAA,EAC5D;AAAA,EACA,YAAY;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EACA,YAAY;AACV,WAAO,6BAA6B,KAAK,YAAY,KAAK,KAAK;AAAA,EACjE;AAAA,EACA,aAAa;AACX,WAAO,KAAK,UAAU,EAAE;AAAA,EAC1B;AAAA,EACA,mBAAmB;AACjB,WAAO,KAAK,UAAU,EAAE;AAAA,EAC1B;AAAA,EACA,YAAY;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EACA,kBAAkB;AAChB,WACE,KAAK,WAAW,KAAK,MAAM,QAAQ,UACnC,KAAK,UAAU,KAAK,MAAM,SAC1B,CAAC,KAAK,MAAM;AAAA,EAEhB;AAAA,EACA,SAAS;AACP,WAAO,KAAK,gBAAgB,IACxB,KAAK,MAAM,OAAO,KAAK,KAAK,KAAK,IACjC,QAAQ,QAAQ,EAAE,UAAU,OAAgB,WAAW,SAAS,CAAC;AAAA,EACvE;AAAA,EACA,SAAS;AACP,WAAO,KAAK,gBAAgB,IACxB,KAAK,MAAM,OAAO,KAAK,KAAK,IAAI,IAChC,QAAQ,QAAQ,EAAE,UAAU,OAAgB,WAAW,SAAS,CAAC;AAAA,EACvE;AAAA,EACA,QAAQ;AACN,QAAI,KAAK,gBAAgB,EAAG,MAAK,MAAM,MAAM,KAAK,GAAG;AAAA,EACvD;AAAA,EACA,WAAW;AACT,QAAI,KAAK,gBAAgB,EAAG,MAAK,MAAM,SAAS,KAAK,GAAG;AAAA,EAC1D;AAAA,EACA,mBAAmB;AACjB,WAAO,CAAC,UAAwB;AAC9B,aAAO,eAAe;AACtB,WAAK,MAAM,OAAO,MAAM,KAAK,OAAO,CAAC;AAAA,IACvC;AAAA,EACF;AAAA,EACA,iBAAiB;AACf,UAAM,WACJ,CAAC,KAAK,eAAe,KACrB,CAAC,KAAK,WAAW,KACjB,KAAK,WAAW,UAChB,CAAC,KAAK;AACR,WAAO;AAAA,MACL,GAAG,KAAK,UAAU,KAAK,GAAG;AAAA,MAC1B,aAAa,KAAK;AAAA,MAClB,MAAM;AAAA,MACN;AAAA,MACA,cAAc,KAAK,WAAW;AAAA,MAC9B,iBAAiB;AAAA,MACjB,SAAS,KAAK,iBAAiB;AAAA,IACjC;AAAA,EACF;AACF;AACA,IAAM,cAAN,MAAkB;AAAA,EAGhB,YACW,aACA,YACT;AAFS;AACA;AAET,SAAK,MAAM,WAAW;AACtB,SAAK,OAAO,WAAW;AAAA,EACzB;AAAA,EALW;AAAA,EACA;AAAA,EAJF;AAAA,EACA;AAAA,EAQT,IAAI,OAAO;AACT,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EACA,IAAI,aAAa;AACf,WAAO,KAAK,WAAW,OAAO;AAAA,EAChC;AAAA,EACA,IAAI,gBAAgB;AAClB,WAAO,YAAY,KAAK,UAAU,IAAI,SAAS;AAAA,EACjD;AAAA,EACA,mBAAmB;AACjB,UAAM,SAAS,KAAK,UAAU;AAC9B,WAAO,KAAK,mBAAmB,EAAE,IAAI,CAAC,WAAW;AAAA,MAC/C;AAAA,MACA,QACG,OAAO,SAAS,YAAY,OAAO,SAAS,eACzC,OAAO,QAAQ,KAAK,CAAC,WAAW,OAAO,GAAG,OAAO,OAAO,KAAK,CAAC,GAC1D,QACJ,YACH,UAAU,OACP,SACA,OAAO,UAAU,WACf,KAAK,UAAU,KAAK,IACpB,OAAO,KAAK;AAAA,MACpB,UAAU,KAAK,cAAc,KAAK;AAAA,MAClC,OAAO,KAAK,eAAe,KAAK;AAAA,IAClC,EAAE;AAAA,EACJ;AAAA,EACA,YAAY;AACV,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EACA,WAAoC;AAClC,WACE,KAAK,YAAY,MAAM,KAAK,GAAG,MAC9B,OAAO,OAAO,KAAK,YAAY,OAAO,KAAK,GAAG,IAC3C,OACA,KAAK,WAAW;AAAA,EAExB;AAAA,EACA,SAAS,OAAoB;AAC3B,QAAI,CAAC,KAAK,YAAY,gBAAgB,EAAG;AACzC,SAAK,YAAY,MAAM,SAAS,KAAK,YAAY,KAAK,KAAK,KAAK,KAAK;AAAA,EACvE;AAAA,EACA,QAAQ;AACN,QAAI,CAAC,KAAK,YAAY,gBAAgB,EAAG;AACzC,SAAK,YAAY,MAAM,WAAW,KAAK,YAAY,KAAK,KAAK,GAAG;AAAA,EAClE;AAAA,EACA,aAAa;AACX,UAAM,aAAa;AAAA,MACjB,GAAG,KAAK,YAAY;AAAA,MACpB,QAAQ,CAAC,KAAK,UAAU;AAAA,IAC1B;AACA,WAAO,6BAA6B,YAAY;AAAA,MAC9C,CAAC,KAAK,GAAG,GAAG,KAAK,SAAS;AAAA,IAC5B,CAAC,EAAE;AAAA,EACL;AAAA,EACA,qBAA6C;AAC3C,UAAM,SAAS,KAAK,WAAW;AAC/B,QAAI,OAAO,SAAS,gBAAgB,OAAO,SAAS;AAClD,aAAO,OAAO;AAChB,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS;AAC9C,aAAO,OAAO,QACX,OAAO,CAAC,WAAW,CAAC,OAAO,QAAQ,EACnC,IAAI,CAAC,WAAW,OAAO,KAAK;AACjC,WAAO,CAAC;AAAA,EACV;AAAA,EACA,cAAc,OAAoB;AAChC,UAAM,QAAQ,KAAK;AACnB,WACE,oBAAoB,MAAM,QAAQ,KAAK,KACvC,uBAAuB,OAAO,KAAK,SAAS,GAAG,KAAK;AAAA,EAExD;AAAA,EACA,cAAc,OAAoB;AAChC,UAAM,UAAU,KAAK,SAAS;AAC9B,WAAO,YAAY,KAAK,UAAU,KAAK,MAAM,QAAQ,OAAO,IACxD,QAAQ,KAAK,CAAC,SAAS,WAAW,MAAM,KAAK,CAAC,IAC9C,WAAW,SAAS,KAAK;AAAA,EAC/B;AAAA,EACA,iBAAiB,OAAoB;AACnC,WAAO,MAAM;AACX,UAAI,KAAK,YAAY,gBAAgB;AACnC,aAAK,YAAY,MAAM,OAAO,KAAK,YAAY,KAAK,KAAK,KAAK,KAAK;AAAA,IACvE;AAAA,EACF;AAAA,EACA,eAAe,OAAoB;AACjC,UAAM,WAAW,KAAK,cAAc,KAAK;AACzC,UAAM,WACJ,CAAC,YACD,CAAC,KAAK,YAAY,eAAe,KACjC,KAAK,YAAY,WAAW,UAC5B,CAAC,KAAK,YAAY;AACpB,WAAO;AAAA,MACL,GAAG,KAAK,UAAU,KAAK,YAAY,KAAK,KAAK,KAAK,KAAK;AAAA,MACvD,aAAa,KAAK,YAAY;AAAA,MAC9B,MAAM;AAAA,MACN;AAAA,MACA,iBAAiB;AAAA,MACjB,iBAAiB,KAAK,cAAc,KAAK;AAAA,MACzC,iBAAiB;AAAA,MACjB,SAAS,MAAM,KAAK,iBAAiB,KAAK,EAAE;AAAA,IAC9C;AAAA,EACF;AAAA,EACA,aAAa;AACX,UAAM,WACJ,CAAC,KAAK,YAAY,eAAe,KACjC,KAAK,YAAY,WAAW,UAC5B,CAAC,KAAK,YAAY;AACpB,WAAO,mBAAmB,MAAM;AAAA,MAC9B,GAAG,KAAK,UAAU,KAAK,YAAY,KAAK,KAAK,GAAG;AAAA,MAChD,aAAa,KAAK,YAAY;AAAA,MAC9B;AAAA,MACA,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH;AACF;AACA,IAAM,aAAN,MAAiB;AAAA,EAMf,YACW,OACA,IACA,MACA,OACT,SACA,WACS,QACT;AAPS;AACA;AACA;AACA;AAGA;AAET,SAAK,QAAQ,MAAM;AACnB,SAAK,OACH,MAAM,YAAY,UAAU,QAAQ;AAAA,MAClC,CAAC,WAAW,OAAO,aAAa,MAAM,YAAY,UAAU;AAAA,IAC9D,KAAK;AACP,SAAK,OAAO,UACR,cAAc,KAAK,MAAM,OAAO,CAAgC,IAChE;AACJ,SAAK,SAAS,KAAK,SAAS;AAC5B,SAAK,YAAY,aAAa;AAAA,EAChC;AAAA,EAlBW;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EAZF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAqBT,IAAI,OAAO;AACT,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EACA,kBAAkB;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,gBAAgB;AACd,WAAO,KAAK,OAAO,KAAK,CAAC,UAAU,MAAM,eAAe,CAAC;AAAA,EAC3D;AAAA,EACA,gBAAgB;AACd,WAAO,KAAK,OAAO;AAAA,MAAK,CAAC,UACvB,MACG,UAAU,EACV;AAAA,QACC,CAAC,UACC,MAAM,WAAW,OAAO,SAAS,gBACjC,MAAM,cAAc,KAAK,EAAE;AAAA,MAC/B;AAAA,IACJ;AAAA,EACF;AAAA,EACA,aAAa,SAAgC;AAC3C,WAAO,KAAK,OAAO;AAAA,MACjB,CAAC,UACC,MAAM,eAAe,MACpB,CAAC,SAAS,eAAe,MAAM,QAAQ,QAAQ,gBAChD,MAAM,WAAW,UACjB,MAAM,aACN,MACG,UAAU,EACV;AAAA,QACC,CAAC,UACC,MAAM,WAAW,OAAO,SAAS,iBAChC,CAAC,SAAS,SAAS,MAAM,QAAQ,QAAQ,UAC1C,MAAM,cAAc,KAAK,EAAE;AAAA,MAC/B;AAAA,IACN;AAAA,EACF;AAAA,EACA,OAAO,SAAgC;AACrC,QAAI,KAAK,UAAU,KAAK,MAAM,SAAS,KAAK,MAAM,SAAU;AAC5D,SAAK,MAAM,WAAW,KAAK,IAAI,OAAO;AAAA,EACxC;AAAA,EACA,iBAAiB,SAAgC;AAC/C,WAAO,MAAM,KAAK,OAAO,OAAO;AAAA,EAClC;AAAA,EACA,SAAS,SAAgC;AACvC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,CAAC,KAAK,aAAa,OAAO;AAAA,MACpC,eAAe;AAAA,MACf,cAAc,KAAK;AAAA,MACnB,oBAAoB,SAAS;AAAA,MAC7B,cAAc,SAAS;AAAA,MACvB,iBAAiB,KAAK,cAAc;AAAA,MACpC,iBAAiB,KAAK,cAAc;AAAA,MACpC,iBAAiB,CAAC,KAAK,aAAa,OAAO;AAAA,MAC3C,eAAe,KAAK;AAAA,MACpB,aAAa,KAAK;AAAA,MAClB,SAAS,KAAK,iBAAiB,OAAO;AAAA,IACxC;AAAA,EACF;AACF;AACA,IAAM,aAAN,MAAiB;AAAA,EACf,YACW,OACA,IACA,OACT;AAHS;AACA;AACA;AAAA,EACR;AAAA,EAHQ;AAAA,EACA;AAAA,EACA;AAAA,EAEX,IAAI,OAAO;AACT,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EACA,IAAI,QAAQ;AACV,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EACA,aAAa;AACX,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EACA,QAAQ,IAAY;AAClB,WAAO,cAAc,KAAK,SAAS,EAAE,GAAG,gBAAgB,KAAK,EAAE,IAAI,EAAE;AAAA,EACvE;AAAA,EACA,SAAS,IAAY;AACnB,WAAO,KAAK,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE;AAAA,EACjD;AAAA,EACA,SAAS,SAA+D;AACtE,WAAO,SAAS,OAAO,CAAC,GAAG,KAAK,KAAK,EAAE,KAAK,QAAQ,IAAI,IAAI,KAAK;AAAA,EACnE;AACF;AACA,IAAM,eAAN,MAAmB;AAAA,EAIjB,YACW,OACT,SACS,OACA,MACA,QACT;AALS;AAEA;AACA;AACA;AAET,SAAK,KAAK,QAAQ;AAClB,SAAK,OAAO,QAAQ;AACpB,SAAK,QAAQ,QAAQ;AAAA,EACvB;AAAA,EATW;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EARF;AAAA,EACA;AAAA,EACA;AAAA,EAYT,IAAI,OAAO;AACT,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AACA,IAAM,cAAN,MAAkB;AAAA,EAChB,YAAqB,SAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EACrB,GAAG,MAAc;AACf,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EACA,OAAU,QAA2C;AACnD,WAAO,KAAK,YAAY,OAAO,OAAO,OAAO,KAAK,OAAO,EAAE;AAAA,EAC7D;AACF;AA+DA,IAAM,aAAN,MAAiB;AAAA,EACf,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACF;AAAA,EACA;AAAA,EACA,aAAa;AAAA,IACpB,aAAa,OAAO,OAAO,kBAAkB,SAAS;AAAA,IACtD,OAAO,OAAO,OAAO,YAAY,SAAS;AAAA,IAC1C,MAAM,OAAO,OAAO,WAAW,SAAS;AAAA,IACxC,MAAM,OAAO,OAAO,WAAW,SAAS;AAAA,IACxC,OAAO,CAAC;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB,oBAAI,QAAqC;AAAA,EAC5D,UASW;AAAA,EACX;AAAA,EACA,iBAAiB,oBAAI,IAAqC;AAAA,EAC1D,mBAAmC,CAAC;AAAA,EACpC,SAAS,oBAAI,IAAY;AAAA,EACzB;AAAA,EACA,WAAW,oBAAI,IAAY;AAAA,EAC3B,YAAY,oBAAI,IAAoB;AAAA,EACpC,aAAuB;AAAA,EACvB,mBAAiD,CAAC;AAAA,EAClD;AAAA,EACA,cAAc;AACZ,UAAM,SAAS,KAAK,OAAO;AAC3B,eAAW,OAAO,oBAAI,IAAI;AAAA,MACxB,GAAG,OAAO,KAAK,KAAK,UAAU;AAAA,MAC9B,GAAG,OAAO,KAAK,MAAM;AAAA,IACvB,CAAC;AACC,UAAI,KAAK,WAAW,GAAG,MAAM,OAAO,GAAG;AACrC,aAAK,UAAU,IAAI,MAAM,KAAK,UAAU,IAAI,GAAG,KAAK,KAAK,CAAC;AAC9D,SAAK,aAAa;AAAA,EACpB;AAAA,EACA,YACE,SACA,UACA;AACA,SAAK,UAAU;AACf,SAAK,cAAc,QAAQ,cAAc,UAAU;AACnD,SAAK,cAAc,QAAQ,cAAc,qBAAqB;AAC9D,SAAK,cAAc,QAAQ,OAAO,MAAM,IAAI;AAC5C,UAAM,UAAU,MAAM,KAAK,YAAY,KAAK,MAAM,IAAI;AACtD,UAAM,OAAoB;AAAA,MACxB,IAAI,WAAW;AACb,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,OAAO;AACT,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,UAAU;AACZ,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,aAAa;AACf,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,UAAU;AACZ,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,UAAU;AACZ,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,QAAQ;AACV,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,QAAQ;AACV,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,OAAO;AACT,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,KAAK;AACP,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,UAAU;AACZ,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,eAAe;AACjB,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,SAAS;AACX,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,QAAQ;AACV,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,QAAQ;AACV,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,IAAI,SAAS;AACX,eAAO,QAAQ,EAAE;AAAA,MACnB;AAAA,MACA,OAAO;AAAA,QACL,KAAK,MAAM,KAAK,MAAM,IAAI;AAAA,QAC1B,WAAW,CAAC,aAAyB,KAAK,MAAM,UAAU,QAAQ;AAAA,MACpE;AAAA,MACA,aAAa,MAAM,KAAK,YAAY,KAAK,MAAM,IAAI;AAAA,MACnD,YAAY,MAAM,KAAK;AAAA,MACvB,YAAY,CAAC,SAAyB,KAAK,WAAW,IAAI;AAAA,MAC1D,WAAW,CAAC,aAAyB;AACnC,cAAM,MAAM,KAAK,MAAM,UAAU,QAAQ;AACzC,eAAO,MAAM,IAAI,YAAY;AAAA,MAC/B;AAAA,MACA,SAAS,MAAM,KAAK,QAAQ;AAAA,MAC5B,gBAAgB,MAAM,KAAK,eAAe;AAAA,MAC1C,SAAS,MAAM,KAAK,MAAM,IAAI;AAAA,IAChC;AAEA,eAAW,CAAC,KAAK,UAAU,KAAK,OAAO;AAAA,MACrC,OAAO,0BAA0B,IAAI;AAAA,IACvC,GAAG;AACD,UAAI,WAAW,KAAK;AAClB,eAAO,eAAe,MAAM,KAAK;AAAA,UAC/B,YAAY;AAAA,UACZ,cAAc;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,eAAe,MAAM,SAAS;AAAA,MACnC,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AACD,SAAK,WAAW;AAChB,SAAK,QAAQ,YAAY,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC;AACpD,QAAI,WAAW,QAAQ;AACrB,aAAO,eAAe,MAAM,SAAS;AAAA,QACnC,OAAO,CAAC,WAEJ,KAAK,QAAQ,OAGb,MAAM,MAAM;AAAA,MAClB,CAAC;AACH,QAAI,aAAa,QAAQ;AACvB,aAAO,eAAe,MAAM,WAAW;AAAA,QACrC,OAAO,IAAI,SAEP,KAAK,QAAQ,OAGb,QAAQ,GAAG,IAAI;AAAA,MACrB,CAAC;AACH,UAAM,UAAiC;AAAA,MACrC,MAAM,KAAK;AAAA,MACX,WAAW,MAAM;AAGf,cAAM,OAAO,KAAK,SAAS;AAG3B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAAA,MAChC;AAAA,MACA,aAAa,CAACA,UACZ,KAAK,OAAO,SAAS;AAAA,QACnB,IAAIA,MAAK;AAAA,QACT,MAAM,cAAcA,KAAI;AAAA,QACxB,MAAM,KAAK;AAAA,MACb,CAAC;AAAA,MACH,aAAa,CAAC,QAAQC,aAAY,KAAK,YAAY,QAAQA,QAAO;AAAA,MAClE,eAAe,CAAC,QAAQ,WAAW,KAAK,cAAc,QAAQ,MAAM;AAAA,MACpE,YAAY,MAAM;AAChB,YAAI,CAAC,KAAK,SAAU,MAAK,QAAQ;AAAA,MACnC;AAAA,IACF;AACA,UAAM,UAA0B,EAAE,GAAG,SAAS,CAAC,eAAe,GAAG,QAAQ;AACzE,eAAW,WAAW,OAAO;AAAA,MAC3B,WAAW,KAAK,UAAU,OAAO,KAAK,CAAC;AAAA,IACzC,GAAG;AACD,UAAI,QAAQ;AACV,mBAAW,OAAO,QAAQ,QAAQ,QAAQ,IAAI,GAAG;AAC/C,cAAI,OAAO,QAAQ,KAAK,eAAe,IAAI,GAAG;AAC5C,kBAAM,IAAI,MAAM,iCAAiC,OAAO,GAAG,CAAC,IAAI;AAClE,eAAK,eAAe;AAAA,YAClB;AAAA,YACA,OAAO,yBAAyB,QAAQ,MAAM,GAAG;AAAA,UACnD;AACA,iBAAO,eAAe,MAAM,KAAK;AAAA,YAC/B,KAAK,MACH,QAAQ,IAAI,KAAK,YAAY,KAAK,MAAM,IAAI,GAAG,GAAG;AAAA,UACtD,CAAC;AAAA,QACH;AACF,iBAAW,QAAQ;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACE,aAAK,QAAQ,KAAK,WAAW,IAAI,GAAG,QAAQ,IAAI,CAAC;AACnD,UAAI,QAAQ,QAAS,MAAK,iBAAiB,KAAK,QAAQ,OAAO;AAAA,IACjE;AACA,SAAK,QAAQ;AACb,SAAK,gBAAgB;AACrB,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EACA,QAAQ,QAAgB,WAA+B;AACrD,QAAI,CAAC,UAAW;AAChB,eAAW,OAAO,QAAQ,QAAQ,SAAS,GAAG;AAC5C,UACE,OAAO,UACP;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,EAAE,SAAS,OAAO,GAAG,CAAC;AAEtB,cAAM,IAAI,MAAM,iCAAiC,OAAO,GAAG,CAAC,IAAI;AAAA,IACpE;AACA,WAAO;AAAA,MACL;AAAA,MACA,OAAO,0BAA0B,SAAS;AAAA,IAC5C;AAAA,EACF;AAAA,EACA,OAAyB,MAAsC,OAAa;AAC1E,WAAO,eAAe,OAAO,KAAK,WAAW,IAAI,CAAC;AAClD,WAAO,OAAO,OAAO,KAAK;AAAA,EAC5B;AAAA,EACA,SAAS;AACP,QACE,KAAK,QAAQ,SACb,KAAK,QAAQ,UAAU,KAAK;AAE5B,aAAO;AACT,WAAO,KAAK,QAAQ,OAAO,UAAU,KAAK;AAAA,EAC5C;AAAA,EACA,SAAS;AACP,QACE,KAAK,QAAQ,SACb,KAAK,QAAQ,UAAU,KAAK;AAE5B,aAAO;AACT,WAAO,KAAK,QAAQ,OAAO,sBAAsB,SAC7C,KAAK,QAAQ,MAAM,oBACnB,KAAK;AAAA,EACX;AAAA,EACA,YAAY,MAAgB;AAC1B,QAAI,KAAK,QAAQ,OAAO,WAAW,OAAW,MAAK,cAAc;AACjE,SAAK,QAAQ,iBAAiB,IAAI;AAClC,SAAK,QAAQ;AAAA,EACf;AAAA,EACA,WAAW,KAAa,OAA2B;AACjD,UAAM,SAAS,KAAK,OAAO;AAC3B,UAAM,OAAO,EAAE,GAAG,OAAO;AACzB,QAAI,UAAU,OAAW,QAAO,KAAK,GAAG;AAAA,QACnC,MAAK,GAAG,IAAI,gBAAgB,KAAK;AACtC,SAAK,YAAY,OAAO,OAAO,IAAI,CAAC;AAAA,EACtC;AAAA,EACA,SAAS,KAAoB;AAC3B,QAAI,KAAK,YAAa,QAAQ,QAAQ,CAAC,KAAK,QAAQ,GAAG,EAAI;AAC3D,QAAI,KAAK,QAAQ,OAAO,sBAAsB;AAC5C,WAAK,cAAc;AACrB,SAAK,QAAQ,4BAA4B,GAAG;AAC5C,SAAK,QAAQ;AAAA,EACf;AAAA,EACA,cAAc,MAA6B,OAAe;AACxD,UAAM,QAAQ,KAAK,YAAY,UAAU,MAAM,SAAS,CAAC;AACzD,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,OAAO,MAAM,MAAM,GAAG;AAC5B,UAAI,MAAM,OAAO,SAAS,gBAAgB,OAAO,SAAS;AACxD;AACF,iBAAW,QAAQ,OAAO,OAAO,KAAK,GAAG;AACvC,cAAM,QAAQ,KAAK,iBAAiB,IAAI,GAAG;AAAA,UACzC,CAAC,UAAU,MAAM,mBAAmB,KAAK;AAAA,QAC3C;AACA,YAAI,MAAO,QAAO;AAAA,MACpB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EACA,QAAQ,KAAa;AACnB,WAAO,KAAK,MAAM,IAAI,EAAE,aAAa,KAAK,GAAG;AAAA,EAC/C;AAAA,EACA,SAAS,KAAa;AACpB,UAAM,cAAc,KAAK,QAAQ,GAAG;AACpC,WAAO,CAAC,KAAK,YACX,KAAK,YAAY,eAAe,WAChC,CAAC,KAAK,YAAY,WAClB,aAAa,eAAe,IAC1B,cACA;AAAA,EACN;AAAA,EACA,SAAS,KAAa,UAAkB,OAAoB;AAC1D,UAAM,cAAc,KAAK,SAAS,GAAG;AACrC,QAAI,CAAC,aAAa,UAAU,QAAQ,EAAG;AACvC,SAAK,WAAW,KAAK,EAAE,GAAG,KAAK,OAAO,EAAE,GAAG,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC;AAAA,EACnE;AAAA,EACA,WAAW,KAAa,UAAkB;AACxC,QAAI,CAAC,KAAK,SAAS,GAAG,GAAG,UAAU,QAAQ,EAAG;AAC9C,UAAM,QAAQ,EAAE,GAAG,KAAK,OAAO,EAAE,GAAG,EAAE;AACtC,WAAO,MAAM,QAAQ;AACrB,SAAK,WAAW,KAAK,KAAK;AAAA,EAC5B;AAAA,EACA,MAAM,KAAa;AACjB,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW,KAAK,MAAS;AAC9B,QAAI,KAAK,OAAO,MAAM,IAAK,MAAK,SAAS,IAAI;AAAA,EAC/C;AAAA,EACA,OACE,KACA,UACA,OACA,OACA;AACA,UAAM,cAAc,SAAS,KAAK,SAAS,GAAG;AAC9C,QACE,UACC,CAAC,MAAM,gBAAgB,KACtB,CAAC,MAAM,eAAe,KACtB,KAAK,YAAY,eAAe,WAChC,KAAK,YAAY,WACjB,KAAK;AAEP;AACF,UAAM,QAAQ,aAAa,UAAU,QAAQ;AAC7C,QAAI,CAAC,eAAe,CAAC,OAAO,cAAc,KAAK,EAAG;AAClD,QACE,YAAY,MAAM,UAAU,KAC3B,OAAO,UAAU,aACf,MAAM,WAAW,OAAO,SAAS,gBAChC,MAAM,WAAW,OAAO,SAAS,gBACrC;AACA,UAAI,OAAgC,EAAE,GAAG,KAAK,OAAO,EAAE,GAAG,EAAE;AAC5D;AAAA,QACE;AAAA,UACE,UAAU,MAAM;AAAA,UAChB,UAAU,CAAC,MAAM,GAAG,MAAM;AACxB,mBAAO,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE;AAAA,UAC3B;AAAA,UACA,YAAY,CAAC,MAAM,MAAM;AACvB,gBAAI,EAAG,QAAO,KAAK,CAAC;AAAA,UACtB;AAAA,QACF;AAAA,QACA,YAAY;AAAA,QACZ,EAAE,UAAU,MAAM;AAAA,MACpB;AACA,WAAK,WAAW,KAAK,IAAc;AAAA,IACrC,MAAO,MAAK,SAAS,KAAK,UAAU,KAAK;AACzC,SAAK,SAAS,GAAG;AACjB,UAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,QACE,WACA,OAAO,OAAO,KAAK,OAAO,EAAE,GAAG,KAAK,OAAO,QAAQ,KACnD,4BAA4B,QAAQ,UAAU,KAC9C,QAAQ,WAAW;AAEnB,WAAK,OAAO,MAAM,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,EAC7C;AAAA,EACA,WAAW,IAAY,SAAgC;AACrD,UAAM,OAAO,KAAK,MAAM,IAAI,EAAE,MAAM,KAAK,EAAE;AAC3C,QACE,CAAC,QACD,KAAK,YAAY,WACjB,KAAK,YAAY,eAAe;AAEhC;AACF,UAAM,aAAa,KAAK,OAAO,QAAQ,CAAC,gBAAgB;AACtD,UACE,CAAC,YAAY,eAAe,KAC5B,CAAC,YAAY,gBAAgB,KAC5B,SAAS,eAAe,YAAY,QAAQ,QAAQ;AAErD,eAAO,CAAC;AACV,aAAO,YACJ,UAAU,EACV;AAAA,QACC,CAAC,UACC,MAAM,WAAW,OAAO,SAAS,iBAChC,CAAC,SAAS,SAAS,MAAM,QAAQ,QAAQ,UAC1C,MAAM,cAAc,EAAE;AAAA,MAC1B,EACC,IAAI,CAAC,WAAW,EAAE,aAAa,MAAM,EAAE;AAAA,IAC5C,CAAC;AACD,QAAI,WAAW,SAAS,EAAG,OAAM,IAAI,qBAAqB,EAAE;AAC5D,UAAM,YAAY,WAAW,CAAC;AAC9B,QAAI;AACF,WAAK;AAAA,QACH,UAAU,YAAY;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB;AAAA,QACA,UAAU;AAAA,MACZ;AAAA,EACJ;AAAA,EACA,OAAO,QAAqC;AAC1C,UAAM,SAAS,KAAK,QAAQ;AAC5B,UAAM,SAAS,MAAM,CAAC,KAAK,YAAY,KAAK,QAAQ,WAAW;AAC/D,SAAK,OAAO,EAAE;AAAA,MACZ,CAAC,WAAW;AACV,YAAI,OAAO,KAAK,CAAC,OAAO;AACtB,eAAK,QAAQ;AAAA,YACX,IAAI,MAAM,OAAO,WAAW,OAAO,WAAW,EAAE,OAAO,OAAO,CAAC;AAAA,UACjE;AAAA,MACJ;AAAA,MACA,CAAC,UAAU;AACT,YAAI,CAAC,OAAO,EAAG;AACf,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,YAAI,MAAM,YAAY,SAAS,MAAM,eAAe,SAAU;AAC9D,aAAK,QAAQ,UAAU,KAAK;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,KAAa,QAAwC;AAChE,UAAM,SAAS,KAAK,QAAQ;AAC5B,UAAM,cAAc,KAAK,QAAQ,GAAG;AACpC,QACE,KAAK,YACL,KAAK,YAAY,eAAe,WAChC,KAAK,YAAY,WACjB,KAAK;AAEL,aAAO,EAAE,UAAU,OAAO,WAAW,OAAO;AAC9C,QAAI,CAAC,YAAa,QAAO,EAAE,UAAU,OAAO,WAAW,cAAc;AACrE,QACE,SACI,CAAC,YAAY,QAAQ,GAAG,YACxB,CAAC,YAAY,eAAe,KAAK,CAAC,YAAY,WAAW;AAE7D,aAAO,EAAE,UAAU,OAAO,WAAW,cAAc;AACrD,QAAI,EAAE,YAAY,WAAW,EAAE,YAAY;AACzC,aAAO,EAAE,UAAU,OAAO,WAAW,YAAY;AACnD,UAAM,gBAAgB;AAItB,UAAM,YAAY;AAAA,MAChB;AAAA,MACA;AAAA,MACA,OAAO,KAAK,OAAO,EAAE,GAAG,KAAK;AAAA,MAC7B,UAAU,KAAK,UAAU,IAAI,GAAG,KAAK;AAAA,MACrC,SAAS,KAAK,YAAY,SAAS;AAAA,MACnC,OAAO,KAAK;AAAA,MACZ,UAAU;AAAA,MACV;AAAA,IACF;AACA,SAAK,UAAU;AACf,QAAI;AACF,YAAM,SAAS,OAAO,SAClB,cAAc,OAAO,YAAY,EAAE,IACnC,cAAc;AAAA,QACZ,YAAY;AAAA,QACZ,YAAY,UAAU,EAAE;AAAA,MAC1B;AACJ,UAAI,KAAK,YAAY,UAAW,QAAO;AACvC,UAAI,CAAC,OAAO,UAAU;AACpB,aAAK,UAAU;AACf,aAAK,QAAQ;AACb,eAAO;AAAA,MACT;AACA,gBAAU,WAAW;AACrB,WAAK,cAAc;AACnB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,KAAK,YAAY,WAAW;AAC9B,aAAK,UAAU;AACf,aAAK,QAAQ;AAAA,MACf;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,gBAAgB;AACd,UAAM,YAAY,KAAK;AACvB,QACE,CAAC,WAAW,YACZ,KAAK,YAAY,WACjB,UAAU,WAAW,KAAK,QAAQ,UAClC,UAAU,UAAU,KAAK;AAEzB;AACF,QACE,KAAK,YAAY,eAAe,YAChC,KAAK,YAAY,eAAe,UAChC;AACA,WAAK,UAAU;AACf,WAAK,QAAQ;AACb;AAAA,IACF;AACA,QACE,KAAK,YAAY,eAAe,YAC/B,KAAK,YAAY,UAAU,WAAW,OAAO,UAAU;AAExD;AACF,SAAK,UAAU;AACf,SAAK,KAAK,UAAU,IAAI,UAAU,GAAG,KAAK,OAAO,UAAU;AACzD,WAAK,MAAM,UAAU,GAAG;AAAA,QACrB,MAAK,QAAQ;AAAA,EACpB;AAAA,EACA,sBAAsB;AACpB,UAAM,UAAU,KAAK,YAAY;AACjC,QACE,CAAC,WACD,CAAC,KAAK,QAAQ,WACd,KAAK,iBAAiB,IAAI,KAAK,QAAQ,MAAM,MAAM;AAEnD;AACF,SAAK,iBAAiB,IAAI,KAAK,QAAQ,QAAQ,OAAO;AACtD,SAAK,QAAQ,UAAU,OAAO;AAAA,EAChC;AAAA,EACA,kBAAkB;AAChB,UAAM,SAAS,KAAK,QAAQ;AAC5B,SAAK,eAAe,OAAO,MAAM,UAAU,MAAM;AAC/C,UAAI,KAAK,YAAY,KAAK,QAAQ,WAAW,OAAQ;AACrD,YAAM,OAAO,OAAO,MAAM,IAAI;AAC9B,YAAM,mBAAmB,KAAK,YAAY;AAC1C,WAAK,cAAc;AACnB,UACE,oBACA,KAAK,YACL,iBAAiB,OAAO,KAAK,SAAS,IACtC;AACA,aAAK;AACL,aAAK,yBAAyB,KAAK,QAAQ;AAC3C,aAAK,UAAU;AACf,aAAK,cAAc;AACnB,aAAK,cAAc;AACnB,aAAK,QAAQ,iBAAiB,CAAC,CAAC;AAChC,aAAK,QAAQ,4BAA4B,IAAI;AAAA,MAC/C;AACA,WAAK,UAAU;AACf,WAAK,QAAQ;AACb,WAAK,cAAc;AACnB,WAAK,oBAAoB;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EACA,WAAW,MAAsB;AAC/B,QAAI,KAAK,SAAU,OAAM,IAAI,MAAM,4BAA4B;AAC/D,UAAM,UAAU,KAAK,WAAW,KAAK,QAAQ;AAC7C,QAAI,SAAS;AACX,WAAK;AACL,WAAK,cAAc,YAAY;AAC/B,WAAK,QAAQ,OAAO,QAAQ;AAC5B,WAAK,UAAU;AAAA,IACjB;AACA,SAAK,UAAU;AACf,QAAI,SAAS;AACX,WAAK,yBAAyB,KAAK;AACnC,WAAK,cAAc;AACnB,WAAK,cAAc;AACnB,WAAK,cAAc,KAAK,OAAO,MAAM,IAAI;AACzC,WAAK,QAAQ,iBAAiB,CAAC,CAAC;AAChC,WAAK,QAAQ,4BAA4B,IAAI;AAC7C,WAAK,gBAAgB;AAAA,IACvB;AACA,SAAK,UAAU;AACf,SAAK,QAAQ;AACb,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EACA,YAAY;AACV,UAAM,WAAW,KAAK,YAAY;AAClC,QAAI,CAAC,SAAU;AACf,UAAM,SAAS,KAAK,OAAO;AAC3B,QAAI,UAAU;AACd,UAAM,OAA2C,EAAE,GAAG,OAAO;AAC7D,eAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,MAAM,GAAG;AAClD,UAAI,CAAC,OAAQ;AACb,YAAM,OAAO,SAAS,MAAM,sBAAsB;AAAA,QAChD,CAAC,UAAU,MAAM,mBAAmB;AAAA,MACtC;AACA,UAAI,CAAC,MAAM;AACT,YAAI,KAAK,SAAS,QAAQ,KAAK;AAC7B,iBAAO,KAAK,GAAG;AACf,oBAAU;AAAA,QACZ;AACA;AAAA,MACF;AACA,YAAM,aAAa,KAAK,cAAc,MAAM,MAAM;AAClD,YAAM,OAAO,EAAE,GAAG,OAAO;AACzB,UAAI,eAAe;AACnB,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAClD,cAAM,QAAQ,WAAW,OAAO,KAAK,CAACC,WAAUA,OAAM,QAAQ,IAAI;AAClE,YAAI,CAAC,SAAS,KAAK,SAAS,QAAQ,IAAK;AACzC,cAAM,YAAY,SAAS,eAAe,KAAK;AAC/C,YAAI,SAAS,WAAW,SAAS,UAAU,MAAM,QAAQ,KAAK,GAAG;AAC/D,gBAAM,WAAW,MAAM;AAAA,YAAO,CAAC,SAC7B,oBAAoB,MAAM,QAAQ,IAAI;AAAA,UACxC;AACA,gBAAM,MAAM,UAAU;AACtB,gBAAM,WACJ,QAAQ,SAAY,WAAW,SAAS,MAAM,GAAG,GAAG;AACtD,cAAI,SAAS,WAAW,MAAM,QAAQ;AACpC,iBAAK,IAAI,IAAI;AACb,sBAAU;AACV,2BAAe;AAAA,UACjB;AACA;AAAA,QACF;AACA,YAAI,CAAC,SAAS,CAAC,SAAS,OAAO,OAAO,IAAI,GAAG;AAC3C,iBAAO,KAAK,IAAI;AAChB,oBAAU;AACV,yBAAe;AAAA,QACjB;AAAA,MACF;AACA,UAAI,aAAc,MAAK,GAAG,IAAI,gBAAgB,IAAI;AAAA,IACpD;AACA,QAAI,QAAS,MAAK,YAAY,OAAO,OAAO,IAAI,CAAC;AACjD,UAAM,SAAS,KAAK,OAAO;AAC3B,QACE,UACA,CAAC,SAAS,MAAM,sBAAsB;AAAA,MACpC,CAAC,UAAU,MAAM,mBAAmB;AAAA,IACtC;AAEA,WAAK,SAAS,IAAI;AAAA,EACtB;AAAA,EACA,UAAU;AACR,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW;AAChB,SAAK,iBAAiB,QAAQ,CAAC,YAAY,QAAQ,CAAC;AACpD,SAAK,cAAc,YAAY;AAC/B,SAAK,UAAU;AACf,SAAK,QAAQ,OAAO,QAAQ;AAC5B,SAAK,cAAc,KAAK,QAAQ,OAAO,MAAM,IAAI;AACjD,SAAK,QAAQ;AAAA,EACf;AAAA,EACA,iBAAiB;AACf,UAAM,UACJ,KAAK,YAAY,UAAU,MAAM,sBAC9B;AAAA,MACC,CAAC,MACC,EAAE,aAAa,WAAW,eAC1B,CAAC,KAAK,SAAS,IAAI,EAAE,cAAc;AAAA,IACvC,EACC,IAAI,CAAC,MAAM,EAAE,cAAc,KAAK,CAAC;AACtC,QAAI,QAAQ;AACV,YAAM,IAAI,MAAM,0BAA0B,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EAClE;AAAA,EACA,YAAY,QAAgC,SAAgC;AAC1E,QAAI,OAAO,SAAS,QAAQ;AAC1B,WAAK,WAAW,OAAO,OAAO,OAAO;AACrC;AAAA,IACF;AACA,UAAM,aAAa,KAAK,iBAAiB;AAAA,MAAQ,CAAC,gBAChD,YACG,UAAU,EACV;AAAA,QACC,CAAC,UACC,mBAAmB,MAAM,YAAY,MAAM,KAC3C,MAAM,cAAc,OAAO,KAAK,KAChC,YAAY,eAAe,MAC1B,CAAC,SAAS,eACT,YAAY,QAAQ,QAAQ,iBAC7B,CAAC,SAAS,SAAS,MAAM,QAAQ,QAAQ;AAAA,MAC9C,EACC,IAAI,CAAC,WAAW,EAAE,aAAa,MAAM,EAAE;AAAA,IAC5C;AACA,QAAI,WAAW,SAAS;AACtB,YAAM,IAAI,qBAAqB,KAAK,UAAU,OAAO,KAAK,CAAC;AAC7D,UAAM,QAAQ,WAAW,CAAC;AAC1B,QAAI;AACF,WAAK,OAAO,MAAM,YAAY,KAAK,MAAM,MAAM,KAAK,OAAO,KAAK;AAAA,EACpE;AAAA,EACA,cAAc,QAAgB,QAA2B;AACvD,QACE,KAAK,YACL,KAAK,YAAY,WACjB,KAAK,WACL,KAAK,YAAY,eAAe;AAEhC;AACF,UAAM,OAAO,KAAK,MAAM,IAAI,EAAE,MAAM,KAAK,MAAM;AAC/C,UAAM,cAAc,MAAM,OAAO;AAAA,MAC/B,CAAC,UAAU,MAAM,QAAQ,OAAO;AAAA,IAClC;AACA,QAAI,CAAC,aAAa,gBAAgB,KAAK,CAAC,YAAY,eAAe;AACjE;AACF,UAAM,YAAY,YAAY,UAAU,OAAO,YAAY;AAC3D,QACE,CAAC,aACD,UAAU,WAAW,OAAO,SAAS,gBACrC,CAAC,UAAU,cAAc,MAAM;AAE/B;AACF,UAAM,QACJ,OAAO,SAAS,gBACZ,SACA,YAAY,UAAU,OAAO,QAAQ;AAC3C,QACE,OAAO,SAAS,kBACf,CAAC,SACA,CAAC,mBAAmB,MAAM,YAAY,MAAM,KAC5C,CAAC,MAAM,cAAc,OAAO,KAAK;AAEnC;AACF,QAAI,OAAgC,EAAE,GAAG,KAAK,OAAO,EAAE,YAAY,GAAG,EAAE;AACxE,UAAM,SAAS,KAAK,UAAU,GAAG;AAEjC,QACE,CAAC,SACD,YAAY,UAAU,UAAU,KAChC,MAAM,QAAQ,MAAM,KACpB,OAAO,SAAS,MAAM,GACtB;AACA,WAAK,SAAS,YAAY,GAAG;AAC7B;AAAA,IACF;AACA;AAAA,MACE;AAAA,QACE,UAAU,MAAM;AAAA,QAChB,UAAU,CAAC,MAAM,KAAK,UAAU;AAC9B,iBAAO,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM;AAAA,QACjC;AAAA,QACA,YAAY,CAAC,MAAM,QAAQ;AACzB,cAAI,IAAK,QAAO,KAAK,GAAG;AAAA,QAC1B;AAAA,MACF;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,QACE;AAAA,QACA,cAAc,UAAU;AAAA,QACxB,YACE,SAAS,OAAO,SAAS,gBACrB,EAAE,UAAU,MAAM,KAAK,OAAO,OAAO,MAAM,IAC3C;AAAA,MACR;AAAA,IACF;AACA,SAAK,WAAW,YAAY,KAAK,IAAc;AAC/C,SAAK,SAAS,YAAY,GAAG;AAC7B,UAAM,UAAU,KAAK,QAAQ,YAAY,GAAG;AAC5C,QACE,WACA,4BAA4B,QAAQ,UAAU,KAC9C,QAAQ,WAAW;AAEnB,WAAK,OAAO,MAAM,QAAQ,OAAO,CAAC;AAAA,EACtC;AAAA,EACA,aAAa;AACX,UAAM,cACH,YAA4C,KAAK,OACjD,WAA6D,SAAS,KACnE,aAAa;AACnB,QAAI,EAAE,KAAK,QAAQ,SAAS,aAAc;AAC1C,mBAAe,MAAM;AACnB,UAAI,KAAK,SAAU;AACnB,iBAAW,cAAc,KAAK,YAAY,UAAU,MACjD,yBAAyB,CAAC,GAAG;AAC9B,cAAM,MAAM,WAAW;AACvB,YACE,WAAW,aAAa,WAAW,eACnC,CAAC,KAAK,SAAS,IAAI,GAAG,KACtB,CAAC,KAAK,OAAO,IAAI,GAAG,GACpB;AACA,eAAK,OAAO,IAAI,GAAG;AACnB,kBAAQ,KAAK,0BAA0B,GAAG,sBAAsB;AAAA,QAClE;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EACA,MAAM,UAAuC;AAC3C,SAAK,YAAY;AACjB,UAAM,EAAE,UAAU,YAAY,SAAS,QAAQ,IAAI,KAAK;AACxD,UAAM,MAAM,UAAU;AACtB,UAAM,SAAS,KAAK,OAAO;AAC3B,UAAM,SAAS,KAAK,OAAO;AAC3B,UAAM,eAAe,aAAa;AAClC,UAAM,aAAa;AACnB,UAAM,YAAY,UAAU,WAAW,CAAC;AACxC,UAAM,YAAY,UAAU,MAAM,KAAK,iBAAiB,CAAC;AACzD,UAAM,gBACJ,cAAc,WACV,SAAS,QAAQ,OAAO,IACxB,OAAO;AAAA,MACL,UAAU;AAAA,QAAI,CAAC,QAAQ,UACrB,OAAO;AAAA,UACL,IAAI;AAAA,YACF;AAAA,YACA;AAAA,YACA;AAAA,YACA,OAAO,aAAa,UAAU;AAAA,YAC9B,UAAU,SAAS,OAAO,QAAQ;AAAA,UACpC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACN,UAAM,UACJ,cAAc,WACV,SAAS,UACT;AAAA,MACE,OAAO,OAAO,OAAO,cAAc,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAAA,MACnD,KAAK,CAAC,OACJ;AAAA,QACE,cAAc,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,QACrC;AAAA,QACA;AAAA,MACF;AAAA,MACF,MAAM,CAAC,OAAe,cAAc,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,MAC3D,QAAQ,MAAM;AAAA,MACd,MAAM,CAAC,OAAe;AACpB,cAAM,QAAQ,cAAc,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACxD,eAAO;AAAA,UACL,QAAQ,IACJ,SACA,eAAe,QAAQ,KAAK,cAAc,MAAM;AAAA,UACpD;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACN,UAAM,KACJ,cAAc,WACV,SAAS,KACT,WACE;AAAA,MACE,IAAI,SAAS;AAAA,MACb,QAAQ,QAAQ,IAAI,SAAS,EAAE;AAAA,MAC/B,WAAW,MACT,SAAS,MAAM,sBAAsB;AAAA,QACnC,CAAC,UAAU,MAAM,aAAa,WAAW;AAAA,MAC3C;AAAA,IACJ,IACA;AACR,UAAM,cAAc,UAAU,MAAM,yBAAyB,CAAC;AAC9D,UAAM,qBAAqB,YAAY,IAAI,CAAC,SAAS;AACnD,YAAM,MAAM,KAAK;AACjB,YAAM,QAAQ,OAAO,GAAG,KAAK;AAC7B,YAAM,aAAa,KAAK,cAAc,MAAM,KAAK;AACjD,YAAM,SACJ,WAAW,KAAK,UACZ,SAAS,kBAAkB,WAAW,iBACtC,QAAQ,UAAU,mBAChB,cACA,eACF;AACN,YAAM,YAAY,KAAK,iBAAiB;AAAA,QACtC,CAAC,UAAU,MAAM,QAAQ;AAAA,MAC3B;AACA,aAAO,WAAW,eAAe,cAC/B,UAAU,UAAU,KAAK,SACzB,UAAU,WAAW,KAAK,QAAQ,UAClC,UAAU,kBAAkB,SAC5B,UAAU,WAAW,UACrB,UAAU,eAAe,eAAe,WACtC,YACA,KAAK;AAAA,QACH;AAAA,QACA,IAAI;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,IACN,CAAC;AACD,UAAM,mBACJ,YACA,mBAAmB,WAAW,KAAK,iBAAiB,UACpD,mBAAmB;AAAA,MACjB,CAAC,OAAO,UAAU,UAAU,KAAK,iBAAiB,KAAK;AAAA,IACzD;AACF,SAAK,mBAAmB,OAAO,OAAO,kBAAkB;AACxD,UAAM,eAAe,mBACjB,SAAS,eACT;AAAA,MACE,KAAK,CAAC,QAAgB;AACpB,aAAK,SAAS,IAAI,GAAG;AACrB,eAAO;AAAA,UACL,mBAAmB,KAAK,CAAC,UAAU,MAAM,QAAQ,GAAG;AAAA,UACpD;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,MAAM,CAAC,QAAgB;AACrB,aAAK,SAAS,IAAI,GAAG;AACrB,eAAO,mBAAmB,KAAK,CAAC,UAAU,MAAM,QAAQ,GAAG;AAAA,MAC7D;AAAA,MACA,MAAM,MAAM;AACV,2BAAmB,QAAQ,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,GAAG,CAAC;AAClE,eAAO,OAAO,OAAO,kBAAkB;AAAA,MACzC;AAAA,MACA,eAAe,MAAM;AACnB,cAAM,YAAY,mBAAmB;AAAA,UAAO,CAAC,UAC3C,MAAM,eAAe;AAAA,QACvB;AACA,kBAAU,QAAQ,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,GAAG,CAAC;AACzD,eAAO,OAAO,OAAO,SAAS;AAAA,MAChC;AAAA,IACF;AACJ,UAAM,SACJ,oBAAoB,WAChB,SAAS,SACT;AAAA,MACE,KAAK,CAAC,KAAa,SACjB;AAAA,QACE,aAAa,KAAK,GAAG,GAAG,UAAU,IAAI;AAAA,QACtC,wBAAwB,GAAG;AAAA,QAC3B;AAAA,MACF;AAAA,MACF,MAAM,CAAC,KAAa,SAClB,aAAa,KAAK,GAAG,GAAG,UAAU,IAAI;AAAA,IAC1C;AACN,UAAM,YAAY,gBAAgB,oBAAoB;AACtD,UAAM,QAAQ,YACV,SAAS,SACR,MAAM;AACL,YAAM,UAAU,OAAO,QAAQ,UAAU,MAAM,SAAS,CAAC,CAAC,EAAE;AAAA,QAC1D,CAAC,CAAC,IAAI,IAAI,MACR,KAAK;AAAA,UACH;AAAA,UACA,IAAI;AAAA,YACF;AAAA,YACA;AAAA,YACA,OAAO;AAAA,cACL,KAAK,QAAQ;AAAA,gBAAI,CAAC,QAAQ,UACxB,KAAK;AAAA,kBACH;AAAA,kBACA,IAAI;AAAA,oBACF;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA,KAAK,cAAc,MAAM;AAAA,oBACzB,KAAK,cAAc,MAAM;AAAA,oBACzB,OAAO;AAAA,uBACJ,KAAK,iBAAiB,MAAM,KAAK,CAAC,GAAG;AAAA,wBACpC,CAAC,eACC,KAAK;AAAA,0BACH;AAAA,0BACA,IAAI;AAAA,4BACF;AAAA,4BACA;AAAA,4BACA,OAAO,WAAW,cAAc,KAAK;AAAA,4BACrC,WAAW,KAAK,UACZ,eACA;AAAA,4BACJ,eAAe;AAAA,0BACjB;AAAA,wBACF;AAAA,sBACJ;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACJ;AACA,aAAO;AAAA,QACL,KAAK,CAAC,OACJ;AAAA,UACE,QAAQ,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE;AAAA,UACrC;AAAA,UACA;AAAA,QACF;AAAA,QACF,MAAM,CAAC,OAAe,QAAQ,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE;AAAA,QAC3D,QAAQ,MAAM,OAAO,OAAO,OAAO;AAAA,MACrC;AAAA,IACF,GAAG;AACP,UAAM,QAAQ,YACV,SAAS,QACT;AAAA,MACE,KAAK,CAAC,OACJ;AAAA,QACE,MACG,OAAO,EACP,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC,EAC/B,KAAK,CAAC,SAAS,SAAS,MAAS;AAAA,QACpC;AAAA,QACA;AAAA,MACF;AAAA,MACF,MAAM,CAAC,OACL,MACG,OAAO,EACP,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC,EAC/B,KAAK,CAAC,SAAS,SAAS,MAAS;AAAA,IACxC;AACJ,UAAM,gBACJ,KAAK,uBAAuB,UAC5B,UAAU,MAAM,sBAAsB,SAClC,SAAS,QACT,cAAc,EAAE,QAAQ,mBAAmB,OAAO,CAAC;AACzD,SAAK,qBAAqB;AAC1B,eAAW,SAAS,CAAC,SAAS,IAAI,cAAc,QAAQ,OAAO,KAAK;AAClE,UAAI,MAAO,QAAO,OAAO,KAAK;AAChC,UAAM,QAAsB;AAAA,MAC1B;AAAA,MACA,MAAM,UAAU,MAAM,QAAQ;AAAA,MAC9B,SAAS,UAAU,WAAW;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,OACE,gBAAgB,WACZ,SAAS,QACT,OAAO;AAAA,QACL,IAAI,YAAY,UAAU,MAAM,KAAK,gBAAgB,IAAI;AAAA,MAC3D;AAAA,MACN,MACE,gBAAgB,WACZ,SAAS,OACT,OAAO,OAAO;AAAA,QACZ,iBAAiB;AAAA,QACjB,iBAAiB,UAAU,WAAW,IAAI,UAAU,CAAC,IAAI;AAAA,QACzD,OAAO,QAAQ;AAAA,QACf,QAAQ,WAAW,UAAU,SAAS,SAAS,EAAE,IAAI;AAAA,MACvD,CAAC;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QACE,gBAAgB,WACZ,SAAS,SACT,OAAO,OAAO;AAAA,QACZ,QAAQ,UAAU,MAAM,UAAU,OAAO,OAAO,CAAC,CAAC;AAAA,MACpD,CAAC;AAAA,IACT;AACA,SAAK,WAAW;AAChB,QAAI;AACF,iBAAW,CAAC,KAAK,UAAU,KAAK,KAAK;AACnC,eAAO,eAAe,OAAO,KAAK;AAAA,UAChC,OAAO,WAAW,MACd,WAAW,IAAI,KAAK,KAAK,QAAQ,IACjC,WAAW;AAAA,UACf,YAAY;AAAA,QACd,CAAC;AAAA,IACL,UAAE;AACA,WAAK,WAAW;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAAA,EACA,UAAU;AACR,QAAI,CAAC,KAAK,MAAO;AACjB,SAAK,MAAM,SAAS,CAAC,aAAa,OAAO,OAAO,KAAK,MAAM,QAAQ,CAAC,CAAC;AACrE,SAAK,WAAW;AAAA,EAClB;AACF;AACO,SAAS,qBAAwB;AACtC,SAAO,SAIL,SAGuB;AAGvB,UAAM,aAAa,IAAI;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,IAEV;AAEA,WAAO,WAAW;AAAA,EACpB;AACF;;;AG7nDO,IAAM,qBAAqB,OAAO,OAAO;AAAA;AAAA,EAE9C,MAAM;AAAA;AAAA,EAEN,QAAQ;AAAA;AAAA,EAER,SAAS;AAAA;AAAA,EAET,UAAU;AACZ,CAAC;AA2CM,SAAS,wBACd,MACA,WACA,UAA0B,CAAC,GACR;AACnB,QAAM,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,KAAK,QAAQ;AAClD,QAAM,QAAQ,KAAK,gBAAgB;AACnC,MAAI,OAAoB;AACxB,MAAI,WAAW;AACf,QAAM,YAAY,QACd,SACA,WAAW,MAAM;AACf,WAAO;AACP,cAAU,KAAK;AAAA,EACjB,GAAG,mBAAmB,MAAM;AAChC,QAAM,QAAQ,CAAC,WAA2B;AAAA,IACxC,GAAG,MAAM;AAAA,IACT,GAAG,MAAM;AAAA,EACX;AACA,QAAM,OAAO,CAAC,UACZ,CAAC,aAAa,CAAC,SAAS,MAAM,cAAc,KAAK;AACnD,WAAS,SAAS;AAChB,eAAW;AACX,iBAAa,SAAS;AAAA,EACxB;AACA,SAAO;AAAA,IACL,KAAK,OAAO;AACV,UAAI,CAAC,KAAK,KAAK,EAAG;AAClB,UAAI,SAAS,OAAQ,QAAO,UAAU,SAAS,MAAM,KAAK,CAAC;AAC3D,YAAM,KAAK,MAAM,UAAU,OAAO;AAClC,YAAM,KAAK,MAAM,UAAU,OAAO;AAClC,UAAI,SAAS,SAAS,KAAK,MAAM,IAAI,EAAE,IAAI,mBAAmB;AAC5D;AACF,mBAAa,SAAS;AACtB,YAAM,QACJ,SACA,QAAQ,kBAAkB,SAC1B,CAAC,KAAK,mBAAmB,WAAW,KAAK,IAAI,EAAE;AACjD,UAAI,SAAS,UAAU,UAAU,MAAM,GAAG;AACxC,eAAO;AACP,kBAAU,SAAS,MAAM,KAAK,CAAC;AAAA,MACjC,MAAO,QAAO;AAAA,IAChB;AAAA,IACA,GAAG,OAAO;AACR,UAAI,CAAC,KAAK,KAAK,EAAG;AAClB,aAAO;AACP,gBAAU,IAAI,MAAM,MAAM,KAAK,CAAC;AAAA,IAClC;AAAA,IACA,OAAO,OAAO;AACZ,UAAI,CAAC,KAAK,KAAK,EAAG;AAClB,aAAO;AACP,gBAAU,OAAO,IAAI;AAAA,IACvB;AAAA,EACF;AACF;;;ACzGO,SAAS,iBACd,MACA,OACS;AACT,MACE,KAAK,mBAAmB,MAAM,kBAC9B,KAAK,iBAAiB,MAAM;AAE5B,WAAO;AACT,MAAI,KAAK,SAAS,iBAAiB,MAAM,SAAS;AAChD,WAAO,KAAK,SAAS,MAAM;AAC7B,SACE,KAAK,SAAS,MAAM,QACpB,KAAK,cAAc,MAAM,aACzB,cAAc,KAAK,KAAK,MAAM,cAAc,MAAM,KAAK,MACtD,KAAK,cAAc,cACjB,MAAM,cAAc,cAAc,KAAK,YAAY,MAAM,YAC5D,KAAK,aAAa,MAAM;AAE5B;","names":["data","options","input"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { a as AnyInput, b as AnyInteraction, B as Board, e as BoardDataOf,
|
|
1
|
+
import { q as Features, E as InstanceOptions, n as CoreInstance, p as FeatureContext, G as GameInstance, C as Card, a8 as Zone, a2 as SeatCardId, d as BoardCollection, h as BoardSpaceCollection, c as BoardBase, _ as RuntimeFeatureContext, Y as RuntimeCollection, V as RuntimeBoard, U as ReadonlyData, a1 as RuntimeTargetOptions, A as ActionProps, g as BoardSpace, a5 as TargetOptions, o as DropTarget, I as IdOf } from './model-D2Z9j0Yi.js';
|
|
2
|
+
export { a as AnyInput, b as AnyInteraction, B as Board, e as BoardDataOf, f as BoardDropTarget, i as BoardSpaceData, j as BoardSpaceId, k as BoardTarget, l as CardBase, m as CardDataOf, D as Drafts, F as Feature, r as GameSnapshot, H as Hook, s as Input, t as InputBase, u as InputControl, v as InputDomainOf, w as InputKey, x as InputKind, y as InputTarget, z as InputTargetOption, J as Interaction, K as InteractionBase, L as InteractionDropTarget, M as InteractionKey, N as InteractionParams, O as LocalState, P as NativeEvent, Q as Phase, R as PhaseName, S as Player, T as ReadModel, W as RuntimeBoardDropTarget, X as RuntimeBoardTarget, Z as RuntimeDropTarget, $ as RuntimeInteractionDropTarget, a0 as RuntimeSelectionTarget, a3 as SelectionTarget, a4 as TableOfGame, a6 as Turn, a7 as ViewOf, a9 as ZoneBase } from './model-D2Z9j0Yi.js';
|
|
3
3
|
import { I as InteractionDescriptor, b as GameplayBasis, e as PluginSessionDescriptor, c as PluginGameplayFrame, G as GameSource, h as SourceSnapshot, C as CommandSource, P as PlayerId, f as ReducerSeatProjectionBundle, R as ReducerBoardStaticProjection } from './types-B3kIhBWb.js';
|
|
4
4
|
export { A as ActionInteractionDescriptor, a as ApplySource, d as PluginPlayerSummary, S as SimultaneousPhaseSnapshot, g as SourceRequest, i as SourceState, j as SubmitResult, Z as ZoneHandlesSnapshot } from './types-B3kIhBWb.js';
|
|
5
5
|
import { z } from 'zod';
|
|
@@ -1307,7 +1307,11 @@ interface DragController<G> {
|
|
|
1307
1307
|
drop(): void;
|
|
1308
1308
|
cancel(): void;
|
|
1309
1309
|
}
|
|
1310
|
-
/**
|
|
1310
|
+
/**
|
|
1311
|
+
* Semantic card/drop routing. A card lands on a board destination when its
|
|
1312
|
+
* interaction has a board input, otherwise on an area that runs the
|
|
1313
|
+
* interaction. Gestures, hit-testing and feedback belong to /react.
|
|
1314
|
+
*/
|
|
1311
1315
|
declare function dragFeature<G>(_game: CoreInstance<G>, context: FeatureContext<G>): {
|
|
1312
1316
|
readonly root: {
|
|
1313
1317
|
readonly drag: DragController<G>;
|
|
@@ -1315,6 +1319,119 @@ declare function dragFeature<G>(_game: CoreInstance<G>, context: FeatureContext<
|
|
|
1315
1319
|
dispose(): void;
|
|
1316
1320
|
};
|
|
1317
1321
|
|
|
1322
|
+
/**
|
|
1323
|
+
* Where a card that arrived in its zone with the current frame was on the
|
|
1324
|
+
* previous one: another zone, or the private zones of the player who moved.
|
|
1325
|
+
* `hidden` says whether the seat saw only the card's back there.
|
|
1326
|
+
*/
|
|
1327
|
+
type CardOrigin<G> = {
|
|
1328
|
+
readonly zone: IdOf<G, "zoneId">;
|
|
1329
|
+
readonly hidden: boolean;
|
|
1330
|
+
} | {
|
|
1331
|
+
readonly player: IdOf<G, "playerId">;
|
|
1332
|
+
readonly hidden: true;
|
|
1333
|
+
};
|
|
1334
|
+
/**
|
|
1335
|
+
* Adds `card.getOrigin()`: where a card that arrived in its zone with the
|
|
1336
|
+
* current frame came from, or null. Origins last until the next frame and
|
|
1337
|
+
* reset when the seat or source changes. Hidden origins are inferred from
|
|
1338
|
+
* net counts; ambiguous sources and arriving positions return null.
|
|
1339
|
+
*/
|
|
1340
|
+
declare function originsFeature<G>(game: CoreInstance<G>): {
|
|
1341
|
+
card: {
|
|
1342
|
+
getOrigin(this: {
|
|
1343
|
+
readonly id: SeatCardId<G>;
|
|
1344
|
+
}): CardOrigin<G> | null;
|
|
1345
|
+
};
|
|
1346
|
+
dispose: () => void;
|
|
1347
|
+
};
|
|
1348
|
+
|
|
1349
|
+
/** Measured with emulated touch; confirm on physical devices before changing. */
|
|
1350
|
+
declare const GESTURE_THRESHOLDS: Readonly<{
|
|
1351
|
+
/** Movement, in CSS pixels, before a press becomes a drag or a browse. */
|
|
1352
|
+
slop: 8;
|
|
1353
|
+
/** A touch or pen held this long without moving inspects the card. */
|
|
1354
|
+
holdMs: 350;
|
|
1355
|
+
/** A mouse resting on a card this long inspects it. */
|
|
1356
|
+
hoverMs: 250;
|
|
1357
|
+
/** A finger drags when upward travel exceeds this multiple of sideways travel. */
|
|
1358
|
+
axisBias: 1.25;
|
|
1359
|
+
}>;
|
|
1360
|
+
interface GesturePointer {
|
|
1361
|
+
readonly pointerId: number;
|
|
1362
|
+
readonly pointerType: string;
|
|
1363
|
+
readonly clientX: number;
|
|
1364
|
+
readonly clientY: number;
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* How a press ended. A tap leaves selection to the native click; a hold
|
|
1368
|
+
* inspected the card; a browse handed sideways movement to native scrolling.
|
|
1369
|
+
*/
|
|
1370
|
+
type GestureKind = "tap" | "hold" | "drag" | "browse";
|
|
1371
|
+
interface GestureCallbacks {
|
|
1372
|
+
/** A touch or pen stayed still for `holdMs`. */
|
|
1373
|
+
hold(): void;
|
|
1374
|
+
/** Return false when the card cannot be dragged; the press then browses. */
|
|
1375
|
+
dragStart(origin: Point): boolean;
|
|
1376
|
+
dragMove(point: Point): void;
|
|
1377
|
+
/** The pointer lifted. */
|
|
1378
|
+
end(kind: GestureKind, point: Point): void;
|
|
1379
|
+
/** The browser or the caller cancelled. A cancelled drag never drops. */
|
|
1380
|
+
cancel(kind: GestureKind): void;
|
|
1381
|
+
}
|
|
1382
|
+
interface GestureRecognizer {
|
|
1383
|
+
move(event: GesturePointer): void;
|
|
1384
|
+
up(event: GesturePointer): void;
|
|
1385
|
+
cancel(event?: Pick<GesturePointer, "pointerId">): void;
|
|
1386
|
+
}
|
|
1387
|
+
interface GestureOptions {
|
|
1388
|
+
/** Hands keep sideways scrolling; piles can be dragged toward any destination. */
|
|
1389
|
+
readonly dragDirection?: "up" | "any";
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Classifies one press. A mouse drags in any direction and never holds. A
|
|
1393
|
+
* finger drags upward, browses sideways and holds when still, so cards can use
|
|
1394
|
+
* `touch-action: pan-x` and keep native sideways scrolling.
|
|
1395
|
+
*/
|
|
1396
|
+
declare function createGestureRecognizer(down: GesturePointer, callbacks: GestureCallbacks, options?: GestureOptions): GestureRecognizer;
|
|
1397
|
+
|
|
1398
|
+
interface FanOptions {
|
|
1399
|
+
readonly count: number;
|
|
1400
|
+
/** The width available to the fan, in pixels. */
|
|
1401
|
+
readonly width: number;
|
|
1402
|
+
readonly cardWidth: number;
|
|
1403
|
+
readonly cardHeight: number;
|
|
1404
|
+
/** Distance between neighbouring cards along the arc when there is room. Default: 60% of the card width. */
|
|
1405
|
+
readonly step?: number;
|
|
1406
|
+
/** The smallest visible slice of a covered card. Default: 25% of the card width. */
|
|
1407
|
+
readonly minStep?: number;
|
|
1408
|
+
/** Degrees between neighbouring cards. Default 5; 0 lays a straight row. */
|
|
1409
|
+
readonly angle?: number;
|
|
1410
|
+
/** The most degrees between the two end cards. Default 30. */
|
|
1411
|
+
readonly maxSpread?: number;
|
|
1412
|
+
}
|
|
1413
|
+
/** A card's CSS `translate` from the fan's top-left corner, and its `rotate` about its own centre. */
|
|
1414
|
+
interface FanCard {
|
|
1415
|
+
readonly x: number;
|
|
1416
|
+
readonly y: number;
|
|
1417
|
+
/** Degrees clockwise. */
|
|
1418
|
+
readonly rotate: number;
|
|
1419
|
+
}
|
|
1420
|
+
interface FanLayout {
|
|
1421
|
+
readonly cards: readonly FanCard[];
|
|
1422
|
+
/** The fan's bounding box. It is wider than the available width only when the cards are at `minStep`. */
|
|
1423
|
+
readonly width: number;
|
|
1424
|
+
readonly height: number;
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Lays cards on a circular arc. The spread grows with the card count up to
|
|
1428
|
+
* `maxSpread`; the step shrinks continuously to fit the width, down to
|
|
1429
|
+
* `minStep`, past which the fan overflows and the hand should scroll.
|
|
1430
|
+
*/
|
|
1431
|
+
declare function fanLayout({ count, width, cardWidth, cardHeight, step, minStep, angle, maxSpread, }: FanOptions): FanLayout;
|
|
1432
|
+
/** Moves a fanned card outward along its own tilt, as for a selected card. */
|
|
1433
|
+
declare function liftFanCard(card: FanCard, distance: number): FanCard;
|
|
1434
|
+
|
|
1318
1435
|
declare function canonicalizePluginRuntimeJson(value: unknown): RuntimeJson;
|
|
1319
1436
|
declare function encodeCanonicalPluginRuntimeJson(value: unknown): string;
|
|
1320
1437
|
declare function digestPluginRuntimeJson(value: unknown): string;
|
|
@@ -3889,4 +4006,4 @@ declare function parsePluginGameplayFrame(value: unknown): PluginGameplayFrame;
|
|
|
3889
4006
|
declare function parseHostToPluginEnvelope(value: unknown): PluginProtocolEnvelope<HostToPluginPayload>;
|
|
3890
4007
|
declare function parsePluginToHostEnvelope(value: unknown): PluginProtocolEnvelope<PluginToHostPayload>;
|
|
3891
4008
|
|
|
3892
|
-
export { ActionProps, type ActionSetVersionInput, AmbiguousTargetError, AuthAcceptedFrameSchema, AuthConnectFrameSchema, AuthRefreshFrameSchema, BoardBase, BoardCollection, type BoardFeature, type BoardLayoutOptions, BoardSpace, BoardSpaceCollection, BoardStaticProjectionSchema, type CancelInteractionCommand, CancelInteractionCommandSchema, Card, type ClientGameplayFrame, ClientGameplayFrameSchema, CommandSource, CoreInstance, DREAMBOARD_PLUGIN_PROTOCOL, DREAMBOARD_PLUGIN_PROTOCOL_VERSION, DREAMBOARD_SDK_PACKAGES, DREAMBOARD_SDK_PACKAGE_SET, DREAMBOARD_SDK_VERSION, type DragController, type DragState, type DreamboardSdkPackageName, type DreamboardSdkPackageSet, DropTarget, FeatureContext, Features, GameEventDetailSchema, GameEventSchema, GameInstance, GameOutcomeSchema, GameSource, GameplayBackpressureFrameSchema, GameplayBackpressureOperationSchema, GameplayBackpressureReasonSchema, GameplayBasis, GameplayBasisSchema, GameplayCloseCode, type GameplayCredential, GameplayCredentialSchema, type HandOptions, type HostToPluginEnvelope, HostToPluginEnvelopeSchema, type HostToPluginPayload, HostToPluginPayloadSchema, InstanceOptions, InteractionDescriptor, type InteractionResult, InteractionResultSchema, type MaterializePluginGameplayFrameInput, type PanZoomOptions, PlayerId, PluginGameplayFrame, PluginGameplayFrameSchema, PluginPlayerSummarySchema, type PluginProtocolEnvelope, PluginSessionDescriptor, PluginSessionDescriptorSchema, type PluginToHostEnvelope, PluginToHostEnvelopeSchema, type PluginToHostPayload, PluginToHostPayloadSchema, ReadonlyData, ReducerBoardStaticProjection, ReducerSeatProjectionBundle, RuntimeJson, RuntimeTargetOptions, SeatCardId, SeatFrameSchema, SeatProjectionBundleSchema, type ServerGameplayFrame, ServerGameplayFrameSchema, SessionResumeFrameSchema, SessionSnapshotFrameSchema, SimultaneousPhaseSnapshotSchema, SourceSnapshot, type SubmitInteractionCommand, SubmitInteractionCommandSchema, SystemActionEventSchema, TargetOptions, type ViewportSurface, type ViewportTransform, type WheelInput, Zone, ZoneHandlesSnapshotSchema, boardFeature, canonicalizePluginRuntimeJson, computePluginActionSetVersion, createGameInstance, createPluginProtocolEnvelopeSchema, digestPluginCommandRequest, digestPluginGameplayFrame, digestPluginRuntimeJson, dragFeature, encodeCanonicalPluginRuntimeJson, handFeature, hostSource, iframeSource, materializePluginGameplayFrame, panZoomFeature, parseHostToPluginEnvelope, parsePluginGameplayFrame, parsePluginSessionDescriptor, parsePluginToHostEnvelope, staticSource };
|
|
4009
|
+
export { ActionProps, type ActionSetVersionInput, AmbiguousTargetError, AuthAcceptedFrameSchema, AuthConnectFrameSchema, AuthRefreshFrameSchema, BoardBase, BoardCollection, type BoardFeature, type BoardLayoutOptions, BoardSpace, BoardSpaceCollection, BoardStaticProjectionSchema, type CancelInteractionCommand, CancelInteractionCommandSchema, Card, type CardOrigin, type ClientGameplayFrame, ClientGameplayFrameSchema, CommandSource, CoreInstance, DREAMBOARD_PLUGIN_PROTOCOL, DREAMBOARD_PLUGIN_PROTOCOL_VERSION, DREAMBOARD_SDK_PACKAGES, DREAMBOARD_SDK_PACKAGE_SET, DREAMBOARD_SDK_VERSION, type DragController, type DragState, type DreamboardSdkPackageName, type DreamboardSdkPackageSet, DropTarget, type FanCard, type FanLayout, type FanOptions, FeatureContext, Features, GESTURE_THRESHOLDS, GameEventDetailSchema, GameEventSchema, GameInstance, GameOutcomeSchema, GameSource, GameplayBackpressureFrameSchema, GameplayBackpressureOperationSchema, GameplayBackpressureReasonSchema, GameplayBasis, GameplayBasisSchema, GameplayCloseCode, type GameplayCredential, GameplayCredentialSchema, type GestureCallbacks, type GestureKind, type GestureOptions, type GesturePointer, type GestureRecognizer, type HandOptions, type HostToPluginEnvelope, HostToPluginEnvelopeSchema, type HostToPluginPayload, HostToPluginPayloadSchema, IdOf, InstanceOptions, InteractionDescriptor, type InteractionResult, InteractionResultSchema, type MaterializePluginGameplayFrameInput, type PanZoomOptions, PlayerId, PluginGameplayFrame, PluginGameplayFrameSchema, PluginPlayerSummarySchema, type PluginProtocolEnvelope, PluginSessionDescriptor, PluginSessionDescriptorSchema, type PluginToHostEnvelope, PluginToHostEnvelopeSchema, type PluginToHostPayload, PluginToHostPayloadSchema, ReadonlyData, ReducerBoardStaticProjection, ReducerSeatProjectionBundle, RuntimeJson, RuntimeTargetOptions, SeatCardId, SeatFrameSchema, SeatProjectionBundleSchema, type ServerGameplayFrame, ServerGameplayFrameSchema, SessionResumeFrameSchema, SessionSnapshotFrameSchema, SimultaneousPhaseSnapshotSchema, SourceSnapshot, type SubmitInteractionCommand, SubmitInteractionCommandSchema, SystemActionEventSchema, TargetOptions, type ViewportSurface, type ViewportTransform, type WheelInput, Zone, ZoneHandlesSnapshotSchema, boardFeature, canonicalizePluginRuntimeJson, computePluginActionSetVersion, createGameInstance, createGestureRecognizer, createPluginProtocolEnvelopeSchema, digestPluginCommandRequest, digestPluginGameplayFrame, digestPluginRuntimeJson, dragFeature, encodeCanonicalPluginRuntimeJson, fanLayout, handFeature, hostSource, iframeSource, liftFanCard, materializePluginGameplayFrame, originsFeature, panZoomFeature, parseHostToPluginEnvelope, parsePluginGameplayFrame, parsePluginSessionDescriptor, parsePluginToHostEnvelope, staticSource };
|