@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,111 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import { type InteractionHandle } from "../../hooks/useInteractionHandle.js";
|
|
3
|
+
import type { InteractionDescriptor } from "../../types/plugin-state.js";
|
|
4
|
+
import type { InteractionDefaultedKeysOf, InteractionParamsByKeyShape, InteractionParamsOf, SurfaceRenderMap } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Resolved salience tier for a panel interaction. Authors set
|
|
7
|
+
* `descriptor.salience` directly; when omitted we derive a sensible
|
|
8
|
+
* default from `descriptor.emphasis` so existing workspaces inherit
|
|
9
|
+
* the new ordering / disclosure behaviour without being touched.
|
|
10
|
+
*
|
|
11
|
+
* - `descriptor.salience === "hero"` → `hero`
|
|
12
|
+
* - `descriptor.salience === "tertiary"` → `tertiary`
|
|
13
|
+
* - `descriptor.emphasis === "primary"` → `hero`
|
|
14
|
+
* - `descriptor.emphasis === "destructive"` → `tertiary`
|
|
15
|
+
* - everything else → `secondary` (the default tier)
|
|
16
|
+
*/
|
|
17
|
+
export type PanelSalience = "hero" | "secondary" | "tertiary";
|
|
18
|
+
export interface PanelSurfaceProps<I extends string = never, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}> {
|
|
19
|
+
/**
|
|
20
|
+
* Optional per-interaction overrides. Omit entirely to use the default
|
|
21
|
+
* renderer (`DefaultInteractionButton`) for every interaction; supply a
|
|
22
|
+
* partial map to replace the default UI for specific interaction ids.
|
|
23
|
+
*/
|
|
24
|
+
render?: SurfaceRenderMap<I, ParamsByKey>;
|
|
25
|
+
/**
|
|
26
|
+
* Fallback renderer for interactions without a `render` entry. Defaults
|
|
27
|
+
* to the built-in `DefaultInteractionButton` which honours metadata
|
|
28
|
+
* (`icon`, `label`, `emphasis`, `unavailableReason`).
|
|
29
|
+
*/
|
|
30
|
+
renderItem?: (descriptor: InteractionDescriptor<I>, handle: InteractionHandle<InteractionParamsOf<ParamsByKey, I>, InteractionDefaultedKeysOf<ParamsByKey, I>>) => ReactNode;
|
|
31
|
+
/** Shown when no panel interactions are available. */
|
|
32
|
+
empty?: ReactNode;
|
|
33
|
+
/**
|
|
34
|
+
* Optional grouping function. Defaults to `descriptor.group`; authors
|
|
35
|
+
* can override to cluster interactions differently. Returning
|
|
36
|
+
* `undefined` keeps the interaction in the ungrouped tail cluster.
|
|
37
|
+
*/
|
|
38
|
+
groupBy?: (descriptor: InteractionDescriptor<I>) => string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Override the default salience derivation. Receives the descriptor
|
|
41
|
+
* and returns the tier it should occupy. Use to demote something the
|
|
42
|
+
* authoring layer mis-tagged as `emphasis: "primary"` without
|
|
43
|
+
* changing the upstream contract.
|
|
44
|
+
*/
|
|
45
|
+
salienceFor?: (descriptor: InteractionDescriptor<I>) => PanelSalience;
|
|
46
|
+
/**
|
|
47
|
+
* Maximum number of `secondary`-tier items to render directly in the
|
|
48
|
+
* panel. Excess secondaries spill into the {@link MoreActions}
|
|
49
|
+
* disclosure (alongside the always-disclosed `tertiary` tier).
|
|
50
|
+
* Defaults to `Infinity` — secondaries stay visible. Lower this on
|
|
51
|
+
* dense HUDs to fight Hick's Law.
|
|
52
|
+
*
|
|
53
|
+
* Hero items are never spilled, so a panel with three hero entries
|
|
54
|
+
* and `maxVisibleSecondary: 0` still renders three buttons inline
|
|
55
|
+
* plus the disclosure.
|
|
56
|
+
*/
|
|
57
|
+
maxVisibleSecondary?: number;
|
|
58
|
+
/**
|
|
59
|
+
* Label for the disclosure toggle. Defaults to `"More"`. Pass a
|
|
60
|
+
* workspace-specific copy ("Advanced", "Manage", …) when the
|
|
61
|
+
* generic label feels wrong.
|
|
62
|
+
*/
|
|
63
|
+
moreActionsLabel?: string;
|
|
64
|
+
/** Interaction keys intentionally rendered elsewhere, such as auto primary actions. */
|
|
65
|
+
excludeInteractionKeys?: readonly string[];
|
|
66
|
+
/**
|
|
67
|
+
* Render unavailable interactions as disabled items. Defaults to false so
|
|
68
|
+
* stale-step actions do not compete with legal actions.
|
|
69
|
+
*/
|
|
70
|
+
showUnavailable?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Layout overrides for the default container. Useful for tightly
|
|
73
|
+
* constrained mobile layouts. When the caller supplies their own
|
|
74
|
+
* `render` for every interaction they can ignore these entirely.
|
|
75
|
+
*/
|
|
76
|
+
layout?: {
|
|
77
|
+
direction?: "row" | "column";
|
|
78
|
+
wrap?: boolean;
|
|
79
|
+
gap?: CSSProperties["gap"];
|
|
80
|
+
align?: CSSProperties["alignItems"];
|
|
81
|
+
justify?: CSSProperties["justifyContent"];
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Default salience resolver — see {@link PanelSalience}. Exported so
|
|
86
|
+
* authors who want to slightly tweak the policy can compose with it
|
|
87
|
+
* (`salienceFor: (d) => d.id === "x" ? "hero" : defaultPanelSalience(d)`).
|
|
88
|
+
*/
|
|
89
|
+
export declare function defaultPanelSalience(_descriptor: InteractionDescriptor): PanelSalience;
|
|
90
|
+
/**
|
|
91
|
+
* Default renderer for `surface: "panel"` interactions.
|
|
92
|
+
*
|
|
93
|
+
* Visual styling comes entirely from the active {@link useTheme}; mount
|
|
94
|
+
* `<ThemeProvider theme={...}/>` to swap the look. Per-interaction overrides
|
|
95
|
+
* via `render` are the escape hatch when a specific interaction needs bespoke
|
|
96
|
+
* UI.
|
|
97
|
+
*
|
|
98
|
+
* Salience policy
|
|
99
|
+
* ===============
|
|
100
|
+
* Each descriptor is assigned a {@link PanelSalience} via
|
|
101
|
+
* {@link defaultPanelSalience} (override with the `salienceFor` prop).
|
|
102
|
+
* The panel sorts groups so `hero` items render first, then
|
|
103
|
+
* `secondary`, then `tertiary` — and the `tertiary` cluster (plus any
|
|
104
|
+
* spill from `maxVisibleSecondary`) lives behind a {@link MoreActions}
|
|
105
|
+
* disclosure so a crowded panel doesn't drown the player in choices
|
|
106
|
+
* (Hick's Law). Groups stay contiguous: a group inherits the highest
|
|
107
|
+
* salience among its members so a hero+secondary cluster doesn't get
|
|
108
|
+
* split across the disclosure boundary.
|
|
109
|
+
*/
|
|
110
|
+
export declare function PanelSurface<I extends string = never, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}>({ render, renderItem, empty, groupBy, salienceFor, maxVisibleSecondary, moreActionsLabel, excludeInteractionKeys, showUnavailable, layout, }: PanelSurfaceProps<I, ParamsByKey>): import("react/jsx-runtime").JSX.Element;
|
|
111
|
+
//# sourceMappingURL=PanelSurface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PanelSurface.d.ts","sourceRoot":"","sources":["../../../src/components/surfaces/PanelSurface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAGzE,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAE9D,MAAM,WAAW,iBAAiB,CAChC,CAAC,SAAS,MAAM,GAAG,KAAK,EACxB,WAAW,SAAS,OAAO,CAAC,2BAA2B,CAAC,GAAG,EAAE;IAE7D;;;;OAIG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAC1C;;;;OAIG;IACH,UAAU,CAAC,EAAE,CACX,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,EACpC,MAAM,EAAE,iBAAiB,CACvB,mBAAmB,CAAC,WAAW,EAAE,CAAC,CAAC,EACnC,0BAA0B,CAAC,WAAW,EAAE,CAAC,CAAC,CAC3C,KACE,SAAS,CAAC;IACf,sDAAsD;IACtD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC;IACtE;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;QAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,GAAG,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3B,KAAK,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;QACpC,OAAO,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;KAC3C,CAAC;CACH;AAQD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,qBAAqB,GACjC,aAAa,CAEf;AAkBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAC1B,CAAC,SAAS,MAAM,GAAG,KAAK,EACxB,WAAW,SAAS,OAAO,CAAC,2BAA2B,CAAC,GAAG,EAAE,EAC7D,EACA,MAAM,EACN,UAAU,EACV,KAAY,EACZ,OAAyB,EACzB,WAAW,EACX,mBAA8C,EAC9C,gBAAgB,EAChB,sBAAsB,EACtB,eAAuB,EACvB,MAAM,GACP,EAAE,iBAAiB,CAAC,CAAC,EAAE,WAAW,CAAC,2CAkGnC"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useSeatInbox } from "../../hooks/useSeatInbox.js";
|
|
3
|
+
import { useInteractionHandle, } from "../../hooks/useInteractionHandle.js";
|
|
4
|
+
import { useTheme } from "../../theme/ThemeProvider.js";
|
|
5
|
+
import { DefaultInteractionButton } from "./internal/DefaultInteractionButton.js";
|
|
6
|
+
import { MoreActions } from "../MoreActions.js";
|
|
7
|
+
const SALIENCE_RANK = {
|
|
8
|
+
hero: 0,
|
|
9
|
+
secondary: 1,
|
|
10
|
+
tertiary: 2,
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Default salience resolver — see {@link PanelSalience}. Exported so
|
|
14
|
+
* authors who want to slightly tweak the policy can compose with it
|
|
15
|
+
* (`salienceFor: (d) => d.id === "x" ? "hero" : defaultPanelSalience(d)`).
|
|
16
|
+
*/
|
|
17
|
+
export function defaultPanelSalience(_descriptor) {
|
|
18
|
+
return "secondary";
|
|
19
|
+
}
|
|
20
|
+
// `align: "flex-start"` is deliberate. Panel items are heterogeneous —
|
|
21
|
+
// a `DefaultInteractionButton` sits next to authored cards that can
|
|
22
|
+
// expand into multi-row draft forms (e.g. an offer-trade card). With
|
|
23
|
+
// `stretch` the short buttons get dragged to the tallest sibling's
|
|
24
|
+
// height and render as floor-to-ceiling bars next to the expanded form.
|
|
25
|
+
// Authors who *do* want uniform heights can opt in via `layout.align`.
|
|
26
|
+
const defaultLayout = {
|
|
27
|
+
direction: "row",
|
|
28
|
+
wrap: true,
|
|
29
|
+
gap: "8px",
|
|
30
|
+
align: "flex-start",
|
|
31
|
+
justify: "flex-start",
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Default renderer for `surface: "panel"` interactions.
|
|
35
|
+
*
|
|
36
|
+
* Visual styling comes entirely from the active {@link useTheme}; mount
|
|
37
|
+
* `<ThemeProvider theme={...}/>` to swap the look. Per-interaction overrides
|
|
38
|
+
* via `render` are the escape hatch when a specific interaction needs bespoke
|
|
39
|
+
* UI.
|
|
40
|
+
*
|
|
41
|
+
* Salience policy
|
|
42
|
+
* ===============
|
|
43
|
+
* Each descriptor is assigned a {@link PanelSalience} via
|
|
44
|
+
* {@link defaultPanelSalience} (override with the `salienceFor` prop).
|
|
45
|
+
* The panel sorts groups so `hero` items render first, then
|
|
46
|
+
* `secondary`, then `tertiary` — and the `tertiary` cluster (plus any
|
|
47
|
+
* spill from `maxVisibleSecondary`) lives behind a {@link MoreActions}
|
|
48
|
+
* disclosure so a crowded panel doesn't drown the player in choices
|
|
49
|
+
* (Hick's Law). Groups stay contiguous: a group inherits the highest
|
|
50
|
+
* salience among its members so a hero+secondary cluster doesn't get
|
|
51
|
+
* split across the disclosure boundary.
|
|
52
|
+
*/
|
|
53
|
+
export function PanelSurface({ render, renderItem, empty = null, groupBy = () => undefined, salienceFor, maxVisibleSecondary = Number.POSITIVE_INFINITY, moreActionsLabel, excludeInteractionKeys, showUnavailable = false, layout, }) {
|
|
54
|
+
const inbox = useSeatInbox();
|
|
55
|
+
const excluded = new Set(excludeInteractionKeys ?? []);
|
|
56
|
+
const items = (inbox.bySurface.panel ?? []).filter((descriptor) => !excluded.has(descriptor.interactionKey) &&
|
|
57
|
+
(showUnavailable || descriptor.available));
|
|
58
|
+
if (items.length === 0)
|
|
59
|
+
return _jsx(_Fragment, { children: empty });
|
|
60
|
+
const resolvedLayout = { ...defaultLayout, ...(layout ?? {}) };
|
|
61
|
+
const resolveSalience = salienceFor ?? defaultPanelSalience;
|
|
62
|
+
// Compute groups first (preserves authored cohesion), then assign
|
|
63
|
+
// each group a tier from its highest-salience member, then sort by
|
|
64
|
+
// tier while keeping members in their original order.
|
|
65
|
+
const grouped = groupInteractions(items, groupBy, resolveSalience);
|
|
66
|
+
const sorted = [...grouped].sort((a, b) => {
|
|
67
|
+
const tierDiff = SALIENCE_RANK[a.tier] - SALIENCE_RANK[b.tier];
|
|
68
|
+
if (tierDiff !== 0)
|
|
69
|
+
return tierDiff;
|
|
70
|
+
// Same tier — preserve authored order via the cached index.
|
|
71
|
+
return a.firstIndex - b.firstIndex;
|
|
72
|
+
});
|
|
73
|
+
// Decide which groups stay in the main row vs. spill into the
|
|
74
|
+
// disclosure. Hero groups always stay; tertiary groups always
|
|
75
|
+
// spill; secondary groups spill once we've already shown
|
|
76
|
+
// `maxVisibleSecondary` of them. A group counts as 1 toward the
|
|
77
|
+
// budget regardless of how many descriptors it contains — losing
|
|
78
|
+
// half a "build" cluster would be more confusing than rendering
|
|
79
|
+
// the whole sub-row.
|
|
80
|
+
const visible = [];
|
|
81
|
+
const disclosed = [];
|
|
82
|
+
let secondariesShown = 0;
|
|
83
|
+
for (const group of sorted) {
|
|
84
|
+
if (group.tier === "hero") {
|
|
85
|
+
visible.push(group);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (group.tier === "tertiary") {
|
|
89
|
+
disclosed.push(group);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (secondariesShown < maxVisibleSecondary) {
|
|
93
|
+
visible.push(group);
|
|
94
|
+
secondariesShown += 1;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
disclosed.push(group);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Count the underlying descriptors so the disclosure badge reads
|
|
101
|
+
// "More (3)" not "More (1 group)".
|
|
102
|
+
const disclosedCount = disclosed.reduce((sum, group) => sum + group.interactions.length, 0);
|
|
103
|
+
return (_jsxs("div", { role: "toolbar", "aria-label": "Panel actions", "data-shell-slot": "panel-actions", style: {
|
|
104
|
+
display: "flex",
|
|
105
|
+
flexDirection: resolvedLayout.direction,
|
|
106
|
+
flexWrap: resolvedLayout.wrap ? "wrap" : "nowrap",
|
|
107
|
+
gap: resolvedLayout.gap,
|
|
108
|
+
alignItems: resolvedLayout.align,
|
|
109
|
+
justifyContent: resolvedLayout.justify,
|
|
110
|
+
}, children: [visible.map((group) => (_jsx(PanelGroup, { group: group, render: render, renderItem: renderItem }, group.id))), disclosed.length > 0 ? (_jsx(MoreActions, { label: moreActionsLabel, count: disclosedCount, children: disclosed.map((group) => (_jsx(PanelGroup, { group: group, render: render, renderItem: renderItem }, group.id))) })) : null] }));
|
|
111
|
+
}
|
|
112
|
+
function groupInteractions(items, groupBy, resolveSalience) {
|
|
113
|
+
const ordered = [];
|
|
114
|
+
const byGroup = new Map();
|
|
115
|
+
items.forEach((descriptor, index) => {
|
|
116
|
+
const tier = resolveSalience(descriptor);
|
|
117
|
+
const key = groupBy(descriptor);
|
|
118
|
+
if (key === undefined) {
|
|
119
|
+
ordered.push({
|
|
120
|
+
id: `solo:${descriptor.interactionId}`,
|
|
121
|
+
grouped: false,
|
|
122
|
+
interactions: [descriptor],
|
|
123
|
+
tier,
|
|
124
|
+
firstIndex: index,
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const bucket = byGroup.get(key);
|
|
129
|
+
if (bucket) {
|
|
130
|
+
bucket.interactions.push(descriptor);
|
|
131
|
+
if (SALIENCE_RANK[tier] < SALIENCE_RANK[bucket.tier]) {
|
|
132
|
+
bucket.tier = tier;
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const fresh = {
|
|
137
|
+
id: `group:${key}`,
|
|
138
|
+
grouped: true,
|
|
139
|
+
interactions: [descriptor],
|
|
140
|
+
tier,
|
|
141
|
+
firstIndex: index,
|
|
142
|
+
};
|
|
143
|
+
byGroup.set(key, fresh);
|
|
144
|
+
ordered.push(fresh);
|
|
145
|
+
});
|
|
146
|
+
return ordered.map((bucket) => ({
|
|
147
|
+
id: bucket.id,
|
|
148
|
+
interactions: bucket.interactions,
|
|
149
|
+
grouped: bucket.grouped,
|
|
150
|
+
tier: bucket.tier,
|
|
151
|
+
firstIndex: bucket.firstIndex,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
function PanelGroup({ group, render, renderItem, }) {
|
|
155
|
+
const theme = useTheme();
|
|
156
|
+
if (!group.grouped || group.interactions.length === 1) {
|
|
157
|
+
return (_jsx(_Fragment, { children: group.interactions.map((descriptor) => (_jsx(PanelItem, { descriptor: descriptor, render: render, renderItem: renderItem, tier: group.tier }, descriptor.interactionKey))) }));
|
|
158
|
+
}
|
|
159
|
+
return (_jsx("div", { "data-panel-group": group.id, "data-panel-tier": group.tier, style: {
|
|
160
|
+
display: "inline-flex",
|
|
161
|
+
gap: theme.space[1],
|
|
162
|
+
padding: theme.space[1],
|
|
163
|
+
borderRadius: theme.radius.lg,
|
|
164
|
+
background: theme.semantic.surface.inset,
|
|
165
|
+
}, children: group.interactions.map((descriptor) => (_jsx(PanelItem, { descriptor: descriptor, render: render, renderItem: renderItem, compact: true, tier: group.tier }, descriptor.interactionKey))) }));
|
|
166
|
+
}
|
|
167
|
+
function PanelItem({ descriptor, render, renderItem, compact, tier, }) {
|
|
168
|
+
const handle = useInteractionHandle(descriptor);
|
|
169
|
+
const override = render?.[descriptor.interactionKey];
|
|
170
|
+
if (override)
|
|
171
|
+
return _jsx(_Fragment, { children: override(descriptor, handle) });
|
|
172
|
+
if (renderItem)
|
|
173
|
+
return _jsx(_Fragment, { children: renderItem(descriptor, handle) });
|
|
174
|
+
// Salience-driven sizing: hero buttons use the `lg` size so they
|
|
175
|
+
// outweigh the `secondary` tier next to them. Tertiary items render
|
|
176
|
+
// inside the disclosure where the smaller `sm` size keeps the
|
|
177
|
+
// disclosed cluster from feeling like a second main panel.
|
|
178
|
+
const size = compact || tier === "tertiary" ? "sm" : tier === "hero" ? "lg" : "md";
|
|
179
|
+
return (_jsx(DefaultInteractionButton, { descriptor: descriptor, handle: handle, compact: compact, size: size, "data-panel-tier": tier }));
|
|
180
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { ViewCard } from "@dreamboard/sdk-types";
|
|
3
|
+
import type { CardSize, HandLayout } from "../../hooks/useHandLayout.js";
|
|
4
|
+
import { type CardZoneInteractionContext } from "./internal/useCardZoneInteractions.js";
|
|
5
|
+
import type { InteractionParamsByKeyShape } from "./types.js";
|
|
6
|
+
export type PlayerCardsLayout<ZoneKey extends string = string> = PlayerCardZoneNode<ZoneKey> | PlayerCardsGroup<ZoneKey>;
|
|
7
|
+
export interface PlayerCardsGroup<ZoneKey extends string = string> {
|
|
8
|
+
kind: "group";
|
|
9
|
+
direction: "row" | "column";
|
|
10
|
+
children: ReadonlyArray<PlayerCardsLayout<ZoneKey>>;
|
|
11
|
+
}
|
|
12
|
+
export interface PlayerCardZoneModel<I extends string = string> {
|
|
13
|
+
zoneId: string;
|
|
14
|
+
label: string;
|
|
15
|
+
totalCount: number;
|
|
16
|
+
visibleCards: readonly ViewCard[];
|
|
17
|
+
hiddenCount: number;
|
|
18
|
+
hiddenCardIds: readonly string[];
|
|
19
|
+
contexts: ReadonlyArray<CardZoneInteractionContext<I>>;
|
|
20
|
+
contextsByCardId: ReadonlyMap<string, CardZoneInteractionContext<I>>;
|
|
21
|
+
}
|
|
22
|
+
export type PlayerCardZoneNode<ZoneKey extends string = string> = PlayerCardsPileNode<ZoneKey> | PlayerCardsFanNode<ZoneKey> | PlayerCardsCustomNode<ZoneKey>;
|
|
23
|
+
export interface PlayerCardsPileNode<ZoneKey extends string = string> {
|
|
24
|
+
kind: "pile";
|
|
25
|
+
zone: ZoneKey;
|
|
26
|
+
label?: string;
|
|
27
|
+
top?: "first" | "last";
|
|
28
|
+
details?: "drawer" | "none";
|
|
29
|
+
/**
|
|
30
|
+
* Explicit override for the count badge. Use when the player view
|
|
31
|
+
* hides the zone's `cardIds` (private decks, hidden draw piles) so
|
|
32
|
+
* the SDK's auto-derived `zone.totalCount` reads zero. The reducer
|
|
33
|
+
* still owns the source of truth — pass it through `defineView`.
|
|
34
|
+
*/
|
|
35
|
+
count?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Explicit override for the visible top-card preview. Use when the
|
|
38
|
+
* top card isn't part of the player's zone projection but is known
|
|
39
|
+
* via a custom view field. Falls back to {@link top} selection over
|
|
40
|
+
* `zone.visibleCards` when omitted.
|
|
41
|
+
*/
|
|
42
|
+
topCard?: ViewCard | null;
|
|
43
|
+
/**
|
|
44
|
+
* Replace just the visible top-card / face-down preview while keeping
|
|
45
|
+
* the SDK's button + count badge + drawer machinery. Use this when you
|
|
46
|
+
* want a custom card face but still want clicks to open the drawer.
|
|
47
|
+
*/
|
|
48
|
+
renderPreview?: (zone: PlayerCardZoneModel) => ReactNode;
|
|
49
|
+
/** Replace the empty-state (no cards) preview only. */
|
|
50
|
+
renderEmpty?: (zone: PlayerCardZoneModel) => ReactNode;
|
|
51
|
+
/**
|
|
52
|
+
* Per-card content renderer used by the default drawer body. Authors
|
|
53
|
+
* who supply this on every node can hoist it to the surface root via
|
|
54
|
+
* {@link PlayerCardsSurfaceConfig.renderCardContent}.
|
|
55
|
+
*/
|
|
56
|
+
renderCardContent?: (card: ViewCard, ctx: CardZoneInteractionContext) => ReactNode;
|
|
57
|
+
/** Replace the drawer body wholesale. */
|
|
58
|
+
renderDrawerContent?: (zone: PlayerCardZoneModel) => ReactNode;
|
|
59
|
+
/**
|
|
60
|
+
* Escape hatch — replaces the pile entirely (button, count badge,
|
|
61
|
+
* drawer, click handling). Prefer {@link renderPreview} +
|
|
62
|
+
* {@link renderDrawerContent} so authors don't accidentally drop the
|
|
63
|
+
* default click-to-open behavior. Reserved for cases that need fully
|
|
64
|
+
* bespoke chrome.
|
|
65
|
+
*/
|
|
66
|
+
renderPile?: (zone: PlayerCardZoneModel) => ReactNode;
|
|
67
|
+
}
|
|
68
|
+
export interface PlayerCardsFanNode<ZoneKey extends string = string> {
|
|
69
|
+
kind: "fan";
|
|
70
|
+
zone: ZoneKey;
|
|
71
|
+
label?: string;
|
|
72
|
+
renderCardContent?: (card: ViewCard, ctx: CardZoneInteractionContext) => ReactNode;
|
|
73
|
+
renderZone?: (zone: PlayerCardZoneModel) => ReactNode;
|
|
74
|
+
cardSize?: CardSize;
|
|
75
|
+
layout?: HandLayout;
|
|
76
|
+
}
|
|
77
|
+
export interface PlayerCardsCustomNode<ZoneKey extends string = string> {
|
|
78
|
+
kind: "custom";
|
|
79
|
+
zone: ZoneKey;
|
|
80
|
+
label?: string;
|
|
81
|
+
renderZone: (zone: PlayerCardZoneModel) => ReactNode;
|
|
82
|
+
}
|
|
83
|
+
export interface PlayerCardsSurfaceConfig<ZoneKey extends string = string> {
|
|
84
|
+
layout: PlayerCardsLayout<ZoneKey>;
|
|
85
|
+
/**
|
|
86
|
+
* Default per-card content renderer inherited by every `pile` and
|
|
87
|
+
* `fan` in the layout. Per-node `renderCardContent` (on a fan) or
|
|
88
|
+
* `renderCardContent` / `renderPreview` (on a pile) still wins. Set
|
|
89
|
+
* this once at the surface root to avoid passing the same `<CardFace>`
|
|
90
|
+
* to every zone.
|
|
91
|
+
*/
|
|
92
|
+
renderCardContent?: (card: ViewCard, ctx: CardZoneInteractionContext) => ReactNode;
|
|
93
|
+
}
|
|
94
|
+
export interface PlayerCardsSurfaceProps<ZoneKey extends string = string> extends PlayerCardsSurfaceConfig<ZoneKey> {
|
|
95
|
+
empty?: ReactNode;
|
|
96
|
+
}
|
|
97
|
+
export declare function definePlayerCardsSurface<const Config extends PlayerCardsSurfaceConfig<string>>(config: Config): Config;
|
|
98
|
+
export declare function row<const ZoneKey extends string>(children: ReadonlyArray<PlayerCardsLayout<ZoneKey>>): PlayerCardsGroup<ZoneKey>;
|
|
99
|
+
export declare function column<const ZoneKey extends string>(children: ReadonlyArray<PlayerCardsLayout<ZoneKey>>): PlayerCardsGroup<ZoneKey>;
|
|
100
|
+
export declare function pile<const ZoneKey extends string>(zone: ZoneKey, options?: Omit<PlayerCardsPileNode<ZoneKey>, "kind" | "zone">): PlayerCardsPileNode<ZoneKey>;
|
|
101
|
+
export declare function fan<const ZoneKey extends string>(zone: ZoneKey, options?: Omit<PlayerCardsFanNode<ZoneKey>, "kind" | "zone">): PlayerCardsFanNode<ZoneKey>;
|
|
102
|
+
export declare function custom<const ZoneKey extends string>(zone: ZoneKey, options: Omit<PlayerCardsCustomNode<ZoneKey>, "kind" | "zone">): PlayerCardsCustomNode<ZoneKey>;
|
|
103
|
+
export declare function PlayerCardsSurface<I extends string = never, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}, ZoneKey extends string = string>({ layout, renderCardContent, empty, }: PlayerCardsSurfaceProps<ZoneKey>): import("react/jsx-runtime").JSX.Element;
|
|
104
|
+
//# sourceMappingURL=PlayerCardsSurface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlayerCardsSurface.d.ts","sourceRoot":"","sources":["../../../src/components/surfaces/PlayerCardsSurface.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, useMemo, useState } from "react";
|
|
3
|
+
import { usePluginState } from "../../context/PluginStateContext.js";
|
|
4
|
+
import { useTheme } from "../../theme/ThemeProvider.js";
|
|
5
|
+
import { Card } from "../Card.js";
|
|
6
|
+
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from "../Drawer.js";
|
|
7
|
+
import { Hand } from "../Hand.js";
|
|
8
|
+
import { useCardZoneInteractions, } from "./internal/useCardZoneInteractions.js";
|
|
9
|
+
import { CardZoneFollowUpForm } from "./internal/CardZoneFollowUpForm.js";
|
|
10
|
+
export function definePlayerCardsSurface(config) {
|
|
11
|
+
return config;
|
|
12
|
+
}
|
|
13
|
+
export function row(children) {
|
|
14
|
+
return { kind: "group", direction: "row", children };
|
|
15
|
+
}
|
|
16
|
+
export function column(children) {
|
|
17
|
+
return { kind: "group", direction: "column", children };
|
|
18
|
+
}
|
|
19
|
+
export function pile(zone, options = {}) {
|
|
20
|
+
return { kind: "pile", zone, ...options };
|
|
21
|
+
}
|
|
22
|
+
export function fan(zone, options = {}) {
|
|
23
|
+
return { kind: "fan", zone, ...options };
|
|
24
|
+
}
|
|
25
|
+
export function custom(zone, options) {
|
|
26
|
+
return { kind: "custom", zone, ...options };
|
|
27
|
+
}
|
|
28
|
+
export function PlayerCardsSurface({ layout, renderCardContent, empty = null, }) {
|
|
29
|
+
if (!layout)
|
|
30
|
+
return _jsx(_Fragment, { children: empty });
|
|
31
|
+
return (_jsx(PlayerCardsLayoutNode, { layout: layout, surfaceRenderCardContent: renderCardContent }));
|
|
32
|
+
}
|
|
33
|
+
function PlayerCardsLayoutNode({ layout, surfaceRenderCardContent, }) {
|
|
34
|
+
const theme = useTheme();
|
|
35
|
+
if (layout.kind === "group") {
|
|
36
|
+
return (_jsx("div", { "data-player-cards-group": layout.direction, style: {
|
|
37
|
+
display: "flex",
|
|
38
|
+
flexDirection: layout.direction,
|
|
39
|
+
gap: theme.space[2],
|
|
40
|
+
alignItems: layout.direction === "row" ? "flex-end" : "stretch",
|
|
41
|
+
// Fill the parent so flex children (especially the fan with
|
|
42
|
+
// `flex: 1 1 ...`) can grow to use the available width.
|
|
43
|
+
// Without this, the row collapses to its children's intrinsic
|
|
44
|
+
// size and the fan never gets room to spread.
|
|
45
|
+
width: "100%",
|
|
46
|
+
minWidth: 0,
|
|
47
|
+
}, children: layout.children.map((child, index) => (_jsx(PlayerCardsLayoutNode, { layout: child, surfaceRenderCardContent: surfaceRenderCardContent }, index))) }));
|
|
48
|
+
}
|
|
49
|
+
return (_jsx(PlayerCardsZoneNode, { node: layout, surfaceRenderCardContent: surfaceRenderCardContent }));
|
|
50
|
+
}
|
|
51
|
+
function PlayerCardsZoneNode({ node, surfaceRenderCardContent, }) {
|
|
52
|
+
const zone = usePlayerCardZone(String(node.zone), node.label);
|
|
53
|
+
if (node.kind === "custom")
|
|
54
|
+
return _jsx(_Fragment, { children: node.renderZone(zone) });
|
|
55
|
+
if (node.kind === "pile") {
|
|
56
|
+
return (_jsx(PlayerCardsPile, { node: node, zone: zone, surfaceRenderCardContent: surfaceRenderCardContent }));
|
|
57
|
+
}
|
|
58
|
+
return (_jsx(PlayerCardsFan, { node: node, zone: zone, surfaceRenderCardContent: surfaceRenderCardContent }));
|
|
59
|
+
}
|
|
60
|
+
function usePlayerCardZone(zoneId, label) {
|
|
61
|
+
const interactions = useCardZoneInteractions(zoneId, { surface: "hand" });
|
|
62
|
+
const zone = usePluginState((s) => s.gameplay.zones?.[zoneId]);
|
|
63
|
+
return useMemo(() => {
|
|
64
|
+
const cardIds = zone?.cardIds ?? [];
|
|
65
|
+
const visibleIds = new Set(interactions.cards.map((card) => card.id));
|
|
66
|
+
const contextsByCardId = new Map(interactions.contexts.map((ctx) => [ctx.card.id, ctx]));
|
|
67
|
+
return {
|
|
68
|
+
...interactions,
|
|
69
|
+
zoneId,
|
|
70
|
+
label: label ?? zoneId,
|
|
71
|
+
totalCount: cardIds.length,
|
|
72
|
+
visibleCards: interactions.cards,
|
|
73
|
+
hiddenCount: Math.max(0, cardIds.length - interactions.cards.length),
|
|
74
|
+
hiddenCardIds: cardIds.filter((cardId) => !visibleIds.has(cardId)),
|
|
75
|
+
contexts: interactions.contexts,
|
|
76
|
+
contextsByCardId,
|
|
77
|
+
};
|
|
78
|
+
}, [interactions, label, zone?.cardIds, zoneId]);
|
|
79
|
+
}
|
|
80
|
+
function PlayerCardsPile({ node, zone, surfaceRenderCardContent, }) {
|
|
81
|
+
const [open, setOpen] = useState(false);
|
|
82
|
+
const top = node.top ?? "first";
|
|
83
|
+
const previewCard = node.topCard !== undefined
|
|
84
|
+
? node.topCard
|
|
85
|
+
: top === "last"
|
|
86
|
+
? (zone.visibleCards[zone.visibleCards.length - 1] ?? null)
|
|
87
|
+
: (zone.visibleCards[0] ?? null);
|
|
88
|
+
const totalCount = node.count ?? zone.totalCount;
|
|
89
|
+
const drawerEnabled = (node.details ?? "drawer") !== "none";
|
|
90
|
+
const cardContent = node.renderCardContent ?? surfaceRenderCardContent;
|
|
91
|
+
// Full escape hatch — author owns button + drawer + everything.
|
|
92
|
+
if (node.renderPile)
|
|
93
|
+
return _jsx(_Fragment, { children: node.renderPile(zone) });
|
|
94
|
+
const previewNode = node.renderPreview ? (node.renderPreview(zone)) : previewCard ? (_jsx(Card, { card: previewCard, disabled: true, size: "sm", renderContent: cardContent
|
|
95
|
+
? (card) => {
|
|
96
|
+
const ctx = zone.contextsByCardId.get(card.id);
|
|
97
|
+
return cardContent(card, ctx ?? emptyZoneContext(card));
|
|
98
|
+
}
|
|
99
|
+
: undefined })) : node.renderEmpty ? (node.renderEmpty(zone)) : (_jsx("div", { "aria-label": "Hidden card", style: {
|
|
100
|
+
width: 72,
|
|
101
|
+
height: 100,
|
|
102
|
+
borderRadius: 8,
|
|
103
|
+
border: "2px solid #111",
|
|
104
|
+
background: "repeating-linear-gradient(135deg, #ddd, #ddd 6px, #bbb 6px, #bbb 12px)",
|
|
105
|
+
} }));
|
|
106
|
+
return (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", "data-player-cards-pile": zone.zoneId, onClick: () => {
|
|
107
|
+
if (drawerEnabled)
|
|
108
|
+
setOpen(true);
|
|
109
|
+
}, style: {
|
|
110
|
+
display: "flex",
|
|
111
|
+
flexDirection: "column",
|
|
112
|
+
alignItems: "center",
|
|
113
|
+
gap: 6,
|
|
114
|
+
border: 0,
|
|
115
|
+
background: "transparent",
|
|
116
|
+
padding: 0,
|
|
117
|
+
cursor: drawerEnabled ? "pointer" : "default",
|
|
118
|
+
}, children: [_jsx("span", { style: { fontSize: 12, fontWeight: 700 }, children: zone.label }), _jsxs("div", { style: { position: "relative", minWidth: 72, minHeight: 100 }, children: [previewNode, _jsx("span", { "data-player-cards-pile-count": true, style: {
|
|
119
|
+
position: "absolute",
|
|
120
|
+
right: -6,
|
|
121
|
+
bottom: -6,
|
|
122
|
+
borderRadius: 999,
|
|
123
|
+
padding: "2px 6px",
|
|
124
|
+
background: "#111",
|
|
125
|
+
color: "#fff",
|
|
126
|
+
fontSize: 12,
|
|
127
|
+
}, children: totalCount })] })] }), _jsx(Drawer, { open: open, onOpenChange: setOpen, children: _jsxs(DrawerContent, { children: [_jsx(DrawerHeader, { children: _jsx(DrawerTitle, { children: zone.label }) }), node.renderDrawerContent ? (node.renderDrawerContent(zone)) : (_jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: [zone.visibleCards.map((card) => (_jsx(Card, { card: card, disabled: true, size: "sm", renderContent: cardContent
|
|
128
|
+
? (c) => {
|
|
129
|
+
const ctx = zone.contextsByCardId.get(c.id);
|
|
130
|
+
return cardContent(c, ctx ?? emptyZoneContext(c));
|
|
131
|
+
}
|
|
132
|
+
: undefined }, card.id))), Array.from({ length: zone.hiddenCount }).map((_, index) => (_jsx("div", { children: "Hidden card" }, index)))] }))] }) })] }));
|
|
133
|
+
}
|
|
134
|
+
function emptyZoneContext(card) {
|
|
135
|
+
return {
|
|
136
|
+
card,
|
|
137
|
+
interactions: [],
|
|
138
|
+
play: null,
|
|
139
|
+
disabled: true,
|
|
140
|
+
actionState: "unavailable",
|
|
141
|
+
selected: false,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function PlayerCardsFan({ node, zone, surfaceRenderCardContent, }) {
|
|
145
|
+
const cardSize = node.cardSize ?? "md";
|
|
146
|
+
if (node.renderZone)
|
|
147
|
+
return _jsx(_Fragment, { children: node.renderZone(zone) });
|
|
148
|
+
const renderCardContent = node.renderCardContent ?? surfaceRenderCardContent;
|
|
149
|
+
return (
|
|
150
|
+
// `min-width: 0` lets the flex item shrink below its intrinsic
|
|
151
|
+
// content width when the row's other children need space. `Hand`
|
|
152
|
+
// self-clamps card positions to the measured container width via
|
|
153
|
+
// `useHandLayout`, so cards no longer bleed into sibling piles
|
|
154
|
+
// without us needing to clip the wrapper (which would also
|
|
155
|
+
// suppress the hover-lift translateY above the dock chrome).
|
|
156
|
+
_jsxs("div", { "data-player-cards-fan": zone.zoneId, style: { flex: "1 1 280px", minWidth: 0 }, children: [_jsx(Hand, { cards: zone.visibleCards, cardSize: cardSize, layout: node.layout, renderCard: (props) => {
|
|
157
|
+
const ctx = zone.contextsByCardId.get(props.card.id);
|
|
158
|
+
const disabled = ctx?.disabled ?? true;
|
|
159
|
+
return (_jsx("div", { className: "absolute bottom-0 transition-all duration-150 ease-out", style: {
|
|
160
|
+
left: props.x,
|
|
161
|
+
zIndex: props.zIndex,
|
|
162
|
+
transform: `translateY(${props.y}px)`,
|
|
163
|
+
}, children: _jsx(Card, { card: props.card, selected: props.isSelected, disabled: disabled, size: cardSize, onCardClick: disabled
|
|
164
|
+
? undefined
|
|
165
|
+
: (cardId) => {
|
|
166
|
+
const clickedCtx = zone.contextsByCardId.get(cardId);
|
|
167
|
+
if (clickedCtx?.play)
|
|
168
|
+
void clickedCtx.play();
|
|
169
|
+
}, renderContent: renderCardContent
|
|
170
|
+
? (card) => {
|
|
171
|
+
const renderCtx = zone.contextsByCardId.get(card.id);
|
|
172
|
+
if (!renderCtx)
|
|
173
|
+
return null;
|
|
174
|
+
return renderCardContent(card, renderCtx);
|
|
175
|
+
}
|
|
176
|
+
: undefined }) }, props.card.id));
|
|
177
|
+
} }), zone.followUp ? (_jsx(Fragment, { children: _jsx(CardZoneFollowUpForm, { descriptor: zone.followUp, onDone: () => zone.setFollowUp(null) }, zone.followUp.interactionKey) })) : null] }));
|
|
178
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InteractionDescriptor } from "../../../types/plugin-state.js";
|
|
2
|
+
import type { InteractionParamsByKeyShape } from "../types.js";
|
|
3
|
+
export declare function CardZoneFollowUpForm<I extends string, ParamsByKey extends Partial<InteractionParamsByKeyShape> = {}>({ descriptor, onDone, }: {
|
|
4
|
+
descriptor: InteractionDescriptor<I>;
|
|
5
|
+
onDone: () => void;
|
|
6
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=CardZoneFollowUpForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CardZoneFollowUpForm.d.ts","sourceRoot":"","sources":["../../../../src/components/surfaces/internal/CardZoneFollowUpForm.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,EAEV,2BAA2B,EAE5B,MAAM,aAAa,CAAC;AAErB,wBAAgB,oBAAoB,CAClC,CAAC,SAAS,MAAM,EAChB,WAAW,SAAS,OAAO,CAAC,2BAA2B,CAAC,GAAG,EAAE,EAC7D,EACA,UAAU,EACV,MAAM,GACP,EAAE;IACD,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,2CAgBA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { InteractionForm } from "../../InteractionForm.js";
|
|
3
|
+
import { useInteractionHandle } from "../../../hooks/useInteractionHandle.js";
|
|
4
|
+
export function CardZoneFollowUpForm({ descriptor, onDone, }) {
|
|
5
|
+
const handle = useInteractionHandle(descriptor);
|
|
6
|
+
return (_jsx(InteractionForm, { descriptor: descriptor, handle: handle, hiddenFields: [
|
|
7
|
+
"cardId",
|
|
8
|
+
], onCancel: onDone, onSubmitSuccess: onDone }));
|
|
9
|
+
}
|