@dreamboard-games/sdk 0.5.0-alpha.7 → 0.5.0-alpha.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/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react/gesture.tsx","../src/react/create-game-hook.tsx"],"sourcesContent":["import { createStore } from \"@tanstack/store\";\nimport { useSelector } from \"@tanstack/react-store\";\nimport {\n createContext,\n useContext,\n type CSSProperties,\n type DragEvent,\n type MouseEvent,\n type PointerEvent,\n} from \"react\";\nimport {\n createGestureRecognizer,\n GESTURE_THRESHOLDS,\n type GestureRecognizer,\n} from \"../headless/gesture.js\";\nimport { isSameDropTarget } from \"../headless/drop-targets.js\";\nimport type { Point } from \"../headless/features/pointer-session.js\";\nimport type {\n RuntimeDropTarget,\n RuntimeTargetOptions,\n} from \"../headless/targets.js\";\n\n/** The runtime surface of `dragFeature` that a gesture needs. */\nexport interface GestureDrag {\n readonly active: { readonly target: RuntimeDropTarget | null } | null;\n getCanDrag(cardId: string, options?: RuntimeTargetOptions): boolean;\n getDropTargets(): readonly RuntimeDropTarget[];\n begin(cardId: string, options?: RuntimeTargetOptions): boolean;\n setDropTarget(target: RuntimeDropTarget | null): void;\n drop(): void;\n cancel(): void;\n}\nexport interface GestureGame {\n readonly drag?: GestureDrag;\n readonly request: unknown;\n subscribe(listener: () => void): () => void;\n}\n\nexport interface GestureState {\n readonly drag: {\n readonly cardId: string;\n /** Pointer offset inside the card where it was picked up. */\n readonly grab: Point;\n readonly size: { readonly width: number; readonly height: number };\n /** Dropped and submitted; waiting for the authoritative frame. */\n readonly settling: boolean;\n } | null;\n readonly inspect: {\n readonly cardId: string;\n readonly via: \"hold\" | \"hover\";\n } | null;\n}\n\nexport interface CardGestureProps {\n onPointerDown(event: PointerEvent<Element>): void;\n onPointerEnter(event: PointerEvent<Element>): void;\n onPointerLeave(event: PointerEvent<Element>): void;\n onContextMenu(event: MouseEvent<Element>): void;\n onDragStart(event: DragEvent<Element>): void;\n readonly style: CSSProperties;\n readonly \"data-dragging\"?: true;\n readonly \"data-inspecting\"?: \"hold\" | \"hover\";\n}\n\nconst CARD_STYLE: CSSProperties = Object.freeze({\n // Sideways movement stays native scrolling; everything else reaches the recognizer.\n touchAction: \"pan-x\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n WebkitTouchCallout: \"none\",\n});\nconst px = (value: number) => `${value}px`;\n\n/** A resolved board destination, or the interaction an area runs. */\nexport type DropAreaInput =\n | RuntimeDropTarget\n | { readonly interaction: string; readonly input?: string }\n | null;\n\nexport function resolveDropArea(\n drag: GestureDrag | undefined,\n binding: DropAreaInput,\n): RuntimeDropTarget | null {\n if (!drag || !binding) return null;\n if (\"interactionKey\" in binding) return binding;\n const matches = drag\n .getDropTargets()\n .filter(\n (target) =>\n target.kind === \"interaction\" &&\n target.interactionKey === binding.interaction &&\n (!binding.input || target.cardInputKey === binding.input),\n );\n // Two card inputs on one interaction need an explicit `input`.\n return matches.length === 1 ? matches[0] : null;\n}\n/** Targets are rebuilt with every drag update; compare what they route. */\nexport const sameDropTarget = (\n left: RuntimeDropTarget | null,\n right: RuntimeDropTarget | null,\n) => left === right || (!!left && !!right && isSameDropTarget(left, right));\nlet sessions = 0;\n\nexport type GestureSession = ReturnType<typeof createGestureSession>;\n\n/**\n * One press at a time for a provider: tap, hold, drag or browse, plus mouse\n * hover intent. The session outlives the pressed element, so a hand may move\n * the card into an overlay mid-drag. Drop areas are found with the browser's\n * own hit testing, so transformed and SVG areas need no geometry.\n */\nexport function createGestureSession(game: GestureGame) {\n const id = `g${++sessions}`;\n const store = createStore<GestureState>({ drag: null, inspect: null });\n const areas = new Map<string, () => DropAreaInput>();\n const followers = new Set<(point: Point) => void>();\n let press: {\n readonly recognizer: GestureRecognizer;\n readonly pointerType: string;\n readonly detach: () => void;\n dragging: boolean;\n area: string | null;\n target: RuntimeDropTarget | null;\n } | null = null;\n let hover: { cardId: string; timer: ReturnType<typeof setTimeout> } | null =\n null;\n let pointer: Point = { x: 0, y: 0 };\n let swallowing = false;\n let guardingClicks = false;\n let disposed = false;\n\n const set = (patch: Partial<GestureState>) =>\n store.setState((previous) => ({ ...previous, ...patch }));\n\n const unsubscribe = game.subscribe(() => {\n // New frames, seats and sources cancel the semantic drag; end the press with it.\n if (press?.dragging && !game.drag?.active) press.recognizer.cancel();\n const drag = store.get().drag;\n if (drag?.settling && game.request === null) set({ drag: null });\n });\n\n function hitArea(at: Point): string | null {\n for (const element of document.elementsFromPoint(at.x, at.y)) {\n if (element.closest(\"[data-drag-overlay]\")) continue;\n const area = element.closest(\"[data-drop-area]\");\n if (area) return area.getAttribute(\"data-drop-area\");\n }\n return null;\n }\n function retarget(at: Point) {\n if (!press?.dragging) return;\n const area = hitArea(at);\n const read = area === null ? undefined : areas.get(area);\n const target = read ? resolveDropArea(game.drag, read()) : null;\n if (area === press.area && sameDropTarget(target, press.target)) return;\n press.area = area;\n press.target = target;\n game.drag?.setDropTarget(target);\n }\n // Keyboard clicks (detail 0) and clicks from a new press are never swallowed.\n function swallow(event: globalThis.MouseEvent) {\n if (!swallowing || event.detail === 0) return;\n swallowing = false;\n event.stopPropagation();\n event.preventDefault();\n }\n function newPress() {\n swallowing = false;\n }\n /** A non-tap stays suppressed until its click or a new press, even after cancellation. */\n function swallowNextClick() {\n swallowing = true;\n if (guardingClicks) return;\n guardingClicks = true;\n addEventListener(\"click\", swallow, true);\n addEventListener(\"pointerdown\", newPress, true);\n }\n function clearHover() {\n if (hover) clearTimeout(hover.timer);\n hover = null;\n }\n function release() {\n press?.detach();\n press = null;\n }\n\n function start(\n event: globalThis.PointerEvent,\n cardId: string,\n element: Element,\n options?: RuntimeTargetOptions,\n ) {\n if (disposed || press || event.button !== 0) return;\n const recognizer = createGestureRecognizer(event, {\n hold() {\n set({ inspect: { cardId, via: \"hold\" } });\n },\n dragStart(origin) {\n if (!game.drag?.begin(cardId, options)) return false;\n const box = element.getBoundingClientRect();\n clearHover();\n press!.dragging = true;\n set({\n drag: {\n cardId,\n grab: { x: origin.x - box.left, y: origin.y - box.top },\n size: { width: box.width, height: box.height },\n settling: false,\n },\n inspect: null,\n });\n return true;\n },\n dragMove(at) {\n pointer = at;\n for (const follow of followers) follow(at);\n retarget(at);\n },\n end(kind, at) {\n const dragging = press!.dragging;\n if (dragging) retarget(at);\n release();\n if (kind !== \"tap\") swallowNextClick();\n if (kind === \"hold\") set({ inspect: null });\n if (!dragging) return;\n const before = game.request;\n game.drag?.drop();\n // A submitted move keeps its overlay until the authoritative frame.\n const drag = store.get().drag;\n if (drag && game.request !== null && game.request !== before)\n set({ drag: { ...drag, settling: true } });\n else set({ drag: null });\n },\n cancel(kind) {\n const dragging = press!.dragging;\n release();\n // Cancellation does not turn a non-tap into a selection on release.\n if (kind !== \"tap\") swallowNextClick();\n if (kind === \"hold\") set({ inspect: null });\n if (dragging) {\n game.drag?.cancel();\n set({ drag: null });\n }\n },\n });\n const move = (next: globalThis.PointerEvent) => recognizer.move(next);\n const up = (next: globalThis.PointerEvent) => recognizer.up(next);\n const cancel = (next: globalThis.PointerEvent) => recognizer.cancel(next);\n const blur = () => recognizer.cancel();\n addEventListener(\"pointermove\", move);\n addEventListener(\"pointerup\", up);\n addEventListener(\"pointercancel\", cancel);\n addEventListener(\"blur\", blur);\n if (event.pointerType === \"mouse\") {\n // A mouse keeps reporting outside the card; touch is captured implicitly.\n try {\n element.setPointerCapture(event.pointerId);\n } catch {\n // The pointer may already be gone.\n }\n }\n press = {\n recognizer,\n pointerType: event.pointerType,\n dragging: false,\n area: null,\n target: null,\n detach() {\n removeEventListener(\"pointermove\", move);\n removeEventListener(\"pointerup\", up);\n removeEventListener(\"pointercancel\", cancel);\n removeEventListener(\"blur\", blur);\n },\n };\n }\n\n function cardProps(\n cardId: string,\n options: RuntimeTargetOptions | undefined,\n flags: { dragging: boolean; inspecting: \"hold\" | \"hover\" | null },\n ): CardGestureProps {\n return {\n onPointerDown: (event) =>\n start(event.nativeEvent, cardId, event.currentTarget, options),\n onPointerEnter(event) {\n if (event.pointerType !== \"mouse\" || press?.dragging) return;\n clearHover();\n hover = {\n cardId,\n timer: setTimeout(\n () => set({ inspect: { cardId, via: \"hover\" } }),\n GESTURE_THRESHOLDS.hoverMs,\n ),\n };\n },\n onPointerLeave() {\n if (hover?.cardId === cardId) clearHover();\n const inspect = store.get().inspect;\n if (inspect?.cardId === cardId && inspect.via === \"hover\")\n set({ inspect: null });\n },\n onContextMenu(event) {\n // A long press must inspect the card, not open the browser's menu.\n if ((press && press.pointerType !== \"mouse\") || swallowing)\n event.preventDefault();\n },\n onDragStart: (event) => event.preventDefault(),\n style: CARD_STYLE,\n \"data-dragging\": flags.dragging || undefined,\n \"data-inspecting\": flags.inspecting ?? undefined,\n };\n }\n\n /** Positions the dragged card's overlay without rendering on each move. */\n function overlayRef(element: HTMLElement | null) {\n const drag = store.get().drag;\n if (!element || !drag) return;\n element.setAttribute(\"data-drag-overlay\", \"\");\n Object.assign(element.style, {\n position: \"fixed\",\n margin: \"0\",\n pointerEvents: \"none\",\n width: px(drag.size.width),\n height: px(drag.size.height),\n });\n const follow = (at: Point) => {\n element.style.left = px(at.x - drag.grab.x);\n element.style.top = px(at.y - drag.grab.y);\n };\n follow(pointer);\n followers.add(follow);\n return () => {\n followers.delete(follow);\n };\n }\n\n return {\n id,\n store,\n cardProps,\n overlayRef,\n /** `read` returns the area's current binding; targets resolve when hit. */\n registerArea(area: string, read: () => DropAreaInput) {\n areas.set(area, read);\n return () => {\n areas.delete(area);\n };\n },\n dispose() {\n disposed = true;\n press?.recognizer.cancel();\n clearHover();\n unsubscribe();\n followers.clear();\n if (!guardingClicks) return;\n removeEventListener(\"click\", swallow, true);\n removeEventListener(\"pointerdown\", newPress, true);\n },\n };\n}\n\nexport const GestureContext = createContext<GestureSession | null>(null);\n\nexport function useGestureSession(): GestureSession {\n const session = useContext(GestureContext);\n if (!session) throw new Error(\"Gesture hooks require their GameProvider.\");\n return session;\n}\n\nexport function useGestureState<Value>(\n session: GestureSession,\n select: (state: GestureState) => Value,\n): Value {\n return useSelector(session.store, select);\n}\n","import {\n createGestureSession,\n resolveDropArea,\n sameDropTarget,\n GestureContext,\n useGestureSession,\n useGestureState,\n type CardGestureProps,\n type DropAreaInput,\n type GestureGame,\n type GestureSession,\n} from \"./gesture.js\";\nimport type { SeatCardId } from \"../headless/model.js\";\nimport type {\n DropTarget,\n RuntimeTargetOptions,\n TargetOptions,\n} from \"../headless/targets.js\";\nimport {\n createContext,\n useContext,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { useSelector } from \"@tanstack/react-store\";\nimport { createGameInstance } from \"../headless/instance.js\";\nimport type {\n CoreInstance,\n FeatureContext,\n Features,\n GameInstance,\n GameSnapshot,\n GameSource,\n InstanceOptions,\n} from \"../headless/model.js\";\n\nexport interface SelectionOptions<Value> {\n readonly compare?: (previous: Value, next: Value) => boolean;\n}\n\n/** An area that runs this interaction with whichever card is dropped on it. */\nexport type DropAreaBinding<G> = Exclude<\n TargetOptions<G>,\n { readonly interaction?: undefined }\n>;\n\nexport interface CardGesture {\n /** Spread on the card's own control, after the card's selection props. */\n readonly props: CardGestureProps;\n readonly canDrag: boolean;\n readonly isDragging: boolean;\n /** Held on touch, or rested on with a mouse. */\n readonly inspecting: \"hold\" | \"hover\" | null;\n}\n\nexport interface DropArea {\n readonly props: {\n readonly \"data-drop-area\": string;\n readonly \"data-drop-target\"?: \"true\";\n readonly \"data-drop-over\"?: true;\n };\n readonly isEligible: boolean;\n readonly isOver: boolean;\n}\n\nexport interface DragOverlay<G> {\n readonly cardId: SeatCardId<G>;\n /** Dropped and submitted; the authoritative frame has not arrived yet. */\n readonly settling: boolean;\n /** Attach to a fixed-position copy of the card; it follows the pointer. */\n readonly ref: (element: HTMLElement | null) => (() => void) | undefined;\n}\n\n/** Bind erased game types and features; each provider owns its source lifetime. */\nexport function createGameHook<Game, Source extends GameSource = GameSource>() {\n return function <const Enabled extends Features = Record<never, never>>(\n defaults: Omit<InstanceOptions<Game, Source>, \"source\"> & {\n features?: (\n core: CoreInstance<Game>,\n context: FeatureContext<Game>,\n ) => Enabled;\n },\n ) {\n type Instance = GameInstance<Game, Enabled, Source>;\n type Snapshot = GameSnapshot<Game, Enabled>;\n type ProviderProps = Partial<\n Omit<InstanceOptions<Game, Source>, \"source\">\n > & {\n source: Source;\n children?: ReactNode;\n };\n const Context = createContext<Instance | null>(null);\n\n /** Owns the source. Do not share it between independently mounted providers. */\n function GameProvider({ children, ...overrides }: ProviderProps) {\n const [owned, setOwned] = useState<{\n instance: Instance;\n session: GestureSession;\n } | null>(null);\n const lifetime = useRef<{\n instance: Instance;\n session: GestureSession;\n generation: number;\n } | null>(null);\n const options = {\n ...defaults,\n ...overrides,\n };\n useLayoutEffect(() => {\n let current = lifetime.current;\n if (!current) {\n const instance = createGameInstance<Game>()(options);\n current = {\n instance,\n session: createGestureSession(instance),\n generation: 0,\n };\n lifetime.current = current;\n setOwned({ instance, session: current.session });\n }\n const owned = current;\n ++owned.generation;\n return () => {\n const generation = ++owned.generation;\n queueMicrotask(() => {\n if (owned.generation !== generation) return;\n owned.session.dispose();\n owned.instance.dispose();\n if (lifetime.current === owned) lifetime.current = null;\n });\n };\n // Construction belongs to this committed provider lifetime. Current\n // options are installed separately without recreating features.\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Construct once per committed provider lifetime; the next effect updates options.\n }, []);\n useLayoutEffect(() => {\n lifetime.current?.instance.setOptions(options);\n });\n return owned ? (\n <Context.Provider value={owned.instance}>\n <GestureContext.Provider value={owned.session}>\n {children}\n </GestureContext.Provider>\n </Context.Provider>\n ) : null;\n }\n\n function useInstance(): Instance {\n const instance = useContext(Context);\n if (!instance) throw new Error(\"useGame requires its GameProvider.\");\n return instance;\n }\n\n function useGame(): Instance;\n function useGame<Value>(\n selector: (snapshot: Snapshot) => Value,\n options?: SelectionOptions<Value>,\n ): Value;\n function useGame<Value>(\n selector?: (snapshot: Snapshot) => Value,\n options?: SelectionOptions<Value>,\n ): Instance | Value {\n const instance = useInstance();\n const selected = useSelector(\n instance.store,\n (snapshot): { value: Value } | { snapshot: Snapshot } =>\n selector ? { value: selector(snapshot) } : { snapshot },\n {\n compare: (previous, next) =>\n \"value\" in previous && \"value\" in next\n ? (options?.compare ?? Object.is)(previous.value, next.value)\n : \"snapshot\" in previous &&\n \"snapshot\" in next &&\n Object.is(previous.snapshot, next.snapshot),\n },\n );\n return \"value\" in selected ? selected.value : instance;\n }\n\n function Subscribe<Value>({\n selector,\n compare,\n children,\n }: {\n selector: (snapshot: Snapshot) => Value;\n compare?: SelectionOptions<Value>[\"compare\"];\n children: (value: Value) => ReactNode;\n }) {\n return children(useGame(selector, { compare }));\n }\n\n // Game-binding boundary: typed ids and routes cross into the erased session.\n const dragOf = (snapshot: Snapshot) =>\n (snapshot as Pick<GestureGame, \"drag\">).drag;\n\n /** Tap, hold, drag and browse on one card; hover intent with a mouse. */\n function useCardGesture(\n cardId: SeatCardId<Game>,\n options?: TargetOptions<Game>,\n ): CardGesture {\n const session = useGestureSession();\n const routes = options as RuntimeTargetOptions | undefined;\n const canDrag = useGame(\n (snapshot) => dragOf(snapshot)?.getCanDrag(cardId, routes) ?? false,\n );\n const dragging = useGestureState(\n session,\n (state) => state.drag?.cardId === cardId,\n );\n const inspecting = useGestureState(session, (state) =>\n state.inspect?.cardId === cardId ? state.inspect.via : null,\n );\n return {\n props: session.cardProps(cardId, routes, { dragging, inspecting }),\n canDrag,\n isDragging: dragging,\n inspecting,\n };\n }\n\n /**\n * Marks an element where a dragged card can land: a board destination,\n * or an area that runs an interaction with the dropped card.\n */\n function useDropArea(\n binding: DropTarget<Game> | DropAreaBinding<Game> | null,\n ): DropArea {\n const session = useGestureSession();\n const id = `${session.id}${useId()}`;\n const erased = binding as DropAreaInput;\n const target = useGame(\n (snapshot) => resolveDropArea(dragOf(snapshot), erased),\n { compare: sameDropTarget },\n );\n const isOver = useGame((snapshot) => {\n const active = dragOf(snapshot)?.active?.target;\n return !!target && sameDropTarget(active ?? null, target);\n });\n const latest = useRef(erased);\n useLayoutEffect(() => {\n latest.current = erased;\n });\n useLayoutEffect(\n () => session.registerArea(id, () => latest.current),\n [session, id],\n );\n return {\n props: {\n \"data-drop-area\": id,\n \"data-drop-target\": target ? \"true\" : undefined,\n \"data-drop-over\": isOver || undefined,\n },\n isEligible: target !== null,\n isOver,\n };\n }\n\n /** The card being dragged, and a ref that keeps its copy under the pointer. */\n function useDragOverlay(): DragOverlay<Game> | null {\n const session = useGestureSession();\n const drag = useGestureState(session, (state) => state.drag);\n return drag\n ? {\n cardId: drag.cardId as SeatCardId<Game>,\n settling: drag.settling,\n ref: session.overlayRef,\n }\n : null;\n }\n\n return {\n GameProvider,\n useGame,\n Subscribe,\n useCardGesture,\n useDropArea,\n useDragOverlay,\n };\n };\n}\n"],"mappings":"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","names":["createContext","useContext","useSelector","createContext","owned","useContext","useSelector"]}
1
+ {"version":3,"sources":["../src/react/gesture.tsx","../src/react/create-game-hook.tsx"],"sourcesContent":["import { createStore } from \"@tanstack/store\";\nimport { useSelector } from \"@tanstack/react-store\";\nimport {\n createContext,\n useContext,\n type CSSProperties,\n type DragEvent,\n type MouseEvent,\n type PointerEvent,\n} from \"react\";\nimport {\n createGestureRecognizer,\n GESTURE_THRESHOLDS,\n type GestureRecognizer,\n} from \"../headless/gesture.js\";\nimport { isSameDropTarget } from \"../headless/drop-targets.js\";\nimport type { Point } from \"../headless/features/pointer-session.js\";\nimport type {\n RuntimeDropTarget,\n RuntimeTargetOptions,\n} from \"../headless/targets.js\";\n\n/** The runtime surface of `dragFeature` that a gesture needs. */\nexport interface GestureDrag {\n readonly active: { readonly target: RuntimeDropTarget | null } | null;\n getCanDrag(cardId: string, options?: RuntimeTargetOptions): boolean;\n getDropTargets(): readonly RuntimeDropTarget[];\n begin(cardId: string, options?: RuntimeTargetOptions): boolean;\n setDropTarget(target: RuntimeDropTarget | null): void;\n drop(): void;\n cancel(): void;\n}\nexport interface GestureGame {\n readonly drag?: GestureDrag;\n readonly request: unknown;\n subscribe(listener: () => void): () => void;\n}\n\nexport interface GestureState {\n readonly drag: {\n readonly cardId: string;\n /** Pointer offset inside the card where it was picked up. */\n readonly grab: Point;\n readonly size: { readonly width: number; readonly height: number };\n /** Dropped and submitted; waiting for the authoritative frame. */\n readonly settling: boolean;\n } | null;\n readonly inspect: {\n readonly cardId: string;\n readonly via: \"hold\" | \"hover\";\n } | null;\n}\n\nexport interface CardGestureProps {\n onPointerDown(event: PointerEvent<Element>): void;\n onPointerEnter(event: PointerEvent<Element>): void;\n onPointerLeave(event: PointerEvent<Element>): void;\n onContextMenu(event: MouseEvent<Element>): void;\n onDragStart(event: DragEvent<Element>): void;\n readonly style: CSSProperties;\n readonly \"data-dragging\"?: true;\n readonly \"data-inspecting\"?: \"hold\" | \"hover\";\n}\n\nconst CARD_STYLE: CSSProperties = Object.freeze({\n // Sideways movement stays native scrolling; everything else reaches the recognizer.\n touchAction: \"pan-x\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n WebkitTouchCallout: \"none\",\n});\nconst INSPECTION_STYLE: CSSProperties = Object.freeze({\n ...CARD_STYLE,\n // Inspection-only cards should not block their table's native scrolling.\n touchAction: \"manipulation\",\n});\nconst px = (value: number) => `${value}px`;\n\n/** A resolved board destination, or the interaction an area runs. */\nexport type DropAreaInput =\n | RuntimeDropTarget\n | { readonly interaction: string; readonly input?: string }\n | null;\n\nexport function resolveDropArea(\n drag: GestureDrag | undefined,\n binding: DropAreaInput,\n): RuntimeDropTarget | null {\n if (!drag || !binding) return null;\n if (\"interactionKey\" in binding) return binding;\n const matches = drag\n .getDropTargets()\n .filter(\n (target) =>\n target.kind === \"interaction\" &&\n target.interactionKey === binding.interaction &&\n (!binding.input || target.cardInputKey === binding.input),\n );\n // Two card inputs on one interaction need an explicit `input`.\n return matches.length === 1 ? matches[0] : null;\n}\n/** Targets are rebuilt with every drag update; compare what they route. */\nexport const sameDropTarget = (\n left: RuntimeDropTarget | null,\n right: RuntimeDropTarget | null,\n) => left === right || (!!left && !!right && isSameDropTarget(left, right));\nlet sessions = 0;\n\nexport type GestureSession = ReturnType<typeof createGestureSession>;\n\n/**\n * One press at a time for a provider: tap, hold, drag or browse, plus mouse\n * hover intent. The session outlives the pressed element, so a hand may move\n * the card into an overlay mid-drag. Drop areas are found with the browser's\n * own hit testing, so transformed and SVG areas need no geometry.\n */\nexport function createGestureSession(game: GestureGame) {\n const id = `g${++sessions}`;\n const store = createStore<GestureState>({ drag: null, inspect: null });\n const areas = new Map<string, () => DropAreaInput>();\n const followers = new Set<(point: Point) => void>();\n let press: {\n readonly recognizer: GestureRecognizer;\n readonly pointerType: string;\n readonly detach: () => void;\n dragging: boolean;\n area: string | null;\n target: RuntimeDropTarget | null;\n } | null = null;\n let hover: { cardId: string; timer: ReturnType<typeof setTimeout> } | null =\n null;\n let pointer: Point = { x: 0, y: 0 };\n let swallowing = false;\n let guardingClicks = false;\n let disposed = false;\n\n const set = (patch: Partial<GestureState>) =>\n store.setState((previous) => ({ ...previous, ...patch }));\n\n const unsubscribe = game.subscribe(() => {\n // New frames, seats and sources cancel the semantic drag; end the press with it.\n if (press?.dragging && !game.drag?.active) press.recognizer.cancel();\n const drag = store.get().drag;\n if (drag?.settling && game.request === null) set({ drag: null });\n });\n\n function hitArea(at: Point): string | null {\n for (const element of document.elementsFromPoint(at.x, at.y)) {\n if (element.closest(\"[data-drag-overlay]\")) continue;\n const area = element.closest(\"[data-drop-area]\");\n if (area) return area.getAttribute(\"data-drop-area\");\n }\n return null;\n }\n function retarget(at: Point) {\n if (!press?.dragging) return;\n const area = hitArea(at);\n const read = area === null ? undefined : areas.get(area);\n const target = read ? resolveDropArea(game.drag, read()) : null;\n if (area === press.area && sameDropTarget(target, press.target)) return;\n press.area = area;\n press.target = target;\n game.drag?.setDropTarget(target);\n }\n // Keyboard clicks (detail 0) and clicks from a new press are never swallowed.\n function swallow(event: globalThis.MouseEvent) {\n if (!swallowing || event.detail === 0) return;\n swallowing = false;\n event.stopPropagation();\n event.preventDefault();\n }\n function newPress() {\n swallowing = false;\n }\n /** A non-tap stays suppressed until its click or a new press, even after cancellation. */\n function swallowNextClick() {\n swallowing = true;\n if (guardingClicks) return;\n guardingClicks = true;\n addEventListener(\"click\", swallow, true);\n addEventListener(\"pointerdown\", newPress, true);\n }\n function clearHover() {\n if (hover) clearTimeout(hover.timer);\n hover = null;\n }\n function release() {\n press?.detach();\n press = null;\n }\n\n function start(\n event: globalThis.PointerEvent,\n cardId: string,\n element: Element,\n options: false | RuntimeTargetOptions,\n ) {\n if (disposed || press || event.button !== 0) return;\n const recognizer = createGestureRecognizer(event, {\n hold() {\n set({ inspect: { cardId, via: \"hold\" } });\n },\n dragStart(origin) {\n if (options === false || !game.drag?.begin(cardId, options))\n return false;\n const box = element.getBoundingClientRect();\n clearHover();\n press!.dragging = true;\n set({\n drag: {\n cardId,\n grab: { x: origin.x - box.left, y: origin.y - box.top },\n size: { width: box.width, height: box.height },\n settling: false,\n },\n inspect: null,\n });\n return true;\n },\n dragMove(at) {\n pointer = at;\n for (const follow of followers) follow(at);\n retarget(at);\n },\n end(kind, at) {\n const dragging = press!.dragging;\n if (dragging) retarget(at);\n release();\n if (kind !== \"tap\") swallowNextClick();\n if (kind === \"hold\") set({ inspect: null });\n if (!dragging) return;\n const before = game.request;\n game.drag?.drop();\n // A submitted move keeps its overlay until the authoritative frame.\n const drag = store.get().drag;\n if (drag && game.request !== null && game.request !== before)\n set({ drag: { ...drag, settling: true } });\n else set({ drag: null });\n },\n cancel(kind) {\n const dragging = press!.dragging;\n release();\n // Cancellation does not turn a non-tap into a selection on release.\n if (kind !== \"tap\") swallowNextClick();\n if (kind === \"hold\") set({ inspect: null });\n if (dragging) {\n game.drag?.cancel();\n set({ drag: null });\n }\n },\n });\n const move = (next: globalThis.PointerEvent) => recognizer.move(next);\n const up = (next: globalThis.PointerEvent) => recognizer.up(next);\n const cancel = (next: globalThis.PointerEvent) => recognizer.cancel(next);\n const blur = () => recognizer.cancel();\n addEventListener(\"pointermove\", move);\n addEventListener(\"pointerup\", up);\n addEventListener(\"pointercancel\", cancel);\n addEventListener(\"blur\", blur);\n if (event.pointerType === \"mouse\") {\n // A mouse keeps reporting outside the card; touch is captured implicitly.\n try {\n element.setPointerCapture(event.pointerId);\n } catch {\n // The pointer may already be gone.\n }\n }\n press = {\n recognizer,\n pointerType: event.pointerType,\n dragging: false,\n area: null,\n target: null,\n detach() {\n removeEventListener(\"pointermove\", move);\n removeEventListener(\"pointerup\", up);\n removeEventListener(\"pointercancel\", cancel);\n removeEventListener(\"blur\", blur);\n },\n };\n }\n\n function cardProps(\n cardId: string,\n options: false | RuntimeTargetOptions,\n flags: { dragging: boolean; inspecting: \"hold\" | \"hover\" | null },\n ): CardGestureProps {\n return {\n onPointerDown: (event) =>\n start(event.nativeEvent, cardId, event.currentTarget, options),\n onPointerEnter(event) {\n if (event.pointerType !== \"mouse\" || press?.dragging) return;\n clearHover();\n hover = {\n cardId,\n timer: setTimeout(\n () => set({ inspect: { cardId, via: \"hover\" } }),\n GESTURE_THRESHOLDS.hoverMs,\n ),\n };\n },\n onPointerLeave() {\n if (hover?.cardId === cardId) clearHover();\n const inspect = store.get().inspect;\n if (inspect?.cardId === cardId && inspect.via === \"hover\")\n set({ inspect: null });\n },\n onContextMenu(event) {\n // A long press must inspect the card, not open the browser's menu.\n if ((press && press.pointerType !== \"mouse\") || swallowing)\n event.preventDefault();\n },\n onDragStart: (event) => event.preventDefault(),\n style: options === false ? INSPECTION_STYLE : CARD_STYLE,\n \"data-dragging\": flags.dragging || undefined,\n \"data-inspecting\": flags.inspecting ?? undefined,\n };\n }\n\n /** Positions the dragged card's overlay without rendering on each move. */\n function overlayRef(element: HTMLElement | null) {\n const drag = store.get().drag;\n if (!element || !drag) return;\n element.setAttribute(\"data-drag-overlay\", \"\");\n Object.assign(element.style, {\n position: \"fixed\",\n margin: \"0\",\n pointerEvents: \"none\",\n width: px(drag.size.width),\n height: px(drag.size.height),\n });\n const follow = (at: Point) => {\n element.style.left = px(at.x - drag.grab.x);\n element.style.top = px(at.y - drag.grab.y);\n };\n follow(pointer);\n followers.add(follow);\n return () => {\n followers.delete(follow);\n };\n }\n\n return {\n id,\n store,\n cardProps,\n overlayRef,\n /** `read` returns the area's current binding; targets resolve when hit. */\n registerArea(area: string, read: () => DropAreaInput) {\n areas.set(area, read);\n return () => {\n areas.delete(area);\n };\n },\n dispose() {\n disposed = true;\n press?.recognizer.cancel();\n clearHover();\n unsubscribe();\n followers.clear();\n if (!guardingClicks) return;\n removeEventListener(\"click\", swallow, true);\n removeEventListener(\"pointerdown\", newPress, true);\n },\n };\n}\n\nexport const GestureContext = createContext<GestureSession | null>(null);\n\nexport function useGestureSession(): GestureSession {\n const session = useContext(GestureContext);\n if (!session) throw new Error(\"Gesture hooks require their GameProvider.\");\n return session;\n}\n\nexport function useGestureState<Value>(\n session: GestureSession,\n select: (state: GestureState) => Value,\n): Value {\n return useSelector(session.store, select);\n}\n","import {\n createGestureSession,\n resolveDropArea,\n sameDropTarget,\n GestureContext,\n useGestureSession,\n useGestureState,\n type CardGestureProps,\n type DropAreaInput,\n type GestureGame,\n type GestureSession,\n} from \"./gesture.js\";\nimport type { SeatCardId } from \"../headless/model.js\";\nimport type {\n DropTarget,\n RuntimeTargetOptions,\n TargetOptions,\n} from \"../headless/targets.js\";\nimport {\n createContext,\n useContext,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { useSelector } from \"@tanstack/react-store\";\nimport { createGameInstance } from \"../headless/instance.js\";\nimport type {\n CoreInstance,\n FeatureContext,\n Features,\n GameInstance,\n GameSnapshot,\n GameSource,\n InstanceOptions,\n} from \"../headless/model.js\";\n\nexport interface SelectionOptions<Value> {\n readonly compare?: (previous: Value, next: Value) => boolean;\n}\n\n/** Inspection stays enabled when this control does not support dragging. */\nexport interface CardGestureOptions<Game> {\n readonly drag: false | TargetOptions<Game>;\n}\n\n/** An area that runs this interaction with whichever card is dropped on it. */\nexport type DropAreaBinding<G> = Exclude<\n TargetOptions<G>,\n { readonly interaction?: undefined }\n>;\n\nexport interface CardGesture {\n /** Spread on the card's own control, after the card's selection props. */\n readonly props: CardGestureProps;\n readonly canDrag: boolean;\n readonly isDragging: boolean;\n /** Held on touch, or rested on with a mouse. */\n readonly inspecting: \"hold\" | \"hover\" | null;\n}\n\nexport interface DropArea {\n readonly props: {\n readonly \"data-drop-area\": string;\n readonly \"data-drop-target\"?: \"true\";\n readonly \"data-drop-over\"?: true;\n };\n readonly isEligible: boolean;\n readonly isOver: boolean;\n}\n\nexport interface DragOverlay<G> {\n readonly cardId: SeatCardId<G>;\n /** Dropped and submitted; the authoritative frame has not arrived yet. */\n readonly settling: boolean;\n /** Attach to a fixed-position copy of the card; it follows the pointer. */\n readonly ref: (element: HTMLElement | null) => (() => void) | undefined;\n}\n\n/** Bind erased game types and features; each provider owns its source lifetime. */\nexport function createGameHook<Game, Source extends GameSource = GameSource>() {\n return function <const Enabled extends Features = Record<never, never>>(\n defaults: Omit<InstanceOptions<Game, Source>, \"source\"> & {\n features?: (\n core: CoreInstance<Game>,\n context: FeatureContext<Game>,\n ) => Enabled;\n },\n ) {\n type Instance = GameInstance<Game, Enabled, Source>;\n type Snapshot = GameSnapshot<Game, Enabled>;\n type ProviderProps = Partial<\n Omit<InstanceOptions<Game, Source>, \"source\">\n > & {\n source: Source;\n children?: ReactNode;\n };\n const Context = createContext<Instance | null>(null);\n\n /** Owns the source. Do not share it between independently mounted providers. */\n function GameProvider({ children, ...overrides }: ProviderProps) {\n const [owned, setOwned] = useState<{\n instance: Instance;\n session: GestureSession;\n } | null>(null);\n const lifetime = useRef<{\n instance: Instance;\n session: GestureSession;\n generation: number;\n } | null>(null);\n const options = {\n ...defaults,\n ...overrides,\n };\n useLayoutEffect(() => {\n let current = lifetime.current;\n if (!current) {\n const instance = createGameInstance<Game>()(options);\n current = {\n instance,\n session: createGestureSession(instance),\n generation: 0,\n };\n lifetime.current = current;\n setOwned({ instance, session: current.session });\n }\n const owned = current;\n ++owned.generation;\n return () => {\n const generation = ++owned.generation;\n queueMicrotask(() => {\n if (owned.generation !== generation) return;\n owned.session.dispose();\n owned.instance.dispose();\n if (lifetime.current === owned) lifetime.current = null;\n });\n };\n // Construction belongs to this committed provider lifetime. Current\n // options are installed separately without recreating features.\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Construct once per committed provider lifetime; the next effect updates options.\n }, []);\n useLayoutEffect(() => {\n lifetime.current?.instance.setOptions(options);\n });\n return owned ? (\n <Context.Provider value={owned.instance}>\n <GestureContext.Provider value={owned.session}>\n {children}\n </GestureContext.Provider>\n </Context.Provider>\n ) : null;\n }\n\n function useInstance(): Instance {\n const instance = useContext(Context);\n if (!instance) throw new Error(\"useGame requires its GameProvider.\");\n return instance;\n }\n\n function useGame(): Instance;\n function useGame<Value>(\n selector: (snapshot: Snapshot) => Value,\n options?: SelectionOptions<Value>,\n ): Value;\n function useGame<Value>(\n selector?: (snapshot: Snapshot) => Value,\n options?: SelectionOptions<Value>,\n ): Instance | Value {\n const instance = useInstance();\n const selected = useSelector(\n instance.store,\n (snapshot): { value: Value } | { snapshot: Snapshot } =>\n selector ? { value: selector(snapshot) } : { snapshot },\n {\n compare: (previous, next) =>\n \"value\" in previous && \"value\" in next\n ? (options?.compare ?? Object.is)(previous.value, next.value)\n : \"snapshot\" in previous &&\n \"snapshot\" in next &&\n Object.is(previous.snapshot, next.snapshot),\n },\n );\n return \"value\" in selected ? selected.value : instance;\n }\n\n function Subscribe<Value>({\n selector,\n compare,\n children,\n }: {\n selector: (snapshot: Snapshot) => Value;\n compare?: SelectionOptions<Value>[\"compare\"];\n children: (value: Value) => ReactNode;\n }) {\n return children(useGame(selector, { compare }));\n }\n\n // Game-binding boundary: typed ids and routes cross into the erased session.\n const dragOf = (snapshot: Snapshot) =>\n (snapshot as Pick<GestureGame, \"drag\">).drag;\n\n /** Tap, hold, drag and browse on one card; hover intent with a mouse. */\n function useCardGesture(\n cardId: SeatCardId<Game>,\n options: CardGestureOptions<Game>,\n ): CardGesture {\n const session = useGestureSession();\n const routes = options.drag as false | RuntimeTargetOptions;\n const canDrag = useGame(\n (snapshot) =>\n routes !== false &&\n (dragOf(snapshot)?.getCanDrag(cardId, routes) ?? false),\n );\n const dragging = useGestureState(\n session,\n (state) => state.drag?.cardId === cardId,\n );\n const inspecting = useGestureState(session, (state) =>\n state.inspect?.cardId === cardId ? state.inspect.via : null,\n );\n return {\n props: session.cardProps(cardId, routes, { dragging, inspecting }),\n canDrag,\n isDragging: dragging,\n inspecting,\n };\n }\n\n /**\n * Marks an element where a dragged card can land: a board destination,\n * or an area that runs an interaction with the dropped card.\n */\n function useDropArea(\n binding: DropTarget<Game> | DropAreaBinding<Game> | null,\n ): DropArea {\n const session = useGestureSession();\n const id = `${session.id}${useId()}`;\n const erased = binding as DropAreaInput;\n const target = useGame(\n (snapshot) => resolveDropArea(dragOf(snapshot), erased),\n { compare: sameDropTarget },\n );\n const isOver = useGame((snapshot) => {\n const active = dragOf(snapshot)?.active?.target;\n return !!target && sameDropTarget(active ?? null, target);\n });\n const latest = useRef(erased);\n useLayoutEffect(() => {\n latest.current = erased;\n });\n useLayoutEffect(\n () => session.registerArea(id, () => latest.current),\n [session, id],\n );\n return {\n props: {\n \"data-drop-area\": id,\n \"data-drop-target\": target ? \"true\" : undefined,\n \"data-drop-over\": isOver || undefined,\n },\n isEligible: target !== null,\n isOver,\n };\n }\n\n /** The card being dragged, and a ref that keeps its copy under the pointer. */\n function useDragOverlay(): DragOverlay<Game> | null {\n const session = useGestureSession();\n const drag = useGestureState(session, (state) => state.drag);\n return drag\n ? {\n cardId: drag.cardId as SeatCardId<Game>,\n settling: drag.settling,\n ref: session.overlayRef,\n }\n : null;\n }\n\n return {\n GameProvider,\n useGame,\n Subscribe,\n useCardGesture,\n useDropArea,\n useDragOverlay,\n };\n };\n}\n"],"mappings":"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","names":["createContext","useContext","useSelector","createContext","owned","useContext","useSelector"]}
package/dist/reducer.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { a7 as ManifestIdSchema, aQ as SchemaLike, l as CollectorState, L as InputCollector, ah as PlayerIdOfState, a_ as TableQueriesOfState, az as ResourceMapDomainDescriptor, g as BoundedNumberDomainDescriptor, i as ChoiceDomainDescriptor, j as ChoiceListDomainDescriptor, n as CollectorValueWitness, m as CollectorValueOf, Q as InputSelectionDescriptor, as as ReducerManifestContractLike, aP as RuntimeTableRecord, aN as RuntimeRecord$1, aW as StateDefinition, a6 as ManifestContractOf, B as BaseGameStateOfContract, E as ErrorCodeOfContract, a$ as TiledBoardIdOfTable, aY as TableOfManifest, b2 as TiledVertexIdOfTable, b0 as TiledEdgeIdOfTable, b1 as TiledSpaceIdOfTable, c as BoardIdOfTable, aU as SpaceIdOfTable, d as BoardStateOfTable, D as DeckIdOfTable, H as HandIdOfTable, C as CardIdOfManifest, a9 as OptionsOfContract, aw as ReducerTransaction, b5 as ViewData, b6 as ViewDefinition, af as PhaseMapOf, b7 as ViewOfContract, aq as ReducerGameDefinitionInput, ap as ReducerGameDefinition, a4 as InteractionSteps, aR as ScopedPhaseState, a2 as InteractionSpec, a1 as InteractionRule, a0 as InteractionMap, ae as PhaseDefinition, w as GameTopologyManifest$2, o as DieTypeSpec$2, h as Brand, ar as ReducerManifestContract, aI as RuntimeHexBoardState, a8 as ObjectSchema, ak as PropertySchema, aL as RuntimePayload, x as HexEdgeId, z as HexVertexId, y as HexSpaceId, aO as RuntimeSquareBoardState, aH as RuntimeGenericBoardState, aD as RuntimeBoardState, aE as RuntimeCardData, aM as RuntimePieceData, aG as RuntimeDieData, aF as RuntimeComponentLocation, an as ReducerGameContract, aX as SystemActionEvent, aZ as TableQueries, ao as ReducerGameContractLike, a as BoardContainerIdOfTable, b as BoardEdgeRef, f as BoardVertexRef, a5 as JsonValue } from './extract-Bjuw_gdF.js';
2
- export { F as FrameworkErrorCodes, G as GameEvent, r as GameEventDetail, t as GameOutcome, aa as OutcomeResult, ab as OutcomeScoreComponent, ac as OutcomeStanding, ad as OutcomeTieBreak, al as ReducerAccept, at as ReducerReject, au as ReducerResult, ax as ReducerTransactionOutcome, ay as ReducerValidationResult, be as ReducerWire, bd as ReducerWireZod, aA as RotatePlayerZoneArgs, aV as SquareBoardSpec, b3 as ValidationIssue, b9 as fromCoordinates, ba as hexagon, bb as rectangle, bc as ring, bf as spiral } from './extract-Bjuw_gdF.js';
3
- import { z } from 'zod';
1
+ import { a7 as ManifestIdSchema, aQ as SchemaLike, l as CollectorState, L as InputCollector, ah as PlayerIdOfState, a_ as TableQueriesOfState, az as ResourceMapDomainDescriptor, g as BoundedNumberDomainDescriptor, i as ChoiceDomainDescriptor, j as ChoiceListDomainDescriptor, n as CollectorValueWitness, m as CollectorValueOf, Q as InputSelectionDescriptor, as as ReducerManifestContractLike, aP as RuntimeTableRecord, aN as RuntimeRecord$1, aW as StateDefinition, a6 as ManifestContractOf, B as BaseGameStateOfContract, E as ErrorCodeOfContract, a$ as TiledBoardIdOfTable, aY as TableOfManifest, b2 as TiledVertexIdOfTable, b0 as TiledEdgeIdOfTable, b1 as TiledSpaceIdOfTable, c as BoardIdOfTable, aU as SpaceIdOfTable, d as BoardStateOfTable, D as DeckIdOfTable, H as HandIdOfTable, C as CardIdOfManifest, a9 as OptionsOfContract, aw as ReducerTransaction, b5 as ViewData, b6 as ViewDefinition, af as PhaseMapOf, b7 as ViewOfContract, aq as ReducerGameDefinitionInput, ap as ReducerGameDefinition, a4 as InteractionSteps, aR as ScopedPhaseState, a2 as InteractionSpec, a1 as InteractionRule, a0 as InteractionMap, ae as PhaseDefinition, w as GameTopologyManifest$2, o as DieTypeSpec$2, h as Brand, ar as ReducerManifestContract, aI as RuntimeHexBoardState, a8 as ObjectSchema, ak as PropertySchema, aL as RuntimePayload, x as HexEdgeId, z as HexVertexId, y as HexSpaceId, aO as RuntimeSquareBoardState, aH as RuntimeGenericBoardState, aD as RuntimeBoardState, aE as RuntimeCardData, aM as RuntimePieceData, aG as RuntimeDieData, aF as RuntimeComponentLocation, an as ReducerGameContract, aX as SystemActionEvent, aZ as TableQueries, ao as ReducerGameContractLike, a as BoardContainerIdOfTable, b as BoardEdgeRef, f as BoardVertexRef, a5 as JsonValue } from './extract-CoLo4qhk.js';
2
+ export { F as FrameworkErrorCodes, G as GameEvent, r as GameEventDetail, t as GameOutcome, aa as OutcomeResult, ab as OutcomeScoreComponent, ac as OutcomeStanding, ad as OutcomeTieBreak, al as ReducerAccept, at as ReducerReject, au as ReducerResult, ax as ReducerTransactionOutcome, ay as ReducerValidationResult, be as ReducerWire, bd as ReducerWireZod, aA as RotatePlayerZoneArgs, aV as SquareBoardSpec, b3 as ValidationIssue, b9 as fromCoordinates, ba as hexagon, bb as rectangle, bc as ring, bf as spiral } from './extract-CoLo4qhk.js';
3
+ import * as z from 'zod';
4
+ import { z as z$1 } from 'zod';
4
5
  import { P as PlayerBoardSpaceTarget } from './board-target-B0QG6OYx.js';
