@almadar/ui 5.61.0 → 5.63.1

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.
Files changed (61) hide show
  1. package/dist/avl/index.cjs +3599 -1810
  2. package/dist/avl/index.js +2431 -642
  3. package/dist/components/core/atoms/Box.d.ts +2 -0
  4. package/dist/components/core/molecules/CalendarGrid.d.ts +9 -1
  5. package/dist/components/core/molecules/GraphCanvas.d.ts +4 -0
  6. package/dist/components/core/molecules/PositionedCanvas.d.ts +14 -1
  7. package/dist/components/core/molecules/ReplyTree.d.ts +13 -1
  8. package/dist/components/core/templates/index.d.ts +4 -0
  9. package/dist/components/game/molecules/CardHand.d.ts +35 -0
  10. package/dist/components/game/molecules/DialogueBox.d.ts +8 -2
  11. package/dist/components/game/molecules/index.d.ts +1 -0
  12. package/dist/components/game/molecules/three/index.cjs +283 -115
  13. package/dist/components/game/molecules/three/index.js +283 -115
  14. package/dist/components/game/organisms/CardBattlerBoard.d.ts +46 -0
  15. package/dist/components/game/organisms/CityBuilderBoard.d.ts +63 -0
  16. package/dist/components/game/organisms/TopDownShooterBoard.d.ts +64 -0
  17. package/dist/components/game/organisms/TowerDefenseBoard.d.ts +10 -1
  18. package/dist/components/game/organisms/TraitSlot.d.ts +1 -3
  19. package/dist/components/game/organisms/VisualNovelBoard.d.ts +53 -0
  20. package/dist/components/game/organisms/hooks/useCamera.d.ts +16 -0
  21. package/dist/components/game/organisms/index.d.ts +4 -0
  22. package/dist/components/game/templates/CardBattlerTemplate.d.ts +35 -0
  23. package/dist/components/game/templates/CityBuilderTemplate.d.ts +40 -0
  24. package/dist/components/game/templates/GameCanvas3DBattleTemplate.d.ts +5 -2
  25. package/dist/components/game/templates/GameCanvas3DCastleTemplate.d.ts +5 -2
  26. package/dist/components/game/templates/GameCanvas3DWorldMapTemplate.d.ts +5 -2
  27. package/dist/components/game/templates/TopDownShooterTemplate.d.ts +42 -0
  28. package/dist/components/game/templates/VisualNovelTemplate.d.ts +28 -0
  29. package/dist/components/game/templates/game3dAssetManifest.d.ts +50 -0
  30. package/dist/components/game/templates/index.d.ts +4 -0
  31. package/dist/components/index.cjs +3465 -1659
  32. package/dist/components/index.js +2444 -647
  33. package/dist/components/marketing/organisms/CaseStudyOrganism.d.ts +10 -1
  34. package/dist/components/marketing/organisms/FeatureGridOrganism.d.ts +10 -1
  35. package/dist/components/marketing/organisms/HeroOrganism.d.ts +24 -1
  36. package/dist/components/marketing/organisms/PricingOrganism.d.ts +14 -1
  37. package/dist/components/marketing/organisms/ShowcaseOrganism.d.ts +14 -1
  38. package/dist/components/marketing/organisms/StatsOrganism.d.ts +6 -1
  39. package/dist/components/marketing/organisms/StepFlowOrganism.d.ts +9 -1
  40. package/dist/components/marketing/organisms/TeamOrganism.d.ts +10 -1
  41. package/dist/docs/index.cjs +169 -1
  42. package/dist/docs/index.d.cts +2 -0
  43. package/dist/docs/index.js +169 -1
  44. package/dist/hooks/index.cjs +253 -1
  45. package/dist/hooks/index.d.ts +2 -0
  46. package/dist/hooks/index.js +252 -2
  47. package/dist/hooks/useCanvasGestures.d.ts +44 -0
  48. package/dist/hooks/useTapReveal.d.ts +32 -0
  49. package/dist/locales/index.cjs +315 -3
  50. package/dist/locales/index.js +315 -3
  51. package/dist/marketing/index.cjs +59 -0
  52. package/dist/marketing/index.d.cts +2 -0
  53. package/dist/marketing/index.js +59 -0
  54. package/dist/providers/index.cjs +3408 -1619
  55. package/dist/providers/index.js +2407 -618
  56. package/dist/runtime/index.cjs +3464 -1675
  57. package/dist/runtime/index.js +2411 -622
  58. package/locales/ar.json +105 -1
  59. package/locales/en.json +105 -1
  60. package/locales/sl.json +105 -1
  61. package/package.json +2 -2
