@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,458 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import { useSeatInbox } from "../../hooks/useSeatInbox.js";
|
|
3
|
+
import {
|
|
4
|
+
useInteractionHandle,
|
|
5
|
+
type InteractionHandle,
|
|
6
|
+
} from "../../hooks/useInteractionHandle.js";
|
|
7
|
+
import { useTheme } from "../../theme/ThemeProvider.js";
|
|
8
|
+
import type { InteractionDescriptor } from "../../types/plugin-state.js";
|
|
9
|
+
import { DefaultInteractionButton } from "./internal/DefaultInteractionButton.js";
|
|
10
|
+
import { MoreActions } from "../MoreActions.js";
|
|
11
|
+
import type {
|
|
12
|
+
InteractionDefaultedKeysOf,
|
|
13
|
+
InteractionParamsByKeyShape,
|
|
14
|
+
InteractionParamsOf,
|
|
15
|
+
SurfaceRenderMap,
|
|
16
|
+
} from "./types.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Resolved salience tier for a panel interaction. Authors set
|
|
20
|
+
* `descriptor.salience` directly; when omitted we derive a sensible
|
|
21
|
+
* default from `descriptor.emphasis` so existing workspaces inherit
|
|
22
|
+
* the new ordering / disclosure behaviour without being touched.
|
|
23
|
+
*
|
|
24
|
+
* - `descriptor.salience === "hero"` → `hero`
|
|
25
|
+
* - `descriptor.salience === "tertiary"` → `tertiary`
|
|
26
|
+
* - `descriptor.emphasis === "primary"` → `hero`
|
|
27
|
+
* - `descriptor.emphasis === "destructive"` → `tertiary`
|
|
28
|
+
* - everything else → `secondary` (the default tier)
|
|
29
|
+
*/
|
|
30
|
+
export type PanelSalience = "hero" | "secondary" | "tertiary";
|
|
31
|
+
|
|
32
|
+
export interface PanelSurfaceProps<
|
|
33
|
+
I extends string = never,
|
|
34
|
+
ParamsByKey extends Partial<InteractionParamsByKeyShape> = {},
|
|
35
|
+
> {
|
|
36
|
+
/**
|
|
37
|
+
* Optional per-interaction overrides. Omit entirely to use the default
|
|
38
|
+
* renderer (`DefaultInteractionButton`) for every interaction; supply a
|
|
39
|
+
* partial map to replace the default UI for specific interaction ids.
|
|
40
|
+
*/
|
|
41
|
+
render?: SurfaceRenderMap<I, ParamsByKey>;
|
|
42
|
+
/**
|
|
43
|
+
* Fallback renderer for interactions without a `render` entry. Defaults
|
|
44
|
+
* to the built-in `DefaultInteractionButton` which honours metadata
|
|
45
|
+
* (`icon`, `label`, `emphasis`, `unavailableReason`).
|
|
46
|
+
*/
|
|
47
|
+
renderItem?: (
|
|
48
|
+
descriptor: InteractionDescriptor<I>,
|
|
49
|
+
handle: InteractionHandle<
|
|
50
|
+
InteractionParamsOf<ParamsByKey, I>,
|
|
51
|
+
InteractionDefaultedKeysOf<ParamsByKey, I>
|
|
52
|
+
>,
|
|
53
|
+
) => ReactNode;
|
|
54
|
+
/** Shown when no panel interactions are available. */
|
|
55
|
+
empty?: ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* Optional grouping function. Defaults to `descriptor.group`; authors
|
|
58
|
+
* can override to cluster interactions differently. Returning
|
|
59
|
+
* `undefined` keeps the interaction in the ungrouped tail cluster.
|
|
60
|
+
*/
|
|
61
|
+
groupBy?: (descriptor: InteractionDescriptor<I>) => string | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Override the default salience derivation. Receives the descriptor
|
|
64
|
+
* and returns the tier it should occupy. Use to demote something the
|
|
65
|
+
* authoring layer mis-tagged as `emphasis: "primary"` without
|
|
66
|
+
* changing the upstream contract.
|
|
67
|
+
*/
|
|
68
|
+
salienceFor?: (descriptor: InteractionDescriptor<I>) => PanelSalience;
|
|
69
|
+
/**
|
|
70
|
+
* Maximum number of `secondary`-tier items to render directly in the
|
|
71
|
+
* panel. Excess secondaries spill into the {@link MoreActions}
|
|
72
|
+
* disclosure (alongside the always-disclosed `tertiary` tier).
|
|
73
|
+
* Defaults to `Infinity` — secondaries stay visible. Lower this on
|
|
74
|
+
* dense HUDs to fight Hick's Law.
|
|
75
|
+
*
|
|
76
|
+
* Hero items are never spilled, so a panel with three hero entries
|
|
77
|
+
* and `maxVisibleSecondary: 0` still renders three buttons inline
|
|
78
|
+
* plus the disclosure.
|
|
79
|
+
*/
|
|
80
|
+
maxVisibleSecondary?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Label for the disclosure toggle. Defaults to `"More"`. Pass a
|
|
83
|
+
* workspace-specific copy ("Advanced", "Manage", …) when the
|
|
84
|
+
* generic label feels wrong.
|
|
85
|
+
*/
|
|
86
|
+
moreActionsLabel?: string;
|
|
87
|
+
/** Interaction keys intentionally rendered elsewhere, such as auto primary actions. */
|
|
88
|
+
excludeInteractionKeys?: readonly string[];
|
|
89
|
+
/**
|
|
90
|
+
* Render unavailable interactions as disabled items. Defaults to false so
|
|
91
|
+
* stale-step actions do not compete with legal actions.
|
|
92
|
+
*/
|
|
93
|
+
showUnavailable?: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Layout overrides for the default container. Useful for tightly
|
|
96
|
+
* constrained mobile layouts. When the caller supplies their own
|
|
97
|
+
* `render` for every interaction they can ignore these entirely.
|
|
98
|
+
*/
|
|
99
|
+
layout?: {
|
|
100
|
+
direction?: "row" | "column";
|
|
101
|
+
wrap?: boolean;
|
|
102
|
+
gap?: CSSProperties["gap"];
|
|
103
|
+
align?: CSSProperties["alignItems"];
|
|
104
|
+
justify?: CSSProperties["justifyContent"];
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const SALIENCE_RANK: Record<PanelSalience, number> = {
|
|
109
|
+
hero: 0,
|
|
110
|
+
secondary: 1,
|
|
111
|
+
tertiary: 2,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Default salience resolver — see {@link PanelSalience}. Exported so
|
|
116
|
+
* authors who want to slightly tweak the policy can compose with it
|
|
117
|
+
* (`salienceFor: (d) => d.id === "x" ? "hero" : defaultPanelSalience(d)`).
|
|
118
|
+
*/
|
|
119
|
+
export function defaultPanelSalience(
|
|
120
|
+
_descriptor: InteractionDescriptor,
|
|
121
|
+
): PanelSalience {
|
|
122
|
+
return "secondary";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// `align: "flex-start"` is deliberate. Panel items are heterogeneous —
|
|
126
|
+
// a `DefaultInteractionButton` sits next to authored cards that can
|
|
127
|
+
// expand into multi-row draft forms (e.g. an offer-trade card). With
|
|
128
|
+
// `stretch` the short buttons get dragged to the tallest sibling's
|
|
129
|
+
// height and render as floor-to-ceiling bars next to the expanded form.
|
|
130
|
+
// Authors who *do* want uniform heights can opt in via `layout.align`.
|
|
131
|
+
const defaultLayout: Required<
|
|
132
|
+
NonNullable<PanelSurfaceProps<string>["layout"]>
|
|
133
|
+
> = {
|
|
134
|
+
direction: "row",
|
|
135
|
+
wrap: true,
|
|
136
|
+
gap: "8px",
|
|
137
|
+
align: "flex-start",
|
|
138
|
+
justify: "flex-start",
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Default renderer for `surface: "panel"` interactions.
|
|
143
|
+
*
|
|
144
|
+
* Visual styling comes entirely from the active {@link useTheme}; mount
|
|
145
|
+
* `<ThemeProvider theme={...}/>` to swap the look. Per-interaction overrides
|
|
146
|
+
* via `render` are the escape hatch when a specific interaction needs bespoke
|
|
147
|
+
* UI.
|
|
148
|
+
*
|
|
149
|
+
* Salience policy
|
|
150
|
+
* ===============
|
|
151
|
+
* Each descriptor is assigned a {@link PanelSalience} via
|
|
152
|
+
* {@link defaultPanelSalience} (override with the `salienceFor` prop).
|
|
153
|
+
* The panel sorts groups so `hero` items render first, then
|
|
154
|
+
* `secondary`, then `tertiary` — and the `tertiary` cluster (plus any
|
|
155
|
+
* spill from `maxVisibleSecondary`) lives behind a {@link MoreActions}
|
|
156
|
+
* disclosure so a crowded panel doesn't drown the player in choices
|
|
157
|
+
* (Hick's Law). Groups stay contiguous: a group inherits the highest
|
|
158
|
+
* salience among its members so a hero+secondary cluster doesn't get
|
|
159
|
+
* split across the disclosure boundary.
|
|
160
|
+
*/
|
|
161
|
+
export function PanelSurface<
|
|
162
|
+
I extends string = never,
|
|
163
|
+
ParamsByKey extends Partial<InteractionParamsByKeyShape> = {},
|
|
164
|
+
>({
|
|
165
|
+
render,
|
|
166
|
+
renderItem,
|
|
167
|
+
empty = null,
|
|
168
|
+
groupBy = () => undefined,
|
|
169
|
+
salienceFor,
|
|
170
|
+
maxVisibleSecondary = Number.POSITIVE_INFINITY,
|
|
171
|
+
moreActionsLabel,
|
|
172
|
+
excludeInteractionKeys,
|
|
173
|
+
showUnavailable = false,
|
|
174
|
+
layout,
|
|
175
|
+
}: PanelSurfaceProps<I, ParamsByKey>) {
|
|
176
|
+
const inbox = useSeatInbox();
|
|
177
|
+
const excluded = new Set(excludeInteractionKeys ?? []);
|
|
178
|
+
const items = (
|
|
179
|
+
(inbox.bySurface.panel ?? []) as ReadonlyArray<InteractionDescriptor<I>>
|
|
180
|
+
).filter(
|
|
181
|
+
(descriptor) =>
|
|
182
|
+
!excluded.has(descriptor.interactionKey) &&
|
|
183
|
+
(showUnavailable || descriptor.available),
|
|
184
|
+
);
|
|
185
|
+
if (items.length === 0) return <>{empty}</>;
|
|
186
|
+
|
|
187
|
+
const resolvedLayout = { ...defaultLayout, ...(layout ?? {}) };
|
|
188
|
+
const resolveSalience: (
|
|
189
|
+
descriptor: InteractionDescriptor<I>,
|
|
190
|
+
) => PanelSalience = salienceFor ?? defaultPanelSalience;
|
|
191
|
+
|
|
192
|
+
// Compute groups first (preserves authored cohesion), then assign
|
|
193
|
+
// each group a tier from its highest-salience member, then sort by
|
|
194
|
+
// tier while keeping members in their original order.
|
|
195
|
+
const grouped = groupInteractions<I>(items, groupBy, resolveSalience);
|
|
196
|
+
const sorted = [...grouped].sort((a, b) => {
|
|
197
|
+
const tierDiff = SALIENCE_RANK[a.tier] - SALIENCE_RANK[b.tier];
|
|
198
|
+
if (tierDiff !== 0) return tierDiff;
|
|
199
|
+
// Same tier — preserve authored order via the cached index.
|
|
200
|
+
return a.firstIndex - b.firstIndex;
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Decide which groups stay in the main row vs. spill into the
|
|
204
|
+
// disclosure. Hero groups always stay; tertiary groups always
|
|
205
|
+
// spill; secondary groups spill once we've already shown
|
|
206
|
+
// `maxVisibleSecondary` of them. A group counts as 1 toward the
|
|
207
|
+
// budget regardless of how many descriptors it contains — losing
|
|
208
|
+
// half a "build" cluster would be more confusing than rendering
|
|
209
|
+
// the whole sub-row.
|
|
210
|
+
const visible: typeof sorted = [];
|
|
211
|
+
const disclosed: typeof sorted = [];
|
|
212
|
+
let secondariesShown = 0;
|
|
213
|
+
for (const group of sorted) {
|
|
214
|
+
if (group.tier === "hero") {
|
|
215
|
+
visible.push(group);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (group.tier === "tertiary") {
|
|
219
|
+
disclosed.push(group);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (secondariesShown < maxVisibleSecondary) {
|
|
223
|
+
visible.push(group);
|
|
224
|
+
secondariesShown += 1;
|
|
225
|
+
} else {
|
|
226
|
+
disclosed.push(group);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Count the underlying descriptors so the disclosure badge reads
|
|
231
|
+
// "More (3)" not "More (1 group)".
|
|
232
|
+
const disclosedCount = disclosed.reduce(
|
|
233
|
+
(sum, group) => sum + group.interactions.length,
|
|
234
|
+
0,
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<div
|
|
239
|
+
role="toolbar"
|
|
240
|
+
aria-label="Panel actions"
|
|
241
|
+
data-shell-slot="panel-actions"
|
|
242
|
+
style={{
|
|
243
|
+
display: "flex",
|
|
244
|
+
flexDirection: resolvedLayout.direction,
|
|
245
|
+
flexWrap: resolvedLayout.wrap ? "wrap" : "nowrap",
|
|
246
|
+
gap: resolvedLayout.gap,
|
|
247
|
+
alignItems: resolvedLayout.align,
|
|
248
|
+
justifyContent: resolvedLayout.justify,
|
|
249
|
+
}}
|
|
250
|
+
>
|
|
251
|
+
{visible.map((group) => (
|
|
252
|
+
<PanelGroup<I, ParamsByKey>
|
|
253
|
+
key={group.id}
|
|
254
|
+
group={group}
|
|
255
|
+
render={render}
|
|
256
|
+
renderItem={renderItem}
|
|
257
|
+
/>
|
|
258
|
+
))}
|
|
259
|
+
{disclosed.length > 0 ? (
|
|
260
|
+
<MoreActions label={moreActionsLabel} count={disclosedCount}>
|
|
261
|
+
{disclosed.map((group) => (
|
|
262
|
+
<PanelGroup<I, ParamsByKey>
|
|
263
|
+
key={group.id}
|
|
264
|
+
group={group}
|
|
265
|
+
render={render}
|
|
266
|
+
renderItem={renderItem}
|
|
267
|
+
/>
|
|
268
|
+
))}
|
|
269
|
+
</MoreActions>
|
|
270
|
+
) : null}
|
|
271
|
+
</div>
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
interface PanelGroupDescriptor<I extends string> {
|
|
276
|
+
readonly id: string;
|
|
277
|
+
readonly interactions: ReadonlyArray<InteractionDescriptor<I>>;
|
|
278
|
+
readonly grouped: boolean;
|
|
279
|
+
readonly tier: PanelSalience;
|
|
280
|
+
/** Original index of the first member, used to preserve authored
|
|
281
|
+
* order when sort keys tie. */
|
|
282
|
+
readonly firstIndex: number;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function groupInteractions<I extends string>(
|
|
286
|
+
items: ReadonlyArray<InteractionDescriptor<I>>,
|
|
287
|
+
groupBy: (descriptor: InteractionDescriptor<I>) => string | undefined,
|
|
288
|
+
resolveSalience: (descriptor: InteractionDescriptor<I>) => PanelSalience,
|
|
289
|
+
): Array<PanelGroupDescriptor<I>> {
|
|
290
|
+
// Two-pass build so each group's tier reflects its highest-salience
|
|
291
|
+
// member regardless of arrival order. Pass 1 collects buckets while
|
|
292
|
+
// preserving the order in which each *cluster* first appears (for
|
|
293
|
+
// the eventual `firstIndex` tie-break). Pass 2 freezes the buckets
|
|
294
|
+
// into the immutable shape `PanelGroupDescriptor` advertises.
|
|
295
|
+
interface MutableBucket {
|
|
296
|
+
id: string;
|
|
297
|
+
grouped: boolean;
|
|
298
|
+
interactions: Array<InteractionDescriptor<I>>;
|
|
299
|
+
tier: PanelSalience;
|
|
300
|
+
firstIndex: number;
|
|
301
|
+
}
|
|
302
|
+
const ordered: MutableBucket[] = [];
|
|
303
|
+
const byGroup = new Map<string, MutableBucket>();
|
|
304
|
+
|
|
305
|
+
items.forEach((descriptor, index) => {
|
|
306
|
+
const tier = resolveSalience(descriptor);
|
|
307
|
+
const key = groupBy(descriptor);
|
|
308
|
+
if (key === undefined) {
|
|
309
|
+
ordered.push({
|
|
310
|
+
id: `solo:${descriptor.interactionId}`,
|
|
311
|
+
grouped: false,
|
|
312
|
+
interactions: [descriptor],
|
|
313
|
+
tier,
|
|
314
|
+
firstIndex: index,
|
|
315
|
+
});
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
const bucket = byGroup.get(key);
|
|
319
|
+
if (bucket) {
|
|
320
|
+
bucket.interactions.push(descriptor);
|
|
321
|
+
if (SALIENCE_RANK[tier] < SALIENCE_RANK[bucket.tier]) {
|
|
322
|
+
bucket.tier = tier;
|
|
323
|
+
}
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const fresh: MutableBucket = {
|
|
327
|
+
id: `group:${key}`,
|
|
328
|
+
grouped: true,
|
|
329
|
+
interactions: [descriptor],
|
|
330
|
+
tier,
|
|
331
|
+
firstIndex: index,
|
|
332
|
+
};
|
|
333
|
+
byGroup.set(key, fresh);
|
|
334
|
+
ordered.push(fresh);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
return ordered.map((bucket) => ({
|
|
338
|
+
id: bucket.id,
|
|
339
|
+
interactions: bucket.interactions,
|
|
340
|
+
grouped: bucket.grouped,
|
|
341
|
+
tier: bucket.tier,
|
|
342
|
+
firstIndex: bucket.firstIndex,
|
|
343
|
+
}));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function PanelGroup<
|
|
347
|
+
I extends string,
|
|
348
|
+
ParamsByKey extends Partial<InteractionParamsByKeyShape> = {},
|
|
349
|
+
>({
|
|
350
|
+
group,
|
|
351
|
+
render,
|
|
352
|
+
renderItem,
|
|
353
|
+
}: {
|
|
354
|
+
group: PanelGroupDescriptor<I>;
|
|
355
|
+
render?: SurfaceRenderMap<I, ParamsByKey>;
|
|
356
|
+
renderItem?: (
|
|
357
|
+
descriptor: InteractionDescriptor<I>,
|
|
358
|
+
handle: InteractionHandle<
|
|
359
|
+
InteractionParamsOf<ParamsByKey, I>,
|
|
360
|
+
InteractionDefaultedKeysOf<ParamsByKey, I>
|
|
361
|
+
>,
|
|
362
|
+
) => ReactNode;
|
|
363
|
+
}) {
|
|
364
|
+
const theme = useTheme();
|
|
365
|
+
if (!group.grouped || group.interactions.length === 1) {
|
|
366
|
+
return (
|
|
367
|
+
<>
|
|
368
|
+
{group.interactions.map((descriptor) => (
|
|
369
|
+
<PanelItem<I, ParamsByKey>
|
|
370
|
+
key={descriptor.interactionKey}
|
|
371
|
+
descriptor={descriptor}
|
|
372
|
+
render={render}
|
|
373
|
+
renderItem={renderItem}
|
|
374
|
+
tier={group.tier}
|
|
375
|
+
/>
|
|
376
|
+
))}
|
|
377
|
+
</>
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
return (
|
|
381
|
+
<div
|
|
382
|
+
data-panel-group={group.id}
|
|
383
|
+
data-panel-tier={group.tier}
|
|
384
|
+
style={{
|
|
385
|
+
display: "inline-flex",
|
|
386
|
+
gap: theme.space[1],
|
|
387
|
+
padding: theme.space[1],
|
|
388
|
+
borderRadius: theme.radius.lg,
|
|
389
|
+
background: theme.semantic.surface.inset,
|
|
390
|
+
}}
|
|
391
|
+
>
|
|
392
|
+
{group.interactions.map((descriptor) => (
|
|
393
|
+
<PanelItem<I, ParamsByKey>
|
|
394
|
+
key={descriptor.interactionKey}
|
|
395
|
+
descriptor={descriptor}
|
|
396
|
+
render={render}
|
|
397
|
+
renderItem={renderItem}
|
|
398
|
+
compact
|
|
399
|
+
tier={group.tier}
|
|
400
|
+
/>
|
|
401
|
+
))}
|
|
402
|
+
</div>
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function PanelItem<
|
|
407
|
+
I extends string,
|
|
408
|
+
ParamsByKey extends Partial<InteractionParamsByKeyShape> = {},
|
|
409
|
+
>({
|
|
410
|
+
descriptor,
|
|
411
|
+
render,
|
|
412
|
+
renderItem,
|
|
413
|
+
compact,
|
|
414
|
+
tier,
|
|
415
|
+
}: {
|
|
416
|
+
descriptor: InteractionDescriptor<I>;
|
|
417
|
+
render?: SurfaceRenderMap<I, ParamsByKey>;
|
|
418
|
+
renderItem?: (
|
|
419
|
+
descriptor: InteractionDescriptor<I>,
|
|
420
|
+
handle: InteractionHandle<
|
|
421
|
+
InteractionParamsOf<ParamsByKey, I>,
|
|
422
|
+
InteractionDefaultedKeysOf<ParamsByKey, I>
|
|
423
|
+
>,
|
|
424
|
+
) => ReactNode;
|
|
425
|
+
compact?: boolean;
|
|
426
|
+
tier: PanelSalience;
|
|
427
|
+
}) {
|
|
428
|
+
const handle = useInteractionHandle<
|
|
429
|
+
InteractionParamsOf<ParamsByKey, I>,
|
|
430
|
+
InteractionDefaultedKeysOf<ParamsByKey, I>
|
|
431
|
+
>(descriptor);
|
|
432
|
+
const override = render?.[descriptor.interactionKey] as
|
|
433
|
+
| ((
|
|
434
|
+
descriptor: InteractionDescriptor<I>,
|
|
435
|
+
handle: InteractionHandle<
|
|
436
|
+
InteractionParamsOf<ParamsByKey, I>,
|
|
437
|
+
InteractionDefaultedKeysOf<ParamsByKey, I>
|
|
438
|
+
>,
|
|
439
|
+
) => ReactNode)
|
|
440
|
+
| undefined;
|
|
441
|
+
if (override) return <>{override(descriptor, handle)}</>;
|
|
442
|
+
if (renderItem) return <>{renderItem(descriptor, handle)}</>;
|
|
443
|
+
// Salience-driven sizing: hero buttons use the `lg` size so they
|
|
444
|
+
// outweigh the `secondary` tier next to them. Tertiary items render
|
|
445
|
+
// inside the disclosure where the smaller `sm` size keeps the
|
|
446
|
+
// disclosed cluster from feeling like a second main panel.
|
|
447
|
+
const size: "sm" | "md" | "lg" =
|
|
448
|
+
compact || tier === "tertiary" ? "sm" : tier === "hero" ? "lg" : "md";
|
|
449
|
+
return (
|
|
450
|
+
<DefaultInteractionButton
|
|
451
|
+
descriptor={descriptor}
|
|
452
|
+
handle={handle}
|
|
453
|
+
compact={compact}
|
|
454
|
+
size={size}
|
|
455
|
+
data-panel-tier={tier}
|
|
456
|
+
/>
|
|
457
|
+
);
|
|
458
|
+
}
|