@datamoc/mw_games 0.7.6 → 0.7.8
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/CHANGELOG.md +359 -0
- package/README.md +7 -7
- package/dist/actors/Inventory.d.ts +7 -1
- package/dist/actors/Inventory.d.ts.map +1 -1
- package/dist/actors/Inventory.js.map +1 -1
- package/dist/actors/Shop.d.ts.map +1 -1
- package/dist/actors/Shop.js +4 -1
- package/dist/actors/Shop.js.map +1 -1
- package/dist/actors/craft.d.ts +35 -14
- package/dist/actors/craft.d.ts.map +1 -1
- package/dist/actors/craft.js +56 -24
- package/dist/actors/craft.js.map +1 -1
- package/dist/actors/index.d.ts +1 -1
- package/dist/actors/index.d.ts.map +1 -1
- package/dist/ai/Heuristics.d.ts +240 -0
- package/dist/ai/Heuristics.d.ts.map +1 -0
- package/dist/ai/Heuristics.js +298 -0
- package/dist/ai/Heuristics.js.map +1 -0
- package/dist/ai/index.d.ts +4 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +2 -0
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/lua.d.ts +21 -0
- package/dist/ai/lua.d.ts.map +1 -1
- package/dist/ai/lua.js +21 -0
- package/dist/ai/lua.js.map +1 -1
- package/dist/ai/score.d.ts +162 -0
- package/dist/ai/score.d.ts.map +1 -0
- package/dist/ai/score.js +147 -0
- package/dist/ai/score.js.map +1 -0
- package/dist/assets/loader.d.ts +18 -4
- package/dist/assets/loader.d.ts.map +1 -1
- package/dist/assets/loader.js +40 -11
- package/dist/assets/loader.js.map +1 -1
- package/dist/audio/Positional.d.ts +125 -0
- package/dist/audio/Positional.d.ts.map +1 -0
- package/dist/audio/Positional.js +135 -0
- package/dist/audio/Positional.js.map +1 -0
- package/dist/audio/Sound.d.ts +7 -1
- package/dist/audio/Sound.d.ts.map +1 -1
- package/dist/audio/Sound.js +8 -2
- package/dist/audio/Sound.js.map +1 -1
- package/dist/audio/index.d.ts +2 -0
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +1 -0
- package/dist/audio/index.js.map +1 -1
- package/dist/battle/AttackDialog.d.ts +75 -0
- package/dist/battle/AttackDialog.d.ts.map +1 -0
- package/dist/battle/AttackDialog.js +115 -0
- package/dist/battle/AttackDialog.js.map +1 -0
- package/dist/battle/AttackPreview.d.ts +70 -0
- package/dist/battle/AttackPreview.d.ts.map +1 -0
- package/dist/battle/AttackPreview.js +78 -0
- package/dist/battle/AttackPreview.js.map +1 -0
- package/dist/battle/BattleStats.d.ts +45 -0
- package/dist/battle/BattleStats.d.ts.map +1 -0
- package/dist/battle/BattleStats.js +63 -0
- package/dist/battle/BattleStats.js.map +1 -0
- package/dist/battle/UnitSelector.d.ts +72 -0
- package/dist/battle/UnitSelector.d.ts.map +1 -0
- package/dist/battle/UnitSelector.js +117 -0
- package/dist/battle/UnitSelector.js.map +1 -0
- package/dist/battle/Whiteboard.d.ts +50 -0
- package/dist/battle/Whiteboard.d.ts.map +1 -0
- package/dist/battle/Whiteboard.js +94 -0
- package/dist/battle/Whiteboard.js.map +1 -0
- package/dist/battle/index.d.ts +10 -0
- package/dist/battle/index.d.ts.map +1 -1
- package/dist/battle/index.js +5 -0
- package/dist/battle/index.js.map +1 -1
- package/dist/board/Classics.d.ts.map +1 -1
- package/dist/board/Classics.js +51 -39
- package/dist/board/Classics.js.map +1 -1
- package/dist/board/FogOfWar.d.ts +32 -2
- package/dist/board/FogOfWar.d.ts.map +1 -1
- package/dist/board/FogOfWar.js +70 -6
- package/dist/board/FogOfWar.js.map +1 -1
- package/dist/board/HexSkirmish.d.ts.map +1 -1
- package/dist/board/HexSkirmish.js +69 -20
- package/dist/board/HexSkirmish.js.map +1 -1
- package/dist/board/Tactics.d.ts +7 -0
- package/dist/board/Tactics.d.ts.map +1 -1
- package/dist/board/Tactics.js +2 -2
- package/dist/board/Tactics.js.map +1 -1
- package/dist/core/Achievements.d.ts +40 -7
- package/dist/core/Achievements.d.ts.map +1 -1
- package/dist/core/Achievements.js +53 -7
- package/dist/core/Achievements.js.map +1 -1
- package/dist/core/Hex.d.ts +26 -6
- package/dist/core/Hex.d.ts.map +1 -1
- package/dist/core/Hex.js +40 -13
- package/dist/core/Hex.js.map +1 -1
- package/dist/core/Input.d.ts +36 -0
- package/dist/core/Input.d.ts.map +1 -1
- package/dist/core/Input.js +63 -1
- package/dist/core/Input.js.map +1 -1
- package/dist/core/Random.d.ts +93 -0
- package/dist/core/Random.d.ts.map +1 -1
- package/dist/core/Random.js +177 -0
- package/dist/core/Random.js.map +1 -1
- package/dist/core/SyncGuard.d.ts +57 -0
- package/dist/core/SyncGuard.d.ts.map +1 -0
- package/dist/core/SyncGuard.js +116 -0
- package/dist/core/SyncGuard.js.map +1 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/i18n/Po.d.ts +51 -0
- package/dist/i18n/Po.d.ts.map +1 -0
- package/dist/i18n/Po.js +176 -0
- package/dist/i18n/Po.js.map +1 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/index.js.map +1 -1
- package/dist/mw_games.global.js +104 -98
- package/dist/mwl/MapFile.d.ts +41 -0
- package/dist/mwl/MapFile.d.ts.map +1 -0
- package/dist/mwl/MapFile.js +43 -0
- package/dist/mwl/MapFile.js.map +1 -0
- package/dist/mwl/actors.d.ts +46 -2
- package/dist/mwl/actors.d.ts.map +1 -1
- package/dist/mwl/actors.js +46 -2
- package/dist/mwl/actors.js.map +1 -1
- package/dist/mwl/campaign.d.ts +51 -0
- package/dist/mwl/campaign.d.ts.map +1 -0
- package/dist/mwl/campaign.js +58 -0
- package/dist/mwl/campaign.js.map +1 -0
- package/dist/mwl/carryover.d.ts +86 -0
- package/dist/mwl/carryover.d.ts.map +1 -0
- package/dist/mwl/carryover.js +70 -0
- package/dist/mwl/carryover.js.map +1 -0
- package/dist/mwl/catalog.d.ts +10 -1
- package/dist/mwl/catalog.d.ts.map +1 -1
- package/dist/mwl/catalog.js +10 -1
- package/dist/mwl/catalog.js.map +1 -1
- package/dist/mwl/compiler.d.ts +70 -3
- package/dist/mwl/compiler.d.ts.map +1 -1
- package/dist/mwl/compiler.js +70 -3
- package/dist/mwl/compiler.js.map +1 -1
- package/dist/mwl/conditions.d.ts +10 -1
- package/dist/mwl/conditions.d.ts.map +1 -1
- package/dist/mwl/conditions.js +10 -1
- package/dist/mwl/conditions.js.map +1 -1
- package/dist/mwl/content.d.ts +21 -0
- package/dist/mwl/content.d.ts.map +1 -1
- package/dist/mwl/content.js +19 -0
- package/dist/mwl/content.js.map +1 -1
- package/dist/mwl/expression.d.ts +21 -0
- package/dist/mwl/expression.d.ts.map +1 -1
- package/dist/mwl/expression.js +21 -0
- package/dist/mwl/expression.js.map +1 -1
- package/dist/mwl/fengari.d.ts +12 -1
- package/dist/mwl/fengari.d.ts.map +1 -1
- package/dist/mwl/fengari.js +12 -1
- package/dist/mwl/fengari.js.map +1 -1
- package/dist/mwl/grammar.d.ts +45 -1
- package/dist/mwl/grammar.d.ts.map +1 -1
- package/dist/mwl/grammar.js +45 -1
- package/dist/mwl/grammar.js.map +1 -1
- package/dist/mwl/hooks.d.ts +51 -6
- package/dist/mwl/hooks.d.ts.map +1 -1
- package/dist/mwl/hooks.js +45 -1
- package/dist/mwl/hooks.js.map +1 -1
- package/dist/mwl/index.d.ts +9 -3
- package/dist/mwl/index.d.ts.map +1 -1
- package/dist/mwl/index.js +5 -2
- package/dist/mwl/index.js.map +1 -1
- package/dist/mwl/persistence.d.ts +32 -0
- package/dist/mwl/persistence.d.ts.map +1 -1
- package/dist/mwl/persistence.js +32 -0
- package/dist/mwl/persistence.js.map +1 -1
- package/dist/mwl/readers.d.ts +24 -2
- package/dist/mwl/readers.d.ts.map +1 -1
- package/dist/mwl/readers.js +27 -4
- package/dist/mwl/readers.js.map +1 -1
- package/dist/mwl/report.d.ts +21 -2
- package/dist/mwl/report.d.ts.map +1 -1
- package/dist/mwl/report.js +21 -2
- package/dist/mwl/report.js.map +1 -1
- package/dist/mwl/runtime.d.ts +212 -7
- package/dist/mwl/runtime.d.ts.map +1 -1
- package/dist/mwl/runtime.js +682 -90
- package/dist/mwl/runtime.js.map +1 -1
- package/dist/mwl/schema.d.ts +57 -1
- package/dist/mwl/schema.d.ts.map +1 -1
- package/dist/mwl/schema.js +181 -21
- package/dist/mwl/schema.js.map +1 -1
- package/dist/mwl/scripts.d.ts +12 -1
- package/dist/mwl/scripts.d.ts.map +1 -1
- package/dist/mwl/scripts.js +12 -1
- package/dist/mwl/scripts.js.map +1 -1
- package/dist/mwl/utils.d.ts +2 -0
- package/dist/mwl/utils.d.ts.map +1 -1
- package/dist/mwl/utils.js +4 -1
- package/dist/mwl/utils.js.map +1 -1
- package/dist/roguelike/MultiTurnBeam.d.ts +50 -12
- package/dist/roguelike/MultiTurnBeam.d.ts.map +1 -1
- package/dist/roguelike/MultiTurnBeam.js +100 -53
- package/dist/roguelike/MultiTurnBeam.js.map +1 -1
- package/dist/roguelike/Targeting.d.ts +94 -0
- package/dist/roguelike/Targeting.d.ts.map +1 -1
- package/dist/roguelike/Targeting.js +123 -0
- package/dist/roguelike/Targeting.js.map +1 -1
- package/dist/roguelike/index.d.ts +3 -1
- package/dist/roguelike/index.d.ts.map +1 -1
- package/dist/roguelike/index.js +1 -0
- package/dist/roguelike/index.js.map +1 -1
- package/dist/rpg/GameState.d.ts +2 -2
- package/dist/rpg/GameState.js +2 -2
- package/dist/simulation/CampaignSave.d.ts +68 -0
- package/dist/simulation/CampaignSave.d.ts.map +1 -0
- package/dist/simulation/CampaignSave.js +54 -0
- package/dist/simulation/CampaignSave.js.map +1 -0
- package/dist/simulation/EventPresentation.d.ts +111 -0
- package/dist/simulation/EventPresentation.d.ts.map +1 -0
- package/dist/simulation/EventPresentation.js +120 -0
- package/dist/simulation/EventPresentation.js.map +1 -0
- package/dist/simulation/index.d.ts +4 -0
- package/dist/simulation/index.d.ts.map +1 -1
- package/dist/simulation/index.js +2 -0
- package/dist/simulation/index.js.map +1 -1
- package/dist/two-d/pixi-interop.d.ts +18 -6
- package/dist/two-d/pixi-interop.d.ts.map +1 -1
- package/dist/two-d/pixi-interop.js +18 -6
- package/dist/two-d/pixi-interop.js.map +1 -1
- package/dist/two-d/render/AnimatedSprite.d.ts +74 -7
- package/dist/two-d/render/AnimatedSprite.d.ts.map +1 -1
- package/dist/two-d/render/AnimatedSprite.js +88 -26
- package/dist/two-d/render/AnimatedSprite.js.map +1 -1
- package/dist/two-d/render/Camera.d.ts +64 -4
- package/dist/two-d/render/Camera.d.ts.map +1 -1
- package/dist/two-d/render/Camera.js +132 -11
- package/dist/two-d/render/Camera.js.map +1 -1
- package/dist/two-d/render/ColorTransformBatcher.d.ts +7 -1
- package/dist/two-d/render/ColorTransformBatcher.d.ts.map +1 -1
- package/dist/two-d/render/ColorTransformBatcher.js +10 -1
- package/dist/two-d/render/ColorTransformBatcher.js.map +1 -1
- package/dist/two-d/render/Halo.d.ts +58 -0
- package/dist/two-d/render/Halo.d.ts.map +1 -0
- package/dist/two-d/render/Halo.js +48 -0
- package/dist/two-d/render/Halo.js.map +1 -0
- package/dist/two-d/render/ImageModifiers.d.ts +174 -0
- package/dist/two-d/render/ImageModifiers.d.ts.map +1 -1
- package/dist/two-d/render/ImageModifiers.js +454 -1
- package/dist/two-d/render/ImageModifiers.js.map +1 -1
- package/dist/two-d/render/LightningArc.d.ts +57 -0
- package/dist/two-d/render/LightningArc.d.ts.map +1 -0
- package/dist/two-d/render/LightningArc.js +91 -0
- package/dist/two-d/render/LightningArc.js.map +1 -0
- package/dist/two-d/render/PaletteRemap.d.ts +135 -0
- package/dist/two-d/render/PaletteRemap.d.ts.map +1 -0
- package/dist/two-d/render/PaletteRemap.js +181 -0
- package/dist/two-d/render/PaletteRemap.js.map +1 -0
- package/dist/two-d/render/Particles.d.ts +26 -0
- package/dist/two-d/render/Particles.d.ts.map +1 -1
- package/dist/two-d/render/Particles.js +23 -2
- package/dist/two-d/render/Particles.js.map +1 -1
- package/dist/two-d/render/SpriteAttachment.d.ts +55 -0
- package/dist/two-d/render/SpriteAttachment.d.ts.map +1 -0
- package/dist/two-d/render/SpriteAttachment.js +60 -0
- package/dist/two-d/render/SpriteAttachment.js.map +1 -0
- package/dist/two-d/render/TerrainGraphics.d.ts +142 -0
- package/dist/two-d/render/TerrainGraphics.d.ts.map +1 -0
- package/dist/two-d/render/TerrainGraphics.js +161 -0
- package/dist/two-d/render/TerrainGraphics.js.map +1 -0
- package/dist/two-d/render/TerrainGraphicsLayer.d.ts +55 -0
- package/dist/two-d/render/TerrainGraphicsLayer.d.ts.map +1 -0
- package/dist/two-d/render/TerrainGraphicsLayer.js +54 -0
- package/dist/two-d/render/TerrainGraphicsLayer.js.map +1 -0
- package/dist/two-d/render/TintedSprite.js +2 -2
- package/dist/two-d/render/TintedSprite.js.map +1 -1
- package/dist/two-d/render/index.d.ts +15 -3
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +7 -1
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/two-d/stage/StoryScreen.d.ts +110 -0
- package/dist/two-d/stage/StoryScreen.d.ts.map +1 -0
- package/dist/two-d/stage/StoryScreen.js +178 -0
- package/dist/two-d/stage/StoryScreen.js.map +1 -0
- package/dist/two-d/stage/index.d.ts +2 -0
- package/dist/two-d/stage/index.d.ts.map +1 -1
- package/dist/two-d/stage/index.js +1 -0
- package/dist/two-d/stage/index.js.map +1 -1
- package/dist/two-d/ui/Checkbox.d.ts +44 -0
- package/dist/two-d/ui/Checkbox.d.ts.map +1 -0
- package/dist/two-d/ui/Checkbox.js +89 -0
- package/dist/two-d/ui/Checkbox.js.map +1 -0
- package/dist/two-d/ui/DataTable.d.ts +79 -0
- package/dist/two-d/ui/DataTable.d.ts.map +1 -0
- package/dist/two-d/ui/DataTable.js +164 -0
- package/dist/two-d/ui/DataTable.js.map +1 -0
- package/dist/two-d/ui/Dropdown.d.ts +72 -0
- package/dist/two-d/ui/Dropdown.d.ts.map +1 -0
- package/dist/two-d/ui/Dropdown.js +126 -0
- package/dist/two-d/ui/Dropdown.js.map +1 -0
- package/dist/two-d/ui/FloatingText.d.ts +43 -4
- package/dist/two-d/ui/FloatingText.d.ts.map +1 -1
- package/dist/two-d/ui/FloatingText.js +52 -5
- package/dist/two-d/ui/FloatingText.js.map +1 -1
- package/dist/two-d/ui/FloatingTextStack.d.ts +86 -13
- package/dist/two-d/ui/FloatingTextStack.d.ts.map +1 -1
- package/dist/two-d/ui/FloatingTextStack.js +89 -18
- package/dist/two-d/ui/FloatingTextStack.js.map +1 -1
- package/dist/two-d/ui/Layout.d.ts +105 -0
- package/dist/two-d/ui/Layout.d.ts.map +1 -0
- package/dist/two-d/ui/Layout.js +174 -0
- package/dist/two-d/ui/Layout.js.map +1 -0
- package/dist/two-d/ui/MarkupText.d.ts +53 -0
- package/dist/two-d/ui/MarkupText.d.ts.map +1 -0
- package/dist/two-d/ui/MarkupText.js +122 -0
- package/dist/two-d/ui/MarkupText.js.map +1 -0
- package/dist/two-d/ui/ScrollBox.d.ts +67 -0
- package/dist/two-d/ui/ScrollBox.d.ts.map +1 -0
- package/dist/two-d/ui/ScrollBox.js +127 -0
- package/dist/two-d/ui/ScrollBox.js.map +1 -0
- package/dist/two-d/ui/Skins.d.ts +59 -0
- package/dist/two-d/ui/Skins.d.ts.map +1 -0
- package/dist/two-d/ui/Skins.js +77 -0
- package/dist/two-d/ui/Skins.js.map +1 -0
- package/dist/two-d/ui/Slider.d.ts +91 -0
- package/dist/two-d/ui/Slider.d.ts.map +1 -0
- package/dist/two-d/ui/Slider.js +170 -0
- package/dist/two-d/ui/Slider.js.map +1 -0
- package/dist/two-d/ui/Spinner.d.ts +67 -0
- package/dist/two-d/ui/Spinner.d.ts.map +1 -0
- package/dist/two-d/ui/Spinner.js +137 -0
- package/dist/two-d/ui/Spinner.js.map +1 -0
- package/dist/two-d/ui/TabbedList.d.ts +118 -0
- package/dist/two-d/ui/TabbedList.d.ts.map +1 -0
- package/dist/two-d/ui/TabbedList.js +221 -0
- package/dist/two-d/ui/TabbedList.js.map +1 -0
- package/dist/two-d/ui/TextModel.d.ts +65 -0
- package/dist/two-d/ui/TextModel.d.ts.map +1 -0
- package/dist/two-d/ui/TextModel.js +126 -0
- package/dist/two-d/ui/TextModel.js.map +1 -0
- package/dist/two-d/ui/TreeView.d.ts +68 -0
- package/dist/two-d/ui/TreeView.d.ts.map +1 -0
- package/dist/two-d/ui/TreeView.js +133 -0
- package/dist/two-d/ui/TreeView.js.map +1 -0
- package/dist/two-d/ui/Window.d.ts +13 -0
- package/dist/two-d/ui/Window.d.ts.map +1 -1
- package/dist/two-d/ui/Window.js +23 -0
- package/dist/two-d/ui/Window.js.map +1 -1
- package/dist/two-d/ui/WindowStack.d.ts.map +1 -1
- package/dist/two-d/ui/WindowStack.js +2 -0
- package/dist/two-d/ui/WindowStack.js.map +1 -1
- package/dist/two-d/ui/index.d.ts +29 -3
- package/dist/two-d/ui/index.d.ts.map +1 -1
- package/dist/two-d/ui/index.js +15 -2
- package/dist/two-d/ui/index.js.map +1 -1
- package/dist/two-d/ui/markup.d.ts +181 -0
- package/dist/two-d/ui/markup.d.ts.map +1 -0
- package/dist/two-d/ui/markup.js +370 -0
- package/dist/two-d/ui/markup.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/world/SideTurns.d.ts +115 -0
- package/dist/world/SideTurns.d.ts.map +1 -0
- package/dist/world/SideTurns.js +138 -0
- package/dist/world/SideTurns.js.map +1 -0
- package/dist/world/index.d.ts +2 -0
- package/dist/world/index.d.ts.map +1 -1
- package/dist/world/index.js +1 -0
- package/dist/world/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Container, Graphics } from 'pixi.js';
|
|
2
|
+
import { Signal } from '../../core/Signal.js';
|
|
3
|
+
import { theme, themeChanged } from './theme.js';
|
|
4
|
+
/**
|
|
5
|
+
* Where `value` sits in `[min, max]`, 0 to 1, clamped. A degenerate range reads 0 rather than
|
|
6
|
+
* dividing by zero.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { sliderFraction } from '@datamoc/mw_games/two-d/ui';
|
|
11
|
+
*
|
|
12
|
+
* console.log(sliderFraction(30, 0, 60)); // 0.5
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function sliderFraction(value, min = 0, max = 1) {
|
|
16
|
+
if (!(max > min))
|
|
17
|
+
return 0;
|
|
18
|
+
return Math.max(0, Math.min(1, (value - min) / (max - min)));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The value at a 0-to-1 position on the track, snapped to `step` and clamped to `[min, max]`.
|
|
22
|
+
* The snap is rounded to the step's own number of decimals, so a 0.1 step reads `0.3` rather
|
|
23
|
+
* than `0.30000000000000004`.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { sliderValueAt } from '@datamoc/mw_games/two-d/ui';
|
|
28
|
+
*
|
|
29
|
+
* console.log(sliderValueAt(0.5, 0, 10, 1)); // 5
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function sliderValueAt(fraction, min = 0, max = 1, step = 0) {
|
|
33
|
+
const clamped = Math.max(0, Math.min(1, fraction));
|
|
34
|
+
const raw = min + clamped * (max - min);
|
|
35
|
+
if (!(step > 0))
|
|
36
|
+
return raw;
|
|
37
|
+
const decimals = (String(step).split('.')[1] ?? '').length;
|
|
38
|
+
const snapped = min + Math.round((raw - min) / step) * step;
|
|
39
|
+
return Number(Math.max(min, Math.min(max, snapped)).toFixed(decimals));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A draggable knob on a track, for a volume, difficulty or zoom setting.
|
|
43
|
+
*
|
|
44
|
+
* The track is drawn from the theme and a partial fill shows where the knob is; the value is
|
|
45
|
+
* always a number in `[min, max]`, and `sliderValueAt` is the arithmetic that turns a click or
|
|
46
|
+
* drag into one, exported so a game routing input itself gets the same snapping.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import { Slider } from '@datamoc/mw_games/two-d/ui';
|
|
51
|
+
*
|
|
52
|
+
* const volume = new Slider({ width: 200, min: 0, max: 100, step: 5, value: 40 });
|
|
53
|
+
* volume.onChange.add((value) => console.log('volume', value));
|
|
54
|
+
* volume.setValue(75);
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export class Slider extends Container {
|
|
58
|
+
constructor(options) {
|
|
59
|
+
super();
|
|
60
|
+
this.onChange = new Signal();
|
|
61
|
+
this.track = new Graphics();
|
|
62
|
+
this.fill = new Graphics();
|
|
63
|
+
this.knob = new Graphics();
|
|
64
|
+
this.dragging = false;
|
|
65
|
+
this.themeListener = () => this.draw();
|
|
66
|
+
this.handleDown = (event) => {
|
|
67
|
+
if (this.disabled_)
|
|
68
|
+
return;
|
|
69
|
+
this.dragging = true;
|
|
70
|
+
this.setFraction(this.fractionAt(this.toLocal(event.global).x));
|
|
71
|
+
};
|
|
72
|
+
this.handleMove = (event) => {
|
|
73
|
+
if (!this.dragging || this.disabled_)
|
|
74
|
+
return;
|
|
75
|
+
this.setFraction(this.fractionAt(this.toLocal(event.global).x));
|
|
76
|
+
};
|
|
77
|
+
this.handleUp = () => {
|
|
78
|
+
this.dragging = false;
|
|
79
|
+
};
|
|
80
|
+
this.width_ = options.width;
|
|
81
|
+
this.height_ = options.height ?? 6;
|
|
82
|
+
this.knobSize = options.knobSize ?? Math.max(12, this.height_ * 2);
|
|
83
|
+
this.min = options.min ?? 0;
|
|
84
|
+
this.max = options.max ?? 1;
|
|
85
|
+
this.step = options.step ?? 0;
|
|
86
|
+
this.value_ = this.snap(options.value ?? this.min);
|
|
87
|
+
this.disabled_ = options.disabled ?? false;
|
|
88
|
+
this.addChild(this.track);
|
|
89
|
+
this.addChild(this.fill);
|
|
90
|
+
this.addChild(this.knob);
|
|
91
|
+
this.draw();
|
|
92
|
+
this.eventMode = 'static';
|
|
93
|
+
this.cursor = 'pointer';
|
|
94
|
+
this.on('pointerdown', this.handleDown);
|
|
95
|
+
this.on('pointermove', this.handleMove);
|
|
96
|
+
this.on('pointerup', this.handleUp);
|
|
97
|
+
this.on('pointerupoutside', this.handleUp);
|
|
98
|
+
themeChanged.add(this.themeListener);
|
|
99
|
+
}
|
|
100
|
+
/** the current value, in `[min, max]` */
|
|
101
|
+
get value() {
|
|
102
|
+
return this.value_;
|
|
103
|
+
}
|
|
104
|
+
/** where the knob sits, 0 to 1 */
|
|
105
|
+
get fraction() {
|
|
106
|
+
return sliderFraction(this.value_, this.min, this.max);
|
|
107
|
+
}
|
|
108
|
+
get disabled() {
|
|
109
|
+
return this.disabled_;
|
|
110
|
+
}
|
|
111
|
+
setDisabled(disabled) {
|
|
112
|
+
this.disabled_ = disabled;
|
|
113
|
+
this.cursor = disabled ? 'default' : 'pointer';
|
|
114
|
+
this.draw();
|
|
115
|
+
}
|
|
116
|
+
setValue(value) {
|
|
117
|
+
const snapped = this.snap(value);
|
|
118
|
+
if (snapped === this.value_) {
|
|
119
|
+
this.draw();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.value_ = snapped;
|
|
123
|
+
this.draw();
|
|
124
|
+
this.onChange.dispatch(snapped);
|
|
125
|
+
}
|
|
126
|
+
/** moves the knob to a 0-to-1 position, the arithmetic a track click uses */
|
|
127
|
+
setFraction(fraction) {
|
|
128
|
+
this.setValue(sliderValueAt(fraction, this.min, this.max, this.step));
|
|
129
|
+
}
|
|
130
|
+
resize(width, height) {
|
|
131
|
+
this.width_ = width;
|
|
132
|
+
this.height_ = height;
|
|
133
|
+
this.draw();
|
|
134
|
+
}
|
|
135
|
+
get trackLength() {
|
|
136
|
+
return Math.max(0, this.width_ - this.knobSize);
|
|
137
|
+
}
|
|
138
|
+
snap(value) {
|
|
139
|
+
return sliderValueAt(sliderFraction(value, this.min, this.max), this.min, this.max, this.step);
|
|
140
|
+
}
|
|
141
|
+
fractionAt(localX) {
|
|
142
|
+
return this.trackLength > 0 ? Math.max(0, Math.min(1, (localX - this.knobSize / 2) / this.trackLength)) : 0;
|
|
143
|
+
}
|
|
144
|
+
draw() {
|
|
145
|
+
const t = theme();
|
|
146
|
+
const color = this.disabled_ ? t.color.textDim : t.color.textHighlight;
|
|
147
|
+
const trackColor = t.color.panelFill;
|
|
148
|
+
const top = (this.knobSize - this.height_) / 2;
|
|
149
|
+
this.track
|
|
150
|
+
.clear()
|
|
151
|
+
.roundRect(0, top, this.width_, this.height_, this.height_ / 2)
|
|
152
|
+
.fill({ color: trackColor });
|
|
153
|
+
const knobX = this.knobSize / 2 + this.fraction * this.trackLength;
|
|
154
|
+
this.fill.clear();
|
|
155
|
+
if (knobX > this.knobSize / 2) {
|
|
156
|
+
this.fill
|
|
157
|
+
.roundRect(this.knobSize / 2, top, knobX - this.knobSize / 2, this.height_, this.height_ / 2)
|
|
158
|
+
.fill({ color });
|
|
159
|
+
}
|
|
160
|
+
this.knob
|
|
161
|
+
.clear()
|
|
162
|
+
.circle(knobX, this.knobSize / 2, this.knobSize / 2)
|
|
163
|
+
.fill({ color });
|
|
164
|
+
}
|
|
165
|
+
destroy(options) {
|
|
166
|
+
themeChanged.remove(this.themeListener);
|
|
167
|
+
super.destroy(options);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=Slider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../src/two-d/ui/Slider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Container } from 'pixi.js';
|
|
2
|
+
import { Signal } from '../../core/Signal.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Steps a number by `delta`, snapped to `step` and kept in `[min, max]`. With `wrap`, passing
|
|
5
|
+
* the top starts again at the bottom and dropping below the bottom lands on the top; without it,
|
|
6
|
+
* the value clamps - a level cap or a bag size, where wrapping would be a surprise.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { spinValue } from '@datamoc/mw_games/two-d/ui';
|
|
11
|
+
*
|
|
12
|
+
* console.log(spinValue(10, 1, 0, 10, 1)); // 10, clamped
|
|
13
|
+
* console.log(spinValue(10, 1, 0, 10, 1, true)); // 0, wrapped
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function spinValue(value: number, delta: number, min: number, max: number, step?: number, wrap?: boolean): number;
|
|
17
|
+
export interface SpinnerOptions {
|
|
18
|
+
width?: number;
|
|
19
|
+
height?: number;
|
|
20
|
+
min?: number;
|
|
21
|
+
max?: number;
|
|
22
|
+
step?: number;
|
|
23
|
+
value?: number;
|
|
24
|
+
/** wrap past the ends instead of clamping */
|
|
25
|
+
wrap?: boolean;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A small up/down stepper: tap the top half to add one step, the bottom half to take one away.
|
|
30
|
+
* It draws only the arrows; the current value is a `Label` the game puts beside it, the same
|
|
31
|
+
* split `Checkbox` and `Slider` keep from their captions.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* import { Spinner } from '@datamoc/mw_games/two-d/ui';
|
|
36
|
+
*
|
|
37
|
+
* const level = new Spinner({ min: 1, max: 99, value: 1 });
|
|
38
|
+
* level.increment();
|
|
39
|
+
* console.log(level.value); // 2
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare class Spinner extends Container {
|
|
43
|
+
readonly onChange: Signal<number>;
|
|
44
|
+
private face;
|
|
45
|
+
private width_;
|
|
46
|
+
private height_;
|
|
47
|
+
private min;
|
|
48
|
+
private max;
|
|
49
|
+
private step;
|
|
50
|
+
private value_;
|
|
51
|
+
private wrap;
|
|
52
|
+
private disabled_;
|
|
53
|
+
private readonly themeListener;
|
|
54
|
+
constructor(options?: SpinnerOptions);
|
|
55
|
+
get value(): number;
|
|
56
|
+
get disabled(): boolean;
|
|
57
|
+
setDisabled(disabled: boolean): void;
|
|
58
|
+
setValue(value: number): void;
|
|
59
|
+
increment(): void;
|
|
60
|
+
decrement(): void;
|
|
61
|
+
resize(width: number, height: number): void;
|
|
62
|
+
private commit;
|
|
63
|
+
private readonly handleTap;
|
|
64
|
+
private draw;
|
|
65
|
+
destroy(options?: Parameters<Container['destroy']>[0]): void;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=Spinner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../../src/two-d/ui/Spinner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,SAAI,EAAE,IAAI,UAAQ,GAAG,MAAM,CAUhH;AAED,MAAM,WAAW,cAAc;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACrC,QAAQ,CAAC,QAAQ,iBAAwB;IAEzC,OAAO,CAAC,IAAI,CAAkB;IAE9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,SAAS,CAAU;IAE3B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IAEnD,YAAY,OAAO,GAAE,cAAmB,EAoBvC;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAInC;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE5B;IAED,SAAS,IAAI,IAAI,CAEhB;IAED,SAAS,IAAI,IAAI,CAEhB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAI1C;IAED,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,QAAQ,CAAC,SAAS,CAKxB;IAEF,OAAO,CAAC,IAAI;IA0BH,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAGpE;CACD"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Container, Graphics } from 'pixi.js';
|
|
2
|
+
import { Signal } from '../../core/Signal.js';
|
|
3
|
+
import { theme, themeChanged } from './theme.js';
|
|
4
|
+
/**
|
|
5
|
+
* Steps a number by `delta`, snapped to `step` and kept in `[min, max]`. With `wrap`, passing
|
|
6
|
+
* the top starts again at the bottom and dropping below the bottom lands on the top; without it,
|
|
7
|
+
* the value clamps - a level cap or a bag size, where wrapping would be a surprise.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { spinValue } from '@datamoc/mw_games/two-d/ui';
|
|
12
|
+
*
|
|
13
|
+
* console.log(spinValue(10, 1, 0, 10, 1)); // 10, clamped
|
|
14
|
+
* console.log(spinValue(10, 1, 0, 10, 1, true)); // 0, wrapped
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function spinValue(value, delta, min, max, step = 1, wrap = false) {
|
|
18
|
+
if (!(max > min))
|
|
19
|
+
return min;
|
|
20
|
+
const grid = step > 0 ? step : 1;
|
|
21
|
+
const decimals = (String(grid).split('.')[1] ?? '').length;
|
|
22
|
+
const steps = Math.round((value - min) / grid) + Math.round(delta);
|
|
23
|
+
const count = Math.round((max - min) / grid) + 1;
|
|
24
|
+
let index = steps;
|
|
25
|
+
if (wrap)
|
|
26
|
+
index = ((index % count) + count) % count;
|
|
27
|
+
else
|
|
28
|
+
index = Math.max(0, Math.min(count - 1, index));
|
|
29
|
+
return Number((min + index * grid).toFixed(decimals));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A small up/down stepper: tap the top half to add one step, the bottom half to take one away.
|
|
33
|
+
* It draws only the arrows; the current value is a `Label` the game puts beside it, the same
|
|
34
|
+
* split `Checkbox` and `Slider` keep from their captions.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { Spinner } from '@datamoc/mw_games/two-d/ui';
|
|
39
|
+
*
|
|
40
|
+
* const level = new Spinner({ min: 1, max: 99, value: 1 });
|
|
41
|
+
* level.increment();
|
|
42
|
+
* console.log(level.value); // 2
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export class Spinner extends Container {
|
|
46
|
+
constructor(options = {}) {
|
|
47
|
+
super();
|
|
48
|
+
this.onChange = new Signal();
|
|
49
|
+
this.face = new Graphics();
|
|
50
|
+
this.themeListener = () => this.draw();
|
|
51
|
+
this.handleTap = (event) => {
|
|
52
|
+
if (this.disabled_)
|
|
53
|
+
return;
|
|
54
|
+
const local = this.toLocal(event.global);
|
|
55
|
+
if (local.y < this.height_ / 2)
|
|
56
|
+
this.increment();
|
|
57
|
+
else
|
|
58
|
+
this.decrement();
|
|
59
|
+
};
|
|
60
|
+
this.width_ = options.width ?? 24;
|
|
61
|
+
this.height_ = options.height ?? 32;
|
|
62
|
+
this.min = options.min ?? 0;
|
|
63
|
+
this.max = options.max ?? 9;
|
|
64
|
+
this.step = options.step ?? 1;
|
|
65
|
+
this.wrap = options.wrap ?? false;
|
|
66
|
+
this.disabled_ = options.disabled ?? false;
|
|
67
|
+
this.value_ = spinValue(options.value ?? this.min, 0, this.min, this.max, this.step, false);
|
|
68
|
+
this.addChild(this.face);
|
|
69
|
+
this.draw();
|
|
70
|
+
this.eventMode = 'static';
|
|
71
|
+
this.cursor = 'pointer';
|
|
72
|
+
this.on('pointertap', this.handleTap);
|
|
73
|
+
themeChanged.add(this.themeListener);
|
|
74
|
+
}
|
|
75
|
+
get value() {
|
|
76
|
+
return this.value_;
|
|
77
|
+
}
|
|
78
|
+
get disabled() {
|
|
79
|
+
return this.disabled_;
|
|
80
|
+
}
|
|
81
|
+
setDisabled(disabled) {
|
|
82
|
+
this.disabled_ = disabled;
|
|
83
|
+
this.cursor = disabled ? 'default' : 'pointer';
|
|
84
|
+
this.draw();
|
|
85
|
+
}
|
|
86
|
+
setValue(value) {
|
|
87
|
+
this.commit(spinValue(value, 0, this.min, this.max, this.step, this.wrap));
|
|
88
|
+
}
|
|
89
|
+
increment() {
|
|
90
|
+
this.commit(spinValue(this.value_, 1, this.min, this.max, this.step, this.wrap));
|
|
91
|
+
}
|
|
92
|
+
decrement() {
|
|
93
|
+
this.commit(spinValue(this.value_, -1, this.min, this.max, this.step, this.wrap));
|
|
94
|
+
}
|
|
95
|
+
resize(width, height) {
|
|
96
|
+
this.width_ = width;
|
|
97
|
+
this.height_ = height;
|
|
98
|
+
this.draw();
|
|
99
|
+
}
|
|
100
|
+
commit(next) {
|
|
101
|
+
if (next === this.value_) {
|
|
102
|
+
this.draw();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.value_ = next;
|
|
106
|
+
this.draw();
|
|
107
|
+
this.onChange.dispatch(next);
|
|
108
|
+
}
|
|
109
|
+
draw() {
|
|
110
|
+
const t = theme();
|
|
111
|
+
const color = this.disabled_ ? t.color.textDim : t.color.textHighlight;
|
|
112
|
+
this.face
|
|
113
|
+
.clear()
|
|
114
|
+
.roundRect(0, 0, this.width_, this.height_, 4)
|
|
115
|
+
.fill({ color: t.color.panelFill })
|
|
116
|
+
.stroke({ color: t.color.panelBorder, width: 1 });
|
|
117
|
+
const cx = this.width_ / 2;
|
|
118
|
+
const arrow = Math.min(this.width_ / 4, this.height_ / 5);
|
|
119
|
+
this.face
|
|
120
|
+
.moveTo(cx - arrow, arrow * 1.6)
|
|
121
|
+
.lineTo(cx, arrow * 0.6)
|
|
122
|
+
.lineTo(cx + arrow, arrow * 1.6)
|
|
123
|
+
.closePath()
|
|
124
|
+
.fill({ color });
|
|
125
|
+
this.face
|
|
126
|
+
.moveTo(cx - arrow, this.height_ - arrow * 1.6)
|
|
127
|
+
.lineTo(cx, this.height_ - arrow * 0.6)
|
|
128
|
+
.lineTo(cx + arrow, this.height_ - arrow * 1.6)
|
|
129
|
+
.closePath()
|
|
130
|
+
.fill({ color });
|
|
131
|
+
}
|
|
132
|
+
destroy(options) {
|
|
133
|
+
themeChanged.remove(this.themeListener);
|
|
134
|
+
super.destroy(options);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=Spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../../src/two-d/ui/Spinner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Signal } from '../../core/Signal.ts';
|
|
2
|
+
/** One tab: an id the caller's `rowsFor` understands, and the label a tab strip draws. */
|
|
3
|
+
export interface ListTab {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
/** a tab a player can see but not open */
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface TabbedListOptions<T> {
|
|
10
|
+
/** the tabs, in display order; the first is selected at construction */
|
|
11
|
+
tabs: readonly ListTab[];
|
|
12
|
+
/** the rows of one tab before the query filter; the caller owns what a row is */
|
|
13
|
+
rowsFor: (tabId: string) => readonly T[];
|
|
14
|
+
/** how many rows make a page; 0 or omitted means every row is one page */
|
|
15
|
+
pageSize?: number;
|
|
16
|
+
/** the row's display text; defaults to `String(row)` */
|
|
17
|
+
label?: (row: T) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Whether a row survives the current query. Defaults to the row's label containing the
|
|
20
|
+
* query, case-insensitively; an empty query keeps every row.
|
|
21
|
+
*/
|
|
22
|
+
filter?: (row: T, query: string) => boolean;
|
|
23
|
+
/** a row a player can see but not choose; `move` skips it */
|
|
24
|
+
disabled?: (row: T) => boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The model behind a tabbed, searchable, paged list - an inventory, journal, shop or codex -
|
|
28
|
+
* kept apart from how it is drawn, the same split `SelectionModel` already draws for plain
|
|
29
|
+
* lists. The caller supplies the tabs and the rows per tab (any type it likes, so no item
|
|
30
|
+
* taxonomy is assumed), plus optionally how a row labels, filters and disables itself; this
|
|
31
|
+
* owns the tab choice, the query, the selection, the page and the detail/close state.
|
|
32
|
+
*
|
|
33
|
+
* The page is derived from the selection rather than tracked beside it: a selection index
|
|
34
|
+
* into the filtered rows decides which page is visible, so the two can never disagree and
|
|
35
|
+
* `nextPage` is just a selection move of one page. `move` skips disabled rows.
|
|
36
|
+
*
|
|
37
|
+
* Rendering is the caller's: read `pageRows` and `selectedIndex` each frame, or listen to
|
|
38
|
+
* `onChange`.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { TabbedList } from '@datamoc/mw_games/two-d/ui';
|
|
43
|
+
*
|
|
44
|
+
* const items = [
|
|
45
|
+
* { name: 'Sword', kind: 'weapon' },
|
|
46
|
+
* { name: 'Bread', kind: 'food' },
|
|
47
|
+
* { name: 'Shield', kind: 'armor' },
|
|
48
|
+
* ];
|
|
49
|
+
*
|
|
50
|
+
* const list = new TabbedList<(typeof items)[number]>({
|
|
51
|
+
* tabs: [{ id: 'all', label: 'All' }, { id: 'weapon', label: 'Weapons' }],
|
|
52
|
+
* rowsFor: (tab) => (tab === 'all' ? items : items.filter((item) => item.kind === tab)),
|
|
53
|
+
* label: (item) => item.name,
|
|
54
|
+
* pageSize: 2,
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* console.log(list.selected?.name); // 'Sword'
|
|
58
|
+
* list.setQuery('sh'); // filter down to Shield; selection and page reset
|
|
59
|
+
* console.log(list.rows.length, list.page); // 1 0
|
|
60
|
+
* list.openDetail(); // true, with the current row
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare class TabbedList<T> {
|
|
64
|
+
/** fires whenever the tab, query, selection, page or detail state changes */
|
|
65
|
+
readonly onChange: Signal<void>;
|
|
66
|
+
private readonly tabList;
|
|
67
|
+
private readonly rowsFor;
|
|
68
|
+
private readonly pageSize;
|
|
69
|
+
private readonly labelOf;
|
|
70
|
+
private readonly filterOf;
|
|
71
|
+
private readonly disabledOf;
|
|
72
|
+
private currentTabIndex;
|
|
73
|
+
private currentQuery;
|
|
74
|
+
private rows_;
|
|
75
|
+
private currentSelectedIndex;
|
|
76
|
+
private detail;
|
|
77
|
+
constructor(options: TabbedListOptions<T>);
|
|
78
|
+
/** every tab, in display order, for a tab strip to draw */
|
|
79
|
+
get tabs(): readonly ListTab[];
|
|
80
|
+
/** the currently open tab */
|
|
81
|
+
get tab(): ListTab;
|
|
82
|
+
get query(): string;
|
|
83
|
+
/** the filtered rows of the current tab, across every page */
|
|
84
|
+
get rows(): readonly T[];
|
|
85
|
+
/** how many pages `rows` fills; always at least 1, so an empty list is one empty page */
|
|
86
|
+
get pageCount(): number;
|
|
87
|
+
/** the page the selection is on, derived from it rather than tracked next to it */
|
|
88
|
+
get page(): number;
|
|
89
|
+
/** the rows the current page shows */
|
|
90
|
+
get pageRows(): readonly T[];
|
|
91
|
+
/** the selection's index into `rows` (not into `pageRows`) */
|
|
92
|
+
get selectedIndex(): number;
|
|
93
|
+
get selected(): T | null;
|
|
94
|
+
/** whether the detail view has been opened for the current selection */
|
|
95
|
+
get detailOpen(): boolean;
|
|
96
|
+
/** opens `id`'s tab; a disabled tab or an unknown id is ignored */
|
|
97
|
+
selectTab(id: string): void;
|
|
98
|
+
/** moves to the next enabled tab, `delta` steps on (wrapping); skips disabled tabs */
|
|
99
|
+
nextTab(delta?: number): void;
|
|
100
|
+
/** replaces the query; the selection and page reset to the first row that survives it */
|
|
101
|
+
setQuery(query: string): void;
|
|
102
|
+
/** moves the selection `delta` rows, skipping disabled ones and clamping at both ends */
|
|
103
|
+
move(delta: number): void;
|
|
104
|
+
/** jumps to a page by number, clamped; the selection moves to its first selectable row */
|
|
105
|
+
setPage(page: number): void;
|
|
106
|
+
/** moves `delta` pages; the selection lands on the target page's first selectable row */
|
|
107
|
+
nextPage(delta: number): void;
|
|
108
|
+
/** opens the detail view for the current selection; false when there is nothing to open */
|
|
109
|
+
openDetail(): boolean;
|
|
110
|
+
closeDetail(): void;
|
|
111
|
+
/** the first row on `page` that is not disabled, or its first row when all are */
|
|
112
|
+
private firstSelectableOnPage;
|
|
113
|
+
private firstSelectable;
|
|
114
|
+
/** rebuilds the visible rows and parks the selection on the first selectable one */
|
|
115
|
+
private recompute;
|
|
116
|
+
private emit;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=TabbedList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabbedList.d.ts","sourceRoot":"","sources":["../../../src/two-d/ui/TabbedList.ts"],"names":[],"mappings":"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"}
|