@@ -2059,7 +2059,111 @@ var en_default = {
2059
2059
  "stateMachine.legend.final": "Final",
2060
2060
  "stateMachine.legend.state": "State",
2061
2061
  "stateMachine.legend.multiEvent": "Multi-event",
2062
- "relationSelect.selectPlaceholder": "Select..."
2062
+ "relationSelect.selectPlaceholder": "Select...",
2063
+ "battle.cancel": "Cancel",
2064
+ "battle.defeat": "Defeat",
2065
+ "battle.endTurn": "End Turn",
2066
+ "battle.playAgain": "Play Again",
2067
+ "battle.turnsPlayed": "Turns Played",
2068
+ "battle.victory": "Victory",
2069
+ "builder.allPlaced": "All placed",
2070
+ "builder.blueprint": "Blueprint",
2071
+ "builder.build": "Build",
2072
+ "builder.components": "Components",
2073
+ "builder.empty": "Empty",
2074
+ "builder.reset": "Reset",
2075
+ "builder.success": "Success",
2076
+ "classifier.allCorrect": "All correct!",
2077
+ "classifier.check": "Check",
2078
+ "classifier.correct": "correct",
2079
+ "classifier.itemsToSort": "Items to sort",
2080
+ "classifier.reset": "Reset",
2081
+ "common.error": "Error",
2082
+ "debugger.allFound": "All bugs found!",
2083
+ "debugger.bugsFound": "bugs found",
2084
+ "debugger.findBugs": "Find {{count}} bugs",
2085
+ "debugger.reset": "Reset",
2086
+ "debugger.submit": "Submit",
2087
+ "error.genericLoad": "Failed to load",
2088
+ "error.loadingData": "Loading data",
2089
+ "eventHandler.addRule": "Add Rule",
2090
+ "eventHandler.chainComplete": "Chain complete!",
2091
+ "eventHandler.clickObject": "Click objects",
2092
+ "eventHandler.eventLog": "Event Log",
2093
+ "eventHandler.heardEvent": "{{object}} heard {{event}} \u2192 {{action}}",
2094
+ "eventHandler.noEvents": "No events yet",
2095
+ "eventHandler.noListeners": "No listeners for {{event}}",
2096
+ "eventHandler.rules": "{{count}}/{{max}} rules",
2097
+ "eventHandler.simulationStarted": "Simulating: {{events}}",
2098
+ "eventHandler.state": "State",
2099
+ "eventHandler.then": "then",
2100
+ "eventHandler.when": "When",
2101
+ "game.goal": "Goal",
2102
+ "game.hint": "Hint",
2103
+ "game.play": "Play",
2104
+ "game.reset": "Reset",
2105
+ "game.runTests": "Run Tests",
2106
+ "negotiator.chooseAction": "Choose an action",
2107
+ "negotiator.failed": "Negotiation failed",
2108
+ "negotiator.finalScore": "Final score",
2109
+ "negotiator.history": "History",
2110
+ "negotiator.opponent": "Opponent",
2111
+ "negotiator.playAgain": "Play Again",
2112
+ "negotiator.round": "Round {{current}} of {{total}}",
2113
+ "negotiator.success": "Negotiation successful",
2114
+ "negotiator.target": "Target",
2115
+ "negotiator.you": "You",
2116
+ "platformer.level": "Level",
2117
+ "platformer.lost": "Game Over",
2118
+ "platformer.nextLevel": "Next Level",
2119
+ "platformer.noLives": "No lives left",
2120
+ "platformer.playAgain": "Play Again",
2121
+ "platformer.score": "Score",
2122
+ "platformer.won": "You won!",
2123
+ "puzzle.tryAgainButton": "Try Again",
2124
+ "roguelike.atk": "ATK",
2125
+ "roguelike.cleared": "Dungeon cleared! Depth reached: {{depth}}",
2126
+ "roguelike.defeat": "Defeated!",
2127
+ "roguelike.depth": "Depth",
2128
+ "roguelike.enemy": "Enemy",
2129
+ "roguelike.hp": "HP",
2130
+ "roguelike.phase": "Phase",
2131
+ "roguelike.playAgain": "Play Again",
2132
+ "roguelike.player": "Hero",
2133
+ "roguelike.victory": "Victory!",
2134
+ "sequencer.actions": "Actions",
2135
+ "sequencer.dragActions": "Drag actions here",
2136
+ "sequencer.levelComplete": "Level complete!",
2137
+ "sequencer.yourSequence": "Your sequence",
2138
+ "simulator.correct": "Correct",
2139
+ "simulator.incorrect": "Incorrect",
2140
+ "simulator.parameters": "Parameters",
2141
+ "simulator.reset": "Reset",
2142
+ "simulator.simulate": "Simulate",
2143
+ "simulator.target": "Target",
2144
+ "stateArchitect.addTransition": "Add transition from {{state}}",
2145
+ "stateArchitect.addTransitionPrompt": "Click target state",
2146
+ "stateArchitect.allPassed": "All tests passed!",
2147
+ "stateArchitect.clickTarget": "Click a target state (current: {{state}})",
2148
+ "stateArchitect.gotState": "Got state: {{state}}",
2149
+ "stateArchitect.graph": "Graph",
2150
+ "stateArchitect.hideJson": "Hide JSON",
2151
+ "stateArchitect.showJson": "Show JSON",
2152
+ "stateArchitect.testResults": "Test Results",
2153
+ "stateArchitect.transitions": "{{count}} transitions",
2154
+ "stateArchitect.variables": "Variables: {{name}}",
2155
+ "stateArchitect.viewCode": "View Code",
2156
+ "td.defeat": "Defeat",
2157
+ "td.gold": "Gold",
2158
+ "td.lives": "Lives",
2159
+ "td.livesReachedZero": "Your base was overrun",
2160
+ "td.placeTower": "Place tower",
2161
+ "td.playAgain": "Play Again",
2162
+ "td.startWave": "Start Wave",
2163
+ "td.survivedAllWaves": "Survived all waves!",
2164
+ "td.victory": "Victory!",
2165
+ "td.wave": "Wave",
2166
+ "td.waveInProgress": "Wave in progress\u2026"
2063
2167
  };