5
- import { a as ReducerBundleContract, c as ReducerDiagnosticsSink } from './diagnostics-9gJgI85c.js';
6
- export { D as DispatchTraceSummaryEntry, M as MaybePromise, R as REDUCER_CONTRACT_VERSION, b as ReducerDiagnosticEvent, d as assertReducerBundleContract, n as noopDiagnosticsSink } from './diagnostics-9gJgI85c.js';
6
+ import { a as ReducerBundleContract, c as ReducerDiagnosticsSink } from './diagnostics-Cg5NZ7NZ.js';
7
+ export { D as DispatchTraceSummaryEntry, M as MaybePromise, R as REDUCER_CONTRACT_VERSION, b as ReducerDiagnosticEvent, d as assertReducerBundleContract, n as noopDiagnosticsSink } from './diagnostics-Cg5NZ7NZ.js';
7
8
  import 'honeycomb-grid';
8
9
 
9
10
  type DomainContext<State extends CollectorState> = {
@@ -290,7 +291,7 @@ type ContractWithPhases = AnyReducerGameContract & {
290
291
  type BoundState<Contract extends ContractWithPhases> = ContractState<Contract>;
291
292
  type BoundManifest<Contract extends ContractWithPhases> = ContractManifest<Contract>;
292
293
  type BoundTable<Contract extends ContractWithPhases> = TableOfManifest<BoundManifest<Contract>>;
293
- type BoundPhaseState<Contract extends ContractWithPhases, PhaseStateSchema extends SchemaLike<object>> = ScopedPhaseState<BoundState<Contract>, z.infer<PhaseStateSchema>>;
294
+ type BoundPhaseState<Contract extends ContractWithPhases, PhaseStateSchema extends SchemaLike<object>> = ScopedPhaseState<BoundState<Contract>, z$1.infer<PhaseStateSchema>>;
294
295
  type BoundFormInputs<Contract extends ContractWithPhases> = ReturnType<typeof formInput.forState<BoundState<Contract>>>;
295
296
  /** The selected board owns the element namespace, including generic spaces. */
296
297
  type BoundBoardInputOptions<Contract extends ContractWithPhases, BoardId, Id> = {
@@ -305,10 +306,10 @@ type PlayerBoardBaseId<Table> = {
305
306
  }[BoardIdOfTable<Table>];
306
307
  type PlayerBoardRuntimeId<Table, Base extends string> = Extract<BoardIdOfTable<Table>, `${Base}:${string}`>;
307
308
  type BoundBoardInputs<Contract extends ContractWithPhases> = {
308
- vertex<B extends TiledBoardIdOfTable<BoundTable<Contract>>>(options: BoundBoardInputOptions<Contract, B, TiledVertexIdOfTable<BoundTable<Contract>, NoInfer<B>>>): InputCollector<z.ZodString, BoundState<Contract>, "board-vertex", TiledVertexIdOfTable<BoundTable<Contract>, B>>;
309
- edge<B extends TiledBoardIdOfTable<BoundTable<Contract>>>(options: BoundBoardInputOptions<Contract, B, TiledEdgeIdOfTable<BoundTable<Contract>, NoInfer<B>>>): InputCollector<z.ZodString, BoundState<Contract>, "board-edge", TiledEdgeIdOfTable<BoundTable<Contract>, B>>;
310
- tile<B extends TiledBoardIdOfTable<BoundTable<Contract>>>(options: BoundBoardInputOptions<Contract, B, TiledSpaceIdOfTable<BoundTable<Contract>, NoInfer<B>>>): InputCollector<z.ZodString, BoundState<Contract>, "board-tile", TiledSpaceIdOfTable<BoundTable<Contract>, B>>;
311
- space<B extends BoardIdOfTable<BoundTable<Contract>>>(options: BoundBoardInputOptions<Contract, B, SpaceIdOfTable<BoundTable<Contract>, NoInfer<B>>>): InputCollector<z.ZodString, BoundState<Contract>, "board-space", SpaceIdOfTable<BoundTable<Contract>, B>>;
309
+ vertex<B extends TiledBoardIdOfTable<BoundTable<Contract>>>(options: BoundBoardInputOptions<Contract, B, TiledVertexIdOfTable<BoundTable<Contract>, NoInfer<B>>>): InputCollector<z$1.ZodString, BoundState<Contract>, "board-vertex", TiledVertexIdOfTable<BoundTable<Contract>, B>>;
310
+ edge<B extends TiledBoardIdOfTable<BoundTable<Contract>>>(options: BoundBoardInputOptions<Contract, B, TiledEdgeIdOfTable<BoundTable<Contract>, NoInfer<B>>>): InputCollector<z$1.ZodString, BoundState<Contract>, "board-edge", TiledEdgeIdOfTable<BoundTable<Contract>, B>>;
311
+ tile<B extends TiledBoardIdOfTable<BoundTable<Contract>>>(options: BoundBoardInputOptions<Contract, B, TiledSpaceIdOfTable<BoundTable<Contract>, NoInfer<B>>>): InputCollector<z$1.ZodString, BoundState<Contract>, "board-tile", TiledSpaceIdOfTable<BoundTable<Contract>, B>>;
312
+ space<B extends BoardIdOfTable<BoundTable<Contract>>>(options: BoundBoardInputOptions<Contract, B, SpaceIdOfTable<BoundTable<Contract>, NoInfer<B>>>): InputCollector<z$1.ZodString, BoundState<Contract>, "board-space", SpaceIdOfTable<BoundTable<Contract>, B>>;
312
313
  playerSpace<B extends PlayerBoardBaseId<BoundTable<Contract>>>(options: {
313
314
  boardId: B;
314
315
  where?: BoundWhere<Contract, PlayerBoardSpaceTarget<NoInfer<B>, SpaceIdOfTable<BoundTable<Contract>, PlayerBoardRuntimeId<BoundTable<Contract>, NoInfer<B>>>, PlayerIdOfState<BoundState<Contract>>>>;
@@ -322,7 +323,7 @@ type BoundTargetPredicate<Contract extends ContractWithPhases, Target> = Omit<Ta
322
323
  errorCode: ContractErrorCode<Contract>;
323
324
  };
324
325
  type BoundWhere<Contract extends ContractWithPhases, Target> = BoundTargetPredicate<Contract, Target> | readonly BoundTargetPredicate<Contract, Target>[];
325
- type BoundCardCollector<Contract extends ContractWithPhases, Id extends string, ZoneIds extends readonly string[]> = InputCollector<z.ZodString, BoundState<Contract>, "card", Id> & {
326
+ type BoundCardCollector<Contract extends ContractWithPhases, Id extends string, ZoneIds extends readonly string[]> = InputCollector<z$1.ZodString, BoundState<Contract>, "card", Id> & {
326
327
  readonly meta: {
327
328
  readonly zoneId: ZoneIds[number];
328
329
  readonly zoneIds: ZoneIds;
@@ -377,7 +378,7 @@ type PhaseAuthoring<Contract extends ContractWithPhases, PhaseStateSchema extend
377
378
  */
378
379
  type PhaseTypes<Contract extends ContractWithPhases, PhaseStateSchema extends SchemaLike<object>> = {
379
380
  readonly State: BoundPhaseState<Contract, PhaseStateSchema>;
380
- readonly PhaseState: z.infer<PhaseStateSchema>;
381
+ readonly PhaseState: z$1.infer<PhaseStateSchema>;
381
382
  readonly Tx: ReducerTransaction<BoundPhaseState<Contract, PhaseStateSchema>, ContractErrorCode<Contract>>;
382
383
  };
383
384
  /**
@@ -782,8 +783,8 @@ type CompiledManifest<M extends AuthoredManifest> = Omit<ReducerManifestContract
782
783
  [K in keyof ManifestIdsOf<M>]: ManifestIdSchema<ManifestIdsOf<M>[K], K>;
783
784
  };
784
785
  schemas: {
785
- table: z.ZodType<ManifestTable<M>>;
786
- runtime: z.ZodTypeAny;
786
+ table: z$1.ZodType<ManifestTable<M>>;
787
+ runtime: z$1.ZodTypeAny;
787
788
  };
788
789
  createInitialTable(options?: {
789
790
  playerIds?: readonly string[];
package/dist/reducer.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  perPlayerBoardRef,
27
27
  sharedBoardRef,
28
28
  validatedReducerDefinition
29
- } from "./chunk-UESVBUPU.js";
29
+ } from "./chunk-DE4LWN42.js";
30
30
  import {
31
31
  createHexBoardGeometry,
32
32
  fromCoordinates,
@@ -36,14 +36,14 @@ import {
36
36
  ring,
37
37
  runtime_schema_exports,
38
38
  spiral
39
- } from "./chunk-K75F5UIJ.js";
39
+ } from "./chunk-4H4TAIV7.js";
40
40
  import {
41
41
  isPlayerBoardSpaceTarget,
42
42
  samePlayerBoardSpaceTarget
43
- } from "./chunk-3JXUL4VN.js";
43
+ } from "./chunk-DPRHGA2C.js";
44
44
 
45
45
  // src/reducer/manifest/compiler.ts
46
- import { z as z2 } from "zod";
46
+ import * as z2 from "zod";
47
47
 
48
48
  // src/reducer/manifest/generated-helpers.ts
49
49
  function buildTypedRecord(ids, initial) {
@@ -2395,7 +2395,7 @@ function materializeManifestTable(options) {
2395
2395
  }
2396
2396
 
2397
2397
  // src/reducer/manifest/schema.ts
2398
- import { z } from "zod";
2398
+ import * as z from "zod";
2399
2399
  function createTableSchema(analysis, ids) {
2400
2400
  const unknownRecordSchema = z.record(z.string(), z.unknown());
2401
2401
  const objectSchema = (schema) => schema && Object.keys(schema.properties).length ? z.object(
@@ -2813,16 +2813,16 @@ function createTableSchema(analysis, ids) {
2813
2813
  message: "Duplicate player id"
2814
2814
  });
2815
2815
  }
2816
- const checkPlayers = (record, path) => {
2816
+ const checkPlayers = (record3, path) => {
2817
2817
  for (const playerId of table.playerOrder) {
2818
- if (!Object.hasOwn(record, playerId))
2818
+ if (!Object.hasOwn(record3, playerId))
2819
2819
  context.addIssue({
2820
2820
  code: "custom",
2821
2821
  path: [...path, playerId],
2822
2822
  message: "Missing active player"
2823
2823
  });
2824
2824
  }
2825
- for (const playerId of Object.keys(record)) {
2825
+ for (const playerId of Object.keys(record3)) {
2826
2826
  if (!players.has(playerId))
2827
2827
  context.addIssue({
2828
2828
  code: "custom",
@@ -3016,7 +3016,7 @@ function compileManifest(manifest) {
3016
3016
  }
3017
3017
 
3018
3018
  // src/reducer/schema-helpers.ts
3019
- import { z as z3 } from "zod";
3019
+ import * as z3 from "zod";
3020
3020
  var sparseSchemas = /* @__PURE__ */ new WeakMap();
3021
3021
  function sparseMap(keySchema, valueSchema) {
3022
3022
  const schema = z3.partialRecord(keySchema, valueSchema);
@@ -3334,7 +3334,7 @@ var InteractionSteps = class _InteractionSteps {
3334
3334
  };
3335
3335
 
3336
3336
  // src/reducer/inputs/formInput.ts
3337
- import { z as z4 } from "zod";
3337
+ import * as z4 from "zod";
3338
3338
  function isResourceMapChoiceSource(choices) {
3339
3339
  return choices === "resourceMap" || typeof choices === "object" && choices !== null && !Array.isArray(choices) && "source" in choices && choices.source === "resourceMap";
3340
3340
  }
@@ -3580,7 +3580,7 @@ var formInput = Object.assign(baseFormInput, {
3580
3580
  });
3581
3581
 
3582
3582
  // src/reducer/inputs/boardInput.ts
3583
- import { z as z5 } from "zod";
3583
+ import * as z5 from "zod";
3584
3584
  function makeBoardCollector(kind) {
3585
3585
  return function collector(options) {
3586
3586
  const target = options.target;
@@ -3794,7 +3794,7 @@ var cardTarget = {
3794
3794
  };
3795
3795
 
3796
3796
  // src/reducer/inputs/cardInput.ts
3797
- import { z as z6 } from "zod";
3797
+ import * as z6 from "zod";
3798
3798
  function cardInput(options) {
3799
3799
  const target = options.target;
3800
3800
  const eligible = (state, playerId, q) => target.eligible({ state, playerId, q });
@@ -3819,7 +3819,7 @@ function cardInput(options) {
3819
3819
  }
3820
3820
 
3821
3821
  // src/reducer/inputs/rngInput.ts
3822
- import { z as z7 } from "zod";
3822
+ import * as z7 from "zod";
3823
3823
  function d6(count = 1) {
3824
3824
  return {
3825
3825
  kind: "rng",
@@ -3841,7 +3841,7 @@ function coin() {
3841
3841
  var rngInput = { d6, coin };
3842
3842
 
3843
3843
  // src/reducer/inputs/many.ts
3844
- import { z as z8 } from "zod";
3844
+ import * as z8 from "zod";
3845
3845
  function normalizeManyOptions(options) {
3846
3846
  if ("count" in options) {
3847
3847
  assertNonNegativeInteger(options.count, "many(...).count");
@@ -4007,7 +4007,7 @@ function createContractAuthoring(contract) {
4007
4007
  }
4008
4008
 
4009
4009
  // src/reducer/authoring/contract.ts
4010
- import { z as z9 } from "zod";
4010
+ import * as z9 from "zod";
4011
4011
  function validateErrorMap(errors) {
4012
4012
  if (!errors) return;
4013
4013
  const codePattern = /^[A-Z][A-Z0-9_]*$/;