@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,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG-based track visualization for racing and path games
|
|
3
|
+
* (Monopoly, Game of Life, Snakes & Ladders). Supports linear, circular, and branching tracks.
|
|
4
|
+
*/
|
|
5
|
+
import { type ReactNode } from "react";
|
|
6
|
+
export interface TrackSpace<SpaceIdValue extends string = string, Data = unknown> {
|
|
7
|
+
id: SpaceIdValue;
|
|
8
|
+
index: number;
|
|
9
|
+
name?: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
/** Override next spaces (for branching) */
|
|
12
|
+
nextSpaces?: readonly SpaceIdValue[];
|
|
13
|
+
/** Jump to another space (snakes/ladders) */
|
|
14
|
+
jumpTo?: SpaceIdValue;
|
|
15
|
+
position: {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
};
|
|
19
|
+
data?: Data;
|
|
20
|
+
}
|
|
21
|
+
export interface TrackPiece<PieceIdValue extends string = string, SpaceIdValue extends string = string, OwnerIdValue extends string = string, Data = unknown> {
|
|
22
|
+
id: PieceIdValue;
|
|
23
|
+
spaceId: SpaceIdValue;
|
|
24
|
+
owner: OwnerIdValue;
|
|
25
|
+
type?: string;
|
|
26
|
+
data?: Data;
|
|
27
|
+
}
|
|
28
|
+
export interface TrackBoardProps {
|
|
29
|
+
spaces: TrackSpace[];
|
|
30
|
+
pieces: TrackPiece[];
|
|
31
|
+
type?: "linear" | "circular" | "branching";
|
|
32
|
+
renderSpace: (space: TrackSpace, pieces: TrackPiece[]) => ReactNode;
|
|
33
|
+
renderConnection?: (from: {
|
|
34
|
+
x: number;
|
|
35
|
+
y: number;
|
|
36
|
+
}, to: {
|
|
37
|
+
x: number;
|
|
38
|
+
y: number;
|
|
39
|
+
}, fromSpace: TrackSpace, toSpace: TrackSpace) => ReactNode;
|
|
40
|
+
renderJump?: (from: {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
}, to: {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
}, fromSpace: TrackSpace, toSpace: TrackSpace, isUp: boolean) => ReactNode;
|
|
47
|
+
width?: number | string;
|
|
48
|
+
height?: number | string;
|
|
49
|
+
enablePanZoom?: boolean;
|
|
50
|
+
initialZoom?: number;
|
|
51
|
+
minZoom?: number;
|
|
52
|
+
maxZoom?: number;
|
|
53
|
+
className?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface DefaultTrackSpaceProps {
|
|
56
|
+
space: TrackSpace;
|
|
57
|
+
size?: number;
|
|
58
|
+
fill?: string;
|
|
59
|
+
stroke?: string;
|
|
60
|
+
strokeWidth?: number;
|
|
61
|
+
isHighlighted?: boolean;
|
|
62
|
+
isSelected?: boolean;
|
|
63
|
+
showJumpIndicator?: boolean;
|
|
64
|
+
onClick?: () => void;
|
|
65
|
+
onHover?: (hovering: boolean) => void;
|
|
66
|
+
className?: string;
|
|
67
|
+
children?: ReactNode;
|
|
68
|
+
}
|
|
69
|
+
export declare function DefaultTrackSpace({ space, size, fill, stroke, strokeWidth, isHighlighted, isSelected, showJumpIndicator, onClick, onHover, className, children, }: DefaultTrackSpaceProps): import("react/jsx-runtime").JSX.Element;
|
|
70
|
+
export interface DefaultTrackPieceProps {
|
|
71
|
+
piece: TrackPiece;
|
|
72
|
+
index?: number;
|
|
73
|
+
total?: number;
|
|
74
|
+
radius?: number;
|
|
75
|
+
color?: string;
|
|
76
|
+
onClick?: () => void;
|
|
77
|
+
className?: string;
|
|
78
|
+
}
|
|
79
|
+
export declare function DefaultTrackPiece({ piece, index, total, radius, color, onClick, className, }: DefaultTrackPieceProps): import("react/jsx-runtime").JSX.Element;
|
|
80
|
+
export interface DefaultTrackConnectionProps {
|
|
81
|
+
from: {
|
|
82
|
+
x: number;
|
|
83
|
+
y: number;
|
|
84
|
+
};
|
|
85
|
+
to: {
|
|
86
|
+
x: number;
|
|
87
|
+
y: number;
|
|
88
|
+
};
|
|
89
|
+
stroke?: string;
|
|
90
|
+
strokeWidth?: number;
|
|
91
|
+
className?: string;
|
|
92
|
+
}
|
|
93
|
+
export declare function DefaultTrackConnection({ from, to, stroke, strokeWidth, className, }: DefaultTrackConnectionProps): import("react/jsx-runtime").JSX.Element;
|
|
94
|
+
export interface DefaultTrackJumpProps {
|
|
95
|
+
from: {
|
|
96
|
+
x: number;
|
|
97
|
+
y: number;
|
|
98
|
+
};
|
|
99
|
+
to: {
|
|
100
|
+
x: number;
|
|
101
|
+
y: number;
|
|
102
|
+
};
|
|
103
|
+
/** Whether the jump goes forward or backward */
|
|
104
|
+
isUp: boolean;
|
|
105
|
+
spaceSize?: number;
|
|
106
|
+
upColor?: string;
|
|
107
|
+
downColor?: string;
|
|
108
|
+
strokeWidth?: number;
|
|
109
|
+
className?: string;
|
|
110
|
+
}
|
|
111
|
+
export declare function DefaultTrackJump({ from, to, isUp, spaceSize, upColor, downColor, strokeWidth, className, }: DefaultTrackJumpProps): import("react/jsx-runtime").JSX.Element;
|
|
112
|
+
export declare function TrackBoard({ spaces, pieces, type, renderSpace, renderConnection, renderJump, width, height, enablePanZoom, initialZoom, minZoom, maxZoom, className, }: TrackBoardProps): import("react/jsx-runtime").JSX.Element;
|
|
113
|
+
//# sourceMappingURL=TrackBoard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrackBoard.d.ts","sourceRoot":"","sources":["../../../src/components/board/TrackBoard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* SVG-based track visualization for racing and path games
|
|
4
|
+
* (Monopoly, Game of Life, Snakes & Ladders). Supports linear, circular, and branching tracks.
|
|
5
|
+
*/
|
|
6
|
+
import { useMemo } from "react";
|
|
7
|
+
import { clsx } from "clsx";
|
|
8
|
+
import { usePanZoom } from "../../hooks/usePanZoom.js";
|
|
9
|
+
import { handleKeyboardActivation } from "./interaction-accessibility.js";
|
|
10
|
+
export function DefaultTrackSpace({ space, size = 50, fill = "#1e293b", stroke = "#475569", strokeWidth = 1, isHighlighted = false, isSelected = false, showJumpIndicator = true, onClick, onHover, className, children, }) {
|
|
11
|
+
const halfSize = size / 2;
|
|
12
|
+
const computedFill = isHighlighted ? "rgba(59, 130, 246, 0.3)" : fill;
|
|
13
|
+
const computedStroke = isSelected
|
|
14
|
+
? "#3b82f6"
|
|
15
|
+
: isHighlighted
|
|
16
|
+
? "#60a5fa"
|
|
17
|
+
: stroke;
|
|
18
|
+
const computedStrokeWidth = isHighlighted || isSelected ? 3 : strokeWidth;
|
|
19
|
+
return (_jsxs("g", { onClick: onClick, onMouseEnter: () => onHover?.(true), onMouseLeave: () => onHover?.(false), onKeyDown: (event) => handleKeyboardActivation(event, onClick), className: clsx(onClick && "cursor-pointer", className), role: onClick ? "button" : "listitem", "aria-label": space.name || `Space ${space.index}`, tabIndex: onClick ? 0 : undefined, children: [_jsx("rect", { x: -halfSize, y: -halfSize, width: size, height: size, rx: 8, fill: computedFill, stroke: computedStroke, strokeWidth: computedStrokeWidth }), space.name ? (_jsx("text", { textAnchor: "middle", dominantBaseline: "middle", fill: "white", fontSize: space.name.length > 4 ? 8 : 10, fontWeight: "bold", children: space.name.length > 8 ? space.name.slice(0, 7) + "…" : space.name })) : (_jsx("text", { textAnchor: "middle", dominantBaseline: "middle", fill: "#94a3b8", fontSize: 12, fontWeight: "bold", children: space.index })), showJumpIndicator && space.jumpTo && (_jsxs("g", { transform: `translate(${halfSize - 6}, ${-halfSize + 6})`, children: [_jsx("circle", { r: 6, fill: "#fbbf24" }), _jsx("text", { textAnchor: "middle", dominantBaseline: "central", fill: "black", fontSize: 8, fontWeight: "bold", children: "\u2197" })] })), children] }));
|
|
20
|
+
}
|
|
21
|
+
export function DefaultTrackPiece({ piece, index = 0, total = 1, radius = 8, color = "#f59e0b", onClick, className, }) {
|
|
22
|
+
// Arrange pieces in a circle around the space center
|
|
23
|
+
const spacing = radius * 2.2;
|
|
24
|
+
const angle = (index / total) * 2 * Math.PI - Math.PI / 2;
|
|
25
|
+
const offset = total > 1 ? spacing : 0;
|
|
26
|
+
const px = Math.cos(angle) * offset;
|
|
27
|
+
const py = Math.sin(angle) * offset;
|
|
28
|
+
return (_jsx("circle", { cx: px, cy: py, r: radius, fill: color, stroke: "white", strokeWidth: 2, onClick: (e) => {
|
|
29
|
+
e.stopPropagation();
|
|
30
|
+
onClick?.();
|
|
31
|
+
}, onKeyDown: (event) => handleKeyboardActivation(event, onClick, { stopPropagation: true }), className: clsx(onClick && "cursor-pointer", className), role: onClick ? "button" : undefined, tabIndex: onClick ? 0 : undefined, "aria-label": `Piece ${piece.id} owned by ${piece.owner}` }));
|
|
32
|
+
}
|
|
33
|
+
export function DefaultTrackConnection({ from, to, stroke = "#475569", strokeWidth = 2, className, }) {
|
|
34
|
+
return (_jsx("line", { x1: from.x, y1: from.y, x2: to.x, y2: to.y, stroke: stroke, strokeWidth: strokeWidth, strokeLinecap: "round", className: className }));
|
|
35
|
+
}
|
|
36
|
+
export function DefaultTrackJump({ from, to, isUp, spaceSize = 50, upColor = "#22c55e", downColor = "#ef4444", strokeWidth = 3, className, }) {
|
|
37
|
+
const color = isUp ? upColor : downColor;
|
|
38
|
+
// Calculate arrow direction
|
|
39
|
+
const dx = to.x - from.x;
|
|
40
|
+
const dy = to.y - from.y;
|
|
41
|
+
const len = Math.sqrt(dx * dx + dy * dy);
|
|
42
|
+
const unitX = dx / len;
|
|
43
|
+
const unitY = dy / len;
|
|
44
|
+
// Offset start and end points
|
|
45
|
+
const startX = from.x + unitX * (spaceSize / 2 + 5);
|
|
46
|
+
const startY = from.y + unitY * (spaceSize / 2 + 5);
|
|
47
|
+
const endX = to.x - unitX * (spaceSize / 2 + 5);
|
|
48
|
+
const endY = to.y - unitY * (spaceSize / 2 + 5);
|
|
49
|
+
// Generate unique marker IDs
|
|
50
|
+
const markerId = `arrow-${isUp ? "up" : "down"}-${from.x}-${from.y}`;
|
|
51
|
+
return (_jsxs("g", { className: className, children: [_jsx("defs", { children: _jsx("marker", { id: markerId, markerWidth: "10", markerHeight: "7", refX: "9", refY: "3.5", orient: "auto", children: _jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: color }) }) }), _jsx("line", { x1: startX, y1: startY, x2: endX, y2: endY, stroke: color, strokeWidth: strokeWidth, strokeDasharray: "6,4", markerEnd: `url(#${markerId})` })] }));
|
|
52
|
+
}
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// Main Component
|
|
55
|
+
// ============================================================================
|
|
56
|
+
export function TrackBoard({ spaces, pieces, type = "linear", renderSpace, renderConnection, renderJump, width = 800, height = 600, enablePanZoom = false, initialZoom = 1, minZoom = 0.5, maxZoom = 3, className, }) {
|
|
57
|
+
// Use the unified pan/zoom hook
|
|
58
|
+
const { transform, bind, isDragging } = usePanZoom({
|
|
59
|
+
enabled: enablePanZoom,
|
|
60
|
+
initialZoom,
|
|
61
|
+
minZoom,
|
|
62
|
+
maxZoom,
|
|
63
|
+
mode: "viewbox",
|
|
64
|
+
});
|
|
65
|
+
// Group pieces by space
|
|
66
|
+
const piecesBySpace = useMemo(() => {
|
|
67
|
+
const map = {};
|
|
68
|
+
pieces.forEach((p) => {
|
|
69
|
+
const existing = map[p.spaceId];
|
|
70
|
+
if (existing) {
|
|
71
|
+
existing.push(p);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
map[p.spaceId] = [p];
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return map;
|
|
78
|
+
}, [pieces]);
|
|
79
|
+
// Sort spaces by index for drawing connections
|
|
80
|
+
const sortedSpaces = useMemo(() => {
|
|
81
|
+
return [...spaces].sort((a, b) => a.index - b.index);
|
|
82
|
+
}, [spaces]);
|
|
83
|
+
// Create space lookup
|
|
84
|
+
const spaceMap = useMemo(() => {
|
|
85
|
+
return new Map(spaces.map((s) => [s.id, s]));
|
|
86
|
+
}, [spaces]);
|
|
87
|
+
// Render connections between spaces
|
|
88
|
+
const renderConnections = () => {
|
|
89
|
+
if (!renderConnection)
|
|
90
|
+
return null;
|
|
91
|
+
return sortedSpaces.map((space, i) => {
|
|
92
|
+
const nextSpace = sortedSpaces[i + 1];
|
|
93
|
+
const firstSpace = sortedSpaces[0];
|
|
94
|
+
const nextSpaceIds = space.nextSpaces ||
|
|
95
|
+
(i < sortedSpaces.length - 1 && nextSpace
|
|
96
|
+
? [nextSpace.id]
|
|
97
|
+
: type === "circular" && firstSpace
|
|
98
|
+
? [firstSpace.id]
|
|
99
|
+
: []);
|
|
100
|
+
return nextSpaceIds.map((nextId) => {
|
|
101
|
+
const targetSpace = spaceMap.get(nextId);
|
|
102
|
+
if (!targetSpace)
|
|
103
|
+
return null;
|
|
104
|
+
return (_jsx("g", { children: renderConnection(space.position, targetSpace.position, space, targetSpace) }, `${space.id}-${nextId}`));
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
// Render jump arrows (snakes/ladders)
|
|
109
|
+
const renderJumps = () => {
|
|
110
|
+
if (!renderJump)
|
|
111
|
+
return null;
|
|
112
|
+
return spaces.flatMap((space) => {
|
|
113
|
+
if (!space.jumpTo)
|
|
114
|
+
return [];
|
|
115
|
+
const targetSpace = spaceMap.get(space.jumpTo);
|
|
116
|
+
if (!targetSpace)
|
|
117
|
+
return [];
|
|
118
|
+
const isUp = targetSpace.index > space.index;
|
|
119
|
+
return [
|
|
120
|
+
_jsx("g", { children: renderJump(space.position, targetSpace.position, space, targetSpace, isUp) }, `jump-${space.id}`),
|
|
121
|
+
];
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
// Calculate viewBox dimensions
|
|
125
|
+
const baseWidth = typeof width === "number" ? width : 800;
|
|
126
|
+
const baseHeight = typeof height === "number" ? height : 600;
|
|
127
|
+
const viewBoxWidth = baseWidth / transform.zoom;
|
|
128
|
+
const viewBoxHeight = baseHeight / transform.zoom;
|
|
129
|
+
const viewBoxX = (baseWidth - viewBoxWidth) / 2 - transform.pan.x;
|
|
130
|
+
const viewBoxY = (baseHeight - viewBoxHeight) / 2 - transform.pan.y;
|
|
131
|
+
return (_jsxs("svg", { width: width, height: height, viewBox: `${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}`, className: clsx("overflow-visible", enablePanZoom && "touch-none", isDragging && "cursor-grabbing", enablePanZoom && !isDragging && "cursor-grab", className), ...bind(), role: "img", "aria-label": "Track board", children: [_jsx("g", { className: "track-connections", children: renderConnections() }), _jsx("g", { className: "track-jumps", children: renderJumps() }), _jsx("g", { className: "track-spaces", role: "list", "aria-label": "Track spaces", children: spaces.map((space) => {
|
|
132
|
+
const spacePieces = piecesBySpace[space.id] || [];
|
|
133
|
+
return (_jsx("g", { transform: `translate(${space.position.x}, ${space.position.y})`, children: renderSpace(space, spacePieces) }, space.id));
|
|
134
|
+
}) }), enablePanZoom && transform.zoom !== 1 && (_jsxs("g", { transform: `translate(${viewBoxX + 10}, ${viewBoxY + viewBoxHeight - 30})`, children: [_jsx("rect", { x: 0, y: 0, width: 60, height: 20, rx: 4, fill: "rgba(0,0,0,0.6)" }), _jsxs("text", { x: 30, y: 14, textAnchor: "middle", fill: "white", fontSize: 12, children: [Math.round(transform.zoom * 100), "%"] })] }))] }));
|
|
135
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG-based area control visualization for territory games (Risk, Small World, Diplomacy).
|
|
3
|
+
*/
|
|
4
|
+
import { type ReactNode } from "react";
|
|
5
|
+
export interface ZoneShape {
|
|
6
|
+
type: "polygon" | "path" | "circle";
|
|
7
|
+
points?: Array<{
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
}>;
|
|
11
|
+
/** SVG path data */
|
|
12
|
+
path?: string;
|
|
13
|
+
center?: {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
};
|
|
17
|
+
radius?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ZoneDefinition {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
adjacentTo: string[];
|
|
23
|
+
shape?: ZoneShape;
|
|
24
|
+
value?: number;
|
|
25
|
+
type?: string;
|
|
26
|
+
data?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
export interface ZonePiece {
|
|
29
|
+
id: string;
|
|
30
|
+
zoneId: string;
|
|
31
|
+
type: string;
|
|
32
|
+
owner?: string;
|
|
33
|
+
/** Count for stackable pieces (armies) */
|
|
34
|
+
count?: number;
|
|
35
|
+
data?: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
export interface ZoneMapProps {
|
|
38
|
+
zones: ZoneDefinition[];
|
|
39
|
+
pieces: ZonePiece[];
|
|
40
|
+
renderZone: (zone: ZoneDefinition, pieces: ZonePiece[]) => ReactNode;
|
|
41
|
+
backgroundImage?: string;
|
|
42
|
+
width?: number | string;
|
|
43
|
+
height?: number | string;
|
|
44
|
+
enablePanZoom?: boolean;
|
|
45
|
+
initialZoom?: number;
|
|
46
|
+
minZoom?: number;
|
|
47
|
+
maxZoom?: number;
|
|
48
|
+
className?: string;
|
|
49
|
+
}
|
|
50
|
+
export type ZoneHighlightType = "valid" | "selected" | "attack" | "defend" | "neutral";
|
|
51
|
+
export interface DefaultZoneProps {
|
|
52
|
+
zone: ZoneDefinition;
|
|
53
|
+
fill?: string;
|
|
54
|
+
stroke?: string;
|
|
55
|
+
strokeWidth?: number;
|
|
56
|
+
isHighlighted?: boolean;
|
|
57
|
+
highlightType?: ZoneHighlightType;
|
|
58
|
+
isSelected?: boolean;
|
|
59
|
+
showLabel?: boolean;
|
|
60
|
+
showValue?: boolean;
|
|
61
|
+
onClick?: () => void;
|
|
62
|
+
onHover?: (hovering: boolean) => void;
|
|
63
|
+
className?: string;
|
|
64
|
+
children?: ReactNode;
|
|
65
|
+
}
|
|
66
|
+
export declare function DefaultZone({ zone, fill, stroke, strokeWidth, isHighlighted, highlightType, isSelected, showLabel, showValue, onClick, onHover, className, children, }: DefaultZoneProps): import("react/jsx-runtime").JSX.Element;
|
|
67
|
+
export interface DefaultZonePiecesProps {
|
|
68
|
+
pieces: ZonePiece[];
|
|
69
|
+
zone: ZoneDefinition;
|
|
70
|
+
playerColors?: Record<string, string>;
|
|
71
|
+
radius?: number;
|
|
72
|
+
spacing?: number;
|
|
73
|
+
yOffset?: number;
|
|
74
|
+
className?: string;
|
|
75
|
+
}
|
|
76
|
+
export declare function DefaultZonePieces({ pieces, zone, playerColors, radius, spacing, yOffset, className, }: DefaultZonePiecesProps): import("react/jsx-runtime").JSX.Element | null;
|
|
77
|
+
export interface DefaultZonePieceProps {
|
|
78
|
+
piece: ZonePiece;
|
|
79
|
+
x?: number;
|
|
80
|
+
y?: number;
|
|
81
|
+
radius?: number;
|
|
82
|
+
color?: string;
|
|
83
|
+
onClick?: () => void;
|
|
84
|
+
className?: string;
|
|
85
|
+
}
|
|
86
|
+
export declare function DefaultZonePiece({ piece, x, y, radius, color, onClick, className, }: DefaultZonePieceProps): import("react/jsx-runtime").JSX.Element;
|
|
87
|
+
export declare function ZoneMap({ zones, pieces, renderZone, backgroundImage, width, height, enablePanZoom, initialZoom, minZoom, maxZoom, className, }: ZoneMapProps): import("react/jsx-runtime").JSX.Element;
|
|
88
|
+
//# sourceMappingURL=ZoneMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ZoneMap.d.ts","sourceRoot":"","sources":["../../../src/components/board/ZoneMap.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* SVG-based area control visualization for territory games (Risk, Small World, Diplomacy).
|
|
4
|
+
*/
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import { clsx } from "clsx";
|
|
7
|
+
import { usePanZoom } from "../../hooks/usePanZoom.js";
|
|
8
|
+
import { handleKeyboardActivation } from "./interaction-accessibility.js";
|
|
9
|
+
// Highlight colors by type
|
|
10
|
+
const HIGHLIGHT_COLORS = {
|
|
11
|
+
valid: "rgba(34, 197, 94, 0.4)", // Green
|
|
12
|
+
selected: "rgba(59, 130, 246, 0.4)", // Blue
|
|
13
|
+
attack: "rgba(239, 68, 68, 0.4)", // Red
|
|
14
|
+
defend: "rgba(234, 179, 8, 0.4)", // Yellow
|
|
15
|
+
neutral: "rgba(148, 163, 184, 0.4)", // Slate
|
|
16
|
+
};
|
|
17
|
+
const HIGHLIGHT_STROKES = {
|
|
18
|
+
valid: "#22c55e",
|
|
19
|
+
selected: "#3b82f6",
|
|
20
|
+
attack: "#ef4444",
|
|
21
|
+
defend: "#eab308",
|
|
22
|
+
neutral: "#94a3b8",
|
|
23
|
+
};
|
|
24
|
+
const EMPTY_PLAYER_COLORS = {};
|
|
25
|
+
export function DefaultZone({ zone, fill = "rgba(100, 116, 139, 0.2)", stroke = "#475569", strokeWidth = 1, isHighlighted = false, highlightType, isSelected = false, showLabel = true, showValue = false, onClick, onHover, className, children, }) {
|
|
26
|
+
// Calculate colors based on state
|
|
27
|
+
let computedFill = fill;
|
|
28
|
+
let computedStroke = stroke;
|
|
29
|
+
let computedStrokeWidth = strokeWidth;
|
|
30
|
+
if (isHighlighted && highlightType && HIGHLIGHT_COLORS[highlightType]) {
|
|
31
|
+
computedFill = HIGHLIGHT_COLORS[highlightType];
|
|
32
|
+
computedStroke = HIGHLIGHT_STROKES[highlightType];
|
|
33
|
+
computedStrokeWidth = 3;
|
|
34
|
+
}
|
|
35
|
+
else if (isSelected) {
|
|
36
|
+
computedFill = HIGHLIGHT_COLORS.selected;
|
|
37
|
+
computedStroke = HIGHLIGHT_STROKES.selected;
|
|
38
|
+
computedStrokeWidth = 3;
|
|
39
|
+
}
|
|
40
|
+
// Render zone shape
|
|
41
|
+
const renderShape = () => {
|
|
42
|
+
if (!zone.shape)
|
|
43
|
+
return null;
|
|
44
|
+
switch (zone.shape.type) {
|
|
45
|
+
case "polygon":
|
|
46
|
+
if (!zone.shape.points)
|
|
47
|
+
return null;
|
|
48
|
+
return (_jsx("polygon", { points: zone.shape.points.map((p) => `${p.x},${p.y}`).join(" "), fill: computedFill, stroke: computedStroke, strokeWidth: computedStrokeWidth }));
|
|
49
|
+
case "path":
|
|
50
|
+
if (!zone.shape.path)
|
|
51
|
+
return null;
|
|
52
|
+
return (_jsx("path", { d: zone.shape.path, fill: computedFill, stroke: computedStroke, strokeWidth: computedStrokeWidth }));
|
|
53
|
+
case "circle":
|
|
54
|
+
if (!zone.shape.center)
|
|
55
|
+
return null;
|
|
56
|
+
return (_jsx("circle", { cx: zone.shape.center.x, cy: zone.shape.center.y, r: zone.shape.radius || 30, fill: computedFill, stroke: computedStroke, strokeWidth: computedStrokeWidth }));
|
|
57
|
+
default:
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return (_jsxs("g", { onClick: onClick, onMouseEnter: () => onHover?.(true), onMouseLeave: () => onHover?.(false), onKeyDown: (event) => handleKeyboardActivation(event, onClick), className: clsx(onClick && "cursor-pointer", className), role: onClick ? "button" : "listitem", "aria-label": zone.name, tabIndex: onClick ? 0 : undefined, children: [renderShape(), showLabel && zone.shape?.center && (_jsx("text", { x: zone.shape.center.x, y: zone.shape.center.y - (showValue ? 8 : 0), textAnchor: "middle", dominantBaseline: "middle", fill: "white", fontSize: 12, fontWeight: "bold", style: { textShadow: "1px 1px 2px rgba(0,0,0,0.8)" }, children: zone.name })), showValue && zone.value !== undefined && zone.shape?.center && (_jsxs("text", { x: zone.shape.center.x, y: zone.shape.center.y + 8, textAnchor: "middle", dominantBaseline: "middle", fill: "#fbbf24", fontSize: 10, fontWeight: "bold", style: { textShadow: "1px 1px 2px rgba(0,0,0,0.8)" }, children: ["+", zone.value] })), children] }));
|
|
62
|
+
}
|
|
63
|
+
export function DefaultZonePieces({ pieces, zone, playerColors = EMPTY_PLAYER_COLORS, radius = 14, spacing = 25, yOffset = 20, className, }) {
|
|
64
|
+
if (pieces.length === 0 || !zone.shape?.center)
|
|
65
|
+
return null;
|
|
66
|
+
const centerX = zone.shape.center.x;
|
|
67
|
+
const centerY = zone.shape.center.y;
|
|
68
|
+
// Group pieces by owner
|
|
69
|
+
const piecesByOwner = {};
|
|
70
|
+
pieces.forEach((p) => {
|
|
71
|
+
const owner = p.owner || "neutral";
|
|
72
|
+
const existing = piecesByOwner[owner];
|
|
73
|
+
if (existing) {
|
|
74
|
+
existing.push(p);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
piecesByOwner[owner] = [p];
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
const owners = Object.keys(piecesByOwner);
|
|
81
|
+
const startOffset = -((owners.length - 1) * spacing) / 2;
|
|
82
|
+
return (_jsx("g", { className: clsx("zone-pieces", className), children: owners.map((owner, i) => {
|
|
83
|
+
const ownerPieces = piecesByOwner[owner] || [];
|
|
84
|
+
const totalCount = ownerPieces.reduce((sum, p) => sum + (p.count || 1), 0);
|
|
85
|
+
const offsetX = startOffset + i * spacing;
|
|
86
|
+
return (_jsxs("g", { transform: `translate(${centerX + offsetX}, ${centerY + yOffset})`, children: [_jsx("circle", { r: radius, fill: playerColors[owner] || "#64748b", stroke: "white", strokeWidth: 2 }), _jsx("text", { textAnchor: "middle", dominantBaseline: "central", fill: "white", fontSize: 10, fontWeight: "bold", children: totalCount })] }, owner));
|
|
87
|
+
}) }));
|
|
88
|
+
}
|
|
89
|
+
export function DefaultZonePiece({ piece, x = 0, y = 0, radius = 14, color = "#64748b", onClick, className, }) {
|
|
90
|
+
const count = piece.count || 1;
|
|
91
|
+
return (_jsxs("g", { transform: `translate(${x}, ${y})`, onClick: (e) => {
|
|
92
|
+
e.stopPropagation();
|
|
93
|
+
onClick?.();
|
|
94
|
+
}, onKeyDown: (event) => handleKeyboardActivation(event, onClick, { stopPropagation: true }), className: clsx(onClick && "cursor-pointer", className), role: onClick ? "button" : undefined, tabIndex: onClick ? 0 : undefined, "aria-label": `Piece ${piece.id}`, children: [_jsx("circle", { r: radius, fill: color, stroke: "white", strokeWidth: 2 }), _jsx("text", { textAnchor: "middle", dominantBaseline: "central", fill: "white", fontSize: 10, fontWeight: "bold", children: count })] }));
|
|
95
|
+
}
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Main Component
|
|
98
|
+
// ============================================================================
|
|
99
|
+
export function ZoneMap({ zones, pieces, renderZone, backgroundImage, width = 800, height = 600, enablePanZoom = false, initialZoom = 1, minZoom = 0.5, maxZoom = 3, className, }) {
|
|
100
|
+
// Use the unified pan/zoom hook
|
|
101
|
+
const { transform, bind, isDragging } = usePanZoom({
|
|
102
|
+
enabled: enablePanZoom,
|
|
103
|
+
initialZoom,
|
|
104
|
+
minZoom,
|
|
105
|
+
maxZoom,
|
|
106
|
+
mode: "viewbox",
|
|
107
|
+
});
|
|
108
|
+
// Group pieces by zone
|
|
109
|
+
const piecesByZone = useMemo(() => {
|
|
110
|
+
const map = {};
|
|
111
|
+
pieces.forEach((p) => {
|
|
112
|
+
const existing = map[p.zoneId];
|
|
113
|
+
if (existing) {
|
|
114
|
+
existing.push(p);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
map[p.zoneId] = [p];
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return map;
|
|
121
|
+
}, [pieces]);
|
|
122
|
+
// Calculate viewBox dimensions
|
|
123
|
+
const baseWidth = typeof width === "number" ? width : 800;
|
|
124
|
+
const baseHeight = typeof height === "number" ? height : 600;
|
|
125
|
+
const viewBoxWidth = baseWidth / transform.zoom;
|
|
126
|
+
const viewBoxHeight = baseHeight / transform.zoom;
|
|
127
|
+
const viewBoxX = (baseWidth - viewBoxWidth) / 2 - transform.pan.x;
|
|
128
|
+
const viewBoxY = (baseHeight - viewBoxHeight) / 2 - transform.pan.y;
|
|
129
|
+
return (_jsxs("svg", { width: width, height: height, viewBox: `${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}`, className: clsx("overflow-visible", enablePanZoom && "touch-none", isDragging && "cursor-grabbing", enablePanZoom && !isDragging && "cursor-grab", className), ...bind(), role: "img", "aria-label": "Zone map", children: [backgroundImage && (_jsx("image", { href: backgroundImage, width: width, height: height })), _jsx("g", { className: "zones", role: "list", "aria-label": "Map zones", children: zones.map((zone) => {
|
|
130
|
+
const zonePieces = piecesByZone[zone.id] || [];
|
|
131
|
+
return _jsx("g", { children: renderZone(zone, zonePieces) }, zone.id);
|
|
132
|
+
}) }), enablePanZoom && transform.zoom !== 1 && (_jsxs("g", { transform: `translate(${viewBoxX + 10}, ${viewBoxY + viewBoxHeight - 30})`, children: [_jsx("rect", { x: 0, y: 0, width: 60, height: 20, rx: 4, fill: "rgba(0,0,0,0.6)" }), _jsxs("text", { x: 30, y: 14, textAnchor: "middle", fill: "white", fontSize: 12, children: [Math.round(transform.zoom * 100), "%"] })] }))] }));
|
|
133
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed adapter for joining static hex-board topology with a dynamic
|
|
3
|
+
* per-space view overlay. Use this to feed `HexGrid` a single board
|
|
4
|
+
* value whose tiles carry both static geometry (`q`, `r`, `id`) and
|
|
5
|
+
* the projected view fields the UI cares about (e.g. `terrain`,
|
|
6
|
+
* `numberToken`).
|
|
7
|
+
*
|
|
8
|
+
* The runtime is intentionally strict: every static space must have
|
|
9
|
+
* exactly one overlay, duplicates throw, and overlays for ids that
|
|
10
|
+
* are not on the board throw. There is no relaxed fallback in v1 —
|
|
11
|
+
* silent merge bugs are far more expensive than a loud throw at
|
|
12
|
+
* dev/CI time.
|
|
13
|
+
*/
|
|
14
|
+
import type { AnyHexBoardInput, BoardIdOf, BoardSpaceIdOf, NormalizedHexTileOf } from "../../types/tiled-board.js";
|
|
15
|
+
/**
|
|
16
|
+
* Per-tile result produced by {@link createHexBoardView}. Each tile
|
|
17
|
+
* carries the static topology (`id`, `q`, `r`) plus the matched
|
|
18
|
+
* overlay row in `view`.
|
|
19
|
+
*
|
|
20
|
+
* Static board fields/properties are preserved from `TBoard`.
|
|
21
|
+
* Consumers should use `tile.properties` for authored static space
|
|
22
|
+
* fields and `tile.view` for dynamic per-space projection data.
|
|
23
|
+
*/
|
|
24
|
+
export type HexBoardViewTile<TBoard extends AnyHexBoardInput, TSpaceView extends {
|
|
25
|
+
id: BoardSpaceIdOf<TBoard>;
|
|
26
|
+
}> = Omit<NormalizedHexTileOf<TBoard>, "view"> & {
|
|
27
|
+
view: TSpaceView;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Result of {@link createHexBoardView}. Shaped like an authored hex
|
|
31
|
+
* board so it can be passed straight to `<HexGrid board={...} />`
|
|
32
|
+
* without any further adapter work.
|
|
33
|
+
*
|
|
34
|
+
* The type-level board id and space id are preserved from `TBoard`,
|
|
35
|
+
* so `tile.id` stays narrow inside `renderTile`. `tile.view` is the
|
|
36
|
+
* authored overlay row, fully typed.
|
|
37
|
+
*/
|
|
38
|
+
export interface HexBoardView<TBoard extends AnyHexBoardInput, TSpaceView extends {
|
|
39
|
+
id: BoardSpaceIdOf<TBoard>;
|
|
40
|
+
}> {
|
|
41
|
+
id: BoardIdOf<TBoard>;
|
|
42
|
+
layout?: "hex";
|
|
43
|
+
orientation?: "pointy-top" | "flat-top";
|
|
44
|
+
tiles: ReadonlyArray<HexBoardViewTile<TBoard, TSpaceView>>;
|
|
45
|
+
edges: TBoard["edges"];
|
|
46
|
+
vertices: TBoard["vertices"];
|
|
47
|
+
}
|
|
48
|
+
interface CreateHexBoardViewOptions<TSpaceView> {
|
|
49
|
+
spaces: readonly TSpaceView[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Join a static hex board topology with a dynamic per-space overlay.
|
|
53
|
+
*
|
|
54
|
+
* The result is suitable for direct use as the `board` prop on
|
|
55
|
+
* `<HexGrid>`. Every overlay is enforced 1-to-1 against the board's
|
|
56
|
+
* spaces:
|
|
57
|
+
*
|
|
58
|
+
* - missing overlay for a board space → throws
|
|
59
|
+
* - duplicate overlay (same `id` twice) → throws
|
|
60
|
+
* - overlay `id` not present on the board → throws
|
|
61
|
+
*
|
|
62
|
+
* Each tile in the result carries a `view` field with the matched
|
|
63
|
+
* overlay row.
|
|
64
|
+
*/
|
|
65
|
+
export declare function createHexBoardView<const TBoard extends AnyHexBoardInput, const TSpaceView extends {
|
|
66
|
+
id: BoardSpaceIdOf<TBoard>;
|
|
67
|
+
}>(board: TBoard, options: CreateHexBoardViewOptions<TSpaceView>): HexBoardView<TBoard, TSpaceView>;
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=hex-board-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hex-board-view.d.ts","sourceRoot":"","sources":["../../../src/components/board/hex-board-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,CAC1B,MAAM,SAAS,gBAAgB,EAC/B,UAAU,SAAS;IAAE,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;CAAE,IAC/C,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY,CAC3B,MAAM,SAAS,gBAAgB,EAC/B,UAAU,SAAS;IAAE,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;CAAE;IAEjD,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACtB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,KAAK,EAAE,aAAa,CAAC,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;CAC9B;AAED,UAAU,yBAAyB,CAAC,UAAU;IAC5C,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;CAC/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,CAAC,MAAM,SAAS,gBAAgB,EACrC,KAAK,CAAC,UAAU,SAAS;IAAE,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;CAAE,EAEvD,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC,GAC7C,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAyClC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed adapter for joining static hex-board topology with a dynamic
|
|
3
|
+
* per-space view overlay. Use this to feed `HexGrid` a single board
|
|
4
|
+
* value whose tiles carry both static geometry (`q`, `r`, `id`) and
|
|
5
|
+
* the projected view fields the UI cares about (e.g. `terrain`,
|
|
6
|
+
* `numberToken`).
|
|
7
|
+
*
|
|
8
|
+
* The runtime is intentionally strict: every static space must have
|
|
9
|
+
* exactly one overlay, duplicates throw, and overlays for ids that
|
|
10
|
+
* are not on the board throw. There is no relaxed fallback in v1 —
|
|
11
|
+
* silent merge bugs are far more expensive than a loud throw at
|
|
12
|
+
* dev/CI time.
|
|
13
|
+
*/
|
|
14
|
+
import { normalizeHexBoardInput } from "../../types/tiled-board.js";
|
|
15
|
+
/**
|
|
16
|
+
* Join a static hex board topology with a dynamic per-space overlay.
|
|
17
|
+
*
|
|
18
|
+
* The result is suitable for direct use as the `board` prop on
|
|
19
|
+
* `<HexGrid>`. Every overlay is enforced 1-to-1 against the board's
|
|
20
|
+
* spaces:
|
|
21
|
+
*
|
|
22
|
+
* - missing overlay for a board space → throws
|
|
23
|
+
* - duplicate overlay (same `id` twice) → throws
|
|
24
|
+
* - overlay `id` not present on the board → throws
|
|
25
|
+
*
|
|
26
|
+
* Each tile in the result carries a `view` field with the matched
|
|
27
|
+
* overlay row.
|
|
28
|
+
*/
|
|
29
|
+
export function createHexBoardView(board, options) {
|
|
30
|
+
const overlayById = new Map();
|
|
31
|
+
for (const overlay of options.spaces) {
|
|
32
|
+
if (overlayById.has(overlay.id)) {
|
|
33
|
+
throw new Error(`createHexBoardView: duplicate overlay for space '${overlay.id}'.`);
|
|
34
|
+
}
|
|
35
|
+
overlayById.set(overlay.id, overlay);
|
|
36
|
+
}
|
|
37
|
+
const consumed = new Set();
|
|
38
|
+
const normalizedBoard = normalizeHexBoardInput(board);
|
|
39
|
+
const tiles = normalizedBoard.tiles.map((tile) => {
|
|
40
|
+
const overlay = overlayById.get(tile.id);
|
|
41
|
+
if (!overlay) {
|
|
42
|
+
throw new Error(`createHexBoardView: missing overlay for space '${tile.id}'.`);
|
|
43
|
+
}
|
|
44
|
+
consumed.add(tile.id);
|
|
45
|
+
return { ...tile, view: overlay };
|
|
46
|
+
});
|
|
47
|
+
for (const id of overlayById.keys()) {
|
|
48
|
+
if (!consumed.has(id)) {
|
|
49
|
+
throw new Error(`createHexBoardView: overlay '${id}' is not on the board.`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
id: normalizedBoard.id,
|
|
54
|
+
layout: "hex",
|
|
55
|
+
orientation: board.orientation,
|
|
56
|
+
tiles,
|
|
57
|
+
edges: board.edges,
|
|
58
|
+
vertices: board.vertices,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board Primitives
|
|
3
|
+
*
|
|
4
|
+
* Reusable board visualization components for different game types.
|
|
5
|
+
*
|
|
6
|
+
* Components:
|
|
7
|
+
* - NetworkGraph: For route-building games (Ticket to Ride, Pandemic)
|
|
8
|
+
* - HexGrid: For hex-based games (Catan, wargames)
|
|
9
|
+
* - SquareGrid: For grid-based games (Chess, Go, Checkers)
|
|
10
|
+
* - ZoneMap: For area control games (Risk, Small World)
|
|
11
|
+
* - TrackBoard: For track/racing games (Monopoly, Game of Life)
|
|
12
|
+
* - SlotSystem: For worker placement games (Agricola, Viticulture)
|
|
13
|
+
*/
|
|
14
|
+
export { NetworkGraph, DefaultNetworkNode, DefaultNetworkEdge, DefaultNetworkPiece, type NetworkGraphProps, type NetworkNode, type NetworkEdge, type NetworkPiece, type DefaultNetworkNodeProps, type DefaultNetworkEdgeProps, type DefaultNetworkPieceProps, } from "./NetworkGraph.js";
|
|
15
|
+
export { HexGrid, hexUtils, DefaultHexTile, DefaultHexEdge, DefaultHexVertex, type HexGridBoardProps, type HexGridProps, type HexOrientation, type HexTileGeometry, type InteractiveHexEdge, type InteractiveHexSpace, type InteractiveHexVertex, type EdgePosition, type DefaultHexTileProps, type DefaultHexEdgeProps, type DefaultHexVertexProps, } from "./HexGrid.js";
|
|
16
|
+
export type { InteractiveTargetLayer, InteractiveTargetRenderState, } from "./target-layer.js";
|
|
17
|
+
export { createHexBoardView, type HexBoardView, type HexBoardViewTile, } from "./hex-board-view.js";
|
|
18
|
+
export { SquareGrid, DefaultGridCell, DefaultGridPiece, DefaultChessPiece, toAlgebraic, toNumeric, type SquareGridBoardProps, type SquareGridProps, type InteractiveSquareEdge, type InteractiveSquareSpace, type InteractiveSquareVertex, type SquareEdgePosition, type SquareVertexPosition, type DefaultGridCellProps, type DefaultGridPieceProps, type DefaultChessPieceProps, } from "./SquareGrid.js";
|
|
19
|
+
export { ZoneMap, DefaultZone, DefaultZonePieces, DefaultZonePiece, type ZoneMapProps, type ZoneDefinition, type ZonePiece, type ZoneShape, type ZoneHighlightType, type DefaultZoneProps, type DefaultZonePiecesProps, type DefaultZonePieceProps, } from "./ZoneMap.js";
|
|
20
|
+
export { TrackBoard, DefaultTrackSpace, DefaultTrackPiece, DefaultTrackConnection, DefaultTrackJump, type TrackBoardProps, type TrackSpace, type TrackPiece, type DefaultTrackSpaceProps, type DefaultTrackPieceProps, type DefaultTrackConnectionProps, type DefaultTrackJumpProps, } from "./TrackBoard.js";
|
|
21
|
+
export { SlotSystem, DefaultSlotItem, DefaultSlotOccupant, DefaultEmptySlot, type SlotSystemProps, type SlotDefinition, type SlotOccupant, type DefaultSlotItemProps, type DefaultSlotOccupantProps, type DefaultEmptySlotProps, } from "./SlotSystem.js";
|
|
22
|
+
export type { HexTileState, HexEdgeState, HexVertexState, SquareCellState, SquareEdgeState, SquarePieceState, SquareVertexState, } from "../../types/player-state.js";
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|