2064
2168
 
2065
2169
  // hooks/useTranslate.ts
@@ -2412,6 +2516,152 @@ function usePinchZoom(options = {}) {
2412
2516
  resetZoom
2413
2517
  };
2414
2518
  }
2519
+ function localPoint(canvas, clientX, clientY) {
2520
+ if (!canvas) return { x: clientX, y: clientY };
2521
+ const rect = canvas.getBoundingClientRect();
2522
+ return { x: clientX - rect.left, y: clientY - rect.top };
2523
+ }
2524
+ function useCanvasGestures(options) {
2525
+ const {
2526
+ canvasRef,
2527
+ enabled = true,
2528
+ wheelStep = 1.1,
2529
+ onPointerDown,
2530
+ onPointerMove,
2531
+ onPointerUp,
2532
+ onZoom,
2533
+ onPanDelta,
2534
+ onMultiTouchStart
2535
+ } = options;
2536
+ const pointers = react.useRef(/* @__PURE__ */ new Map());
2537
+ const pinch = react.useRef(null);
2538
+ const computePinch = react.useCallback(() => {
2539
+ const pts = [...pointers.current.values()];
2540
+ const dx = pts[1].x - pts[0].x;
2541
+ const dy = pts[1].y - pts[0].y;
2542
+ return {
2543
+ distance: Math.hypot(dx, dy) || 1,
2544
+ centroid: { x: (pts[0].x + pts[1].x) / 2, y: (pts[0].y + pts[1].y) / 2 }
2545
+ };
2546
+ }, []);
2547
+ const handlePointerDown = react.useCallback(
2548
+ (e) => {
2549
+ if (!enabled) return;
2550
+ e.currentTarget.setPointerCapture(e.pointerId);
2551
+ pointers.current.set(e.pointerId, localPoint(canvasRef.current, e.clientX, e.clientY));
2552
+ if (pointers.current.size === 2) {
2553
+ onMultiTouchStart?.();
2554
+ pinch.current = computePinch();
2555
+ } else if (pointers.current.size === 1) {
2556
+ onPointerDown?.(e);
2557
+ }
2558
+ },
2559
+ [enabled, canvasRef, onMultiTouchStart, computePinch, onPointerDown]
2560
+ );
2561
+ const handlePointerMove = react.useCallback(
2562
+ (e) => {
2563
+ if (!enabled) return;
2564
+ if (pointers.current.has(e.pointerId)) {
2565
+ pointers.current.set(e.pointerId, localPoint(canvasRef.current, e.clientX, e.clientY));
2566
+ }
2567
+ if (pointers.current.size >= 2 && pinch.current) {
2568
+ const next = computePinch();
2569
+ const prev = pinch.current;
2570
+ if (next.distance !== prev.distance) {
2571
+ onZoom?.(next.distance / prev.distance, next.centroid.x, next.centroid.y);
2572
+ }
2573
+ onPanDelta?.(next.centroid.x - prev.centroid.x, next.centroid.y - prev.centroid.y);
2574
+ pinch.current = next;
2575
+ return;
2576
+ }
2577
+ onPointerMove?.(e);
2578
+ },
2579
+ [enabled, canvasRef, computePinch, onZoom, onPanDelta, onPointerMove]
2580
+ );
2581
+ const endPointer = react.useCallback(
2582
+ (e, fireUp) => {
2583
+ const wasMulti = pointers.current.size >= 2;
2584
+ pointers.current.delete(e.pointerId);
2585
+ if (pointers.current.size < 2) pinch.current = null;
2586
+ if (wasMulti && pointers.current.size === 1) return;
2587
+ if (pointers.current.size === 0 && fireUp) onPointerUp?.(e);
2588
+ },
2589
+ [onPointerUp]
2590
+ );
2591
+ const handlePointerUp = react.useCallback(
2592
+ (e) => {
2593
+ if (!enabled) return;
2594
+ endPointer(e, true);
2595
+ },
2596
+ [enabled, endPointer]
2597
+ );
2598
+ const handlePointerCancel = react.useCallback(
2599
+ (e) => {
2600
+ if (!enabled) return;
2601
+ endPointer(e, false);
2602
+ },
2603
+ [enabled, endPointer]
2604
+ );
2605
+ const handleWheel = react.useCallback(
2606
+ (e) => {
2607
+ if (!enabled) return;
2608
+ e.preventDefault();
2609
+ const { x, y } = localPoint(canvasRef.current, e.clientX, e.clientY);
2610
+ onZoom?.(e.deltaY < 0 ? wheelStep : 1 / wheelStep, x, y);
2611
+ },
2612
+ [enabled, canvasRef, wheelStep, onZoom]
2613
+ );
2614
+ return {
2615
+ onPointerDown: handlePointerDown,
2616
+ onPointerMove: handlePointerMove,
2617
+ onPointerUp: handlePointerUp,
2618
+ onPointerCancel: handlePointerCancel,
2619
+ onWheel: handleWheel
2620
+ };
2621
+ }
2622
+ function useTapReveal(options = {}) {
2623
+ const { onReveal, onDismiss, refs, enabled = true } = options;
2624
+ const [revealed, setRevealed] = react.useState(false);
2625
+ const onRevealRef = react.useRef(onReveal);
2626
+ const onDismissRef = react.useRef(onDismiss);
2627
+ onRevealRef.current = onReveal;
2628
+ onDismissRef.current = onDismiss;
2629
+ const reveal = react.useCallback(() => {
2630
+ setRevealed((wasRevealed) => {
2631
+ if (!wasRevealed) onRevealRef.current?.();
2632
+ return true;
2633
+ });
2634
+ }, []);
2635
+ const dismiss = react.useCallback(() => {
2636
+ setRevealed((wasRevealed) => {
2637
+ if (wasRevealed) onDismissRef.current?.();
2638
+ return false;
2639
+ });
2640
+ }, []);
2641
+ const onPointerDown = react.useCallback(
2642
+ (e) => {
2643
+ if (!enabled || e.pointerType === "mouse") return;
2644
+ if (revealed) dismiss();
2645
+ else reveal();
2646
+ },
2647
+ [enabled, revealed, reveal, dismiss]
2648
+ );
2649
+ react.useEffect(() => {
2650
+ if (!revealed || typeof document === "undefined") return;
2651
+ const onDocDown = (ev) => {
2652
+ const target = ev.target;
2653
+ if (!(target instanceof Node)) return;
2654
+ const inside = (refs ?? []).some((r) => r.current?.contains(target));
2655
+ if (!inside) dismiss();
2656
+ };
2657
+ const id = setTimeout(() => document.addEventListener("pointerdown", onDocDown), 0);
2658
+ return () => {
2659
+ clearTimeout(id);
2660
+ document.removeEventListener("pointerdown", onDocDown);
2661
+ };
2662
+ }, [revealed, refs, dismiss]);
2663
+ return { revealed, triggerProps: { onPointerDown }, reveal, dismiss };
2664
+ }
2415
2665
  var ALMADAR_DND_MIME = "application/x-almadar-dnd";
