@dreamboard-games/ui-sdk 0.0.41
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/LICENSE +89 -0
- package/NOTICE +1 -0
- package/README.md +154 -0
- package/dist/components/ActionButton.d.ts +13 -0
- package/dist/components/ActionButton.d.ts.map +1 -0
- package/dist/components/ActionButton.js +14 -0
- package/dist/components/ActionPanel.d.ts +33 -0
- package/dist/components/ActionPanel.d.ts.map +1 -0
- package/dist/components/ActionPanel.js +148 -0
- package/dist/components/Card.d.ts +29 -0
- package/dist/components/Card.d.ts.map +1 -0
- package/dist/components/Card.js +220 -0
- package/dist/components/ChromeSuppressionContext.d.ts +7 -0
- package/dist/components/ChromeSuppressionContext.d.ts.map +1 -0
- package/dist/components/ChromeSuppressionContext.js +34 -0
- package/dist/components/CostDisplay.d.ts +22 -0
- package/dist/components/CostDisplay.d.ts.map +1 -0
- package/dist/components/CostDisplay.js +41 -0
- package/dist/components/DiceRoller.d.ts +30 -0
- package/dist/components/DiceRoller.d.ts.map +1 -0
- package/dist/components/DiceRoller.js +319 -0
- package/dist/components/Drawer.d.ts +19 -0
- package/dist/components/Drawer.d.ts.map +1 -0
- package/dist/components/Drawer.js +55 -0
- package/dist/components/ErrorBoundary.d.ts +24 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.js +37 -0
- package/dist/components/GameEndDisplay.d.ts +27 -0
- package/dist/components/GameEndDisplay.d.ts.map +1 -0
- package/dist/components/GameEndDisplay.js +185 -0
- package/dist/components/GameSkeleton.d.ts +12 -0
- package/dist/components/GameSkeleton.d.ts.map +1 -0
- package/dist/components/GameSkeleton.js +54 -0
- package/dist/components/Hand.d.ts +99 -0
- package/dist/components/Hand.d.ts.map +1 -0
- package/dist/components/Hand.js +162 -0
- package/dist/components/HandDock.d.ts +35 -0
- package/dist/components/HandDock.d.ts.map +1 -0
- package/dist/components/HandDock.js +124 -0
- package/dist/components/InteractionForm.d.ts +50 -0
- package/dist/components/InteractionForm.d.ts.map +1 -0
- package/dist/components/InteractionForm.js +402 -0
- package/dist/components/MoreActions.d.ts +49 -0
- package/dist/components/MoreActions.d.ts.map +1 -0
- package/dist/components/MoreActions.js +64 -0
- package/dist/components/PhaseIndicator.d.ts +35 -0
- package/dist/components/PhaseIndicator.d.ts.map +1 -0
- package/dist/components/PhaseIndicator.js +212 -0
- package/dist/components/PlayArea.d.ts +28 -0
- package/dist/components/PlayArea.d.ts.map +1 -0
- package/dist/components/PlayArea.js +48 -0
- package/dist/components/PluginRuntime.d.ts +37 -0
- package/dist/components/PluginRuntime.d.ts.map +1 -0
- package/dist/components/PluginRuntime.js +47 -0
- package/dist/components/PrimaryActionButton.d.ts +98 -0
- package/dist/components/PrimaryActionButton.d.ts.map +1 -0
- package/dist/components/PrimaryActionButton.js +183 -0
- package/dist/components/PrimaryButton.d.ts +20 -0
- package/dist/components/PrimaryButton.d.ts.map +1 -0
- package/dist/components/PrimaryButton.js +5 -0
- package/dist/components/PromptDialogHost.d.ts +15 -0
- package/dist/components/PromptDialogHost.d.ts.map +1 -0
- package/dist/components/PromptDialogHost.js +22 -0
- package/dist/components/ResourceCounter.d.ts +38 -0
- package/dist/components/ResourceCounter.d.ts.map +1 -0
- package/dist/components/ResourceCounter.js +118 -0
- package/dist/components/ThemedButton.d.ts +12 -0
- package/dist/components/ThemedButton.d.ts.map +1 -0
- package/dist/components/ThemedButton.js +38 -0
- package/dist/components/Toast.d.ts +35 -0
- package/dist/components/Toast.d.ts.map +1 -0
- package/dist/components/Toast.js +116 -0
- package/dist/components/board/HexGrid.d.ts +344 -0
- package/dist/components/board/HexGrid.d.ts.map +1 -0
- package/dist/components/board/HexGrid.js +340 -0
- package/dist/components/board/NetworkGraph.d.ts +100 -0
- package/dist/components/board/NetworkGraph.d.ts.map +1 -0
- package/dist/components/board/NetworkGraph.js +123 -0
- package/dist/components/board/SlotSystem.d.ts +71 -0
- package/dist/components/board/SlotSystem.d.ts.map +1 -0
- package/dist/components/board/SlotSystem.js +87 -0
- package/dist/components/board/SquareGrid.d.ts +188 -0
- package/dist/components/board/SquareGrid.d.ts.map +1 -0
- package/dist/components/board/SquareGrid.js +328 -0
- package/dist/components/board/TrackBoard.d.ts +113 -0
- package/dist/components/board/TrackBoard.d.ts.map +1 -0
- package/dist/components/board/TrackBoard.js +135 -0
- package/dist/components/board/ZoneMap.d.ts +88 -0
- package/dist/components/board/ZoneMap.d.ts.map +1 -0
- package/dist/components/board/ZoneMap.js +133 -0
- package/dist/components/board/hex-board-view.d.ts +69 -0
- package/dist/components/board/hex-board-view.d.ts.map +1 -0
- package/dist/components/board/hex-board-view.js +60 -0
- package/dist/components/board/index.d.ts +23 -0
- package/dist/components/board/index.d.ts.map +1 -0
- package/dist/components/board/index.js +40 -0
- package/dist/components/board/interaction-accessibility.d.ts +5 -0
- package/dist/components/board/interaction-accessibility.d.ts.map +1 -0
- package/dist/components/board/interaction-accessibility.js +13 -0
- package/dist/components/board/target-layer.d.ts +13 -0
- package/dist/components/board/target-layer.d.ts.map +1 -0
- package/dist/components/board/target-layer.js +10 -0
- package/dist/components/card-render-content.type-test.d.ts +2 -0
- package/dist/components/card-render-content.type-test.d.ts.map +1 -0
- package/dist/components/card-render-content.type-test.js +1 -0
- package/dist/components/index.d.ts +34 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +35 -0
- package/dist/components/interaction-dialog-behavior.d.ts +15 -0
- package/dist/components/interaction-dialog-behavior.d.ts.map +1 -0
- package/dist/components/interaction-dialog-behavior.js +9 -0
- package/dist/components/surfaces/BlockerSurface.d.ts +27 -0
- package/dist/components/surfaces/BlockerSurface.d.ts.map +1 -0
- package/dist/components/surfaces/BlockerSurface.js +38 -0
- package/dist/components/surfaces/BoardSurface.d.ts +77 -0
- package/dist/components/surfaces/BoardSurface.d.ts.map +1 -0
- package/dist/components/surfaces/BoardSurface.js +180 -0
- package/dist/components/surfaces/ChromeSurface.d.ts +29 -0
- package/dist/components/surfaces/ChromeSurface.d.ts.map +1 -0
- package/dist/components/surfaces/ChromeSurface.js +34 -0
- package/dist/components/surfaces/ExhaustivenessAudit.d.ts +32 -0
- package/dist/components/surfaces/ExhaustivenessAudit.d.ts.map +1 -0
- package/dist/components/surfaces/ExhaustivenessAudit.js +65 -0
- package/dist/components/surfaces/InboxSurface.d.ts +40 -0
- package/dist/components/surfaces/InboxSurface.d.ts.map +1 -0
- package/dist/components/surfaces/InboxSurface.js +99 -0
- package/dist/components/surfaces/MarketSurface.d.ts +62 -0
- package/dist/components/surfaces/MarketSurface.d.ts.map +1 -0
- package/dist/components/surfaces/MarketSurface.js +242 -0
- package/dist/components/surfaces/PanelSurface.d.ts +111 -0
- package/dist/components/surfaces/PanelSurface.d.ts.map +1 -0
- package/dist/components/surfaces/PanelSurface.js +180 -0
- package/dist/components/surfaces/PlayerCardsSurface.d.ts +104 -0
- package/dist/components/surfaces/PlayerCardsSurface.d.ts.map +1 -0
- package/dist/components/surfaces/PlayerCardsSurface.js +178 -0
- package/dist/components/surfaces/internal/CardZoneFollowUpForm.d.ts +7 -0
- package/dist/components/surfaces/internal/CardZoneFollowUpForm.d.ts.map +1 -0
- package/dist/components/surfaces/internal/CardZoneFollowUpForm.js +9 -0
- package/dist/components/surfaces/internal/DefaultInteractionButton.d.ts +71 -0
- package/dist/components/surfaces/internal/DefaultInteractionButton.d.ts.map +1 -0
- package/dist/components/surfaces/internal/DefaultInteractionButton.js +82 -0
- package/dist/components/surfaces/internal/useCardZoneInteractions.d.ts +21 -0
- package/dist/components/surfaces/internal/useCardZoneInteractions.d.ts.map +1 -0
- package/dist/components/surfaces/internal/useCardZoneInteractions.js +202 -0
- package/dist/components/surfaces/types.d.ts +59 -0
- package/dist/components/surfaces/types.d.ts.map +1 -0
- package/dist/components/surfaces/types.js +1 -0
- package/dist/context/ClientParamSchemaContext.d.ts +21 -0
- package/dist/context/ClientParamSchemaContext.d.ts.map +1 -0
- package/dist/context/ClientParamSchemaContext.js +12 -0
- package/dist/context/InteractionDraftContext.d.ts +69 -0
- package/dist/context/InteractionDraftContext.d.ts.map +1 -0
- package/dist/context/InteractionDraftContext.js +145 -0
- package/dist/context/PluginSessionContext.d.ts +33 -0
- package/dist/context/PluginSessionContext.d.ts.map +1 -0
- package/dist/context/PluginSessionContext.js +38 -0
- package/dist/context/PluginStateContext.d.ts +116 -0
- package/dist/context/PluginStateContext.d.ts.map +1 -0
- package/dist/context/PluginStateContext.js +186 -0
- package/dist/context/RuntimeContext.d.ts +49 -0
- package/dist/context/RuntimeContext.d.ts.map +1 -0
- package/dist/context/RuntimeContext.js +67 -0
- package/dist/defaults/components.d.ts +52 -0
- package/dist/defaults/components.d.ts.map +1 -0
- package/dist/defaults/components.js +159 -0
- package/dist/defaults/index.d.ts +2 -0
- package/dist/defaults/index.d.ts.map +1 -0
- package/dist/defaults/index.js +1 -0
- package/dist/errors/ValidationError.d.ts +10 -0
- package/dist/errors/ValidationError.d.ts.map +1 -0
- package/dist/errors/ValidationError.js +23 -0
- package/dist/helpers/cards.d.ts +3 -0
- package/dist/helpers/cards.d.ts.map +1 -0
- package/dist/helpers/cards.js +11 -0
- package/dist/helpers/track-board.d.ts +79 -0
- package/dist/helpers/track-board.d.ts.map +1 -0
- package/dist/helpers/track-board.js +56 -0
- package/dist/hooks/useActivePlayers.d.ts +16 -0
- package/dist/hooks/useActivePlayers.d.ts.map +1 -0
- package/dist/hooks/useActivePlayers.js +17 -0
- package/dist/hooks/useBoardInteractions.d.ts +110 -0
- package/dist/hooks/useBoardInteractions.d.ts.map +1 -0
- package/dist/hooks/useBoardInteractions.js +248 -0
- package/dist/hooks/useBoardTopology.d.ts +23 -0
- package/dist/hooks/useBoardTopology.d.ts.map +1 -0
- package/dist/hooks/useBoardTopology.js +128 -0
- package/dist/hooks/useCards.d.ts +3 -0
- package/dist/hooks/useCards.d.ts.map +1 -0
- package/dist/hooks/useCards.js +5 -0
- package/dist/hooks/useGameSelector.d.ts +13 -0
- package/dist/hooks/useGameSelector.d.ts.map +1 -0
- package/dist/hooks/useGameSelector.js +67 -0
- package/dist/hooks/useGameView.d.ts +6 -0
- package/dist/hooks/useGameView.d.ts.map +1 -0
- package/dist/hooks/useGameView.js +7 -0
- package/dist/hooks/useHandLayout.d.ts +120 -0
- package/dist/hooks/useHandLayout.d.ts.map +1 -0
- package/dist/hooks/useHandLayout.js +235 -0
- package/dist/hooks/useHexBoard.d.ts +19 -0
- package/dist/hooks/useHexBoard.d.ts.map +1 -0
- package/dist/hooks/useHexBoard.js +28 -0
- package/dist/hooks/useHexGrid.d.ts +56 -0
- package/dist/hooks/useHexGrid.d.ts.map +1 -0
- package/dist/hooks/useHexGrid.js +112 -0
- package/dist/hooks/useInteractionByKey.d.ts +29 -0
- package/dist/hooks/useInteractionByKey.d.ts.map +1 -0
- package/dist/hooks/useInteractionByKey.js +263 -0
- package/dist/hooks/useInteractionHandle.d.ts +103 -0
- package/dist/hooks/useInteractionHandle.d.ts.map +1 -0
- package/dist/hooks/useInteractionHandle.js +254 -0
- package/dist/hooks/useIsMobile.d.ts +7 -0
- package/dist/hooks/useIsMobile.d.ts.map +1 -0
- package/dist/hooks/useIsMobile.js +29 -0
- package/dist/hooks/useIsMyTurn.d.ts +6 -0
- package/dist/hooks/useIsMyTurn.d.ts.map +1 -0
- package/dist/hooks/useIsMyTurn.js +11 -0
- package/dist/hooks/useLobby.d.ts +28 -0
- package/dist/hooks/useLobby.d.ts.map +1 -0
- package/dist/hooks/useLobby.js +60 -0
- package/dist/hooks/useMe.d.ts +11 -0
- package/dist/hooks/useMe.d.ts.map +1 -0
- package/dist/hooks/useMe.js +32 -0
- package/dist/hooks/usePanZoom.d.ts +113 -0
- package/dist/hooks/usePanZoom.d.ts.map +1 -0
- package/dist/hooks/usePanZoom.js +165 -0
- package/dist/hooks/usePlayerInfo.d.ts +4 -0
- package/dist/hooks/usePlayerInfo.d.ts.map +1 -0
- package/dist/hooks/usePlayerInfo.js +21 -0
- package/dist/hooks/usePlayerTurnOrder.d.ts +15 -0
- package/dist/hooks/usePlayerTurnOrder.d.ts.map +1 -0
- package/dist/hooks/usePlayerTurnOrder.js +22 -0
- package/dist/hooks/usePluginRuntime.d.ts +45 -0
- package/dist/hooks/usePluginRuntime.d.ts.map +1 -0
- package/dist/hooks/usePluginRuntime.js +92 -0
- package/dist/hooks/useSeatInbox.d.ts +22 -0
- package/dist/hooks/useSeatInbox.d.ts.map +1 -0
- package/dist/hooks/useSeatInbox.js +43 -0
- package/dist/hooks/useSimultaneousPhase.d.ts +7 -0
- package/dist/hooks/useSimultaneousPhase.d.ts.map +1 -0
- package/dist/hooks/useSimultaneousPhase.js +8 -0
- package/dist/hooks/useSquareBoard.d.ts +21 -0
- package/dist/hooks/useSquareBoard.d.ts.map +1 -0
- package/dist/hooks/useSquareBoard.js +67 -0
- package/dist/hooks/useSquareGrid.d.ts +96 -0
- package/dist/hooks/useSquareGrid.d.ts.map +1 -0
- package/dist/hooks/useSquareGrid.js +152 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/internal/ui/alert.d.ts +8 -0
- package/dist/internal/ui/alert.d.ts.map +1 -0
- package/dist/internal/ui/alert.js +11 -0
- package/dist/internal/ui/button.d.ts +10 -0
- package/dist/internal/ui/button.d.ts.map +1 -0
- package/dist/internal/ui/button.js +21 -0
- package/dist/internal/ui/dialog.d.ts +16 -0
- package/dist/internal/ui/dialog.d.ts.map +1 -0
- package/dist/internal/ui/dialog.js +35 -0
- package/dist/internal/ui/input.d.ts +3 -0
- package/dist/internal/ui/input.d.ts.map +1 -0
- package/dist/internal/ui/input.js +5 -0
- package/dist/internal/ui/label.d.ts +4 -0
- package/dist/internal/ui/label.d.ts.map +1 -0
- package/dist/internal/ui/label.js +7 -0
- package/dist/internal/ui/select.d.ts +9 -0
- package/dist/internal/ui/select.d.ts.map +1 -0
- package/dist/internal/ui/select.js +23 -0
- package/dist/internal/ui/tooltip.d.ts +7 -0
- package/dist/internal/ui/tooltip.d.ts.map +1 -0
- package/dist/internal/ui/tooltip.js +16 -0
- package/dist/internal/ui/utils.d.ts +3 -0
- package/dist/internal/ui/utils.d.ts.map +1 -0
- package/dist/internal/ui/utils.js +4 -0
- package/dist/internal.d.ts +7 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +4 -0
- package/dist/plugin-styles.css +246 -0
- package/dist/primitives/board.d.ts +29 -0
- package/dist/primitives/board.d.ts.map +1 -0
- package/dist/primitives/board.js +163 -0
- package/dist/primitives/game-ui-provider.d.ts +12 -0
- package/dist/primitives/game-ui-provider.d.ts.map +1 -0
- package/dist/primitives/game-ui-provider.js +7 -0
- package/dist/primitives/index.d.ts +8 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +7 -0
- package/dist/primitives/interaction.d.ts +52 -0
- package/dist/primitives/interaction.d.ts.map +1 -0
- package/dist/primitives/interaction.js +250 -0
- package/dist/primitives/phase.d.ts +15 -0
- package/dist/primitives/phase.d.ts.map +1 -0
- package/dist/primitives/phase.js +18 -0
- package/dist/primitives/player-roster.d.ts +64 -0
- package/dist/primitives/player-roster.d.ts.map +1 -0
- package/dist/primitives/player-roster.js +149 -0
- package/dist/primitives/primitive-props.d.ts +15 -0
- package/dist/primitives/primitive-props.d.ts.map +1 -0
- package/dist/primitives/primitive-props.js +39 -0
- package/dist/primitives/prompt.d.ts +44 -0
- package/dist/primitives/prompt.d.ts.map +1 -0
- package/dist/primitives/prompt.js +101 -0
- package/dist/primitives/zone.d.ts +31 -0
- package/dist/primitives/zone.d.ts.map +1 -0
- package/dist/primitives/zone.js +58 -0
- package/dist/reducer.d.ts +21 -0
- package/dist/reducer.d.ts.map +1 -0
- package/dist/reducer.js +14 -0
- package/dist/runtime/createPluginRuntimeAPI.d.ts +67 -0
- package/dist/runtime/createPluginRuntimeAPI.d.ts.map +1 -0
- package/dist/runtime/createPluginRuntimeAPI.js +419 -0
- package/dist/theme/ThemeProvider.d.ts +98 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +148 -0
- package/dist/theme/board.d.ts +42 -0
- package/dist/theme/board.d.ts.map +1 -0
- package/dist/theme/board.js +34 -0
- package/dist/theme/css-vars.d.ts +31 -0
- package/dist/theme/css-vars.d.ts.map +1 -0
- package/dist/theme/css-vars.js +88 -0
- package/dist/theme/derive.d.ts +66 -0
- package/dist/theme/derive.d.ts.map +1 -0
- package/dist/theme/derive.js +161 -0
- package/dist/theme/index.d.ts +22 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +20 -0
- package/dist/theme/presets/arcade.d.ts +10 -0
- package/dist/theme/presets/arcade.d.ts.map +1 -0
- package/dist/theme/presets/arcade.js +257 -0
- package/dist/theme/presets/studio.d.ts +10 -0
- package/dist/theme/presets/studio.d.ts.map +1 -0
- package/dist/theme/presets/studio.js +257 -0
- package/dist/theme/presets/tabletop.d.ts +15 -0
- package/dist/theme/presets/tabletop.d.ts.map +1 -0
- package/dist/theme/presets/tabletop.js +262 -0
- package/dist/theme/tokens.d.ts +345 -0
- package/dist/theme/tokens.d.ts.map +1 -0
- package/dist/theme/tokens.js +57 -0
- package/dist/types/player-state.d.ts +337 -0
- package/dist/types/player-state.d.ts.map +1 -0
- package/dist/types/player-state.js +1 -0
- package/dist/types/plugin-state.d.ts +324 -0
- package/dist/types/plugin-state.d.ts.map +1 -0
- package/dist/types/plugin-state.js +1 -0
- package/dist/types/reducer-state.d.ts +10 -0
- package/dist/types/reducer-state.d.ts.map +1 -0
- package/dist/types/reducer-state.js +1 -0
- package/dist/types/runtime-api.d.ts +99 -0
- package/dist/types/runtime-api.d.ts.map +1 -0
- package/dist/types/runtime-api.js +1 -0
- package/dist/types/tiled-board.d.ts +187 -0
- package/dist/types/tiled-board.d.ts.map +1 -0
- package/dist/types/tiled-board.js +226 -0
- package/dist/ui-contract.d.ts +78 -0
- package/dist/ui-contract.d.ts.map +1 -0
- package/dist/ui-contract.js +15 -0
- package/dist/ui-sdk.d.ts +3409 -0
- package/dist/utils/interaction-inputs.d.ts +22 -0
- package/dist/utils/interaction-inputs.d.ts.map +1 -0
- package/dist/utils/interaction-inputs.js +219 -0
- package/dist/utils/interaction-labels.d.ts +4 -0
- package/dist/utils/interaction-labels.d.ts.map +1 -0
- package/dist/utils/interaction-labels.js +18 -0
- package/dist/utils/interaction-status.d.ts +15 -0
- package/dist/utils/interaction-status.d.ts.map +1 -0
- package/dist/utils/interaction-status.js +31 -0
- package/package.json +101 -0
- package/src/components/ActionButton.tsx +48 -0
- package/src/components/ActionPanel.tsx +310 -0
- package/src/components/Card.tsx +385 -0
- package/src/components/ChromeSuppressionContext.tsx +70 -0
- package/src/components/CostDisplay.test.tsx +23 -0
- package/src/components/CostDisplay.tsx +145 -0
- package/src/components/DiceRoller.tsx +601 -0
- package/src/components/Drawer.tsx +179 -0
- package/src/components/ErrorBoundary.tsx +119 -0
- package/src/components/GameEndDisplay.test.tsx +19 -0
- package/src/components/GameEndDisplay.tsx +398 -0
- package/src/components/GameSkeleton.tsx +260 -0
- package/src/components/Hand.tsx +387 -0
- package/src/components/HandDock.tsx +257 -0
- package/src/components/InteractionForm.test.tsx +303 -0
- package/src/components/InteractionForm.tsx +1029 -0
- package/src/components/MoreActions.test.tsx +93 -0
- package/src/components/MoreActions.tsx +143 -0
- package/src/components/PhaseIndicator.tsx +341 -0
- package/src/components/PlayArea.tsx +125 -0
- package/src/components/PluginRuntime.tsx +92 -0
- package/src/components/PrimaryActionButton.test.tsx +138 -0
- package/src/components/PrimaryActionButton.tsx +351 -0
- package/src/components/PrimaryButton.tsx +44 -0
- package/src/components/PromptDialogHost.tsx +92 -0
- package/src/components/ResourceCounter.test.tsx +29 -0
- package/src/components/ResourceCounter.tsx +275 -0
- package/src/components/ThemedButton.tsx +78 -0
- package/src/components/Toast.tsx +251 -0
- package/src/components/__fixtures__/ActionButton.fixture.tsx +234 -0
- package/src/components/__fixtures__/ActionPanel.fixture.tsx +298 -0
- package/src/components/__fixtures__/Card.fixture.tsx +185 -0
- package/src/components/__fixtures__/CostDisplay.fixture.tsx +156 -0
- package/src/components/__fixtures__/DiceRoller.fixture.tsx +435 -0
- package/src/components/__fixtures__/Drawer.fixture.tsx +113 -0
- package/src/components/__fixtures__/ErrorBoundary.fixture.tsx +82 -0
- package/src/components/__fixtures__/GameEndDisplay.fixture.tsx +188 -0
- package/src/components/__fixtures__/GameSkeleton.fixture.tsx +46 -0
- package/src/components/__fixtures__/Hand.fixture.tsx +522 -0
- package/src/components/__fixtures__/HexGrid.fixture.tsx +1181 -0
- package/src/components/__fixtures__/NetworkGraph.fixture.tsx +599 -0
- package/src/components/__fixtures__/PhaseIndicator.fixture.tsx +181 -0
- package/src/components/__fixtures__/PlayArea.fixture.tsx +221 -0
- package/src/components/__fixtures__/ResourceCounter.fixture.tsx +227 -0
- package/src/components/__fixtures__/SlotSystem.fixture.tsx +824 -0
- package/src/components/__fixtures__/SquareGrid.fixture.tsx +764 -0
- package/src/components/__fixtures__/Toast.fixture.tsx +97 -0
- package/src/components/__fixtures__/TrackBoard.fixture.tsx +685 -0
- package/src/components/__fixtures__/ZoneMap.fixture.tsx +754 -0
- package/src/components/board/HexGrid.tsx +1294 -0
- package/src/components/board/NetworkGraph.tsx +476 -0
- package/src/components/board/SlotSystem.tsx +339 -0
- package/src/components/board/SquareGrid.tsx +1165 -0
- package/src/components/board/TrackBoard.tsx +496 -0
- package/src/components/board/ZoneMap.tsx +448 -0
- package/src/components/board/hex-board-view.test.tsx +114 -0
- package/src/components/board/hex-board-view.ts +123 -0
- package/src/components/board/index.ts +142 -0
- package/src/components/board/interaction-accessibility.ts +21 -0
- package/src/components/board/target-layer-grids.test.tsx +420 -0
- package/src/components/board/target-layer.ts +30 -0
- package/src/components/card-render-content.type-test.ts +27 -0
- package/src/components/index.ts +208 -0
- package/src/components/interaction-dialog-behavior.test.ts +23 -0
- package/src/components/interaction-dialog-behavior.ts +22 -0
- package/src/components/surfaces/BlockerSurface.test.tsx +158 -0
- package/src/components/surfaces/BlockerSurface.tsx +127 -0
- package/src/components/surfaces/BoardSurface.tsx +340 -0
- package/src/components/surfaces/ChromeSurface.tsx +123 -0
- package/src/components/surfaces/ExhaustivenessAudit.tsx +91 -0
- package/src/components/surfaces/InboxSurface.test.tsx +149 -0
- package/src/components/surfaces/InboxSurface.tsx +245 -0
- package/src/components/surfaces/MarketSurface.tsx +544 -0
- package/src/components/surfaces/PanelSurface.test.tsx +496 -0
- package/src/components/surfaces/PanelSurface.tsx +458 -0
- package/src/components/surfaces/PlayerCardsSurface.tsx +525 -0
- package/src/components/surfaces/internal/CardZoneFollowUpForm.tsx +35 -0
- package/src/components/surfaces/internal/DefaultInteractionButton.tsx +219 -0
- package/src/components/surfaces/internal/useCardZoneInteractions.ts +311 -0
- package/src/components/surfaces/types.ts +100 -0
- package/src/context/ClientParamSchemaContext.tsx +44 -0
- package/src/context/InteractionDraftContext.tsx +204 -0
- package/src/context/PluginSessionContext.tsx +47 -0
- package/src/context/PluginStateContext.tsx +254 -0
- package/src/context/RuntimeContext.tsx +96 -0
- package/src/defaults/components.tsx +442 -0
- package/src/defaults/defaults.test.tsx +230 -0
- package/src/defaults/index.ts +1 -0
- package/src/errors/ValidationError.ts +29 -0
- package/src/helpers/cards.ts +19 -0
- package/src/helpers/track-board.ts +211 -0
- package/src/hooks/useActivePlayers.ts +19 -0
- package/src/hooks/useBoardInteractions.test.tsx +622 -0
- package/src/hooks/useBoardInteractions.ts +434 -0
- package/src/hooks/useBoardTopology.ts +316 -0
- package/src/hooks/useCards.test.tsx +129 -0
- package/src/hooks/useCards.ts +10 -0
- package/src/hooks/useGameSelector.ts +105 -0
- package/src/hooks/useGameView.ts +9 -0
- package/src/hooks/useHandLayout.ts +349 -0
- package/src/hooks/useHexBoard.ts +74 -0
- package/src/hooks/useHexGrid.ts +185 -0
- package/src/hooks/useInteractionByKey.ts +349 -0
- package/src/hooks/useInteractionHandle.ts +437 -0
- package/src/hooks/useIsMobile.ts +35 -0
- package/src/hooks/useIsMyTurn.test.tsx +99 -0
- package/src/hooks/useIsMyTurn.ts +15 -0
- package/src/hooks/useLobby.ts +76 -0
- package/src/hooks/useMe.ts +48 -0
- package/src/hooks/usePanZoom.ts +278 -0
- package/src/hooks/usePlayerInfo.ts +28 -0
- package/src/hooks/usePlayerTurnOrder.ts +23 -0
- package/src/hooks/usePluginRuntime.test.tsx +102 -0
- package/src/hooks/usePluginRuntime.ts +130 -0
- package/src/hooks/useSeatInbox.ts +61 -0
- package/src/hooks/useSimultaneousPhase.ts +10 -0
- package/src/hooks/useSquareBoard.ts +124 -0
- package/src/hooks/useSquareGrid.ts +328 -0
- package/src/index.test.ts +474 -0
- package/src/index.ts +148 -0
- package/src/internal/ui/alert.tsx +51 -0
- package/src/internal/ui/button.tsx +58 -0
- package/src/internal/ui/dialog.tsx +134 -0
- package/src/internal/ui/input.tsx +21 -0
- package/src/internal/ui/label.tsx +21 -0
- package/src/internal/ui/select.tsx +129 -0
- package/src/internal/ui/tooltip.tsx +54 -0
- package/src/internal/ui/utils.ts +5 -0
- package/src/internal.ts +18 -0
- package/src/plugin-styles.css +246 -0
- package/src/primitives/board.test.tsx +139 -0
- package/src/primitives/board.tsx +267 -0
- package/src/primitives/game-ui-provider.tsx +35 -0
- package/src/primitives/index.ts +83 -0
- package/src/primitives/interaction.test.tsx +420 -0
- package/src/primitives/interaction.tsx +405 -0
- package/src/primitives/phase.test.tsx +82 -0
- package/src/primitives/phase.tsx +43 -0
- package/src/primitives/player-roster.test.tsx +168 -0
- package/src/primitives/player-roster.tsx +301 -0
- package/src/primitives/primitive-props.tsx +82 -0
- package/src/primitives/prompt.test.tsx +159 -0
- package/src/primitives/prompt.tsx +203 -0
- package/src/primitives/zone.tsx +113 -0
- package/src/reducer.ts +42 -0
- package/src/runtime/createPluginRuntimeAPI.ts +605 -0
- package/src/theme/ThemeProvider.test.tsx +36 -0
- package/src/theme/ThemeProvider.tsx +252 -0
- package/src/theme/board.ts +61 -0
- package/src/theme/css-vars.ts +105 -0
- package/src/theme/derive.ts +240 -0
- package/src/theme/index.ts +61 -0
- package/src/theme/presets/arcade.ts +261 -0
- package/src/theme/presets/studio.ts +261 -0
- package/src/theme/presets/tabletop.ts +266 -0
- package/src/theme/theme.test.ts +258 -0
- package/src/theme/tokens.ts +392 -0
- package/src/types/player-state.ts +445 -0
- package/src/types/plugin-state.ts +407 -0
- package/src/types/reducer-state.ts +24 -0
- package/src/types/runtime-api.ts +114 -0
- package/src/types/tiled-board.ts +785 -0
- package/src/ui-contract.ts +168 -0
- package/src/utils/interaction-inputs.test.ts +109 -0
- package/src/utils/interaction-inputs.ts +331 -0
- package/src/utils/interaction-labels.ts +23 -0
- package/src/utils/interaction-status.ts +59 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { usePluginState } from "../context/PluginStateContext.js";
|
|
2
|
+
import { usePluginSession } from "../context/PluginSessionContext.js";
|
|
3
|
+
/**
|
|
4
|
+
* Returns whether the currently controlled player is one of the engine-tracked
|
|
5
|
+
* active players for the current gameplay snapshot.
|
|
6
|
+
*/
|
|
7
|
+
export function useIsMyTurn() {
|
|
8
|
+
const { controllingPlayerId } = usePluginSession();
|
|
9
|
+
const activePlayers = usePluginState((state) => state.gameplay.activePlayers);
|
|
10
|
+
return (controllingPlayerId !== null && activePlayers.includes(controllingPlayerId));
|
|
11
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { LobbyState } from "../types/plugin-state.js";
|
|
2
|
+
export type { LobbyState };
|
|
3
|
+
/**
|
|
4
|
+
* Subscribes to lobby updates from the plugin runtime snapshot when present.
|
|
5
|
+
* Returns `null` until the host provides lobby state (SSR/tests/minimal runtimes).
|
|
6
|
+
*/
|
|
7
|
+
export declare function useLobbyState(): LobbyState | null;
|
|
8
|
+
/**
|
|
9
|
+
* Hook to subscribe to lobby state updates.
|
|
10
|
+
* Returns the latest lobby information from state-sync messages.
|
|
11
|
+
*
|
|
12
|
+
* State is provided by PluginStateProvider from host's state-sync messages.
|
|
13
|
+
* The host transforms raw SSE LOBBY_UPDATE messages into clean LobbyState objects.
|
|
14
|
+
*
|
|
15
|
+
* @returns Current lobby state (never null - throws if not available)
|
|
16
|
+
* @throws Error if lobby state is not available
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* function LobbyScreen() {
|
|
21
|
+
* const lobby = useLobby();
|
|
22
|
+
* // lobby is guaranteed to be non-null
|
|
23
|
+
* return <div>{lobby.seats.length} seats</div>;
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function useLobby(): LobbyState;
|
|
28
|
+
//# sourceMappingURL=useLobby.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLobby.d.ts","sourceRoot":"","sources":["../../src/hooks/useLobby.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI3D,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B;;;GAGG;AACH,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAgCjD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,IAAI,UAAU,CAUrC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { useRuntimeContext } from "../context/RuntimeContext.js";
|
|
3
|
+
/**
|
|
4
|
+
* Subscribes to lobby updates from the plugin runtime snapshot when present.
|
|
5
|
+
* Returns `null` until the host provides lobby state (SSR/tests/minimal runtimes).
|
|
6
|
+
*/
|
|
7
|
+
export function useLobbyState() {
|
|
8
|
+
const runtime = useRuntimeContext();
|
|
9
|
+
const getStateFromSnapshot = () => {
|
|
10
|
+
if (!runtime.getSnapshot)
|
|
11
|
+
return null;
|
|
12
|
+
const snapshot = runtime.getSnapshot();
|
|
13
|
+
if (!snapshot?.lobby)
|
|
14
|
+
return null;
|
|
15
|
+
return snapshot.lobby;
|
|
16
|
+
};
|
|
17
|
+
const [lobbyState, setLobbyState] = useState(getStateFromSnapshot);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!runtime.subscribeToState) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const initialState = runtime.getSnapshot?.();
|
|
23
|
+
if (initialState?.lobby) {
|
|
24
|
+
setLobbyState(initialState.lobby);
|
|
25
|
+
}
|
|
26
|
+
return runtime.subscribeToState((snapshot) => {
|
|
27
|
+
if (snapshot.lobby) {
|
|
28
|
+
setLobbyState(snapshot.lobby);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}, [runtime]);
|
|
32
|
+
return lobbyState;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Hook to subscribe to lobby state updates.
|
|
36
|
+
* Returns the latest lobby information from state-sync messages.
|
|
37
|
+
*
|
|
38
|
+
* State is provided by PluginStateProvider from host's state-sync messages.
|
|
39
|
+
* The host transforms raw SSE LOBBY_UPDATE messages into clean LobbyState objects.
|
|
40
|
+
*
|
|
41
|
+
* @returns Current lobby state (never null - throws if not available)
|
|
42
|
+
* @throws Error if lobby state is not available
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* function LobbyScreen() {
|
|
47
|
+
* const lobby = useLobby();
|
|
48
|
+
* // lobby is guaranteed to be non-null
|
|
49
|
+
* return <div>{lobby.seats.length} seats</div>;
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function useLobby() {
|
|
54
|
+
const lobbyState = useLobbyState();
|
|
55
|
+
if (lobbyState === null) {
|
|
56
|
+
throw new Error("useLobby: Lobby state not available. " +
|
|
57
|
+
"The host should only render the plugin when lobby state is ready.");
|
|
58
|
+
}
|
|
59
|
+
return lobbyState;
|
|
60
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Player } from "../types/player-state.js";
|
|
2
|
+
export type { Player } from "../types/player-state.js";
|
|
3
|
+
/**
|
|
4
|
+
* Hook to get information about the player currently being controlled by this user.
|
|
5
|
+
* Returns the currently selected player that the user is controlling.
|
|
6
|
+
*
|
|
7
|
+
* @returns Currently controlled player's info
|
|
8
|
+
* @throws Error if called before session is ready or if player not found in lobby
|
|
9
|
+
*/
|
|
10
|
+
export declare function useMe(): Player;
|
|
11
|
+
//# sourceMappingURL=useMe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMe.d.ts","sourceRoot":"","sources":["../../src/hooks/useMe.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGvD,YAAY,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,KAAK,IAAI,MAAM,CA+B9B"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { usePluginSession } from "../context/PluginSessionContext.js";
|
|
3
|
+
import { useLobby } from "./useLobby.js";
|
|
4
|
+
/**
|
|
5
|
+
* Hook to get information about the player currently being controlled by this user.
|
|
6
|
+
* Returns the currently selected player that the user is controlling.
|
|
7
|
+
*
|
|
8
|
+
* @returns Currently controlled player's info
|
|
9
|
+
* @throws Error if called before session is ready or if player not found in lobby
|
|
10
|
+
*/
|
|
11
|
+
export function useMe() {
|
|
12
|
+
const { controllingPlayerId } = usePluginSession();
|
|
13
|
+
const lobby = useLobby();
|
|
14
|
+
return useMemo(() => {
|
|
15
|
+
if (!controllingPlayerId) {
|
|
16
|
+
throw new Error("useMe: No controlling player available. Ensure session is initialized and user is not a spectator.");
|
|
17
|
+
}
|
|
18
|
+
if (!lobby) {
|
|
19
|
+
throw new Error("useMe: Lobby state not available. Ensure component is rendered during lobby or game phase.");
|
|
20
|
+
}
|
|
21
|
+
const seat = lobby.seats.find((s) => s.playerId === controllingPlayerId);
|
|
22
|
+
if (!seat) {
|
|
23
|
+
throw new Error(`useMe: Player ${controllingPlayerId} not found in lobby seats. This should not happen.`);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
playerId: seat.playerId,
|
|
27
|
+
name: seat.displayName,
|
|
28
|
+
isHost: seat.isHost,
|
|
29
|
+
color: seat.playerColor,
|
|
30
|
+
};
|
|
31
|
+
}, [controllingPlayerId, lobby]);
|
|
32
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* usePanZoom hook - Unified pan and zoom gestures using @use-gesture/react
|
|
3
|
+
*
|
|
4
|
+
* Provides a declarative API for pan and zoom interactions on board components.
|
|
5
|
+
* Works with both SVG (via viewBox) and HTML (via CSS transforms) elements.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Single finger/mouse drag for panning
|
|
9
|
+
* - Pinch-to-zoom on touch devices
|
|
10
|
+
* - Mouse wheel zoom on desktop
|
|
11
|
+
* - Configurable zoom limits
|
|
12
|
+
* - Optional momentum/inertia
|
|
13
|
+
*
|
|
14
|
+
* @example SVG usage (NetworkGraph, HexGrid, etc.)
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const { transform, bind, resetTransform } = usePanZoom({
|
|
17
|
+
* enabled: enablePanZoom,
|
|
18
|
+
* minZoom: 0.5,
|
|
19
|
+
* maxZoom: 3,
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Apply to viewBox calculation
|
|
23
|
+
* const viewBoxWidth = contentWidth / transform.zoom;
|
|
24
|
+
* const viewBoxX = baseX - transform.pan.x;
|
|
25
|
+
*
|
|
26
|
+
* <svg {...bind()} style={{ touchAction: 'none' }}>
|
|
27
|
+
* ...
|
|
28
|
+
* </svg>
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example HTML usage (SlotSystem, etc.)
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const { transform, bind, style } = usePanZoom({
|
|
34
|
+
* enabled: enablePanZoom,
|
|
35
|
+
* mode: 'css',
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* <div {...bind()} style={{ ...style, touchAction: 'none' }}>
|
|
39
|
+
* ...
|
|
40
|
+
* </div>
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export interface PanZoomTransform {
|
|
44
|
+
/** Current zoom level (1 = 100%) */
|
|
45
|
+
zoom: number;
|
|
46
|
+
/** Current pan offset */
|
|
47
|
+
pan: {
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface UsePanZoomOptions {
|
|
53
|
+
/** Whether pan/zoom is enabled */
|
|
54
|
+
enabled?: boolean;
|
|
55
|
+
/** Initial zoom level */
|
|
56
|
+
initialZoom?: number;
|
|
57
|
+
/** Minimum zoom level */
|
|
58
|
+
minZoom?: number;
|
|
59
|
+
/** Maximum zoom level */
|
|
60
|
+
maxZoom?: number;
|
|
61
|
+
/** Initial pan offset */
|
|
62
|
+
initialPan?: {
|
|
63
|
+
x: number;
|
|
64
|
+
y: number;
|
|
65
|
+
};
|
|
66
|
+
/** Transform mode: 'viewbox' for SVG, 'css' for HTML elements */
|
|
67
|
+
mode?: "viewbox" | "css";
|
|
68
|
+
/** Zoom sensitivity for wheel events (default: 0.002) */
|
|
69
|
+
wheelSensitivity?: number;
|
|
70
|
+
/** Called when transform changes */
|
|
71
|
+
onTransformChange?: (transform: PanZoomTransform) => void;
|
|
72
|
+
}
|
|
73
|
+
/** Type for gesture bind function that returns props to spread on element
|
|
74
|
+
* Note: We omit ref from the return type to avoid conflicts with explicit refs on elements.
|
|
75
|
+
* The gesture library handles its own internal ref binding.
|
|
76
|
+
*/
|
|
77
|
+
type GestureBindFunction = () => Omit<React.HTMLAttributes<Element>, "ref">;
|
|
78
|
+
export interface UsePanZoomReturn {
|
|
79
|
+
/** Current transform state */
|
|
80
|
+
transform: PanZoomTransform;
|
|
81
|
+
/** Gesture handlers to spread on the target element - always returns spreadable props */
|
|
82
|
+
bind: GestureBindFunction;
|
|
83
|
+
/** Reset transform to initial values */
|
|
84
|
+
resetTransform: () => void;
|
|
85
|
+
/** Set zoom programmatically */
|
|
86
|
+
setZoom: (zoom: number) => void;
|
|
87
|
+
/** Set pan programmatically */
|
|
88
|
+
setPan: (pan: {
|
|
89
|
+
x: number;
|
|
90
|
+
y: number;
|
|
91
|
+
}) => void;
|
|
92
|
+
/** CSS transform style (for mode: 'css') */
|
|
93
|
+
style: React.CSSProperties;
|
|
94
|
+
/** Whether currently dragging/panning */
|
|
95
|
+
isDragging: boolean;
|
|
96
|
+
/** Whether currently pinching */
|
|
97
|
+
isPinching: boolean;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Hook for pan and zoom gestures on board components
|
|
101
|
+
*/
|
|
102
|
+
export declare function usePanZoom(options?: UsePanZoomOptions): UsePanZoomReturn;
|
|
103
|
+
/**
|
|
104
|
+
* Helper to calculate SVG viewBox with pan/zoom applied
|
|
105
|
+
*/
|
|
106
|
+
export declare function calculateViewBox(bounds: {
|
|
107
|
+
minX: number;
|
|
108
|
+
minY: number;
|
|
109
|
+
width: number;
|
|
110
|
+
height: number;
|
|
111
|
+
}, transform: PanZoomTransform): string;
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=usePanZoom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePanZoom.d.ts","sourceRoot":"","sources":["../../src/hooks/usePanZoom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAKH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,UAAU,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,iEAAiE;IACjE,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IACzB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oCAAoC;IACpC,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC3D;AAED;;;GAGG;AACH,KAAK,mBAAmB,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;AAE5E,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,yFAAyF;IACzF,IAAI,EAAE,mBAAmB,CAAC;IAC1B,wCAAwC;IACxC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,gCAAgC;IAChC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,+BAA+B;IAC/B,MAAM,EAAE,CAAC,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAChD,4CAA4C;IAC5C,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC;IAC3B,yCAAyC;IACzC,UAAU,EAAE,OAAO,CAAC;IACpB,iCAAiC;IACjC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAgK5E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACrE,SAAS,EAAE,gBAAgB,GAC1B,MAAM,CASR"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* usePanZoom hook - Unified pan and zoom gestures using @use-gesture/react
|
|
3
|
+
*
|
|
4
|
+
* Provides a declarative API for pan and zoom interactions on board components.
|
|
5
|
+
* Works with both SVG (via viewBox) and HTML (via CSS transforms) elements.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Single finger/mouse drag for panning
|
|
9
|
+
* - Pinch-to-zoom on touch devices
|
|
10
|
+
* - Mouse wheel zoom on desktop
|
|
11
|
+
* - Configurable zoom limits
|
|
12
|
+
* - Optional momentum/inertia
|
|
13
|
+
*
|
|
14
|
+
* @example SVG usage (NetworkGraph, HexGrid, etc.)
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const { transform, bind, resetTransform } = usePanZoom({
|
|
17
|
+
* enabled: enablePanZoom,
|
|
18
|
+
* minZoom: 0.5,
|
|
19
|
+
* maxZoom: 3,
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Apply to viewBox calculation
|
|
23
|
+
* const viewBoxWidth = contentWidth / transform.zoom;
|
|
24
|
+
* const viewBoxX = baseX - transform.pan.x;
|
|
25
|
+
*
|
|
26
|
+
* <svg {...bind()} style={{ touchAction: 'none' }}>
|
|
27
|
+
* ...
|
|
28
|
+
* </svg>
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example HTML usage (SlotSystem, etc.)
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const { transform, bind, style } = usePanZoom({
|
|
34
|
+
* enabled: enablePanZoom,
|
|
35
|
+
* mode: 'css',
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* <div {...bind()} style={{ ...style, touchAction: 'none' }}>
|
|
39
|
+
* ...
|
|
40
|
+
* </div>
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
import { useState, useCallback, useEffect, useMemo } from "react";
|
|
44
|
+
import { useGesture } from "@use-gesture/react";
|
|
45
|
+
/**
|
|
46
|
+
* Hook for pan and zoom gestures on board components
|
|
47
|
+
*/
|
|
48
|
+
export function usePanZoom(options = {}) {
|
|
49
|
+
const { enabled = true, initialZoom = 1, minZoom = 0.5, maxZoom = 3, initialPan = { x: 0, y: 0 }, mode = "viewbox", wheelSensitivity = 0.002, onTransformChange, } = options;
|
|
50
|
+
const [zoom, setZoomState] = useState(initialZoom);
|
|
51
|
+
const [pan, setPanState] = useState(initialPan);
|
|
52
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
53
|
+
const [isPinching, setIsPinching] = useState(false);
|
|
54
|
+
// Clamp zoom to bounds
|
|
55
|
+
const clampZoom = useCallback((z) => Math.min(maxZoom, Math.max(minZoom, z)), [minZoom, maxZoom]);
|
|
56
|
+
// Update transform and notify
|
|
57
|
+
const updateTransform = useCallback((newZoom, newPan) => {
|
|
58
|
+
const clampedZoom = clampZoom(newZoom);
|
|
59
|
+
setZoomState(clampedZoom);
|
|
60
|
+
setPanState(newPan);
|
|
61
|
+
onTransformChange?.({ zoom: clampedZoom, pan: newPan });
|
|
62
|
+
}, [clampZoom, onTransformChange]);
|
|
63
|
+
// Gesture bindings
|
|
64
|
+
const bind = useGesture({
|
|
65
|
+
onDrag: (({ delta: [dx, dy], active, pinching, }) => {
|
|
66
|
+
if (!enabled || pinching)
|
|
67
|
+
return;
|
|
68
|
+
setIsDragging(active);
|
|
69
|
+
if (active) {
|
|
70
|
+
// For viewbox mode, we invert and scale the delta
|
|
71
|
+
// For CSS mode, we apply directly
|
|
72
|
+
const scaleFactor = mode === "viewbox" ? 1 / zoom : 1;
|
|
73
|
+
setPanState((prev) => ({
|
|
74
|
+
x: prev.x + dx * scaleFactor,
|
|
75
|
+
y: prev.y + dy * scaleFactor,
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
}),
|
|
79
|
+
onPinch: (({ offset: [scale], active, }) => {
|
|
80
|
+
if (!enabled)
|
|
81
|
+
return;
|
|
82
|
+
setIsPinching(active);
|
|
83
|
+
if (active) {
|
|
84
|
+
const newZoom = clampZoom(scale);
|
|
85
|
+
setZoomState(newZoom);
|
|
86
|
+
onTransformChange?.({ zoom: newZoom, pan });
|
|
87
|
+
}
|
|
88
|
+
}),
|
|
89
|
+
onWheel: (({ delta: [, dy], event }) => {
|
|
90
|
+
if (!enabled)
|
|
91
|
+
return;
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
const newZoom = clampZoom(zoom - dy * wheelSensitivity);
|
|
94
|
+
setZoomState(newZoom);
|
|
95
|
+
onTransformChange?.({ zoom: newZoom, pan });
|
|
96
|
+
}),
|
|
97
|
+
}, {
|
|
98
|
+
drag: {
|
|
99
|
+
enabled,
|
|
100
|
+
filterTaps: true,
|
|
101
|
+
},
|
|
102
|
+
pinch: {
|
|
103
|
+
enabled,
|
|
104
|
+
scaleBounds: { min: minZoom, max: maxZoom },
|
|
105
|
+
from: () => [zoom, 0],
|
|
106
|
+
},
|
|
107
|
+
wheel: {
|
|
108
|
+
enabled,
|
|
109
|
+
eventOptions: { passive: false },
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
// Reset to initial values
|
|
113
|
+
const resetTransform = useCallback(() => {
|
|
114
|
+
updateTransform(initialZoom, initialPan);
|
|
115
|
+
}, [initialZoom, initialPan, updateTransform]);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
updateTransform(initialZoom, initialPan);
|
|
118
|
+
}, [initialZoom, initialPan.x, initialPan.y, updateTransform]);
|
|
119
|
+
// Programmatic setters
|
|
120
|
+
const setZoom = useCallback((newZoom) => {
|
|
121
|
+
updateTransform(clampZoom(newZoom), pan);
|
|
122
|
+
}, [pan, clampZoom, updateTransform]);
|
|
123
|
+
const setPan = useCallback((newPan) => {
|
|
124
|
+
updateTransform(zoom, newPan);
|
|
125
|
+
}, [zoom, updateTransform]);
|
|
126
|
+
// CSS transform style for HTML mode
|
|
127
|
+
const style = useMemo(() => mode === "css"
|
|
128
|
+
? {
|
|
129
|
+
transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
|
|
130
|
+
transformOrigin: "center center",
|
|
131
|
+
}
|
|
132
|
+
: {}, [mode, pan.x, pan.y, zoom]);
|
|
133
|
+
// Current transform state
|
|
134
|
+
const transform = useMemo(() => ({ zoom, pan }), [zoom, pan]);
|
|
135
|
+
// Wrap bind to ensure it always returns spreadable props (never void)
|
|
136
|
+
// We exclude 'ref' from the result to avoid type conflicts with explicit element refs
|
|
137
|
+
const safeBind = useCallback(() => {
|
|
138
|
+
const result = bind();
|
|
139
|
+
// If bind returns void (shouldn't happen with our config), return empty object
|
|
140
|
+
// Destructure to omit ref, avoiding type conflicts with SVG/HTML element refs
|
|
141
|
+
const { ref: _ref, ...propsWithoutRef } = (result ??
|
|
142
|
+
{});
|
|
143
|
+
return propsWithoutRef;
|
|
144
|
+
}, [bind]);
|
|
145
|
+
return {
|
|
146
|
+
transform,
|
|
147
|
+
bind: safeBind,
|
|
148
|
+
resetTransform,
|
|
149
|
+
setZoom,
|
|
150
|
+
setPan,
|
|
151
|
+
style,
|
|
152
|
+
isDragging,
|
|
153
|
+
isPinching,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Helper to calculate SVG viewBox with pan/zoom applied
|
|
158
|
+
*/
|
|
159
|
+
export function calculateViewBox(bounds, transform) {
|
|
160
|
+
const viewBoxWidth = bounds.width / transform.zoom;
|
|
161
|
+
const viewBoxHeight = bounds.height / transform.zoom;
|
|
162
|
+
const viewBoxX = bounds.minX + (bounds.width - viewBoxWidth) / 2 - transform.pan.x;
|
|
163
|
+
const viewBoxY = bounds.minY + (bounds.height - viewBoxHeight) / 2 - transform.pan.y;
|
|
164
|
+
return `${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}`;
|
|
165
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePlayerInfo.d.ts","sourceRoot":"","sources":["../../src/hooks/usePlayerInfo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,wBAAgB,aAAa,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAsBrD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useLobbyState } from "./useLobby.js";
|
|
3
|
+
export function usePlayerInfo() {
|
|
4
|
+
const lobby = useLobbyState();
|
|
5
|
+
return useMemo(() => {
|
|
6
|
+
if (!lobby) {
|
|
7
|
+
return new Map();
|
|
8
|
+
}
|
|
9
|
+
const playerMap = new Map();
|
|
10
|
+
for (const seat of lobby.seats) {
|
|
11
|
+
const playerId = seat.playerId;
|
|
12
|
+
playerMap.set(playerId, {
|
|
13
|
+
playerId,
|
|
14
|
+
name: seat.displayName,
|
|
15
|
+
isHost: seat.isHost,
|
|
16
|
+
color: seat.playerColor,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return playerMap;
|
|
20
|
+
}, [lobby]);
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PlayerId } from "@dreamboard/manifest-contract";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the player ids in turn order, as provided by the lobby seat
|
|
4
|
+
* assignments. Matches `q.player.order()` on the reducer side: the
|
|
5
|
+
* engine's turn order is seeded from the same seat assignments.
|
|
6
|
+
*
|
|
7
|
+
* - Returns an empty array before the first lobby snapshot arrives.
|
|
8
|
+
* - Stable reference across renders when the seats don't change.
|
|
9
|
+
*
|
|
10
|
+
* Prefer this hook (combined with `useActivePlayers()` for the current
|
|
11
|
+
* seat) over re-projecting `turnOrder` into the view — flow state
|
|
12
|
+
* belongs to the engine and the SDK, not to game-specific projections.
|
|
13
|
+
*/
|
|
14
|
+
export declare function usePlayerTurnOrder(): readonly PlayerId[];
|
|
15
|
+
//# sourceMappingURL=usePlayerTurnOrder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePlayerTurnOrder.d.ts","sourceRoot":"","sources":["../../src/hooks/usePlayerTurnOrder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAG9D;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,QAAQ,EAAE,CAMxD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useLobby } from "./useLobby.js";
|
|
3
|
+
/**
|
|
4
|
+
* Returns the player ids in turn order, as provided by the lobby seat
|
|
5
|
+
* assignments. Matches `q.player.order()` on the reducer side: the
|
|
6
|
+
* engine's turn order is seeded from the same seat assignments.
|
|
7
|
+
*
|
|
8
|
+
* - Returns an empty array before the first lobby snapshot arrives.
|
|
9
|
+
* - Stable reference across renders when the seats don't change.
|
|
10
|
+
*
|
|
11
|
+
* Prefer this hook (combined with `useActivePlayers()` for the current
|
|
12
|
+
* seat) over re-projecting `turnOrder` into the view — flow state
|
|
13
|
+
* belongs to the engine and the SDK, not to game-specific projections.
|
|
14
|
+
*/
|
|
15
|
+
export function usePlayerTurnOrder() {
|
|
16
|
+
const lobby = useLobby();
|
|
17
|
+
return useMemo(() => {
|
|
18
|
+
if (!lobby)
|
|
19
|
+
return [];
|
|
20
|
+
return lobby.seats.map((seat) => seat.playerId);
|
|
21
|
+
}, [lobby]);
|
|
22
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type PluginRuntimeAPI } from "../runtime/createPluginRuntimeAPI.js";
|
|
2
|
+
export interface UsePluginRuntimeOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Timeout in milliseconds to wait for state-sync.
|
|
5
|
+
* @default 10000 (10 seconds)
|
|
6
|
+
*/
|
|
7
|
+
timeout?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface UsePluginRuntimeResult {
|
|
10
|
+
/** The RuntimeAPI instance */
|
|
11
|
+
runtime: PluginRuntimeAPI;
|
|
12
|
+
/** Whether the initial reducer-native snapshot is available and ready */
|
|
13
|
+
isReady: boolean;
|
|
14
|
+
/** Error message if initialization failed */
|
|
15
|
+
error: string | null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook that creates and manages a PluginRuntimeAPI instance.
|
|
19
|
+
*
|
|
20
|
+
* This hook handles:
|
|
21
|
+
* 1. Creating the RuntimeAPI
|
|
22
|
+
* 2. Waiting for the first state-sync snapshot before setting isReady
|
|
23
|
+
*
|
|
24
|
+
* In the new architecture, the host only renders the plugin when a reducer-native
|
|
25
|
+
* snapshot is available, so isReady should become true quickly after init.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* function PluginRuntime({ children }: { children: React.ReactNode }) {
|
|
30
|
+
* const { runtime, isReady, error } = usePluginRuntime();
|
|
31
|
+
*
|
|
32
|
+
* if (error) {
|
|
33
|
+
* return <div>Error: {error}</div>;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* if (!isReady) {
|
|
37
|
+
* return <GameSkeleton message="Waiting for game state..." />;
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* return <RuntimeProvider runtime={runtime}>{children}</RuntimeProvider>;
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function usePluginRuntime(options?: UsePluginRuntimeOptions): UsePluginRuntimeResult;
|
|
45
|
+
//# sourceMappingURL=usePluginRuntime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePluginRuntime.d.ts","sourceRoot":"","sources":["../../src/hooks/usePluginRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,sCAAsC,CAAC;AAE9C,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,yEAAyE;IACzE,OAAO,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CAkExB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { createPluginRuntimeAPI, } from "../runtime/createPluginRuntimeAPI.js";
|
|
3
|
+
function hasProjectedView(snapshot) {
|
|
4
|
+
return (snapshot !== null &&
|
|
5
|
+
snapshot !== undefined &&
|
|
6
|
+
snapshot.view !== null &&
|
|
7
|
+
snapshot.view !== undefined);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Hook that creates and manages a PluginRuntimeAPI instance.
|
|
11
|
+
*
|
|
12
|
+
* This hook handles:
|
|
13
|
+
* 1. Creating the RuntimeAPI
|
|
14
|
+
* 2. Waiting for the first state-sync snapshot before setting isReady
|
|
15
|
+
*
|
|
16
|
+
* In the new architecture, the host only renders the plugin when a reducer-native
|
|
17
|
+
* snapshot is available, so isReady should become true quickly after init.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* function PluginRuntime({ children }: { children: React.ReactNode }) {
|
|
22
|
+
* const { runtime, isReady, error } = usePluginRuntime();
|
|
23
|
+
*
|
|
24
|
+
* if (error) {
|
|
25
|
+
* return <div>Error: {error}</div>;
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* if (!isReady) {
|
|
29
|
+
* return <GameSkeleton message="Waiting for game state..." />;
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* return <RuntimeProvider runtime={runtime}>{children}</RuntimeProvider>;
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function usePluginRuntime(options = {}) {
|
|
37
|
+
const { timeout = 10000 } = options;
|
|
38
|
+
// Create runtime once and keep stable reference
|
|
39
|
+
const [runtime] = useState(() => createPluginRuntimeAPI());
|
|
40
|
+
const [isReady, setIsReady] = useState(() => {
|
|
41
|
+
const snapshot = runtime.getSnapshot?.();
|
|
42
|
+
return hasProjectedView(snapshot);
|
|
43
|
+
});
|
|
44
|
+
const [error, setError] = useState(null);
|
|
45
|
+
// Subscribe to state-sync and set isReady when the first snapshot arrives.
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
const markReadyFromSnapshot = () => {
|
|
48
|
+
const currentSnapshot = runtime.getSnapshot?.();
|
|
49
|
+
if (!hasProjectedView(currentSnapshot)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
setError(null);
|
|
53
|
+
setIsReady(true);
|
|
54
|
+
return true;
|
|
55
|
+
};
|
|
56
|
+
if (markReadyFromSnapshot()) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Set up timeout
|
|
60
|
+
const timeoutId = setTimeout(() => {
|
|
61
|
+
if (!markReadyFromSnapshot()) {
|
|
62
|
+
setError(`Timed out waiting for the initial projected view after ${timeout}ms. ` +
|
|
63
|
+
"Ensure the host sends a reducer-native state-sync with a seat view.");
|
|
64
|
+
}
|
|
65
|
+
}, timeout);
|
|
66
|
+
// Fallback poll for dev/HMR flows where the runtime snapshot may already
|
|
67
|
+
// exist but the first subscribe callback is missed.
|
|
68
|
+
const pollId = setInterval(() => {
|
|
69
|
+
if (markReadyFromSnapshot()) {
|
|
70
|
+
clearInterval(pollId);
|
|
71
|
+
clearTimeout(timeoutId);
|
|
72
|
+
}
|
|
73
|
+
}, 100);
|
|
74
|
+
// Subscribe to state changes
|
|
75
|
+
const unsubscribe = runtime.subscribeToState?.((state) => {
|
|
76
|
+
if (!hasProjectedView(state)) {
|
|
77
|
+
setIsReady(false);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
clearInterval(pollId);
|
|
81
|
+
clearTimeout(timeoutId);
|
|
82
|
+
setError(null);
|
|
83
|
+
setIsReady(true);
|
|
84
|
+
});
|
|
85
|
+
return () => {
|
|
86
|
+
clearInterval(pollId);
|
|
87
|
+
clearTimeout(timeoutId);
|
|
88
|
+
unsubscribe?.();
|
|
89
|
+
};
|
|
90
|
+
}, [runtime, timeout]);
|
|
91
|
+
return { runtime, isReady, error };
|
|
92
|
+
}
|