@dreamboard-games/sdk 0.2.0 → 0.2.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ThemeProvider-fy0_QzgO.d.ts → ThemeProvider-BBMVT3KG.d.ts} +1 -1
- package/dist/attributes-BeRyboMS.d.ts +279 -0
- package/dist/browser-interaction.d.ts +708 -0
- package/dist/browser-interaction.js +106 -0
- package/dist/browser-interaction.js.map +1 -0
- package/dist/{bundle-TIZcw8LB.d.ts → bundle-CDd5FKeD.d.ts} +3 -1
- package/dist/{chunk-U5C6BONG.js → chunk-326PGVAA.js} +2 -2
- package/dist/{chunk-VFTAA4WO.js → chunk-MKXPVOUT.js} +4 -2
- package/dist/chunk-MKXPVOUT.js.map +1 -0
- package/dist/{chunk-GKKBPPSW.js → chunk-MZNVHMJ5.js} +4 -4
- package/dist/{chunk-KAELH4KC.js → chunk-NKCRKGR2.js} +2 -2
- package/dist/{chunk-WN74KVNY.js → chunk-PEI3FIL2.js} +2 -2
- package/dist/chunk-PEI3FIL2.js.map +1 -0
- package/dist/chunk-QLG6VEMW.js +1691 -0
- package/dist/chunk-QLG6VEMW.js.map +1 -0
- package/dist/{chunk-WYPQ3GG5.js → chunk-WG4JQL3S.js} +4 -1
- package/dist/{chunk-WYPQ3GG5.js.map → chunk-WG4JQL3S.js.map} +1 -1
- package/dist/{chunk-7YAHLYBR.js → chunk-XV6D3ET4.js} +8 -4
- package/dist/{chunk-7YAHLYBR.js.map → chunk-XV6D3ET4.js.map} +1 -1
- package/dist/{chunk-TDSWKVZ4.js → chunk-ZABVH7AO.js} +1236 -17
- package/dist/chunk-ZABVH7AO.js.map +1 -0
- package/dist/{components-D5ZRE2Hl.d.ts → components-BoiVSYqx.d.ts} +1 -1
- package/dist/generated/runtime/primitives.d.ts +5 -4
- package/dist/generated/runtime/primitives.js +4 -3
- package/dist/generated/runtime-api.d.ts +1 -1
- package/dist/generated/runtime.d.ts +5 -4
- package/dist/generated/runtime.js +7 -6
- package/dist/generated/workspace-contract.d.ts +5 -4
- package/dist/generated/workspace-contract.js +6 -5
- package/dist/{hex-board-view-D_07hO6O.d.ts → hex-board-view-1iAyJRFn.d.ts} +1 -0
- package/dist/index.js +1 -1
- package/dist/infrastructure/reducer-bundle-abi.d.ts +113 -113
- package/dist/infrastructure/reducer-bundle-abi.js +1 -1
- package/dist/package-set.d.ts +2 -2
- package/dist/package-set.js +1 -1
- package/dist/reducer.d.ts +1 -1
- package/dist/reducer.js +305 -12
- package/dist/reducer.js.map +1 -1
- package/dist/runtime/primitives.d.ts +6 -5
- package/dist/runtime/primitives.js +4 -3
- package/dist/runtime/workspace-contract.d.ts +6 -5
- package/dist/runtime/workspace-contract.js +6 -5
- package/dist/{runtime-api-DWxvTr-O.d.ts → runtime-api-CPLm_XDG.d.ts} +6 -0
- package/dist/runtime.d.ts +5 -4
- package/dist/runtime.js +6 -5
- package/dist/testing.d.ts +2 -2
- package/dist/ui/components.d.ts +2 -2
- package/dist/ui/components.js +1 -1
- package/dist/{ui-contract-iQfTtUSL.d.ts → ui-contract-rzKBwOLC.d.ts} +5 -3
- package/dist/ui.d.ts +5 -5
- package/dist/ui.js +2 -2
- package/package.json +15 -9
- package/src/browser-interaction/attributes.ts +211 -0
- package/src/browser-interaction/canonical.ts +77 -0
- package/src/browser-interaction/constants.ts +77 -0
- package/src/browser-interaction/effects.ts +176 -0
- package/src/browser-interaction/index.ts +111 -0
- package/src/browser-interaction/normalize.ts +997 -0
- package/src/browser-interaction/registry.ts +70 -0
- package/src/browser-interaction/resolve.ts +596 -0
- package/src/browser-interaction/schemas.ts +152 -0
- package/src/browser-interaction/types.ts +304 -0
- package/src/browser-interaction.ts +1 -0
- package/src/generated/reducer-contract/wire.ts +1 -1
- package/src/generated/reducer-contract/zod.ts +3 -1
- package/src/package-set.ts +1 -1
- package/src/reducer/bundle/ingress-bundle.ts +1 -1
- package/src/reducer/bundle/trusted/interaction-types.ts +3 -0
- package/src/reducer/bundle/trusted/projection-builder.ts +337 -13
- package/src/reducer/ingress/input-codec.ts +1 -1
- package/src/reducer/ingress/session-codec.ts +1 -1
- package/src/runtime-internal/components/InteractionForm.tsx +345 -7
- package/src/runtime-internal/components/PluginRuntime.tsx +2 -0
- package/src/runtime-internal/components/board/target-layer.ts +2 -0
- package/src/runtime-internal/context/PluginStateContext.tsx +41 -0
- package/src/runtime-internal/hooks/useBoardInteractions.ts +73 -11
- package/src/runtime-internal/primitives/board.tsx +71 -0
- package/src/runtime-internal/primitives/interaction.tsx +160 -1
- package/src/runtime-internal/types/plugin-state.ts +6 -0
- package/src/runtime-internal/utils/browser-interaction-effects.ts +240 -0
- package/src/runtime-internal/utils/interaction-draft-digest.ts +252 -0
- package/src/runtime-internal/utils/semantic-projection-digest.ts +407 -0
- package/src/ui/components/board/HexGrid.tsx +3 -0
- package/src/ui/components/board/target-layer.ts +1 -0
- package/dist/chunk-TDSWKVZ4.js.map +0 -1
- package/dist/chunk-VFTAA4WO.js.map +0 -1
- package/dist/chunk-WN74KVNY.js.map +0 -1
- /package/dist/{chunk-U5C6BONG.js.map → chunk-326PGVAA.js.map} +0 -0
- /package/dist/{chunk-GKKBPPSW.js.map → chunk-MZNVHMJ5.js.map} +0 -0
- /package/dist/{chunk-KAELH4KC.js.map → chunk-NKCRKGR2.js.map} +0 -0
|
@@ -30,6 +30,12 @@ import {
|
|
|
30
30
|
shouldRouteInteractionPending,
|
|
31
31
|
} from "../utils/interaction-router.js";
|
|
32
32
|
import { isInteractionAvailable } from "../utils/interaction-status.js";
|
|
33
|
+
import {
|
|
34
|
+
createGameplayActuatorAttributes,
|
|
35
|
+
type BrowserInteractionAttributeMap,
|
|
36
|
+
} from "../../browser-interaction/index.js";
|
|
37
|
+
import { interactionDraftDigestForValues } from "../utils/interaction-draft-digest.js";
|
|
38
|
+
import { gameplayCandidateMetadata } from "../utils/browser-interaction-effects.js";
|
|
33
39
|
|
|
34
40
|
export type BoardEligibleTargets = Readonly<
|
|
35
41
|
Record<BoardTargetKind, ReadonlySet<string>>
|
|
@@ -379,7 +385,7 @@ export function useBoardInteractions<I extends string = string>(
|
|
|
379
385
|
return [];
|
|
380
386
|
}
|
|
381
387
|
if (!isInteractionAvailable(descriptor)) return [];
|
|
382
|
-
const draft =
|
|
388
|
+
const draft = drafts[descriptor.interactionKey] ?? {};
|
|
383
389
|
const inputKey = inputKeyForTarget(
|
|
384
390
|
descriptor,
|
|
385
391
|
targetKind,
|
|
@@ -388,14 +394,7 @@ export function useBoardInteractions<I extends string = string>(
|
|
|
388
394
|
);
|
|
389
395
|
if (!inputKey) return [];
|
|
390
396
|
const input = inputByTarget(descriptor, targetKind, targetId, draft);
|
|
391
|
-
if (
|
|
392
|
-
input &&
|
|
393
|
-
!isTargetSelectable(
|
|
394
|
-
input,
|
|
395
|
-
store.getDraft(descriptor.interactionKey),
|
|
396
|
-
targetId,
|
|
397
|
-
)
|
|
398
|
-
) {
|
|
397
|
+
if (input && !isTargetSelectable(input, draft, targetId)) {
|
|
399
398
|
return [];
|
|
400
399
|
}
|
|
401
400
|
const targets = eligibleTargetsForInput(descriptor, inputKey, draft);
|
|
@@ -410,7 +409,7 @@ export function useBoardInteractions<I extends string = string>(
|
|
|
410
409
|
});
|
|
411
410
|
return matches;
|
|
412
411
|
},
|
|
413
|
-
[armedIds,
|
|
412
|
+
[armedIds, drafts, interactions],
|
|
414
413
|
);
|
|
415
414
|
|
|
416
415
|
const selectByKind = useCallback(
|
|
@@ -486,9 +485,19 @@ export function useBoardInteractions<I extends string = string>(
|
|
|
486
485
|
? candidates.map((candidate) => candidate.descriptor.interactionKey)
|
|
487
486
|
: undefined,
|
|
488
487
|
unavailableReason: candidateUnavailableReason(selected, conflict),
|
|
488
|
+
browserAttributes: selected
|
|
489
|
+
? boardTargetBrowserAttributes({
|
|
490
|
+
descriptor: selected.descriptor,
|
|
491
|
+
inputKey: selected.inputKey,
|
|
492
|
+
targetKind,
|
|
493
|
+
targetId,
|
|
494
|
+
enabled: eligible && !!controllingPlayerId,
|
|
495
|
+
draft: drafts[selected.descriptor.interactionKey] ?? {},
|
|
496
|
+
})
|
|
497
|
+
: undefined,
|
|
489
498
|
};
|
|
490
499
|
},
|
|
491
|
-
[controllingPlayerId, pendingInteractionKey, resolveTargetMatches],
|
|
500
|
+
[controllingPlayerId, drafts, pendingInteractionKey, resolveTargetMatches],
|
|
492
501
|
);
|
|
493
502
|
|
|
494
503
|
const targetLayers = useMemo(() => {
|
|
@@ -634,6 +643,59 @@ interface MatchingDescriptor<I extends string> {
|
|
|
634
643
|
armed: boolean;
|
|
635
644
|
}
|
|
636
645
|
|
|
646
|
+
const GAMEPLAY_BROWSER_SCOPE_ID = "runtime";
|
|
647
|
+
|
|
648
|
+
function boardTargetBrowserAttributes({
|
|
649
|
+
descriptor,
|
|
650
|
+
inputKey,
|
|
651
|
+
targetKind,
|
|
652
|
+
targetId,
|
|
653
|
+
enabled,
|
|
654
|
+
draft,
|
|
655
|
+
}: {
|
|
656
|
+
descriptor: InteractionDescriptor;
|
|
657
|
+
inputKey: string;
|
|
658
|
+
targetKind: BoardTargetKind;
|
|
659
|
+
targetId: string;
|
|
660
|
+
enabled: boolean;
|
|
661
|
+
draft: Readonly<Record<string, unknown>>;
|
|
662
|
+
}): BrowserInteractionAttributeMap {
|
|
663
|
+
return createGameplayActuatorAttributes({
|
|
664
|
+
scopeId: GAMEPLAY_BROWSER_SCOPE_ID,
|
|
665
|
+
interactionKey: descriptor.interactionKey,
|
|
666
|
+
interactionId: descriptor.interactionId,
|
|
667
|
+
intent: "select",
|
|
668
|
+
enabled,
|
|
669
|
+
actuatorKind: "click",
|
|
670
|
+
actuatorId: `board:${targetKind}:${targetId}`,
|
|
671
|
+
...(descriptor.descriptorDigest !== undefined
|
|
672
|
+
? { descriptorDigest: descriptor.descriptorDigest }
|
|
673
|
+
: {}),
|
|
674
|
+
...(descriptor.draftDigest !== undefined
|
|
675
|
+
? { draftDigest: interactionDraftDigestForValues(descriptor, draft) }
|
|
676
|
+
: {}),
|
|
677
|
+
inputKey,
|
|
678
|
+
candidateValue: targetId,
|
|
679
|
+
candidateState: isBoardTargetSelected(draft[inputKey], targetId)
|
|
680
|
+
? "selected"
|
|
681
|
+
: "unselected",
|
|
682
|
+
semanticEffects: gameplayCandidateMetadata({
|
|
683
|
+
descriptor,
|
|
684
|
+
draftValues: draft,
|
|
685
|
+
inputKey,
|
|
686
|
+
candidateValue: targetId,
|
|
687
|
+
intent: "select",
|
|
688
|
+
}).semanticEffects,
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
function isBoardTargetSelected(value: unknown, targetId: string): boolean {
|
|
693
|
+
if (Array.isArray(value)) {
|
|
694
|
+
return value.some((item) => String(item) === targetId);
|
|
695
|
+
}
|
|
696
|
+
return value !== undefined && String(value) === targetId;
|
|
697
|
+
}
|
|
698
|
+
|
|
637
699
|
function selectDispatchCandidate<I extends string>(
|
|
638
700
|
matches: ReadonlyArray<MatchingDescriptor<I>>,
|
|
639
701
|
targetKind: BoardTargetKind,
|
|
@@ -40,6 +40,12 @@ import { runInteractionAction } from "./interaction-submit.js";
|
|
|
40
40
|
import { useGameActionError } from "./game.js";
|
|
41
41
|
import { isInteractionAvailable } from "../utils/interaction-status.js";
|
|
42
42
|
import { useInteractionUiStore } from "../context/InteractionDraftContext.js";
|
|
43
|
+
import {
|
|
44
|
+
createGameplayActuatorAttributes,
|
|
45
|
+
type BrowserInteractionAttributeMap,
|
|
46
|
+
} from "../../browser-interaction/index.js";
|
|
47
|
+
import { interactionDraftDigestForValues } from "../utils/interaction-draft-digest.js";
|
|
48
|
+
import { gameplayCandidateMetadata } from "../utils/browser-interaction-effects.js";
|
|
43
49
|
|
|
44
50
|
type BoardContextValue = BoardInteractionsContext;
|
|
45
51
|
|
|
@@ -312,6 +318,7 @@ function UnambiguousBoardTarget({
|
|
|
312
318
|
return renderPrimitive("button", {
|
|
313
319
|
type: "button",
|
|
314
320
|
...props,
|
|
321
|
+
...targetState.browserAttributes,
|
|
315
322
|
children,
|
|
316
323
|
disabled: isDisabled,
|
|
317
324
|
"aria-disabled": isDisabled,
|
|
@@ -377,9 +384,20 @@ function ExplicitBoardTarget({
|
|
|
377
384
|
(eligibleTargets ?? inputDescriptor.domain.eligibleTargets).includes(value);
|
|
378
385
|
const isDisabled =
|
|
379
386
|
disabled ?? (!isInteractionAvailable(descriptor) || !eligible);
|
|
387
|
+
const browserAttributes = inputKey
|
|
388
|
+
? boardTargetBrowserAttributes({
|
|
389
|
+
descriptor,
|
|
390
|
+
inputKey,
|
|
391
|
+
targetKind: kind,
|
|
392
|
+
targetId: value,
|
|
393
|
+
enabled: !isDisabled,
|
|
394
|
+
draft,
|
|
395
|
+
})
|
|
396
|
+
: undefined;
|
|
380
397
|
return renderPrimitive("button", {
|
|
381
398
|
type: "button",
|
|
382
399
|
...props,
|
|
400
|
+
...browserAttributes,
|
|
383
401
|
children,
|
|
384
402
|
disabled: isDisabled,
|
|
385
403
|
"aria-disabled": isDisabled,
|
|
@@ -447,6 +465,59 @@ function resolveExtraInputs(
|
|
|
447
465
|
: (extraInputs ?? {});
|
|
448
466
|
}
|
|
449
467
|
|
|
468
|
+
const GAMEPLAY_BROWSER_SCOPE_ID = "runtime";
|
|
469
|
+
|
|
470
|
+
function boardTargetBrowserAttributes({
|
|
471
|
+
descriptor,
|
|
472
|
+
inputKey,
|
|
473
|
+
targetKind,
|
|
474
|
+
targetId,
|
|
475
|
+
enabled,
|
|
476
|
+
draft,
|
|
477
|
+
}: {
|
|
478
|
+
descriptor: InteractionDescriptor;
|
|
479
|
+
inputKey: string;
|
|
480
|
+
targetKind: BoardTargetKind;
|
|
481
|
+
targetId: string;
|
|
482
|
+
enabled: boolean;
|
|
483
|
+
draft: Readonly<Record<string, unknown>>;
|
|
484
|
+
}): BrowserInteractionAttributeMap {
|
|
485
|
+
return createGameplayActuatorAttributes({
|
|
486
|
+
scopeId: GAMEPLAY_BROWSER_SCOPE_ID,
|
|
487
|
+
interactionKey: descriptor.interactionKey,
|
|
488
|
+
interactionId: descriptor.interactionId,
|
|
489
|
+
intent: "select",
|
|
490
|
+
enabled,
|
|
491
|
+
actuatorKind: "click",
|
|
492
|
+
actuatorId: `board:${targetKind}:${targetId}`,
|
|
493
|
+
...(descriptor.descriptorDigest !== undefined
|
|
494
|
+
? { descriptorDigest: descriptor.descriptorDigest }
|
|
495
|
+
: {}),
|
|
496
|
+
...(descriptor.draftDigest !== undefined
|
|
497
|
+
? { draftDigest: interactionDraftDigestForValues(descriptor, draft) }
|
|
498
|
+
: {}),
|
|
499
|
+
inputKey,
|
|
500
|
+
candidateValue: targetId,
|
|
501
|
+
candidateState: isBoardTargetSelected(draft[inputKey], targetId)
|
|
502
|
+
? "selected"
|
|
503
|
+
: "unselected",
|
|
504
|
+
semanticEffects: gameplayCandidateMetadata({
|
|
505
|
+
descriptor,
|
|
506
|
+
draftValues: draft,
|
|
507
|
+
inputKey,
|
|
508
|
+
candidateValue: targetId,
|
|
509
|
+
intent: "select",
|
|
510
|
+
}).semanticEffects,
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function isBoardTargetSelected(value: unknown, targetId: string): boolean {
|
|
515
|
+
if (Array.isArray(value)) {
|
|
516
|
+
return value.some((item) => String(item) === targetId);
|
|
517
|
+
}
|
|
518
|
+
return value !== undefined && String(value) === targetId;
|
|
519
|
+
}
|
|
520
|
+
|
|
450
521
|
export const Board = {
|
|
451
522
|
Root: BoardRoot,
|
|
452
523
|
State: BoardState,
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
isResolvedTargetDomain,
|
|
35
35
|
isTargetDomain,
|
|
36
36
|
isManyTargetSelectable,
|
|
37
|
+
resolveInputDomain,
|
|
37
38
|
} from "../utils/interaction-inputs.js";
|
|
38
39
|
import {
|
|
39
40
|
getInteractionDraftReadiness,
|
|
@@ -45,12 +46,25 @@ import {
|
|
|
45
46
|
interactionUnavailableReason,
|
|
46
47
|
isInteractionAvailable,
|
|
47
48
|
} from "../utils/interaction-status.js";
|
|
49
|
+
import {
|
|
50
|
+
gameplayCandidateMetadata,
|
|
51
|
+
gameplayPreparationPatternsForDescriptor,
|
|
52
|
+
gameplayScalarFillMetadata,
|
|
53
|
+
gameplaySubmitMetadata,
|
|
54
|
+
} from "../utils/browser-interaction-effects.js";
|
|
48
55
|
import { interactionLabel } from "../utils/interaction-labels.js";
|
|
49
56
|
import {
|
|
50
57
|
composeEventHandlers,
|
|
51
58
|
renderPrimitive,
|
|
52
59
|
type PrimitiveCommonProps,
|
|
53
60
|
} from "./primitive-props.js";
|
|
61
|
+
import {
|
|
62
|
+
createGameplayActuatorAttributes,
|
|
63
|
+
createGameplayInteractionRootAttributes,
|
|
64
|
+
type BrowserInteractionAttributeMap,
|
|
65
|
+
type GameplayActuatorAttributesInput,
|
|
66
|
+
type GameplayBrowserInteractionIntent,
|
|
67
|
+
} from "../../browser-interaction/index.js";
|
|
54
68
|
import {
|
|
55
69
|
BoundInteractionForm,
|
|
56
70
|
castInteractionDraft,
|
|
@@ -92,6 +106,56 @@ function humanizeInteraction(value: string): string {
|
|
|
92
106
|
.replace(/^./, (first: string) => first.toUpperCase());
|
|
93
107
|
}
|
|
94
108
|
|
|
109
|
+
const GAMEPLAY_BROWSER_SCOPE_ID = "runtime";
|
|
110
|
+
|
|
111
|
+
function gameplayActuatorAttributes({
|
|
112
|
+
descriptor,
|
|
113
|
+
inputKey,
|
|
114
|
+
intent,
|
|
115
|
+
candidateValue,
|
|
116
|
+
candidateState,
|
|
117
|
+
semanticEffects,
|
|
118
|
+
acceptedEffectPatterns,
|
|
119
|
+
preparationPatterns,
|
|
120
|
+
enabled,
|
|
121
|
+
actuatorKind,
|
|
122
|
+
actuatorId,
|
|
123
|
+
}: {
|
|
124
|
+
descriptor: InteractionDescriptor;
|
|
125
|
+
inputKey?: string;
|
|
126
|
+
intent: GameplayBrowserInteractionIntent;
|
|
127
|
+
candidateValue?: unknown;
|
|
128
|
+
candidateState?: "selected" | "unselected" | "mixed";
|
|
129
|
+
semanticEffects?: GameplayActuatorAttributesInput["semanticEffects"];
|
|
130
|
+
acceptedEffectPatterns?: GameplayActuatorAttributesInput["acceptedEffectPatterns"];
|
|
131
|
+
preparationPatterns?: GameplayActuatorAttributesInput["preparationPatterns"];
|
|
132
|
+
enabled: boolean;
|
|
133
|
+
actuatorKind: GameplayActuatorAttributesInput["actuatorKind"];
|
|
134
|
+
actuatorId: string;
|
|
135
|
+
}): BrowserInteractionAttributeMap {
|
|
136
|
+
return createGameplayActuatorAttributes({
|
|
137
|
+
scopeId: GAMEPLAY_BROWSER_SCOPE_ID,
|
|
138
|
+
interactionKey: descriptor.interactionKey,
|
|
139
|
+
interactionId: descriptor.interactionId,
|
|
140
|
+
intent,
|
|
141
|
+
enabled,
|
|
142
|
+
actuatorKind,
|
|
143
|
+
actuatorId,
|
|
144
|
+
...(descriptor.descriptorDigest !== undefined
|
|
145
|
+
? { descriptorDigest: descriptor.descriptorDigest }
|
|
146
|
+
: {}),
|
|
147
|
+
...(descriptor.draftDigest !== undefined
|
|
148
|
+
? { draftDigest: descriptor.draftDigest }
|
|
149
|
+
: {}),
|
|
150
|
+
...(inputKey !== undefined ? { inputKey } : {}),
|
|
151
|
+
...(candidateValue !== undefined ? { candidateValue } : {}),
|
|
152
|
+
...(candidateState !== undefined ? { candidateState } : {}),
|
|
153
|
+
...(semanticEffects !== undefined ? { semanticEffects } : {}),
|
|
154
|
+
...(acceptedEffectPatterns !== undefined ? { acceptedEffectPatterns } : {}),
|
|
155
|
+
...(preparationPatterns !== undefined ? { preparationPatterns } : {}),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
95
159
|
export function useInteractionPrimitiveContext(): InteractionContextValue {
|
|
96
160
|
const value = useContext(InteractionContext);
|
|
97
161
|
if (!value) {
|
|
@@ -155,9 +219,30 @@ function ResolvedInteractionRoot({
|
|
|
155
219
|
() => ({ interaction, descriptor, handle }),
|
|
156
220
|
[descriptor, handle, interaction],
|
|
157
221
|
);
|
|
222
|
+
const available = isInteractionAvailable(descriptor);
|
|
223
|
+
const rootAttributes = createGameplayInteractionRootAttributes({
|
|
224
|
+
scopeId: GAMEPLAY_BROWSER_SCOPE_ID,
|
|
225
|
+
interactionKey: descriptor.interactionKey,
|
|
226
|
+
interactionId: descriptor.interactionId,
|
|
227
|
+
...(descriptor.descriptorDigest !== undefined
|
|
228
|
+
? { descriptorDigest: descriptor.descriptorDigest }
|
|
229
|
+
: {}),
|
|
230
|
+
...(descriptor.draftDigest !== undefined
|
|
231
|
+
? { draftDigest: descriptor.draftDigest }
|
|
232
|
+
: {}),
|
|
233
|
+
readiness: available
|
|
234
|
+
? handle.isReady
|
|
235
|
+
? "ready"
|
|
236
|
+
: "blocked"
|
|
237
|
+
: "unavailable",
|
|
238
|
+
});
|
|
158
239
|
return (
|
|
159
240
|
<InteractionContext.Provider value={value}>
|
|
160
|
-
{
|
|
241
|
+
{renderPrimitive("span", {
|
|
242
|
+
...rootAttributes,
|
|
243
|
+
style: { display: "contents" },
|
|
244
|
+
children,
|
|
245
|
+
})}
|
|
161
246
|
</InteractionContext.Provider>
|
|
162
247
|
);
|
|
163
248
|
}
|
|
@@ -447,6 +532,19 @@ export function InteractionTrigger({
|
|
|
447
532
|
return renderPrimitive("button", {
|
|
448
533
|
type: "button",
|
|
449
534
|
...props,
|
|
535
|
+
...(descriptor
|
|
536
|
+
? gameplayActuatorAttributes({
|
|
537
|
+
descriptor,
|
|
538
|
+
intent: "arm",
|
|
539
|
+
enabled: !isDisabled,
|
|
540
|
+
actuatorKind: "click",
|
|
541
|
+
actuatorId: "primitive-trigger",
|
|
542
|
+
preparationPatterns: gameplayPreparationPatternsForDescriptor(
|
|
543
|
+
descriptor,
|
|
544
|
+
(handle?.values ?? {}) as Readonly<Record<string, unknown>>,
|
|
545
|
+
),
|
|
546
|
+
})
|
|
547
|
+
: {}),
|
|
450
548
|
disabled: isDisabled,
|
|
451
549
|
"aria-disabled": isDisabled,
|
|
452
550
|
"data-dreamboard-interaction-trigger": "",
|
|
@@ -595,6 +693,9 @@ export function InteractionSubmit({
|
|
|
595
693
|
const gameActionError = useGameActionError();
|
|
596
694
|
const isSubmitting = handle?.status === "submitting";
|
|
597
695
|
const hasExplicitParams = params !== undefined;
|
|
696
|
+
const submitMetadata = descriptor
|
|
697
|
+
? gameplaySubmitMetadata({ descriptor, explicitParams: hasExplicitParams })
|
|
698
|
+
: null;
|
|
598
699
|
const available = isInteractionAvailable(descriptor);
|
|
599
700
|
const isDisabled =
|
|
600
701
|
disabled === true ||
|
|
@@ -604,6 +705,16 @@ export function InteractionSubmit({
|
|
|
604
705
|
return renderPrimitive("button", {
|
|
605
706
|
type: "button",
|
|
606
707
|
...props,
|
|
708
|
+
...(descriptor
|
|
709
|
+
? gameplayActuatorAttributes({
|
|
710
|
+
descriptor,
|
|
711
|
+
intent: submitMetadata?.intent ?? "submit",
|
|
712
|
+
enabled: !isDisabled,
|
|
713
|
+
actuatorKind: "click",
|
|
714
|
+
actuatorId: "primitive-submit",
|
|
715
|
+
semanticEffects: submitMetadata?.semanticEffects,
|
|
716
|
+
})
|
|
717
|
+
: {}),
|
|
607
718
|
disabled: isDisabled,
|
|
608
719
|
"aria-disabled": isDisabled,
|
|
609
720
|
"data-dreamboard-interaction-submit": "",
|
|
@@ -650,9 +761,35 @@ export function InteractionInput({
|
|
|
650
761
|
const { descriptor, handle } = useInteractionPrimitiveContext();
|
|
651
762
|
const value = handle?.draft[name];
|
|
652
763
|
const isDisabled = disabled === true || !isInteractionAvailable(descriptor);
|
|
764
|
+
const inputDescriptor = descriptor ? inputByKey(descriptor, name) : undefined;
|
|
765
|
+
const resolvedInputDescriptor =
|
|
766
|
+
inputDescriptor && handle
|
|
767
|
+
? resolveInputDomain(
|
|
768
|
+
inputDescriptor,
|
|
769
|
+
handle.values as Readonly<Record<string, unknown>>,
|
|
770
|
+
)
|
|
771
|
+
: undefined;
|
|
772
|
+
const scalarFillMetadata =
|
|
773
|
+
resolvedInputDescriptor?.domain.type === "boundedNumber"
|
|
774
|
+
? gameplayScalarFillMetadata({
|
|
775
|
+
inputKey: name,
|
|
776
|
+
domain: resolvedInputDescriptor.domain,
|
|
777
|
+
})
|
|
778
|
+
: undefined;
|
|
653
779
|
return renderPrimitive("input", {
|
|
654
780
|
...props,
|
|
655
781
|
name,
|
|
782
|
+
...(descriptor
|
|
783
|
+
? gameplayActuatorAttributes({
|
|
784
|
+
descriptor,
|
|
785
|
+
inputKey: name,
|
|
786
|
+
intent: "fill",
|
|
787
|
+
enabled: !isDisabled,
|
|
788
|
+
actuatorKind: "fill",
|
|
789
|
+
actuatorId: `primitive-input:${name}`,
|
|
790
|
+
acceptedEffectPatterns: scalarFillMetadata?.acceptedEffectPatterns,
|
|
791
|
+
})
|
|
792
|
+
: {}),
|
|
656
793
|
disabled: isDisabled,
|
|
657
794
|
"aria-disabled": isDisabled,
|
|
658
795
|
"data-dreamboard-interaction-input": "",
|
|
@@ -850,6 +987,28 @@ export function InteractionCardInput<
|
|
|
850
987
|
type: "button",
|
|
851
988
|
...props,
|
|
852
989
|
children: renderedChildren,
|
|
990
|
+
...(descriptor
|
|
991
|
+
? gameplayActuatorAttributes({
|
|
992
|
+
descriptor,
|
|
993
|
+
inputKey: input,
|
|
994
|
+
intent: selection?.mode === "many" ? "toggle" : "select",
|
|
995
|
+
candidateValue: cardId,
|
|
996
|
+
candidateState: isSelected ? "selected" : "unselected",
|
|
997
|
+
enabled: !isDisabled,
|
|
998
|
+
actuatorKind: "click",
|
|
999
|
+
actuatorId: `primitive-card:${input}:${cardId ?? "missing"}`,
|
|
1000
|
+
semanticEffects:
|
|
1001
|
+
cardId !== undefined
|
|
1002
|
+
? gameplayCandidateMetadata({
|
|
1003
|
+
descriptor,
|
|
1004
|
+
draftValues: liveDraft,
|
|
1005
|
+
inputKey: input,
|
|
1006
|
+
candidateValue: cardId,
|
|
1007
|
+
intent: selection?.mode === "many" ? "toggle" : "select",
|
|
1008
|
+
}).semanticEffects
|
|
1009
|
+
: undefined,
|
|
1010
|
+
})
|
|
1011
|
+
: {}),
|
|
853
1012
|
disabled: isDisabled,
|
|
854
1013
|
"aria-disabled": isDisabled,
|
|
855
1014
|
"aria-pressed": isSelected,
|
|
@@ -388,6 +388,12 @@ interface InteractionDescriptorBase<Key extends string = string> {
|
|
|
388
388
|
interactionId: string;
|
|
389
389
|
/** Draft commit policy. Always materialized by the trusted reducer bundle. */
|
|
390
390
|
commit: InteractionCommitPolicy;
|
|
391
|
+
/** Canonical descriptor digest used by browser replay/protocol tooling when projected by the host. */
|
|
392
|
+
descriptorDigest?: string;
|
|
393
|
+
/** Explicit authoring/runtime actor seat used by browser replay draft digests. */
|
|
394
|
+
actorSeat?: number;
|
|
395
|
+
/** Canonical draft digest used by browser replay/protocol tooling when projected by the host. */
|
|
396
|
+
draftDigest?: string;
|
|
391
397
|
/** Source zone id for zone-scoped interactions (e.g., cardInput). */
|
|
392
398
|
zoneId?: string;
|
|
393
399
|
/** Source zone ids for zone-scoped interactions that span multiple zones. */
|