2416
2666
  function useDraggable({ payload, disabled = false }) {
2417
2667
  const [isDragging, setIsDragging] = react.useState(false);
@@ -2663,6 +2913,7 @@ exports.updateEntity = updateEntity;
2663
2913
  exports.updateSingleton = updateSingleton;
2664
2914
  exports.useAgentChat = useAgentChat;
2665
2915
  exports.useAuthContext = useAuthContext;
2916
+ exports.useCanvasGestures = useCanvasGestures;
2666
2917
  exports.useCompile = useCompile;
2667
2918
  exports.useConnectGitHub = useConnectGitHub;
2668
2919
  exports.useDeepAgentGeneration = useDeepAgentGeneration;
@@ -2696,6 +2947,7 @@ exports.useQuerySingleton = useQuerySingleton;
2696
2947
  exports.useRenderInterpolation = useRenderInterpolation;
2697
2948
  exports.useSingletonEntity = useSingletonEntity;
2698
2949
  exports.useSwipeGesture = useSwipeGesture;
2950
+ exports.useTapReveal = useTapReveal;
2699
2951
  exports.useTraitListens = useTraitListens;
2700
2952
  exports.useTranslate = useTranslate;
2701
2953
  exports.useUIEvents = useUIEvents;
@@ -24,6 +24,8 @@ export { useDragReorder, type DragReorderResult, } from './useDragReorder';
24
24
  export { useInfiniteScroll, type InfiniteScrollOptions, type InfiniteScrollResult, } from './useInfiniteScroll';
25
25
  export { usePullToRefresh, type PullToRefreshOptions, type PullToRefreshResult, } from './usePullToRefresh';
26
26
  export { usePinchZoom, type PinchZoomOptions, type PinchZoomResult, } from './usePinchZoom';
27
+ export { useCanvasGestures, type UseCanvasGesturesOptions, type CanvasGestureCallbacks, type CanvasGestureHandlers, } from './useCanvasGestures';
28
+ export { useTapReveal, type TapRevealOptions, type TapRevealResult, } from './useTapReveal';
27
29
  export { useDraggable, ALMADAR_DND_MIME, type DraggablePayload, type UseDraggableOptions, type UseDraggableResult, } from './useDraggable';
28
30
  export { useDropZone, type UseDropZoneOptions, type UseDropZoneResult, } from './useDropZone';
29
31
  export { useRenderInterpolation, type Positioned, type RenderInterpolationOptions, type RenderInterpolationHandle, } from './useRenderInterpolation';
@@ -2057,7 +2057,111 @@ var en_default = {
2057
2057
  "stateMachine.legend.final": "Final",
2058
2058
  "stateMachine.legend.state": "State",
2059
2059
  "stateMachine.legend.multiEvent": "Multi-event",
2060
- "relationSelect.selectPlaceholder": "Select..."
2060
+ "relationSelect.selectPlaceholder": "Select...",
2061
+ "battle.cancel": "Cancel",
2062
+ "battle.defeat": "Defeat",
2063
+ "battle.endTurn": "End Turn",
2064
+ "battle.playAgain": "Play Again",
2065
+ "battle.turnsPlayed": "Turns Played",
2066
+ "battle.victory": "Victory",
2067
+ "builder.allPlaced": "All placed",
2068
+ "builder.blueprint": "Blueprint",
2069
+ "builder.build": "Build",
2070
+ "builder.components": "Components",
2071
+ "builder.empty": "Empty",
2072
+ "builder.reset": "Reset",
2073
+ "builder.success": "Success",
2074
+ "classifier.allCorrect": "All correct!",
2075
+ "classifier.check": "Check",
2076
+ "classifier.correct": "correct",
2077
+ "classifier.itemsToSort": "Items to sort",
2078
+ "classifier.reset": "Reset",
2079
+ "common.error": "Error",
2080
+ "debugger.allFound": "All bugs found!",
2081
+ "debugger.bugsFound": "bugs found",
2082
+ "debugger.findBugs": "Find {{count}} bugs",
2083
+ "debugger.reset": "Reset",
2084
+ "debugger.submit": "Submit",
2085
+ "error.genericLoad": "Failed to load",
2086
+ "error.loadingData": "Loading data",
2087
+ "eventHandler.addRule": "Add Rule",
2088
+ "eventHandler.chainComplete": "Chain complete!",
2089
+ "eventHandler.clickObject": "Click objects",
2090
+ "eventHandler.eventLog": "Event Log",
2091
+ "eventHandler.heardEvent": "{{object}} heard {{event}} \u2192 {{action}}",
2092
+ "eventHandler.noEvents": "No events yet",
2093
+ "eventHandler.noListeners": "No listeners for {{event}}",
2094
+ "eventHandler.rules": "{{count}}/{{max}} rules",
2095
+ "eventHandler.simulationStarted": "Simulating: {{events}}",
2096
+ "eventHandler.state": "State",
2097
+ "eventHandler.then": "then",
2098
+ "eventHandler.when": "When",
2099
+ "game.goal": "Goal",
2100
+ "game.hint": "Hint",
2101
+ "game.play": "Play",
2102
+ "game.reset": "Reset",
2103
+ "game.runTests": "Run Tests",
2104
+ "negotiator.chooseAction": "Choose an action",
2105
+ "negotiator.failed": "Negotiation failed",
2106
+ "negotiator.finalScore": "Final score",
2107
+ "negotiator.history": "History",
2108
+ "negotiator.opponent": "Opponent",
2109
+ "negotiator.playAgain": "Play Again",
2110
+ "negotiator.round": "Round {{current}} of {{total}}",
2111
+ "negotiator.success": "Negotiation successful",
2112
+ "negotiator.target": "Target",
2113
+ "negotiator.you": "You",
2114
+ "platformer.level": "Level",
2115
+ "platformer.lost": "Game Over",
2116
+ "platformer.nextLevel": "Next Level",
2117
+ "platformer.noLives": "No lives left",
2118
+ "platformer.playAgain": "Play Again",
2119
+ "platformer.score": "Score",
2120
+ "platformer.won": "You won!",
2121
+ "puzzle.tryAgainButton": "Try Again",
2122
+ "roguelike.atk": "ATK",
2123
+ "roguelike.cleared": "Dungeon cleared! Depth reached: {{depth}}",
2124
+ "roguelike.defeat": "Defeated!",
2125
+ "roguelike.depth": "Depth",
2126
+ "roguelike.enemy": "Enemy",
2127
+ "roguelike.hp": "HP",
2128
+ "roguelike.phase": "Phase",
2129
+ "roguelike.playAgain": "Play Again",
2130
+ "roguelike.player": "Hero",
2131
+ "roguelike.victory": "Victory!",
2132
+ "sequencer.actions": "Actions",
2133
+ "sequencer.dragActions": "Drag actions here",
2134
+ "sequencer.levelComplete": "Level complete!",
2135
+ "sequencer.yourSequence": "Your sequence",
2136
+ "simulator.correct": "Correct",
2137
+ "simulator.incorrect": "Incorrect",
2138
+ "simulator.parameters": "Parameters",
2139
+ "simulator.reset": "Reset",
2140
+ "simulator.simulate": "Simulate",
2141
+ "simulator.target": "Target",
2142
+ "stateArchitect.addTransition": "Add transition from {{state}}",
2143
+ "stateArchitect.addTransitionPrompt": "Click target state",
2144
+ "stateArchitect.allPassed": "All tests passed!",
2145
+ "stateArchitect.clickTarget": "Click a target state (current: {{state}})",
2146
+ "stateArchitect.gotState": "Got state: {{state}}",
2147
+ "stateArchitect.graph": "Graph",
2148
+ "stateArchitect.hideJson": "Hide JSON",
2149
+ "stateArchitect.showJson": "Show JSON",
2150
+ "stateArchitect.testResults": "Test Results",
2151
+ "stateArchitect.transitions": "{{count}} transitions",
2152
+ "stateArchitect.variables": "Variables: {{name}}",
2153
+ "stateArchitect.viewCode": "View Code",
2154
+ "td.defeat": "Defeat",
2155
+ "td.gold": "Gold",
2156
+ "td.lives": "Lives",
2157
+ "td.livesReachedZero": "Your base was overrun",
2158
+ "td.placeTower": "Place tower",
2159
+ "td.playAgain": "Play Again",
2160
+ "td.startWave": "Start Wave",
2161
+ "td.survivedAllWaves": "Survived all waves!",
2162
+ "td.victory": "Victory!",
2163
+ "td.wave": "Wave",
2164
+ "td.waveInProgress": "Wave in progress\u2026"
2061
2165
  };
2062
2166
 
2063
2167
  // hooks/useTranslate.ts
@@ -2410,6 +2514,152 @@ function usePinchZoom(options = {}) {
2410
2514
  resetZoom
2411
2515
  };
2412
2516
  }
2517
+ function localPoint(canvas, clientX, clientY) {
2518
+ if (!canvas) return { x: clientX, y: clientY };
2519
+ const rect = canvas.getBoundingClientRect();
2520
+ return { x: clientX - rect.left, y: clientY - rect.top };
2521
+ }
2522
+ function useCanvasGestures(options) {
2523
+ const {
2524
+ canvasRef,
2525
+ enabled = true,
2526
+ wheelStep = 1.1,
2527
+ onPointerDown,
2528
+ onPointerMove,
2529
+ onPointerUp,
2530
+ onZoom,
2531
+ onPanDelta,
2532
+ onMultiTouchStart
2533
+ } = options;
2534
+ const pointers = useRef(/* @__PURE__ */ new Map());
2535
+ const pinch = useRef(null);
2536
+ const computePinch = useCallback(() => {
2537
+ const pts = [...pointers.current.values()];
2538
+ const dx = pts[1].x - pts[0].x;
2539
+ const dy = pts[1].y - pts[0].y;
2540
+ return {
2541
+ distance: Math.hypot(dx, dy) || 1,
2542
+ centroid: { x: (pts[0].x + pts[1].x) / 2, y: (pts[0].y + pts[1].y) / 2 }
2543
+ };
2544
+ }, []);
2545
+ const handlePointerDown = useCallback(
2546
+ (e) => {
2547
+ if (!enabled) return;
2548
+ e.currentTarget.setPointerCapture(e.pointerId);
2549
+ pointers.current.set(e.pointerId, localPoint(canvasRef.current, e.clientX, e.clientY));
2550
+ if (pointers.current.size === 2) {
2551
+ onMultiTouchStart?.();
2552
+ pinch.current = computePinch();
2553
+ } else if (pointers.current.size === 1) {
2554
+ onPointerDown?.(e);
2555
+ }
2556
+ },
2557
+ [enabled, canvasRef, onMultiTouchStart, computePinch, onPointerDown]
2558
+ );
2559
+ const handlePointerMove = useCallback(
2560
+ (e) => {
2561
+ if (!enabled) return;
2562
+ if (pointers.current.has(e.pointerId)) {
2563
+ pointers.current.set(e.pointerId, localPoint(canvasRef.current, e.clientX, e.clientY));
2564
+ }
2565
+ if (pointers.current.size >= 2 && pinch.current) {
2566
+ const next = computePinch();
2567
+ const prev = pinch.current;
2568
+ if (next.distance !== prev.distance) {
2569
+ onZoom?.(next.distance / prev.distance, next.centroid.x, next.centroid.y);
2570
+ }
2571
+ onPanDelta?.(next.centroid.x - prev.centroid.x, next.centroid.y - prev.centroid.y);
2572
+ pinch.current = next;
2573
+ return;
2574
+ }
2575
+ onPointerMove?.(e);
2576
+ },
2577
+ [enabled, canvasRef, computePinch, onZoom, onPanDelta, onPointerMove]
2578
+ );
2579
+ const endPointer = useCallback(
2580
+ (e, fireUp) => {
2581
+ const wasMulti = pointers.current.size >= 2;
2582
+ pointers.current.delete(e.pointerId);
2583
+ if (pointers.current.size < 2) pinch.current = null;
2584
+ if (wasMulti && pointers.current.size === 1) return;
2585
+ if (pointers.current.size === 0 && fireUp) onPointerUp?.(e);
2586
+ },
2587
+ [onPointerUp]
2588
+ );
2589
+ const handlePointerUp = useCallback(
2590
+ (e) => {
2591
+ if (!enabled) return;
2592
+ endPointer(e, true);
2593
+ },
2594
+ [enabled, endPointer]
2595
+ );
2596
+ const handlePointerCancel = useCallback(
2597
+ (e) => {
2598
+ if (!enabled) return;
2599
+ endPointer(e, false);
2600
+ },
2601
+ [enabled, endPointer]
2602
+ );
2603
+ const handleWheel = useCallback(
2604
+ (e) => {
2605
+ if (!enabled) return;
2606
+ e.preventDefault();
2607
+ const { x, y } = localPoint(canvasRef.current, e.clientX, e.clientY);
2608
+ onZoom?.(e.deltaY < 0 ? wheelStep : 1 / wheelStep, x, y);
2609
+ },
2610
+ [enabled, canvasRef, wheelStep, onZoom]
2611
+ );
2612
+ return {
2613
+ onPointerDown: handlePointerDown,
2614
+ onPointerMove: handlePointerMove,
2615
+ onPointerUp: handlePointerUp,
2616
+ onPointerCancel: handlePointerCancel,
2617
+ onWheel: handleWheel
2618
+ };
2619
+ }
2620
+ function useTapReveal(options = {}) {
2621
+ const { onReveal, onDismiss, refs, enabled = true } = options;
2622
+ const [revealed, setRevealed] = useState(false);
2623
+ const onRevealRef = useRef(onReveal);
2624
+ const onDismissRef = useRef(onDismiss);
2625
+ onRevealRef.current = onReveal;
2626
+ onDismissRef.current = onDismiss;
2627
+ const reveal = useCallback(() => {
2628
+ setRevealed((wasRevealed) => {
2629
+ if (!wasRevealed) onRevealRef.current?.();
2630
+ return true;
2631
+ });
2632
+ }, []);
2633
+ const dismiss = useCallback(() => {
2634
+ setRevealed((wasRevealed) => {
2635
+ if (wasRevealed) onDismissRef.current?.();
2636
+ return false;
2637
+ });
2638
+ }, []);
2639
+ const onPointerDown = useCallback(
2640
+ (e) => {
2641
+ if (!enabled || e.pointerType === "mouse") return;
2642
+ if (revealed) dismiss();
2643
+ else reveal();
2644
+ },
2645
+ [enabled, revealed, reveal, dismiss]
2646
+ );
2647
+ useEffect(() => {
2648
+ if (!revealed || typeof document === "undefined") return;
2649
+ const onDocDown = (ev) => {
2650
+ const target = ev.target;
2651
+ if (!(target instanceof Node)) return;
2652
+ const inside = (refs ?? []).some((r) => r.current?.contains(target));
2653
+ if (!inside) dismiss();
2654
+ };
2655
+ const id = setTimeout(() => document.addEventListener("pointerdown", onDocDown), 0);
2656
+ return () => {
2657
+ clearTimeout(id);
2658
+ document.removeEventListener("pointerdown", onDocDown);
2659
+ };
2660
+ }, [revealed, refs, dismiss]);
2661
+ return { revealed, triggerProps: { onPointerDown }, reveal, dismiss };
2662
+ }
2413
2663
  var ALMADAR_DND_MIME = "application/x-almadar-dnd";
2414
2664
  function useDraggable({ payload, disabled = false }) {
2415
2665
  const [isDragging, setIsDragging] = useState(false);
@@ -2645,4 +2895,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
2645
2895
  });
2646
2896
  }
2647
2897
 
2648
- export { ALMADAR_DND_MIME, DEFAULT_SLOTS, I18nProvider, clearEntities, createTranslate, getAllEntities, getByType, getEntity, getSingleton, parseQueryBinding, removeEntity, spawnEntity, updateEntity, updateSingleton, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEntities, useEntitiesByType, useEntity as useEntityById, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInfiniteScroll, useInput, useLongPress, useOrbitalHistory, usePhysics, usePinchZoom, usePlayer, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSingletonEntity, useSwipeGesture, useTraitListens, useTranslate, useUIEvents, useUISlotManager, useValidation };
2898
+ export { ALMADAR_DND_MIME, DEFAULT_SLOTS, I18nProvider, clearEntities, createTranslate, getAllEntities, getByType, getEntity, getSingleton, parseQueryBinding, removeEntity, spawnEntity, updateEntity, updateSingleton, useAgentChat, useAuthContext, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEntities, useEntitiesByType, useEntity as useEntityById, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInfiniteScroll, useInput, useLongPress, useOrbitalHistory, usePhysics, usePinchZoom, usePlayer, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSingletonEntity, useSwipeGesture, useTapReveal, useTraitListens, useTranslate, useUIEvents, useUISlotManager, useValidation };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Unified pointer/touch gesture detection for canvas surfaces (graph, isometric, etc.).
3
+ *
4
+ * It owns the hard part — pointer tracking + two-finger pinch (scale factor + centroid) —
5
+ * and DELEGATES application to the consumer via callbacks, so each canvas applies pan/zoom
6
+ * in its own coordinate convention (screen-offset vs world-camera). A single pointer is
7
+ * passed straight through to the consumer's domain handlers (pan / node-drag / tile-select);
8
+ * a second pointer takes over as a pinch and cancels any in-flight single-pointer action.
9
+ *
10
+ * Pointer Events cover mouse, touch and pen, so this REPLACES mouse handlers — no dual paths.
11
+ */
12
+ export interface CanvasGestureCallbacks {
13
+ /** Single-pointer down — start the consumer's pan / drag / select (domain-specific). */
14
+ onPointerDown?: (e: React.PointerEvent<HTMLCanvasElement>) => void;
15
+ /** Single-pointer move. */
16
+ onPointerMove?: (e: React.PointerEvent<HTMLCanvasElement>) => void;
17
+ /** Single-pointer up. */
18
+ onPointerUp?: (e: React.PointerEvent<HTMLCanvasElement>) => void;
19
+ /**
20
+ * Multiplicative zoom around a canvas-local point. Fired by wheel and by pinch.
21
+ * Consumer applies `newZoom = clamp(oldZoom * factor)` keeping (centerX,centerY) fixed.
22
+ */
23
+ onZoom?: (factor: number, centerX: number, centerY: number) => void;
24
+ /** Two-finger pan delta in canvas-local px (fired alongside pinch). */
25
+ onPanDelta?: (dx: number, dy: number) => void;
26
+ /** A second pointer arrived — cancel any single-pointer pan/drag the consumer started. */
27
+ onMultiTouchStart?: () => void;
28
+ }
29
+ export interface UseCanvasGesturesOptions extends CanvasGestureCallbacks {
30
+ /** The canvas being gestured on (for coordinate translation). */
31
+ canvasRef: React.RefObject<HTMLCanvasElement | null>;
32
+ /** When false, all gestures are inert. Default true. */
33
+ enabled?: boolean;
34
+ /** Wheel zoom step per notch (>1). Default 1.1. */
35
+ wheelStep?: number;
36
+ }
37
+ export interface CanvasGestureHandlers {
38
+ onPointerDown: (e: React.PointerEvent<HTMLCanvasElement>) => void;
39
+ onPointerMove: (e: React.PointerEvent<HTMLCanvasElement>) => void;
40
+ onPointerUp: (e: React.PointerEvent<HTMLCanvasElement>) => void;
41
+ onPointerCancel: (e: React.PointerEvent<HTMLCanvasElement>) => void;
42
+ onWheel: (e: React.WheelEvent<HTMLCanvasElement>) => void;
43
+ }
44
+ export declare function useCanvasGestures(options: UseCanvasGesturesOptions): CanvasGestureHandlers;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Hover-only reveals (tooltips, hover-popovers, submenus, `Box.hoverEvent`) have no hover on
3
+ * touch, so they're invisible/unreachable. This adds the tap-to-reveal fallback: on a touch/pen
4
+ * tap the surface reveals and fires the SAME event the hover path fires; a tap outside dismisses.
5
+ * Mouse is left to the component's existing hover handlers (`pointerType === 'mouse'` is ignored),
6
+ * so this is purely additive — no behavior change on desktop.
7
+ */
8
+ export interface TapRevealOptions {
9
+ /** Fired when a tap reveals — reuse to emit the component's existing hover event. */
10
+ onReveal?: () => void;
11
+ /** Fired when an outside tap (or a second trigger tap) dismisses. */
12
+ onDismiss?: () => void;
13
+ /**
14
+ * Elements considered "inside" for outside-tap detection. Pass the trigger and the surface
15
+ * (the surface may be portaled, so it isn't a DOM descendant of the trigger). A tap whose
16
+ * target is inside none of these dismisses.
17
+ */
18
+ refs?: ReadonlyArray<React.RefObject<HTMLElement | null>>;
19
+ /** When false, taps are ignored (hover-only). Default true. */
20
+ enabled?: boolean;
21
+ }
22
+ export interface TapRevealResult {
23
+ /** Whether the surface is currently revealed via a tap. OR this with the hover state. */
24
+ revealed: boolean;
25
+ /** Spread on the trigger; toggles reveal on a touch/pen tap (ignores mouse). */
26
+ triggerProps: {
27
+ onPointerDown: (e: React.PointerEvent) => void;
28
+ };
29
+ reveal: () => void;
30
+ dismiss: () => void;
31
+ }
32
+ export declare function useTapReveal(options?: TapRevealOptions): TapRevealResult;