{"version":3,"sources":["../../src/gestures/types.ts","../../src/core/input-classifier.ts","../../src/gestures/normalize.ts","../../src/gestures/timed-state.ts","../../src/gestures/timed-state-runner.ts","../../src/gestures/specificity.ts","../../src/gestures/mapper.ts","../../src/gestures/keyboard-contexts.ts","../../src/gestures/pointer-bindings.ts","../../src/gestures/keyboard-bindings.ts","../../src/gestures/pointer-contexts.ts","../../src/gestures/contexts.ts","../../src/gestures/dispatcher.ts","../../src/gestures/inertia.ts","../../src/core/graph-store.ts","../../src/core/graph-position.ts","../../src/utils/debug.ts","../../src/utils/mutation-queue.ts","../../src/core/perf.ts","../../src/core/graph-derived.ts","../../src/core/viewport-store.ts","../../src/core/selection-store.ts","../../src/utils/layout.ts","../../src/core/group-store.ts","../../src/core/history-store.ts","../../src/core/history-actions.ts","../../src/core/graph-mutations.ts","../../src/core/graph-mutations-edges.ts","../../src/core/reduced-motion-store.ts","../../src/core/graph-mutations-advanced.ts","../../src/core/sync-store.ts","../../src/core/interaction-store.ts","../../src/core/locked-node-store.ts","../../src/core/node-type-registry.tsx","../../src/core/toast-store.ts","../../src/core/snap-store.ts","../../src/core/event-types.ts","../../src/core/action-types.ts","../../src/core/settings-state-types.ts","../../src/core/actions-node.ts","../../src/core/actions-viewport.ts","../../src/core/built-in-actions.ts","../../src/core/action-registry.ts","../../src/core/action-executor.ts","../../src/core/settings-store.ts","../../src/core/settings-presets.ts","../../src/core/canvas-serializer.ts","../../src/core/clipboard-store.ts","../../src/core/virtualization-store.ts","../../src/core/spatial-index.ts","../../src/core/input-store.ts","../../src/core/selection-path-store.ts","../../src/core/search-store.ts","../../src/core/gesture-rules-defaults.ts","../../src/core/gesture-rules.ts","../../src/core/gesture-rule-store.ts","../../src/core/external-keyboard-store.ts","../../src/commands/registry.ts","../../src/core/plugin-registry.ts","../../src/commands/store.ts","../../src/commands/store-atoms.ts","../../src/gestures/modifier-helpers.ts","../../src/gestures/gesture-classification.ts","../../src/gestures/input-action-helpers.ts","../../src/gestures/useCanvasGestures.ts","../../src/gestures/useGuardContext.ts","../../src/gestures/useInertia.ts","../../src/gestures/useWheelZoom.ts","../../src/gestures/usePinchZoom.ts","../../src/gestures/useNodeGestures.ts","../../src/gestures/useGestureSystem.ts","../../src/gestures/useInputModeGestureContext.ts","../../src/gestures/useRegisterInputActions.ts","../../src/gestures/GestureProvider.tsx","../../src/gestures/gesture-provider-utils.ts"],"sourcesContent":["/**\n * Gesture System v2 — Core Types\n *\n * Single source of truth for every type in the gesture pipeline.\n * No runtime code — pure type definitions.\n */\n\n// =============================================================================\n// Layer 1: Normalize\n// =============================================================================\n\nexport const NO_MODIFIERS = Object.freeze({\n shift: false,\n ctrl: false,\n alt: false,\n meta: false\n});\nexport const NO_HELD_KEYS = Object.freeze({\n byKey: Object.freeze({}),\n byCode: Object.freeze({})\n});\n\n// =============================================================================\n// Layer 2: Recognize\n// =============================================================================\n\n// =============================================================================\n// Layer 2: Timed State\n// =============================================================================\n\n// =============================================================================\n// Layer 3: Resolve\n// =============================================================================\n\n// =============================================================================\n// Layer 4: Dispatch\n// =============================================================================\n\n/**\n * Action handler. Simple function form fires only on 'start' and 'instant'.\n * Object form routes each phase to a dedicated method.\n */\n\nexport function isKeyInputEvent(event) {\n return event.kind === 'key';\n}\nexport function isPointerGestureEvent(event) {\n return event.kind !== 'key';\n}\n\n// =============================================================================\n// Re-exports for convenience\n// =============================================================================","/**\n * Input Classifier\n *\n * Classifies pointer events into input sources (finger, pencil, mouse)\n * and extracts stylus-specific data (pressure, tilt).\n *\n * This is the foundation of the touch-first input architecture:\n * - Pencil draws/selects\n * - Fingers navigate (pan/zoom)\n * - Mouse does both\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Input device type */\n\n/** Classified pointer with source-specific metadata */\n\n/** Capabilities detected for the current device */\n\n// =============================================================================\n// Classification\n// =============================================================================\n\n/**\n * Classify a PointerEvent into an InputSource with metadata.\n *\n * Uses `PointerEvent.pointerType` as the primary signal:\n * - 'pen' → pencil (Apple Pencil, Surface Pen, Wacom, etc.)\n * - 'touch' → finger\n * - 'mouse' → mouse\n *\n * Falls back to 'mouse' for unknown pointer types.\n */\nexport function classifyPointer(e) {\n const source = pointerTypeToSource(e.pointerType);\n return {\n source,\n pointerId: e.pointerId,\n pressure: e.pressure,\n tiltX: e.tiltX,\n tiltY: e.tiltY,\n isPrimary: e.isPrimary,\n rawPointerType: e.pointerType\n };\n}\n\n/**\n * Map PointerEvent.pointerType string to InputSource.\n */\nfunction pointerTypeToSource(pointerType) {\n switch (pointerType) {\n case 'pen':\n return 'pencil';\n case 'touch':\n return 'finger';\n case 'mouse':\n return 'mouse';\n default:\n // Unknown pointer types (e.g. future devices) default to mouse behavior\n return 'mouse';\n }\n}\n\n// =============================================================================\n// Device Capability Detection\n// =============================================================================\n\n/**\n * Detect input capabilities of the current device.\n *\n * Uses media queries and navigator APIs for initial detection.\n * Note: `hasStylus` starts as false and is set to true on first pen event\n * (there's no reliable way to detect stylus support without an event).\n */\nexport function detectInputCapabilities() {\n if (typeof window === 'undefined') {\n // SSR: assume desktop defaults\n return {\n hasTouch: false,\n hasStylus: false,\n hasMouse: true,\n hasCoarsePointer: false\n };\n }\n const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n\n // matchMedia for pointer capabilities\n const supportsMatchMedia = typeof window.matchMedia === 'function';\n const hasCoarsePointer = supportsMatchMedia ? window.matchMedia('(pointer: coarse)').matches : false;\n const hasFinePointer = supportsMatchMedia ? window.matchMedia('(pointer: fine)').matches : true;\n\n // Heuristic: if we have both coarse and fine, likely a tablet with stylus support\n // But we won't confirm stylus until we see a pen event\n const hasMouse = hasFinePointer || !hasTouch;\n return {\n hasTouch,\n hasStylus: false,\n // Set to true on first pen event\n hasMouse,\n hasCoarsePointer\n };\n}\n\n// =============================================================================\n// Gesture Threshold Helpers\n// =============================================================================\n\n/** Threshold values per input source */\n\n/**\n * Get gesture thresholds appropriate for the given input source.\n *\n * Fingers need larger thresholds (imprecise, large contact area).\n * Stylus is the most precise.\n * Mouse is in between.\n */\nexport function getGestureThresholds(source) {\n switch (source) {\n case 'finger':\n return {\n dragThreshold: 10,\n tapThreshold: 10,\n longPressDuration: 600,\n longPressMoveLimit: 10\n };\n case 'pencil':\n return {\n dragThreshold: 2,\n tapThreshold: 3,\n longPressDuration: 500,\n longPressMoveLimit: 5\n };\n case 'mouse':\n return {\n dragThreshold: 3,\n tapThreshold: 5,\n longPressDuration: 0,\n // Mouse uses right-click instead\n longPressMoveLimit: 0\n };\n }\n}\n\n// =============================================================================\n// Hit Target Helpers\n// =============================================================================\n\n/** Minimum interactive target sizes per Apple HIG / Material Design */\nexport const HIT_TARGET_SIZES = {\n /** Minimum touch target (Apple HIG: 44pt) */\n finger: 44,\n /** Stylus target (precise, can use smaller targets) */\n pencil: 24,\n /** Mouse target (hover-discoverable, smallest) */\n mouse: 16\n};\n\n/**\n * Get the appropriate hit target size for the current input source.\n * Used to size invisible padding around small visual elements\n * (resize handles, ports, edge connection handles).\n */\nexport function getHitTargetSize(source) {\n return HIT_TARGET_SIZES[source];\n}","/**\n * Layer 1: Normalize\n *\n * Converts raw DOM PointerEvents into NormalizedPointer structs.\n * Pure functions — no side effects, no DOM listeners.\n */\n\nimport { classifyPointer } from '../core/input-classifier';\nimport { NO_MODIFIERS } from './types';\n\n/**\n * Extract modifiers from any DOM event with modifier flags.\n */\nexport function extractModifiers(e) {\n if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {\n return NO_MODIFIERS;\n }\n return {\n shift: e.shiftKey,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n meta: e.metaKey\n };\n}\n\n/**\n * Clamp a raw button value to 0 | 1 | 2.\n */\nfunction clampButton(raw) {\n if (raw === 1) return 1;\n if (raw === 2) return 2;\n return 0;\n}\n\n/**\n * Determine pointer lifecycle from event type.\n */\nfunction lifecycleFromEventType(type) {\n switch (type) {\n case 'pointerdown':\n return 'down';\n case 'pointerup':\n return 'up';\n case 'pointercancel':\n return 'cancel';\n default:\n return 'move';\n }\n}\n\n/**\n * Normalize a raw PointerEvent into a NormalizedPointer.\n */\nexport function normalizePointer(e) {\n const classified = classifyPointer(e);\n return {\n pointerId: e.pointerId,\n lifecycle: lifecycleFromEventType(e.type),\n source: classified.source,\n button: clampButton(e.button),\n modifiers: extractModifiers(e),\n screenX: e.clientX,\n screenY: e.clientY,\n pressure: e.pressure,\n timestamp: e.timeStamp\n };\n}","/**\n * Layer 2: Timed State Machine\n *\n * Per-pointer state machine for recognizing taps, double-taps,\n * triple-taps, and long-press. Pure functions — no timers inside.\n * The caller manages setTimeout via the returned timer commands.\n *\n * State diagram:\n * idle → pressed (on down)\n * pressed → released (on up, emit tap/double-tap/triple-tap)\n * pressed → idle (on move-beyond-threshold, becomes drag)\n * pressed → long-pressed (on long-press-timer)\n * released → pressed (on down within multi-tap window)\n * released → idle (on settle-timer)\n * long-pressed → idle (on up)\n * any → idle (on cancel)\n */\n\n// Timer IDs\nexport const LONG_PRESS_TIMER = 'long-press';\nexport const SETTLE_TIMER = 'settle';\n\n// Defaults (overridable via config)\nexport const DEFAULT_LONG_PRESS_MS = 600;\nexport const DEFAULT_MULTI_TAP_WINDOW_MS = 300;\nexport const IDLE = {\n tag: 'idle',\n tapCount: 0\n};\nconst DEFAULT_CONFIG = {\n longPressMs: DEFAULT_LONG_PRESS_MS,\n multiTapWindowMs: DEFAULT_MULTI_TAP_WINDOW_MS\n};\n\n/**\n * Pure state transition. Returns new state + optional side effects\n * (emit gesture, schedule/cancel timer).\n */\nexport function transition(state, event, config = DEFAULT_CONFIG) {\n switch (event) {\n case 'down':\n return onDown(state, config);\n case 'up':\n return onUp(state, config);\n case 'move-beyond-threshold':\n return onMoveBeyond(state);\n case 'cancel':\n return onCancel();\n case 'timer:long-press':\n return onLongPressTimer(state);\n case 'timer:settle':\n return onSettleTimer();\n default:\n return {\n state\n };\n }\n}\nfunction onDown(state, config) {\n switch (state.tag) {\n case 'idle':\n return {\n state: {\n tag: 'pressed',\n tapCount: 0\n },\n cancelTimer: SETTLE_TIMER,\n scheduleTimer: {\n id: LONG_PRESS_TIMER,\n delayMs: config.longPressMs\n }\n };\n case 'released':\n // Continue multi-tap sequence\n return {\n state: {\n tag: 'pressed',\n tapCount: state.tapCount\n },\n cancelTimer: SETTLE_TIMER,\n scheduleTimer: {\n id: LONG_PRESS_TIMER,\n delayMs: config.longPressMs\n }\n };\n default:\n return {\n state\n };\n }\n}\nfunction onUp(state, config) {\n if (state.tag !== 'pressed') {\n // long-pressed → idle on up\n if (state.tag === 'long-pressed') {\n return {\n state: IDLE,\n cancelTimer: LONG_PRESS_TIMER\n };\n }\n return {\n state\n };\n }\n const newCount = state.tapCount + 1;\n const emit = tapTypeForCount(newCount);\n return {\n state: {\n tag: 'released',\n tapCount: newCount\n },\n emit,\n cancelTimer: LONG_PRESS_TIMER,\n scheduleTimer: {\n id: SETTLE_TIMER,\n delayMs: config.multiTapWindowMs\n }\n };\n}\nfunction onMoveBeyond(state) {\n if (state.tag === 'pressed') {\n return {\n state: IDLE,\n cancelTimer: LONG_PRESS_TIMER\n };\n }\n return {\n state\n };\n}\nfunction onCancel() {\n return {\n state: IDLE,\n cancelTimer: LONG_PRESS_TIMER\n };\n}\nfunction onLongPressTimer(state) {\n if (state.tag === 'pressed') {\n return {\n state: {\n tag: 'long-pressed',\n tapCount: 0\n },\n emit: 'long-press'\n };\n }\n return {\n state\n };\n}\nfunction onSettleTimer() {\n return {\n state: IDLE\n };\n}\nfunction tapTypeForCount(count) {\n switch (count) {\n case 2:\n return 'double-tap';\n case 3:\n return 'triple-tap';\n default:\n return 'tap';\n }\n}","/**\n * Timed State Runner\n *\n * Timer bridge that wraps the pure TimedState transitions with actual\n * setTimeout/clearTimeout. Each pointer gets its own runner.\n *\n * The runner is imperative on purpose — it's managed by refs in hooks,\n * not by React state. This avoids re-renders on timer state changes.\n */\n\nimport { transition, IDLE, DEFAULT_LONG_PRESS_MS, DEFAULT_MULTI_TAP_WINDOW_MS } from './timed-state';\nexport class TimedStateRunner {\n state = IDLE;\n timers = new Map();\n /** Called when the state machine emits a gesture (tap, double-tap, long-press, etc.) */\n onEmit = null;\n constructor(config) {\n this.config = {\n longPressMs: config?.longPressMs ?? DEFAULT_LONG_PRESS_MS,\n multiTapWindowMs: config?.multiTapWindowMs ?? DEFAULT_MULTI_TAP_WINDOW_MS\n };\n }\n\n /**\n * Feed a lifecycle event into the state machine.\n * Returns the emitted gesture type if any (synchronous emit only).\n * Timer-based emits are delivered asynchronously via `onEmit`.\n */\n feed(event) {\n return this.apply(event);\n }\n\n /** Current state tag (for debugging/testing). */\n get tag() {\n return this.state.tag;\n }\n\n /** Destroy: cancel all pending timers. */\n destroy() {\n for (const timer of this.timers.values()) {\n clearTimeout(timer);\n }\n this.timers.clear();\n this.state = IDLE;\n this.onEmit = null;\n }\n apply(event) {\n const result = transition(this.state, event, this.config);\n this.state = result.state;\n if (result.cancelTimer) {\n const timer = this.timers.get(result.cancelTimer);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.timers.delete(result.cancelTimer);\n }\n }\n if (result.scheduleTimer) {\n const {\n id,\n delayMs\n } = result.scheduleTimer;\n // Clear any existing timer with this id\n const existing = this.timers.get(id);\n if (existing !== undefined) {\n clearTimeout(existing);\n }\n this.timers.set(id, setTimeout(() => {\n this.timers.delete(id);\n const timerEvent = `timer:${id}`;\n const timerResult = transition(this.state, timerEvent, this.config);\n this.state = timerResult.state;\n if (timerResult.emit) {\n this.onEmit?.(timerResult.emit);\n }\n }, delayMs));\n }\n return result.emit;\n }\n}","/**\n * Layer 3: Specificity Scoring\n *\n * Scores how well an InputPattern matches an InputEvent.\n * Higher score = more specific match. Returns -1 on mismatch.\n *\n * Score weights:\n * type 128 (must outweigh all others combined)\n * subjectKind 32\n * modifier+ 16 (per positive flag)\n * modifier- 8 (per negative flag)\n * source 4\n * button 2\n */\n\nimport { isKeyInputEvent, isPointerGestureEvent } from './types';\nconst SCORE_TYPE = 128;\nconst SCORE_KEY = 64;\nconst SCORE_CODE = 64;\nconst SCORE_SUBJECT = 32;\nconst SCORE_MODIFIER_POSITIVE = 16;\nconst SCORE_MODIFIER_NEGATIVE = 8;\nconst SCORE_HELD_KEY_POSITIVE = 16;\nconst SCORE_HELD_KEY_NEGATIVE = 8;\nconst SCORE_SOURCE = 4;\nconst SCORE_BUTTON = 2;\n\n/**\n * Compute the specificity score of a pattern against an event.\n * Returns -1 if the pattern does not match.\n */\nexport function specificity(pattern, event) {\n let score = 0;\n\n // kind\n if (pattern.kind !== undefined) {\n const actualKind = isKeyInputEvent(event) ? 'key' : 'pointer';\n if (pattern.kind !== actualKind) return -1;\n }\n\n // type\n if (pattern.type !== undefined) {\n if (!isPointerGestureEvent(event) || pattern.type !== event.type) return -1;\n score += SCORE_TYPE;\n }\n\n // subjectKind\n if (pattern.subjectKind !== undefined) {\n if (event.subject === undefined || pattern.subjectKind !== event.subject.kind) return -1;\n score += SCORE_SUBJECT;\n }\n\n // phase\n if (pattern.phase !== undefined && pattern.phase !== event.phase) {\n return -1;\n }\n\n // source\n if (pattern.source !== undefined) {\n if (!isPointerGestureEvent(event)) return -1;\n if (pattern.source !== event.source) return -1;\n score += SCORE_SOURCE;\n }\n\n // button\n if (pattern.button !== undefined) {\n if (!isPointerGestureEvent(event)) return -1;\n if (pattern.button !== event.button) return -1;\n score += SCORE_BUTTON;\n }\n\n // key / code\n if (pattern.key !== undefined) {\n if (!isKeyInputEvent(event) || pattern.key !== event.key) return -1;\n score += SCORE_KEY;\n }\n if (pattern.code !== undefined) {\n if (!isKeyInputEvent(event) || pattern.code !== event.code) return -1;\n score += SCORE_CODE;\n }\n\n // modifiers\n if (pattern.modifiers !== undefined) {\n const ms = modifierScore(pattern.modifiers, event.modifiers);\n if (ms === -1) return -1;\n score += ms;\n }\n\n // held keys\n if (pattern.heldKeys !== undefined) {\n const hs = heldKeyScore(pattern.heldKeys, event.heldKeys);\n if (hs === -1) return -1;\n score += hs;\n }\n return score;\n}\n\n/**\n * Score modifier pattern against actual modifier state.\n * Each explicit true flag adds SCORE_MODIFIER_POSITIVE.\n * Each explicit false flag adds SCORE_MODIFIER_NEGATIVE.\n * Returns -1 if any constraint is violated.\n */\nfunction modifierScore(pattern, actual) {\n let score = 0;\n const keys = ['shift', 'ctrl', 'alt', 'meta'];\n for (const key of keys) {\n const required = pattern[key];\n if (required === undefined) continue;\n if (required !== actual[key]) return -1;\n score += required ? SCORE_MODIFIER_POSITIVE : SCORE_MODIFIER_NEGATIVE;\n }\n if (pattern.custom) {\n const actualCustom = actual.custom ?? {};\n for (const [key, required] of Object.entries(pattern.custom)) {\n const actualVal = actualCustom[key] ?? false;\n if (required !== actualVal) return -1;\n score += required ? SCORE_MODIFIER_POSITIVE : SCORE_MODIFIER_NEGATIVE;\n }\n }\n return score;\n}\nfunction heldKeyScore(pattern, actual) {\n let score = 0;\n for (const [key, required] of Object.entries(pattern.byKey ?? {})) {\n const actualVal = actual.byKey[key] ?? false;\n if (required !== actualVal) return -1;\n score += required ? SCORE_HELD_KEY_POSITIVE : SCORE_HELD_KEY_NEGATIVE;\n }\n for (const [code, required] of Object.entries(pattern.byCode ?? {})) {\n const actualVal = actual.byCode[code] ?? false;\n if (required !== actualVal) return -1;\n score += required ? SCORE_HELD_KEY_POSITIVE : SCORE_HELD_KEY_NEGATIVE;\n }\n return score;\n}","/**\n * Layer 3: Gesture Mapper\n *\n * Resolves an InputEvent against a priority-sorted stack of MappingContexts.\n * Each context is bucketed by pointer gesture type or keyboard phase for O(1) lookup.\n */\n\nimport { specificity } from './specificity';\nimport { isKeyInputEvent } from './types';\n\n// =============================================================================\n// Index\n// =============================================================================\n\n/** Pre-indexed bindings for a single MappingContext. */\n\nconst WILDCARD = '__wildcard__';\nfunction getPatternBucketKey(binding) {\n const {\n pattern\n } = binding;\n if (pattern.type !== undefined) {\n return `pointer:${pattern.type}`;\n }\n if (pattern.kind === 'key' || pattern.key !== undefined || pattern.code !== undefined) {\n return pattern.phase === 'down' || pattern.phase === 'up' ? `key:${pattern.phase}` : null;\n }\n return null;\n}\nfunction getEventBucketKey(event) {\n return isKeyInputEvent(event) ? `key:${event.phase}` : `pointer:${event.type}`;\n}\n\n/**\n * Build a lookup index from a MappingContext.\n * Wildcard bindings (no `type` in pattern) are concatenated into every bucket.\n */\nexport function indexContext(ctx) {\n const typed = new Map();\n const wildcards = [];\n for (const binding of ctx.bindings) {\n const key = getPatternBucketKey(binding);\n if (key === null) {\n wildcards.push(binding);\n } else {\n let bucket = typed.get(key);\n if (!bucket) {\n bucket = [];\n typed.set(key, bucket);\n }\n bucket.push(binding);\n }\n }\n const buckets = new Map();\n for (const [key, bucket] of typed) {\n buckets.set(key, bucket);\n }\n if (wildcards.length > 0) {\n buckets.set(WILDCARD, wildcards);\n }\n return {\n contextId: ctx.id,\n priority: ctx.priority,\n enabled: ctx.enabled,\n buckets\n };\n}\n\n// =============================================================================\n// Stack Index\n// =============================================================================\n\n/** The full indexed context stack, sorted by priority ascending. */\n\n/**\n * Build the full mapping index from a list of contexts.\n * Sorts by priority ascending (lower number = higher priority).\n */\nexport function buildMappingIndex(contexts) {\n return contexts.map(indexContext).sort((a, b) => a.priority - b.priority);\n}\n\n// =============================================================================\n// Resolution\n// =============================================================================\n\n/**\n * Resolve a gesture event against the indexed context stack.\n *\n * Algorithm:\n * 1. Walk contexts in priority order (ascending = highest priority first).\n * 2. For each enabled context, look up the bucket for event.type.\n * 3. For each binding in the bucket, compute specificity score.\n * 4. If binding has a `when` guard, evaluate it.\n * 5. Track best match per context.\n * 6. If best match has `consumeInput`, return immediately.\n * 7. Otherwise, continue to lower-priority contexts.\n * 8. Return the highest-priority best match across all contexts.\n */\nexport function resolve(event, index, guard) {\n let winner = null;\n for (const ctx of index) {\n if (!ctx.enabled) continue;\n const bucket = ctx.buckets.get(getEventBucketKey(event));\n const wildcardBucket = ctx.buckets.get(WILDCARD);\n if (!bucket && !wildcardBucket) continue;\n let bestScore = -1;\n let bestBinding = null;\n for (const binding of [...(bucket ?? []), ...(wildcardBucket ?? [])]) {\n const score = specificity(binding.pattern, event);\n if (score === -1) continue;\n if (binding.when && !binding.when(guard)) continue;\n if (score > bestScore) {\n bestScore = score;\n bestBinding = binding;\n }\n }\n if (bestBinding !== null) {\n const action = {\n actionId: bestBinding.actionId,\n binding: bestBinding,\n contextId: ctx.contextId,\n score: bestScore,\n consumed: bestBinding.consumeInput === true\n };\n if (action.consumed) {\n return action;\n }\n\n // First (highest-priority) match wins\n if (winner === null) {\n winner = action;\n }\n }\n }\n return winner;\n}","/**\n * Keyboard Mapping Contexts\n *\n * Search, manipulate, and navigate keyboard contexts extracted from contexts.ts.\n */\n\n// =============================================================================\n// Search Context (priority 25)\n// =============================================================================\n\nexport const SEARCH_CONTEXT = {\n id: 'search-active',\n priority: 25,\n enabled: true,\n bindings: [{\n id: 'search-next-enter',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Enter',\n modifiers: {\n shift: false\n }\n },\n actionId: 'search-next-result',\n when: ctx => ctx.isSearchActive && !ctx.commandLineVisible,\n consumeInput: true\n }, {\n id: 'search-prev-enter',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Enter',\n modifiers: {\n shift: true\n }\n },\n actionId: 'search-prev-result',\n when: ctx => ctx.isSearchActive && !ctx.commandLineVisible,\n consumeInput: true\n }, {\n id: 'search-next-ctrl-g',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'g',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'search-next-result',\n when: ctx => ctx.isSearchActive,\n consumeInput: true\n }, {\n id: 'search-prev-ctrl-g',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'g',\n modifiers: {\n ctrl: true,\n shift: true\n }\n },\n actionId: 'search-prev-result',\n when: ctx => ctx.isSearchActive,\n consumeInput: true\n }, {\n id: 'search-next-meta-g',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'g',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'search-next-result',\n when: ctx => ctx.isSearchActive,\n consumeInput: true\n }, {\n id: 'search-prev-meta-g',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'g',\n modifiers: {\n meta: true,\n shift: true\n }\n },\n actionId: 'search-prev-result',\n when: ctx => ctx.isSearchActive,\n consumeInput: true\n }]\n};\n\n// =============================================================================\n// Keyboard Interaction Contexts (priority 30 / 40)\n// =============================================================================\n\nexport const KEYBOARD_MANIPULATE_CONTEXT = {\n id: 'keyboard:manipulate',\n priority: 30,\n enabled: true,\n bindings: [{\n id: 'manipulate-arrow-up',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowUp',\n modifiers: {\n shift: false\n }\n },\n actionId: 'nudge-selection-up',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }, {\n id: 'manipulate-arrow-down',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowDown',\n modifiers: {\n shift: false\n }\n },\n actionId: 'nudge-selection-down',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }, {\n id: 'manipulate-arrow-left',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowLeft',\n modifiers: {\n shift: false\n }\n },\n actionId: 'nudge-selection-left',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }, {\n id: 'manipulate-arrow-right',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowRight',\n modifiers: {\n shift: false\n }\n },\n actionId: 'nudge-selection-right',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }, {\n id: 'manipulate-shift-arrow-up',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowUp',\n modifiers: {\n shift: true\n }\n },\n actionId: 'nudge-selection-up-large',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }, {\n id: 'manipulate-shift-arrow-down',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowDown',\n modifiers: {\n shift: true\n }\n },\n actionId: 'nudge-selection-down-large',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }, {\n id: 'manipulate-shift-arrow-left',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowLeft',\n modifiers: {\n shift: true\n }\n },\n actionId: 'nudge-selection-left-large',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }, {\n id: 'manipulate-shift-arrow-right',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowRight',\n modifiers: {\n shift: true\n }\n },\n actionId: 'nudge-selection-right-large',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }, {\n id: 'manipulate-escape',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Escape'\n },\n actionId: 'exit-keyboard-manipulate-mode',\n when: ctx => ctx.keyboardInteractionMode === 'manipulate',\n consumeInput: true\n }]\n};\nexport const KEYBOARD_NAVIGATE_CONTEXT = {\n id: 'keyboard:navigate',\n priority: 40,\n enabled: true,\n bindings: [{\n id: 'navigate-arrow-up',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowUp'\n },\n actionId: 'navigate-focus-up',\n when: ctx => ctx.keyboardInteractionMode === 'navigate',\n consumeInput: true\n }, {\n id: 'navigate-arrow-down',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowDown'\n },\n actionId: 'navigate-focus-down',\n when: ctx => ctx.keyboardInteractionMode === 'navigate',\n consumeInput: true\n }, {\n id: 'navigate-arrow-left',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowLeft'\n },\n actionId: 'navigate-focus-left',\n when: ctx => ctx.keyboardInteractionMode === 'navigate',\n consumeInput: true\n }, {\n id: 'navigate-arrow-right',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'ArrowRight'\n },\n actionId: 'navigate-focus-right',\n when: ctx => ctx.keyboardInteractionMode === 'navigate',\n consumeInput: true\n }, {\n id: 'navigate-enter',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Enter'\n },\n actionId: 'enter-keyboard-manipulate-mode',\n when: ctx => ctx.keyboardInteractionMode === 'navigate',\n consumeInput: true\n }, {\n id: 'navigate-space',\n pattern: {\n kind: 'key',\n phase: 'down',\n code: 'Space'\n },\n actionId: 'activate-focused-node',\n when: ctx => ctx.keyboardInteractionMode === 'navigate',\n consumeInput: true\n }, {\n id: 'navigate-tab',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Tab',\n modifiers: {\n shift: false\n }\n },\n actionId: 'cycle-focus-forward',\n when: ctx => ctx.keyboardInteractionMode === 'navigate',\n consumeInput: true\n }, {\n id: 'navigate-shift-tab',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Tab',\n modifiers: {\n shift: true\n }\n },\n actionId: 'cycle-focus-backward',\n when: ctx => ctx.keyboardInteractionMode === 'navigate',\n consumeInput: true\n }]\n};","/**\n * Pointer Bindings\n *\n * All pointer/touch gesture bindings for the DEFAULT_CONTEXT.\n * Separated from keyboard bindings for readability.\n *\n * Extracted from pointer-contexts.ts in v1.7.0.\n *\n * @since 1.7.0\n */\n\n/**\n * All pointer gesture bindings (tap, drag, long-press, pinch, scroll).\n */\nexport const POINTER_BINDINGS = [\n// --- Pointer taps ---\n{\n id: 'tap-node',\n pattern: {\n type: 'tap',\n subjectKind: 'node'\n },\n actionId: 'select-node'\n}, {\n id: 'tap-edge',\n pattern: {\n type: 'tap',\n subjectKind: 'edge'\n },\n actionId: 'select-edge'\n}, {\n id: 'tap-bg',\n pattern: {\n type: 'tap',\n subjectKind: 'background'\n },\n actionId: 'clear-selection'\n}, {\n id: 'shift-tap-node',\n pattern: {\n type: 'tap',\n subjectKind: 'node',\n modifiers: {\n shift: true\n }\n },\n actionId: 'toggle-selection'\n},\n// --- Right-click ---\n{\n id: 'rc-node',\n pattern: {\n type: 'tap',\n subjectKind: 'node',\n button: 2\n },\n actionId: 'context-menu',\n consumeInput: true\n}, {\n id: 'rc-bg',\n pattern: {\n type: 'tap',\n subjectKind: 'background',\n button: 2\n },\n actionId: 'context-menu',\n consumeInput: true\n},\n// --- Double/triple tap ---\n{\n id: 'dtap-node',\n pattern: {\n type: 'double-tap',\n subjectKind: 'node'\n },\n actionId: 'fit-to-view'\n}, {\n id: 'ttap-node',\n pattern: {\n type: 'triple-tap',\n subjectKind: 'node'\n },\n actionId: 'toggle-lock'\n},\n// --- Drags ---\n{\n id: 'drag-node',\n pattern: {\n type: 'drag',\n subjectKind: 'node'\n },\n actionId: 'move-node'\n}, {\n id: 'drag-bg-finger',\n pattern: {\n type: 'drag',\n subjectKind: 'background',\n source: 'finger'\n },\n actionId: 'pan'\n}, {\n id: 'drag-bg-mouse',\n pattern: {\n type: 'drag',\n subjectKind: 'background',\n source: 'mouse'\n },\n actionId: 'pan'\n}, {\n id: 'drag-bg-pencil',\n pattern: {\n type: 'drag',\n subjectKind: 'background',\n source: 'pencil'\n },\n actionId: 'lasso-select'\n}, {\n id: 'space-drag-pan',\n pattern: {\n type: 'drag',\n heldKeys: {\n byCode: {\n Space: true\n }\n }\n },\n actionId: 'pan'\n}, {\n id: 'shift-drag-bg',\n pattern: {\n type: 'drag',\n subjectKind: 'background',\n modifiers: {\n shift: true\n }\n },\n actionId: 'rect-select'\n},\n// Right/middle drag — no-ops by default\n{\n id: 'rdrag-node',\n pattern: {\n type: 'drag',\n subjectKind: 'node',\n button: 2\n },\n actionId: 'none'\n}, {\n id: 'rdrag-bg',\n pattern: {\n type: 'drag',\n subjectKind: 'background',\n button: 2\n },\n actionId: 'none'\n},\n// --- Long-press ---\n{\n id: 'lp-node',\n pattern: {\n type: 'long-press',\n subjectKind: 'node'\n },\n actionId: 'context-menu'\n}, {\n id: 'lp-bg-finger',\n pattern: {\n type: 'long-press',\n subjectKind: 'background',\n source: 'finger'\n },\n actionId: 'create-node'\n},\n// --- Pinch / scroll ---\n{\n id: 'pinch-bg',\n pattern: {\n type: 'pinch',\n subjectKind: 'background'\n },\n actionId: 'zoom'\n}, {\n id: 'scroll-any',\n pattern: {\n type: 'scroll'\n },\n actionId: 'zoom'\n}, {\n id: 'pinch-node',\n pattern: {\n type: 'pinch',\n subjectKind: 'node'\n },\n actionId: 'split-node'\n}];","/**\n * Keyboard Bindings\n *\n * All keyboard shortcut bindings for the DEFAULT_CONTEXT.\n * Separated from pointer bindings for readability.\n *\n * Extracted from pointer-contexts.ts in v1.7.0.\n *\n * @since 1.7.0\n */\n\nconst isCommandShortcut = ctx => !ctx.commandLineVisible;\n\n/**\n * All keyboard shortcut gesture bindings.\n * Each binding maps a key pattern to an action ID.\n */\nexport const KEYBOARD_BINDINGS = [{\n id: 'slash-open-command-line',\n pattern: {\n kind: 'key',\n phase: 'down',\n code: 'Slash',\n modifiers: {\n ctrl: false,\n meta: false,\n shift: false\n }\n },\n actionId: 'open-command-line',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'escape-fallback',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Escape'\n },\n actionId: 'escape-input',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'delete-selection',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Delete'\n },\n actionId: 'delete-selection',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'backspace-delete-selection',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Backspace',\n modifiers: {\n ctrl: false,\n meta: false\n }\n },\n actionId: 'delete-selection',\n when: isCommandShortcut,\n consumeInput: true\n},\n// Search\n{\n id: 'open-search-ctrl-f',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'f',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'open-search',\n consumeInput: true\n}, {\n id: 'open-search-meta-f',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'f',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'open-search',\n consumeInput: true\n},\n// Copy / Cut / Paste\n{\n id: 'copy-selection-ctrl-c',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'c',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'copy-selection',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'copy-selection-meta-c',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'c',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'copy-selection',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'cut-selection-ctrl-x',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'x',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'cut-selection',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'cut-selection-meta-x',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'x',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'cut-selection',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'paste-selection-ctrl-v',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'v',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'paste-selection',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'paste-selection-meta-v',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'v',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'paste-selection',\n when: isCommandShortcut,\n consumeInput: true\n},\n// Duplicate\n{\n id: 'duplicate-selection-ctrl-d',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'd',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'duplicate-selection',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'duplicate-selection-meta-d',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'd',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'duplicate-selection',\n when: isCommandShortcut,\n consumeInput: true\n},\n// Select All\n{\n id: 'select-all-ctrl-a',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'a',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'select-all',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'select-all-meta-a',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'a',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'select-all',\n when: isCommandShortcut,\n consumeInput: true\n},\n// Merge\n{\n id: 'merge-selection-ctrl-m',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'm',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'merge-selection',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'merge-selection-meta-m',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'm',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'merge-selection',\n when: isCommandShortcut,\n consumeInput: true\n},\n// Undo / Redo\n{\n id: 'undo-ctrl-z',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'z',\n modifiers: {\n ctrl: true,\n shift: false\n }\n },\n actionId: 'undo',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'undo-meta-z',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'z',\n modifiers: {\n meta: true,\n shift: false\n }\n },\n actionId: 'undo',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'redo-ctrl-shift-z',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'z',\n modifiers: {\n ctrl: true,\n shift: true\n }\n },\n actionId: 'redo',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'redo-meta-shift-z',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'z',\n modifiers: {\n meta: true,\n shift: true\n }\n },\n actionId: 'redo',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'redo-ctrl-y',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'y',\n modifiers: {\n ctrl: true\n }\n },\n actionId: 'redo',\n when: isCommandShortcut,\n consumeInput: true\n}, {\n id: 'redo-meta-y',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'y',\n modifiers: {\n meta: true\n }\n },\n actionId: 'redo',\n when: isCommandShortcut,\n consumeInput: true\n}];","/**\n * Pointer & Default Mapping Contexts\n *\n * DEFAULT_CONTEXT assembled from pointer-bindings + keyboard-bindings.\n * Input mode contexts for pick operations.\n *\n * @since 1.7.0 — bindings extracted into keyboard-bindings.ts and pointer-bindings.ts\n */\n\nimport { POINTER_BINDINGS } from './pointer-bindings';\nimport { KEYBOARD_BINDINGS } from './keyboard-bindings';\n\n// Re-export for consumers\nexport { POINTER_BINDINGS } from './pointer-bindings';\nexport { KEYBOARD_BINDINGS } from './keyboard-bindings';\n\n// =============================================================================\n// Default Context (priority 100 — lowest built-in)\n// =============================================================================\n\nexport const DEFAULT_CONTEXT = {\n id: 'default',\n priority: 100,\n enabled: true,\n bindings: [...POINTER_BINDINGS, ...KEYBOARD_BINDINGS]\n};\n\n// =============================================================================\n// Input Mode Contexts (priority 5 — override most things)\n// =============================================================================\n\nexport const PICK_NODE_CONTEXT = {\n id: 'input-mode:pickNode',\n priority: 5,\n enabled: true,\n bindings: [{\n id: 'pick-tap-node',\n pattern: {\n type: 'tap',\n subjectKind: 'node'\n },\n actionId: 'resolve-pick-node',\n consumeInput: true\n }, {\n id: 'pick-cancel-bg',\n pattern: {\n type: 'tap',\n subjectKind: 'background'\n },\n actionId: 'cancel-pick',\n consumeInput: true\n }, {\n id: 'pick-cancel-key',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Escape'\n },\n actionId: 'cancel-pick',\n consumeInput: true\n }]\n};\nexport const PICK_NODES_CONTEXT = {\n id: 'input-mode:pickNodes',\n priority: 5,\n enabled: true,\n bindings: [{\n id: 'pick-tap-node',\n pattern: {\n type: 'tap',\n subjectKind: 'node'\n },\n actionId: 'resolve-pick-node',\n consumeInput: true\n }, {\n id: 'pick-done',\n pattern: {\n type: 'double-tap',\n subjectKind: 'background'\n },\n actionId: 'finish-pick-nodes',\n consumeInput: true\n }, {\n id: 'pick-cancel-bg',\n pattern: {\n type: 'tap',\n subjectKind: 'background',\n button: 2\n },\n actionId: 'cancel-pick',\n consumeInput: true\n }, {\n id: 'pick-cancel-key',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Escape'\n },\n actionId: 'cancel-pick',\n consumeInput: true\n }]\n};\nexport const PICK_POINT_CONTEXT = {\n id: 'input-mode:pickPoint',\n priority: 5,\n enabled: true,\n bindings: [{\n id: 'pick-tap',\n pattern: {\n type: 'tap'\n },\n actionId: 'resolve-pick-point',\n consumeInput: true\n }, {\n id: 'pick-cancel-key',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Escape'\n },\n actionId: 'cancel-pick',\n consumeInput: true\n }]\n};\n\n/**\n * Lookup table: input mode type → MappingContext to push.\n * 'normal' maps to null (no extra context).\n */\nexport const INPUT_MODE_CONTEXTS = {\n normal: null,\n pickNode: PICK_NODE_CONTEXT,\n pickNodes: PICK_NODES_CONTEXT,\n pickPoint: PICK_POINT_CONTEXT,\n text: null,\n select: null\n};","/**\n * Built-in Mapping Contexts\n *\n * Default bindings, palm rejection, and input-mode contexts.\n * All are plain data with runtime conditions expressed via guard predicates.\n *\n * Keyboard contexts are in ./keyboard-contexts.ts\n * Default + input mode contexts are in ./pointer-contexts.ts\n */\n\n// Re-export all contexts for backward compat\nexport { SEARCH_CONTEXT, KEYBOARD_MANIPULATE_CONTEXT, KEYBOARD_NAVIGATE_CONTEXT } from './keyboard-contexts';\nexport { DEFAULT_CONTEXT, PICK_NODE_CONTEXT, PICK_NODES_CONTEXT, PICK_POINT_CONTEXT, INPUT_MODE_CONTEXTS } from './pointer-contexts';\n\n// =============================================================================\n// Palm Rejection Context (priority 0 — highest)\n// =============================================================================\n\n/**\n * When a stylus is active, block finger taps and remap finger-on-node\n * drags to pan. Pinch and scroll are intentionally NOT blocked.\n */\nexport const PALM_REJECTION_CONTEXT = {\n id: 'palm-rejection',\n priority: 0,\n enabled: true,\n bindings: [{\n id: 'pr-finger-tap',\n pattern: {\n type: 'tap',\n source: 'finger'\n },\n actionId: 'none',\n when: ctx => ctx.isStylusActive,\n consumeInput: true\n }, {\n id: 'pr-finger-dtap',\n pattern: {\n type: 'double-tap',\n source: 'finger'\n },\n actionId: 'none',\n when: ctx => ctx.isStylusActive,\n consumeInput: true\n }, {\n id: 'pr-finger-ttap',\n pattern: {\n type: 'triple-tap',\n source: 'finger'\n },\n actionId: 'none',\n when: ctx => ctx.isStylusActive,\n consumeInput: true\n }, {\n id: 'pr-finger-lp',\n pattern: {\n type: 'long-press',\n source: 'finger'\n },\n actionId: 'none',\n when: ctx => ctx.isStylusActive,\n consumeInput: true\n }, {\n id: 'pr-finger-drag-node',\n pattern: {\n type: 'drag',\n subjectKind: 'node',\n source: 'finger'\n },\n actionId: 'pan',\n when: ctx => ctx.isStylusActive,\n consumeInput: true\n }]\n};\n\n// =============================================================================\n// Active Interaction Context (priority 15)\n// =============================================================================\n\nexport const ACTIVE_INTERACTION_CONTEXT = {\n id: 'active-interaction',\n priority: 15,\n enabled: true,\n bindings: [{\n id: 'escape-cancel-active-interaction',\n pattern: {\n kind: 'key',\n phase: 'down',\n key: 'Escape'\n },\n actionId: 'cancel-active-input',\n when: ctx => ctx.isDragging || ctx.isSplitting || Boolean(ctx.custom.isSelecting) || Boolean(ctx.custom.isCreatingEdge),\n consumeInput: true\n }]\n};","/**\n * Layer 4: Gesture Dispatcher\n *\n * Routes resolved actions to registered handlers, respecting input phase.\n * Simple function handlers fire only on pointer 'start'/'instant' and key 'down'.\n * Object handlers route each phase to a dedicated method.\n */\n\nimport { isKeyInputEvent } from './types';\n\n// =============================================================================\n// Action Registry\n// =============================================================================\n\nconst handlers = new Map();\n\n/**\n * Register an action handler. Overwrites any existing handler for the same ID.\n */\nexport function registerAction(actionId, handler) {\n handlers.set(actionId, handler);\n}\n\n/**\n * Remove a registered action handler.\n */\nexport function unregisterAction(actionId) {\n handlers.delete(actionId);\n}\n\n/**\n * Get a registered handler (for testing/introspection).\n */\nexport function getHandler(actionId) {\n return handlers.get(actionId);\n}\n\n/**\n * Clear all registered handlers (for testing).\n */\nexport function clearHandlers() {\n handlers.clear();\n}\n\n// =============================================================================\n// Dispatch\n// =============================================================================\n\n/**\n * Dispatch a resolved gesture event to its action handler.\n *\n * Returns true if a handler was found and invoked, false otherwise.\n * The 'none' action ID is always a no-op — it means the binding\n * intentionally blocks the gesture without executing anything.\n */\nexport function dispatch(event, resolution) {\n if (resolution.actionId === 'none') return true;\n const handler = handlers.get(resolution.actionId);\n if (!handler) return false;\n if (typeof handler === 'function') {\n // Simple handler: fire on pointer start/instant and key down.\n if (isKeyInputEvent(event) && event.phase === 'down' || !isKeyInputEvent(event) && (event.phase === 'start' || event.phase === 'instant')) {\n handler(event);\n }\n return true;\n }\n\n // Phase-aware handler\n routePhase(handler, event.phase, event);\n return true;\n}\nfunction routePhase(handler, phase, event) {\n if (isKeyInputEvent(event)) {\n routeKeyPhase(handler, phase, event);\n return;\n }\n switch (phase) {\n case 'start':\n handler.onStart?.(event);\n break;\n case 'move':\n handler.onMove?.(event);\n break;\n case 'end':\n handler.onEnd?.(event);\n break;\n case 'instant':\n handler.onInstant?.(event);\n break;\n case 'cancel':\n handler.onCancel?.(event);\n break;\n }\n}\nfunction routeKeyPhase(handler, phase, event) {\n switch (phase) {\n case 'down':\n handler.onDown?.(event);\n break;\n case 'up':\n handler.onUp?.(event);\n break;\n }\n}","/**\n * Inertia Engine\n *\n * Pure momentum simulation with friction decay.\n * No requestAnimationFrame — the caller drives ticks.\n * Fully testable without any DOM or timer dependency.\n */\n\n// =============================================================================\n// Constants (from current Viewport.tsx)\n// =============================================================================\n\nexport const PAN_FRICTION = 0.92;\nexport const ZOOM_FRICTION = 0.88;\nexport const MIN_VELOCITY = 0.5;\nexport const ZOOM_SNAP_THRESHOLD = 0.03;\nexport const VELOCITY_SAMPLE_COUNT = 5;\n\n// =============================================================================\n// Velocity Sampler\n// =============================================================================\n\n/**\n * Ring buffer that tracks recent velocity samples.\n * Call `sample()` on each move, then `average()` on end.\n */\nexport class VelocitySampler {\n samples = [];\n constructor(maxSamples = VELOCITY_SAMPLE_COUNT) {\n this.maxSamples = maxSamples;\n }\n sample(vx, vy, t) {\n if (this.samples.length >= this.maxSamples) {\n this.samples.shift();\n }\n this.samples.push({\n vx,\n vy,\n t\n });\n }\n average() {\n const n = this.samples.length;\n if (n === 0) return {\n x: 0,\n y: 0\n };\n let sx = 0;\n let sy = 0;\n for (const s of this.samples) {\n sx += s.vx;\n sy += s.vy;\n }\n return {\n x: sx / n,\n y: sy / n\n };\n }\n reset() {\n this.samples.length = 0;\n }\n}\n\n// =============================================================================\n// Pan Inertia\n// =============================================================================\n\nexport class PanInertia {\n constructor(velocity, friction = PAN_FRICTION, minVelocity = MIN_VELOCITY) {\n this.friction = friction;\n this.minVelocity = minVelocity;\n this.vx = velocity.x;\n this.vy = velocity.y;\n }\n\n /**\n * Advance one frame. Returns the velocity delta to apply,\n * or null if below threshold (animation complete).\n */\n tick() {\n this.vx *= this.friction;\n this.vy *= this.friction;\n if (Math.abs(this.vx) < this.minVelocity && Math.abs(this.vy) < this.minVelocity) {\n return null;\n }\n return {\n x: this.vx,\n y: this.vy\n };\n }\n}\n\n// =============================================================================\n// Zoom Inertia\n// =============================================================================\n\nexport class ZoomInertia {\n constructor(velocity, origin, friction = ZOOM_FRICTION, minVelocity = MIN_VELOCITY, snapThreshold = ZOOM_SNAP_THRESHOLD) {\n this.origin = origin;\n this.friction = friction;\n this.minVelocity = minVelocity;\n this.snapThreshold = snapThreshold;\n this.v = velocity;\n }\n\n /**\n * Advance one frame. Returns zoom delta + origin,\n * or null if below threshold.\n */\n tick(currentZoom) {\n this.v *= this.friction;\n if (Math.abs(this.v) < this.minVelocity) {\n // Snap to 100% if close\n if (Math.abs(currentZoom - 1) < this.snapThreshold) {\n const snapDelta = 1 - currentZoom;\n return Math.abs(snapDelta) > 0.001 ? {\n delta: snapDelta,\n origin: this.origin\n } : null;\n }\n return null;\n }\n return {\n delta: this.v,\n origin: this.origin\n };\n }\n}","/**\n * Graph state management — core atoms\n *\n * Foundation atoms for the Graphology + Jotai graph system.\n * Position, derived, and mutation atoms live in their own modules.\n *\n * @see ./graph-position.ts — position atoms\n * @see ./graph-derived.ts — read-only UI derivation atoms\n * @see ./graph-mutations.ts — write atoms (CRUD, split/merge, DB sync)\n */\n\nimport { atom } from 'jotai';\nimport Graph from 'graphology';\n// --- Graph Configuration ---\n\nexport const graphOptions = {\n type: 'directed',\n multi: true,\n allowSelfLoops: true\n};\n\n// --- Core Graph Atoms ---\n\n/**\n * Currently active graph ID\n */\nexport const currentGraphIdAtom = atom(null);\n\n/**\n * Main graph instance\n */\nexport const graphAtom = atom(new Graph(graphOptions));\n\n/**\n * Version counter to trigger re-renders\n */\nexport const graphUpdateVersionAtom = atom(0);\n\n// --- Edge Creation State ---\n\nexport const edgeCreationAtom = atom({\n isCreating: false,\n sourceNodeId: null,\n sourceNodePosition: null,\n targetPosition: null,\n hoveredTargetNodeId: null,\n sourceHandle: null,\n targetHandle: null,\n sourcePort: null,\n targetPort: null,\n snappedTargetPosition: null\n});\n\n// --- Drag State ---\n\nexport const draggingNodeIdAtom = atom(null);\nexport const preDragNodeAttributesAtom = atom(null);","/**\n * Graph position management\n *\n * Per-node position atoms derived from Graphology.\n * Structural equality caching prevents unnecessary re-renders.\n */\n\nimport { atom } from 'jotai';\nimport { atomFamily } from 'jotai-family';\nimport Graph from 'graphology';\nimport { graphAtom, graphUpdateVersionAtom, graphOptions } from './graph-store';\nimport { createDebug } from '../utils/debug';\nimport { clearAllPendingMutations } from '../utils/mutation-queue';\nimport { canvasMark } from './perf';\nconst debug = createDebug('graph:position');\n\n// --- Position Cache ---\n\n/**\n * Cache for the previous position values, scoped per Graph instance via WeakMap.\n * Enables structural equality — only notify dependents when x/y actually changed.\n */\nconst _positionCacheByGraph = new WeakMap();\nfunction getPositionCache(graph) {\n let cache = _positionCacheByGraph.get(graph);\n if (!cache) {\n cache = new Map();\n _positionCacheByGraph.set(graph, cache);\n }\n return cache;\n}\n\n// --- Position Atoms ---\n\n/**\n * Counter to trigger edge re-renders when positions change\n */\nexport const nodePositionUpdateCounterAtom = atom(0);\n\n/**\n * Per-node position atoms - derived from Graphology (single source of truth)\n * These are read-only atoms that derive position from the graph.\n */\nexport const nodePositionAtomFamily = atomFamily(nodeId => atom(get => {\n get(nodePositionUpdateCounterAtom); // Invalidation trigger for fine-grained updates\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) {\n return {\n x: 0,\n y: 0\n };\n }\n const x = graph.getNodeAttribute(nodeId, 'x');\n const y = graph.getNodeAttribute(nodeId, 'y');\n\n // Structural equality: return the same reference if position unchanged\n const cache = getPositionCache(graph);\n const prev = cache.get(nodeId);\n if (prev && prev.x === x && prev.y === y) {\n return prev;\n }\n const pos = {\n x,\n y\n };\n cache.set(nodeId, pos);\n return pos;\n}));\n\n/**\n * Update a node's position\n */\nexport const updateNodePositionAtom = atom(null, (get, set, {\n nodeId,\n position\n}) => {\n const end = canvasMark('drag-frame');\n const graph = get(graphAtom);\n if (graph.hasNode(nodeId)) {\n debug('Updating node %s position to %o', nodeId, position);\n graph.setNodeAttribute(nodeId, 'x', position.x);\n graph.setNodeAttribute(nodeId, 'y', position.y);\n // Position atom is derived - no need to set it, just trigger re-read\n set(nodePositionUpdateCounterAtom, c => c + 1);\n }\n end();\n});\n\n/**\n * Cleanup position atom for a deleted node\n * Note: Position atoms are now derived, so cleanup is optional but helps memory\n */\nexport const cleanupNodePositionAtom = atom(null, (get, _set, nodeId) => {\n nodePositionAtomFamily.remove(nodeId);\n const graph = get(graphAtom);\n getPositionCache(graph).delete(nodeId);\n debug('Removed position atom for node: %s', nodeId);\n});\n\n/**\n * Cleanup all position atoms (used when switching graphs)\n * Note: Position atoms are now derived, so cleanup is optional but helps memory\n */\nexport const cleanupAllNodePositionsAtom = atom(null, (get, _set) => {\n const graph = get(graphAtom);\n const nodeIds = graph.nodes();\n nodeIds.forEach(nodeId => {\n nodePositionAtomFamily.remove(nodeId);\n });\n _positionCacheByGraph.delete(graph);\n debug('Removed %d position atoms', nodeIds.length);\n});\n\n/**\n * Clear graph when switching to a new graph\n */\nexport const clearGraphOnSwitchAtom = atom(null, (get, set) => {\n debug('Clearing graph for switch');\n set(cleanupAllNodePositionsAtom);\n clearAllPendingMutations();\n const emptyGraph = new Graph(graphOptions);\n set(graphAtom, emptyGraph);\n set(graphUpdateVersionAtom, v => v + 1);\n});","/**\n * Debug utility for @blinksgg/canvas\n *\n * Uses the `debug` package with `canvas:*` namespaces.\n * Enable in browser: `localStorage.debug = 'canvas:*'`\n * Enable in Node: `DEBUG=canvas:* node ...`\n *\n * Log levels:\n * debug('message') — verbose trace (blue)\n * debug.warn('message') — warnings (yellow, always stderr)\n * debug.error('message') — errors (red, always stderr)\n */\n\nimport debugFactory from 'debug';\nconst NAMESPACE = 'canvas';\n/**\n * Create a debug logger for a specific module.\n *\n * @example\n * ```ts\n * const debug = createDebug('graph');\n * debug('loaded %d nodes', count); // canvas:graph\n * debug.warn('node %s not found', id); // canvas:graph:warn\n * debug.error('sync failed: %O', err); // canvas:graph:error\n * ```\n */\nexport function createDebug(module) {\n const base = debugFactory(`${NAMESPACE}:${module}`);\n const warn = debugFactory(`${NAMESPACE}:${module}:warn`);\n const error = debugFactory(`${NAMESPACE}:${module}:error`);\n\n // Warnings and errors always log (even without DEBUG=canvas:*)\n warn.enabled = true;\n error.enabled = true;\n\n // Color hints: warn = yellow, error = red\n warn.log = console.warn.bind(console);\n error.log = console.error.bind(console);\n\n // Build the debugger with warn/error sub-loggers\n const debugFn = Object.assign(base, {\n warn,\n error\n });\n return debugFn;\n}\n\n// Pre-configured debug loggers\nexport const debug = {\n graph: {\n node: createDebug('graph:node'),\n edge: createDebug('graph:edge'),\n sync: createDebug('graph:sync')\n },\n ui: {\n selection: createDebug('ui:selection'),\n drag: createDebug('ui:drag'),\n resize: createDebug('ui:resize')\n },\n sync: {\n status: createDebug('sync:status'),\n mutations: createDebug('sync:mutations'),\n queue: createDebug('sync:queue')\n },\n viewport: createDebug('viewport')\n};","/**\n * Mutation queue for tracking pending node updates\n *\n * Prevents race conditions during rapid drag operations.\n */\n\n/**\n * Global map to track pending mutations per node\n */\nexport const pendingNodeMutations = new Map();\n\n/**\n * Get or create pending mutation state for a node\n */\nexport function getPendingState(nodeId) {\n let state = pendingNodeMutations.get(nodeId);\n if (!state) {\n state = {\n inFlight: false,\n queuedPosition: null,\n queuedUiProperties: null,\n graphId: null\n };\n pendingNodeMutations.set(nodeId, state);\n }\n return state;\n}\n\n/**\n * Clear pending state for a node\n */\nexport function clearPendingState(nodeId) {\n pendingNodeMutations.delete(nodeId);\n}\n\n/**\n * Clear all pending mutation state (used on graph switch)\n */\nexport function clearAllPendingMutations() {\n pendingNodeMutations.clear();\n}\n\n/**\n * Check if any node has pending mutations\n */\nexport function hasPendingMutations() {\n for (const state of pendingNodeMutations.values()) {\n if (state.inFlight || state.queuedPosition !== null || state.queuedUiProperties !== null) {\n return true;\n }\n }\n return false;\n}","/**\n * Performance Instrumentation\n *\n * Opt-in performance.mark / performance.measure wrappers for DevTools profiling.\n * All marks are prefixed with \"canvas:\" for easy filtering.\n *\n * Usage:\n * const end = canvasMark('drag-frame');\n * // ... work ...\n * end(); // calls performance.measure automatically\n */\n\nimport { atom } from 'jotai';\n\n/**\n * Whether performance instrumentation is enabled.\n * Off by default — set to true to see marks in DevTools Performance tab.\n */\nexport const perfEnabledAtom = atom(false);\n\n// Module-level flag mirrored from atom for zero-overhead checks in hot paths.\n// Updated by `setPerfEnabled`.\nlet _enabled = false;\n\n/**\n * Imperatively set perf instrumentation on/off.\n * Useful from devtools console: `window.__canvasPerf?.(true)`.\n */\nexport function setPerfEnabled(enabled) {\n _enabled = enabled;\n}\n\n// Expose on window for easy devtools access\nif (typeof window !== 'undefined') {\n window.__canvasPerf = setPerfEnabled;\n}\n\n/**\n * Start a performance mark. Returns a function that, when called,\n * creates a measure from the mark to the current time.\n *\n * When instrumentation is disabled, returns a no-op (zero overhead).\n */\nexport function canvasMark(name) {\n if (!_enabled) return _noop;\n const markName = `canvas:${name}`;\n try {\n performance.mark(markName);\n } catch {\n return _noop;\n }\n return () => {\n try {\n performance.measure(`canvas:${name}`, markName);\n } catch {\n // mark may have been cleared\n }\n };\n}\nfunction _noop() {}\n\n/**\n * Measure a synchronous function call.\n */\nexport function canvasWrap(name, fn) {\n const end = canvasMark(name);\n try {\n return fn();\n } finally {\n end();\n }\n}","/**\n * Graph derived atoms\n *\n * Read-only UI atoms derived from the Graphology graph.\n * Provides node/edge state for rendering with structural equality caching.\n */\n\nimport { atom } from 'jotai';\nimport { atomFamily } from 'jotai-family';\nimport { graphAtom, graphUpdateVersionAtom, currentGraphIdAtom, edgeCreationAtom, draggingNodeIdAtom } from './graph-store';\nimport { nodePositionAtomFamily } from './graph-position';\nimport { panAtom, zoomAtom, viewportRectAtom } from './viewport-store';\nimport { collapsedGroupsAtom, collapsedEdgeRemapAtom } from './group-store';\n\n// --- Derived Node Atoms ---\n\n/**\n * Highest z-index among nodes\n */\nexport const highestZIndexAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n let maxZ = 0;\n graph.forEachNode((_node, attributes) => {\n if (attributes.zIndex > maxZ) {\n maxZ = attributes.zIndex;\n }\n });\n return maxZ;\n});\n\n/**\n * All UI nodes with current positions\n *\n * Uses structural equality: if every entry is reference-equal to the\n * previous result, the same array is returned to avoid downstream re-renders.\n */\nconst _prevUiNodesByGraph = new WeakMap();\nexport const uiNodesAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n const currentDraggingId = get(draggingNodeIdAtom);\n const collapsed = get(collapsedGroupsAtom);\n const nodes = [];\n graph.forEachNode((nodeId, attributes) => {\n // Skip nodes whose parent (or ancestor) is collapsed\n if (collapsed.size > 0) {\n let current = nodeId;\n let hidden = false;\n while (true) {\n if (!graph.hasNode(current)) break;\n const pid = graph.getNodeAttributes(current).parentId;\n if (!pid) break;\n if (collapsed.has(pid)) {\n hidden = true;\n break;\n }\n current = pid;\n }\n if (hidden) return;\n }\n const position = get(nodePositionAtomFamily(nodeId));\n nodes.push({\n ...attributes,\n id: nodeId,\n position,\n isDragging: nodeId === currentDraggingId\n });\n });\n\n // Structural equality: return previous array if length and entries match\n const prev = _prevUiNodesByGraph.get(graph) ?? [];\n if (nodes.length === prev.length && nodes.every((n, i) => n.id === prev[i].id && n.position === prev[i].position && n.isDragging === prev[i].isDragging)) {\n return prev;\n }\n _prevUiNodesByGraph.set(graph, nodes);\n return nodes;\n});\n\n/**\n * All node keys\n */\nexport const nodeKeysAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n return graph.nodes();\n});\n\n/**\n * Per-node UI state\n */\nexport const nodeFamilyAtom = atomFamily(nodeId => atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) {\n return null;\n }\n const attributes = graph.getNodeAttributes(nodeId);\n const position = get(nodePositionAtomFamily(nodeId));\n const currentDraggingId = get(draggingNodeIdAtom);\n return {\n ...attributes,\n id: nodeId,\n position,\n isDragging: nodeId === currentDraggingId\n };\n}), (a, b) => a === b);\n\n// --- Derived Edge Atoms ---\n\n/**\n * All edge keys\n */\nexport const edgeKeysAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n return graph.edges();\n});\n\n/**\n * Edge keys including temp edge during creation\n */\nexport const edgeKeysWithTempEdgeAtom = atom(get => {\n const keys = get(edgeKeysAtom);\n const edgeCreation = get(edgeCreationAtom);\n if (edgeCreation.isCreating) {\n return [...keys, 'temp-creating-edge'];\n }\n return keys;\n});\n\n/**\n * Per-edge UI state\n *\n * Structural equality cache: stores previous result per edge key.\n * Returns previous object when all fields match — prevents downstream re-renders.\n */\nconst _edgeCacheByGraph = new WeakMap();\nfunction getEdgeCache(graph) {\n let cache = _edgeCacheByGraph.get(graph);\n if (!cache) {\n cache = new Map();\n _edgeCacheByGraph.set(graph, cache);\n }\n return cache;\n}\nexport const edgeFamilyAtom = atomFamily(key => atom(get => {\n // Position reactivity flows through nodePositionAtomFamily(sourceId/targetId)\n // with structural equality caching — only connected edges re-render on drag.\n // graphUpdateVersionAtom handles non-position attribute changes (label, color)\n // and is NOT bumped during drag, so it won't cause O(E) re-renders.\n get(graphUpdateVersionAtom);\n if (key === 'temp-creating-edge') {\n const edgeCreationState = get(edgeCreationAtom);\n const graph = get(graphAtom);\n if (edgeCreationState.isCreating && edgeCreationState.sourceNodeId && edgeCreationState.targetPosition) {\n const sourceNodeAttrs = graph.getNodeAttributes(edgeCreationState.sourceNodeId);\n const sourceNodePosition = get(nodePositionAtomFamily(edgeCreationState.sourceNodeId));\n const pan = get(panAtom);\n const zoom = get(zoomAtom);\n const viewportRect = get(viewportRectAtom);\n if (sourceNodeAttrs && viewportRect) {\n const mouseX = edgeCreationState.targetPosition.x - viewportRect.left;\n const mouseY = edgeCreationState.targetPosition.y - viewportRect.top;\n const worldTargetX = (mouseX - pan.x) / zoom;\n const worldTargetY = (mouseY - pan.y) / zoom;\n const tempEdge = {\n key: 'temp-creating-edge',\n sourceId: edgeCreationState.sourceNodeId,\n targetId: 'temp-cursor',\n sourcePosition: sourceNodePosition,\n targetPosition: {\n x: worldTargetX,\n y: worldTargetY\n },\n sourceNodeSize: sourceNodeAttrs.size,\n sourceNodeWidth: sourceNodeAttrs.width,\n sourceNodeHeight: sourceNodeAttrs.height,\n targetNodeSize: 0,\n targetNodeWidth: 0,\n targetNodeHeight: 0,\n type: 'dashed',\n color: '#FF9800',\n weight: 2,\n label: undefined,\n dbData: {\n id: 'temp-creating-edge',\n graph_id: get(currentGraphIdAtom) || '',\n source_node_id: edgeCreationState.sourceNodeId,\n target_node_id: 'temp-cursor',\n edge_type: 'temp',\n filter_condition: null,\n ui_properties: null,\n data: null,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString()\n }\n };\n return tempEdge;\n }\n }\n return null;\n }\n const graph = get(graphAtom);\n if (!graph.hasEdge(key)) {\n getEdgeCache(graph).delete(key);\n return null;\n }\n const sourceId = graph.source(key);\n const targetId = graph.target(key);\n const attributes = graph.getEdgeAttributes(key);\n\n // Re-route edges through collapsed groups: if a source/target is inside\n // a collapsed group, use the group node's position and dimensions instead\n const remap = get(collapsedEdgeRemapAtom);\n const effectiveSourceId = remap.get(sourceId) ?? sourceId;\n const effectiveTargetId = remap.get(targetId) ?? targetId;\n if (!graph.hasNode(effectiveSourceId) || !graph.hasNode(effectiveTargetId)) {\n getEdgeCache(graph).delete(key);\n return null;\n }\n const sourceAttributes = graph.getNodeAttributes(effectiveSourceId);\n const targetAttributes = graph.getNodeAttributes(effectiveTargetId);\n const sourcePosition = get(nodePositionAtomFamily(effectiveSourceId));\n const targetPosition = get(nodePositionAtomFamily(effectiveTargetId));\n if (sourceAttributes && targetAttributes) {\n const next = {\n ...attributes,\n key,\n sourceId: effectiveSourceId,\n targetId: effectiveTargetId,\n sourcePosition,\n targetPosition,\n sourceNodeSize: sourceAttributes.size,\n targetNodeSize: targetAttributes.size,\n sourceNodeWidth: sourceAttributes.width ?? sourceAttributes.size,\n sourceNodeHeight: sourceAttributes.height ?? sourceAttributes.size,\n targetNodeWidth: targetAttributes.width ?? targetAttributes.size,\n targetNodeHeight: targetAttributes.height ?? targetAttributes.size\n };\n\n // Structural equality: return cached object if all fields match\n const edgeCache = getEdgeCache(graph);\n const prev = edgeCache.get(key);\n if (prev && prev.sourcePosition === next.sourcePosition && prev.targetPosition === next.targetPosition && prev.sourceId === next.sourceId && prev.targetId === next.targetId && prev.type === next.type && prev.color === next.color && prev.weight === next.weight && prev.label === next.label && prev.sourceNodeSize === next.sourceNodeSize && prev.targetNodeSize === next.targetNodeSize && prev.sourceNodeWidth === next.sourceNodeWidth && prev.sourceNodeHeight === next.sourceNodeHeight && prev.targetNodeWidth === next.targetNodeWidth && prev.targetNodeHeight === next.targetNodeHeight) {\n return prev;\n }\n edgeCache.set(key, next);\n return next;\n }\n getEdgeCache(graph).delete(key);\n return null;\n}), (a, b) => a === b);","/**\n * Viewport state management\n *\n * Manages pan, zoom, and viewport rect for the canvas.\n */\n\nimport { atom } from 'jotai';\n// --- Core Viewport Atoms ---\n\n/**\n * Current zoom level (1 = 100%)\n */\nexport const zoomAtom = atom(1);\n\n/**\n * Current pan offset in pixels\n */\nexport const panAtom = atom({\n x: 0,\n y: 0\n});\n\n/**\n * Viewport DOM rect (set by the Viewport component)\n */\nexport const viewportRectAtom = atom(null);\n\n// --- Coordinate Conversion ---\n\n/**\n * Convert screen coordinates to world coordinates\n */\nexport const screenToWorldAtom = atom(get => {\n return (screenX, screenY) => {\n const pan = get(panAtom);\n const zoom = get(zoomAtom);\n const rect = get(viewportRectAtom);\n if (!rect) {\n return {\n x: screenX,\n y: screenY\n };\n }\n const relativeX = screenX - rect.left;\n const relativeY = screenY - rect.top;\n return {\n x: (relativeX - pan.x) / zoom,\n y: (relativeY - pan.y) / zoom\n };\n };\n});\n\n/**\n * Convert world coordinates to screen coordinates\n */\nexport const worldToScreenAtom = atom(get => {\n return (worldX, worldY) => {\n const pan = get(panAtom);\n const zoom = get(zoomAtom);\n const rect = get(viewportRectAtom);\n if (!rect) {\n return {\n x: worldX,\n y: worldY\n };\n }\n return {\n x: worldX * zoom + pan.x + rect.left,\n y: worldY * zoom + pan.y + rect.top\n };\n };\n});\n\n// --- Viewport Actions ---\n\n/**\n * Set zoom level with optional center point\n */\nexport const setZoomAtom = atom(null, (get, set, {\n zoom,\n centerX,\n centerY\n}) => {\n const currentZoom = get(zoomAtom);\n const pan = get(panAtom);\n const rect = get(viewportRectAtom);\n\n // Clamp zoom\n const newZoom = Math.max(0.1, Math.min(5, zoom));\n if (centerX !== undefined && centerY !== undefined && rect) {\n // Zoom towards the center point\n const relativeX = centerX - rect.left;\n const relativeY = centerY - rect.top;\n const worldX = (relativeX - pan.x) / currentZoom;\n const worldY = (relativeY - pan.y) / currentZoom;\n const newPanX = relativeX - worldX * newZoom;\n const newPanY = relativeY - worldY * newZoom;\n set(panAtom, {\n x: newPanX,\n y: newPanY\n });\n }\n set(zoomAtom, newZoom);\n});\n\n/**\n * Reset viewport to default state\n */\nexport const resetViewportAtom = atom(null, (_get, set) => {\n set(zoomAtom, 1);\n set(panAtom, {\n x: 0,\n y: 0\n });\n});\n\n// =============================================================================\n// Headless Layout Atoms\n// Fit-to-bounds and center-on-node without React hooks\n// =============================================================================\n\nimport { graphAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { uiNodesAtom } from './graph-derived';\nimport { selectedNodeIdsAtom } from './selection-store';\nimport { calculateBounds, FitToBoundsMode } from '../utils/layout';\n\n/**\n * Write atom: fit viewport to show all nodes or selection.\n * Pure Jotai — no React required.\n */\nexport const fitToBoundsAtom = atom(null, (get, set, {\n mode,\n padding = 20\n}) => {\n const normalizedMode = typeof mode === 'string' ? mode === 'graph' ? FitToBoundsMode.Graph : FitToBoundsMode.Selection : mode;\n const viewportSize = get(viewportRectAtom);\n if (!viewportSize || viewportSize.width <= 0 || viewportSize.height <= 0) return;\n\n // Force position counter read so bounds are fresh\n get(nodePositionUpdateCounterAtom);\n let bounds;\n if (normalizedMode === FitToBoundsMode.Graph) {\n const graph = get(graphAtom);\n const nodes = graph.nodes().map(node => {\n const attrs = graph.getNodeAttributes(node);\n return {\n x: attrs.x,\n y: attrs.y,\n width: attrs.width || 500,\n height: attrs.height || 500\n };\n });\n bounds = calculateBounds(nodes);\n } else {\n const selectedIds = get(selectedNodeIdsAtom);\n const allNodes = get(uiNodesAtom);\n const selectedNodes = allNodes.filter(n => selectedIds.has(n.id)).map(n => ({\n x: n.position.x,\n y: n.position.y,\n width: n.width ?? 500,\n height: n.height ?? 500\n }));\n bounds = calculateBounds(selectedNodes);\n }\n if (bounds.width <= 0 || bounds.height <= 0) return;\n const maxHPad = Math.max(0, viewportSize.width / 2 - 1);\n const maxVPad = Math.max(0, viewportSize.height / 2 - 1);\n const safePadding = Math.max(0, Math.min(padding, maxHPad, maxVPad));\n const effW = Math.max(1, viewportSize.width - 2 * safePadding);\n const effH = Math.max(1, viewportSize.height - 2 * safePadding);\n const scale = Math.min(effW / bounds.width, effH / bounds.height);\n if (scale <= 0 || !isFinite(scale)) return;\n set(zoomAtom, scale);\n const scaledW = bounds.width * scale;\n const scaledH = bounds.height * scale;\n const startX = safePadding + (effW - scaledW) / 2;\n const startY = safePadding + (effH - scaledH) / 2;\n set(panAtom, {\n x: startX - bounds.x * scale,\n y: startY - bounds.y * scale\n });\n});\n\n/**\n * Write atom: center viewport on a specific node.\n */\nexport const centerOnNodeAtom = atom(null, (get, set, nodeId) => {\n const nodes = get(uiNodesAtom);\n const node = nodes.find(n => n.id === nodeId);\n if (!node) return;\n const {\n x,\n y,\n width = 200,\n height = 100\n } = node;\n const zoom = get(zoomAtom);\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const rect = get(viewportRectAtom);\n const halfWidth = rect ? rect.width / 2 : 400;\n const halfHeight = rect ? rect.height / 2 : 300;\n set(panAtom, {\n x: halfWidth - centerX * zoom,\n y: halfHeight - centerY * zoom\n });\n});\n\n// =============================================================================\n// Zoom Transition State\n// When zooming in on a node past a threshold, trigger a fade transition\n// =============================================================================\n\n/** The zoom level at which we start the transition (zoom in) */\nexport const ZOOM_TRANSITION_THRESHOLD = 3.5;\n\n/** The zoom level at which we exit transition mode (zoom out) */\nexport const ZOOM_EXIT_THRESHOLD = 2.0;\n\n/** The node ID that's currently being zoomed into (center of viewport) */\nexport const zoomFocusNodeIdAtom = atom(null);\n\n/** Transition progress: 0 = normal view, 1 = fully transitioned to locked view */\nexport const zoomTransitionProgressAtom = atom(0);\n\n/** Computed: whether we're in a zoom transition */\nexport const isZoomTransitioningAtom = atom(get => {\n const progress = get(zoomTransitionProgressAtom);\n return progress > 0 && progress < 1;\n});\n\n// --- Zoom Animation Target ---\n\n/** Current zoom animation target, or null when idle */\nexport const zoomAnimationTargetAtom = atom(null);\n\n/**\n * Write atom: start an animated zoom-to-node transition.\n * Sets the animation target; the actual animation loop runs in useZoomTransition hook.\n */\nexport const animateZoomToNodeAtom = atom(null, (get, set, {\n nodeId,\n targetZoom,\n duration = 300\n}) => {\n const nodes = get(uiNodesAtom);\n const node = nodes.find(n => n.id === nodeId);\n if (!node) return;\n const {\n x,\n y,\n width = 200,\n height = 100\n } = node;\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const rect = get(viewportRectAtom);\n const halfWidth = rect ? rect.width / 2 : 400;\n const halfHeight = rect ? rect.height / 2 : 300;\n const finalZoom = targetZoom ?? get(zoomAtom);\n const targetPan = {\n x: halfWidth - centerX * finalZoom,\n y: halfHeight - centerY * finalZoom\n };\n set(zoomFocusNodeIdAtom, nodeId);\n set(zoomAnimationTargetAtom, {\n targetZoom: finalZoom,\n targetPan,\n startZoom: get(zoomAtom),\n startPan: {\n ...get(panAtom)\n },\n duration,\n startTime: performance.now()\n });\n});\n\n/**\n * Write atom: start an animated fit-to-bounds transition.\n * Computes the target viewport, then animates to it.\n */\nexport const animateFitToBoundsAtom = atom(null, (get, set, {\n mode,\n padding = 20,\n duration = 300\n}) => {\n const viewportSize = get(viewportRectAtom);\n if (!viewportSize || viewportSize.width <= 0 || viewportSize.height <= 0) return;\n get(nodePositionUpdateCounterAtom);\n let bounds;\n if (mode === 'graph') {\n const graph = get(graphAtom);\n const nodes = graph.nodes().map(node => {\n const attrs = graph.getNodeAttributes(node);\n return {\n x: attrs.x,\n y: attrs.y,\n width: attrs.width || 500,\n height: attrs.height || 500\n };\n });\n bounds = calculateBounds(nodes);\n } else {\n const selectedIds = get(selectedNodeIdsAtom);\n const allNodes = get(uiNodesAtom);\n const selectedNodes = allNodes.filter(n => selectedIds.has(n.id)).map(n => ({\n x: n.position.x,\n y: n.position.y,\n width: n.width ?? 500,\n height: n.height ?? 500\n }));\n bounds = calculateBounds(selectedNodes);\n }\n if (bounds.width <= 0 || bounds.height <= 0) return;\n const safePadding = Math.max(0, Math.min(padding, viewportSize.width / 2 - 1, viewportSize.height / 2 - 1));\n const effW = Math.max(1, viewportSize.width - 2 * safePadding);\n const effH = Math.max(1, viewportSize.height - 2 * safePadding);\n const scale = Math.min(effW / bounds.width, effH / bounds.height);\n if (scale <= 0 || !isFinite(scale)) return;\n const scaledW = bounds.width * scale;\n const scaledH = bounds.height * scale;\n const startX = safePadding + (effW - scaledW) / 2;\n const startY = safePadding + (effH - scaledH) / 2;\n const targetPan = {\n x: startX - bounds.x * scale,\n y: startY - bounds.y * scale\n };\n set(zoomAnimationTargetAtom, {\n targetZoom: scale,\n targetPan,\n startZoom: get(zoomAtom),\n startPan: {\n ...get(panAtom)\n },\n duration,\n startTime: performance.now()\n });\n});","/**\n * Selection state management\n *\n * Manages node and edge selection state.\n */\n\nimport { atom } from 'jotai';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('selection');\n\n// --- Core Selection Atoms ---\n\n/**\n * Set of currently selected node IDs\n */\nexport const selectedNodeIdsAtom = atom(new Set());\n\n/**\n * Currently selected edge ID (only one edge can be selected at a time)\n */\nexport const selectedEdgeIdAtom = atom(null);\n\n// --- Selection Actions ---\n\n/**\n * Handle node pointer down with shift-click support for multi-select\n */\n\nexport const handleNodePointerDownSelectionAtom = atom(null, (get, set, {\n nodeId,\n isShiftPressed\n}) => {\n const currentSelection = get(selectedNodeIdsAtom);\n debug('handleNodePointerDownSelection: nodeId=%s, shift=%s, current=%o', nodeId, isShiftPressed, Array.from(currentSelection));\n\n // Clear edge selection when selecting a node\n set(selectedEdgeIdAtom, null);\n if (isShiftPressed) {\n const newSelection = new Set(currentSelection);\n if (newSelection.has(nodeId)) {\n newSelection.delete(nodeId);\n } else {\n newSelection.add(nodeId);\n }\n debug('Shift-click, setting selection to: %o', Array.from(newSelection));\n set(selectedNodeIdsAtom, newSelection);\n } else {\n // Only change selection if node is NOT already selected\n // This allows multi-node drag to work\n if (!currentSelection.has(nodeId)) {\n debug('Node not in selection, selecting: %s', nodeId);\n set(selectedNodeIdsAtom, new Set([nodeId]));\n } else {\n debug('Node already selected, preserving multi-select');\n }\n }\n});\n\n/**\n * Select a single node, clearing any previous selection\n */\nexport const selectSingleNodeAtom = atom(null, (get, set, nodeId) => {\n debug('selectSingleNode: %s', nodeId);\n set(selectedEdgeIdAtom, null);\n if (nodeId === null || nodeId === undefined) {\n debug('Clearing selection');\n set(selectedNodeIdsAtom, new Set());\n } else {\n const currentSelection = get(selectedNodeIdsAtom);\n if (currentSelection.has(nodeId) && currentSelection.size === 1) {\n return; // Already the only selection\n }\n set(selectedNodeIdsAtom, new Set([nodeId]));\n }\n});\n\n/**\n * Toggle a node in/out of selection\n */\nexport const toggleNodeInSelectionAtom = atom(null, (get, set, nodeId) => {\n const currentSelection = get(selectedNodeIdsAtom);\n const newSelection = new Set(currentSelection);\n if (newSelection.has(nodeId)) {\n newSelection.delete(nodeId);\n } else {\n newSelection.add(nodeId);\n }\n set(selectedNodeIdsAtom, newSelection);\n});\n\n/**\n * Clear all node selection\n */\nexport const clearSelectionAtom = atom(null, (_get, set) => {\n debug('clearSelection');\n set(selectedNodeIdsAtom, new Set());\n});\n\n/**\n * Add multiple nodes to selection\n */\nexport const addNodesToSelectionAtom = atom(null, (get, set, nodeIds) => {\n const currentSelection = get(selectedNodeIdsAtom);\n const newSelection = new Set(currentSelection);\n for (const nodeId of nodeIds) {\n newSelection.add(nodeId);\n }\n set(selectedNodeIdsAtom, newSelection);\n});\n\n/**\n * Remove multiple nodes from selection\n */\nexport const removeNodesFromSelectionAtom = atom(null, (get, set, nodeIds) => {\n const currentSelection = get(selectedNodeIdsAtom);\n const newSelection = new Set(currentSelection);\n for (const nodeId of nodeIds) {\n newSelection.delete(nodeId);\n }\n set(selectedNodeIdsAtom, newSelection);\n});\n\n/**\n * Select an edge (clears node selection)\n */\nexport const selectEdgeAtom = atom(null, (get, set, edgeId) => {\n set(selectedEdgeIdAtom, edgeId);\n if (edgeId !== null) {\n set(selectedNodeIdsAtom, new Set());\n }\n});\n\n/**\n * Clear edge selection\n */\nexport const clearEdgeSelectionAtom = atom(null, (_get, set) => {\n set(selectedEdgeIdAtom, null);\n});\n\n// --- Keyboard Focus ---\n\n/**\n * The node that has keyboard focus (distinct from selection).\n * Used for arrow key navigation between nodes.\n * null means no node has keyboard focus.\n */\nexport const focusedNodeIdAtom = atom(null);\n\n/**\n * Set keyboard focus to a node, or clear focus with null\n */\nexport const setFocusedNodeAtom = atom(null, (_get, set, nodeId) => {\n set(focusedNodeIdAtom, nodeId);\n});\n\n/**\n * Whether a node currently has keyboard focus\n */\nexport const hasFocusedNodeAtom = atom(get => get(focusedNodeIdAtom) !== null);\n\n// --- Derived Atoms ---\n\n/**\n * Count of selected nodes\n */\nexport const selectedNodesCountAtom = atom(get => get(selectedNodeIdsAtom).size);\n\n/**\n * Whether any node is selected\n */\nexport const hasSelectionAtom = atom(get => get(selectedNodeIdsAtom).size > 0);","/**\n * Layout utilities for canvas operations.\n *\n * Provides geometry calculations, bounds computation, and node overlap detection.\n */\n\n// ============================================================\n// Types\n// ============================================================\n\n/**\n * Rectangle with position and dimensions\n */\n\n/**\n * Node with position and dimensions (alias for geometry functions)\n */\n\n/**\n * Extended bounds with computed edges\n */\n\n/**\n * Mode for fitToBounds operation\n */\nexport let FitToBoundsMode = /*#__PURE__*/function (FitToBoundsMode) {\n /** Fit all nodes in the graph */\n FitToBoundsMode[\"Graph\"] = \"graph\";\n /** Fit only selected nodes */\n FitToBoundsMode[\"Selection\"] = \"selection\";\n return FitToBoundsMode;\n}({});\n\n// ============================================================\n// Bounds Calculation\n// ============================================================\n\n/**\n * Calculate the bounding rectangle that contains all nodes.\n *\n * @param nodes - Array of rectangles (nodes with x, y, width, height)\n * @returns Bounding rectangle containing all nodes\n *\n * @example\n * const bounds = calculateBounds([\n * { x: 0, y: 0, width: 100, height: 100 },\n * { x: 200, y: 150, width: 100, height: 100 },\n * ]);\n * // bounds = { x: 0, y: 0, width: 300, height: 250 }\n */\nexport const calculateBounds = nodes => {\n if (nodes.length === 0) {\n return {\n x: 0,\n y: 0,\n width: 0,\n height: 0\n };\n }\n const minX = Math.min(...nodes.map(node => node.x));\n const minY = Math.min(...nodes.map(node => node.y));\n const maxX = Math.max(...nodes.map(node => node.x + node.width));\n const maxY = Math.max(...nodes.map(node => node.y + node.height));\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY\n };\n};\n\n// ============================================================\n// Node Geometry\n// ============================================================\n\n/**\n * Get the center point of a node.\n */\nexport function getNodeCenter(node) {\n return {\n x: node.x + node.width / 2,\n y: node.y + node.height / 2\n };\n}\n\n/**\n * Set a node's position based on center coordinates.\n * Returns a new node object with updated position.\n */\nexport function setNodeCenter(node, centerX, centerY) {\n return {\n ...node,\n x: centerX - node.width / 2,\n y: centerY - node.height / 2\n };\n}\n\n/**\n * Check if two nodes overlap.\n */\nexport function checkNodesOverlap(node1, node2) {\n const center1 = getNodeCenter(node1);\n const center2 = getNodeCenter(node2);\n const dx = Math.abs(center1.x - center2.x);\n const dy = Math.abs(center1.y - center2.y);\n const minDistanceX = (node1.width + node2.width) / 2;\n const minDistanceY = (node1.height + node2.height) / 2;\n return dx < minDistanceX && dy < minDistanceY;\n}\n\n/**\n * Get the bounding box of a node.\n */\nexport function getNodeBounds(node) {\n return {\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n left: node.x,\n right: node.x + node.width,\n top: node.y,\n bottom: node.y + node.height\n };\n}\n\n/**\n * Check if two nodes are within a certain distance of each other.\n */\nexport function areNodesClose(node1, node2, threshold = 200) {\n const center1 = getNodeCenter(node1);\n const center2 = getNodeCenter(node2);\n const distance = Math.sqrt(Math.pow(center1.x - center2.x, 2) + Math.pow(center1.y - center2.y, 2));\n return distance <= threshold;\n}","/**\n * Group Store\n *\n * Manages node grouping/nesting: parent-child relationships,\n * collapse/expand state, and group membership operations.\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { pushHistoryAtom } from './history-store';\n// =============================================================================\n// Collapse State\n// =============================================================================\n\n/**\n * Set of group node IDs that are currently collapsed.\n * Collapsed groups hide their children from uiNodesAtom.\n */\nexport const collapsedGroupsAtom = atom(new Set());\n\n/**\n * Toggle a group's collapsed state\n */\nexport const toggleGroupCollapseAtom = atom(null, (get, set, groupId) => {\n const current = get(collapsedGroupsAtom);\n const next = new Set(current);\n if (next.has(groupId)) {\n next.delete(groupId);\n } else {\n next.add(groupId);\n }\n set(collapsedGroupsAtom, next);\n});\n\n/**\n * Collapse a group\n */\nexport const collapseGroupAtom = atom(null, (get, set, groupId) => {\n const current = get(collapsedGroupsAtom);\n if (!current.has(groupId)) {\n const next = new Set(current);\n next.add(groupId);\n set(collapsedGroupsAtom, next);\n }\n});\n\n/**\n * Expand a group\n */\nexport const expandGroupAtom = atom(null, (get, set, groupId) => {\n const current = get(collapsedGroupsAtom);\n if (current.has(groupId)) {\n const next = new Set(current);\n next.delete(groupId);\n set(collapsedGroupsAtom, next);\n }\n});\n\n// =============================================================================\n// Parent/Child Queries\n// =============================================================================\n\n/**\n * Get children of a group node (reads from graph attributes)\n */\nexport const nodeChildrenAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n return parentId => {\n const children = [];\n graph.forEachNode((nodeId, attrs) => {\n if (attrs.parentId === parentId) {\n children.push(nodeId);\n }\n });\n return children;\n };\n});\n\n/**\n * Get the parent ID of a node\n */\nexport const nodeParentAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n return nodeId => {\n if (!graph.hasNode(nodeId)) return undefined;\n return graph.getNodeAttribute(nodeId, 'parentId');\n };\n});\n\n/**\n * Check if a node is a group (has any children)\n */\nexport const isGroupNodeAtom = atom(get => {\n const getChildren = get(nodeChildrenAtom);\n return nodeId => getChildren(nodeId).length > 0;\n});\n\n/**\n * Get count of children for a group node\n */\nexport const groupChildCountAtom = atom(get => {\n const getChildren = get(nodeChildrenAtom);\n return groupId => getChildren(groupId).length;\n});\n\n// =============================================================================\n// Group Membership Operations\n// =============================================================================\n\n/**\n * Set a node's parent (move into a group)\n */\nexport const setNodeParentAtom = atom(null, (get, set, {\n nodeId,\n parentId\n}) => {\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) return;\n\n // Prevent circular grouping\n if (parentId) {\n if (parentId === nodeId) return;\n // Check if parentId is a descendant of nodeId\n let current = parentId;\n while (current) {\n if (current === nodeId) return; // Circular!\n if (!graph.hasNode(current)) break;\n current = graph.getNodeAttribute(current, 'parentId');\n }\n }\n graph.setNodeAttribute(nodeId, 'parentId', parentId);\n set(graphUpdateVersionAtom, v => v + 1);\n});\n\n/**\n * Move multiple nodes into a group\n */\nexport const moveNodesToGroupAtom = atom(null, (get, set, {\n nodeIds,\n groupId\n}) => {\n for (const nodeId of nodeIds) {\n set(setNodeParentAtom, {\n nodeId,\n parentId: groupId\n });\n }\n});\n\n/**\n * Remove a node from its group (set parentId to undefined)\n */\nexport const removeFromGroupAtom = atom(null, (get, set, nodeId) => {\n set(setNodeParentAtom, {\n nodeId,\n parentId: undefined\n });\n});\n\n/**\n * Create a group from selected nodes:\n * 1. Create a new \"group\" type node at the bounding box center\n * 2. Set all selected nodes as children\n * Returns the new group node ID (set via callback since node creation is async)\n */\nexport const groupSelectedNodesAtom = atom(null, (get, set, {\n nodeIds,\n groupNodeId\n}) => {\n set(pushHistoryAtom, `Group ${nodeIds.length} nodes`);\n const graph = get(graphAtom);\n\n // Compute bounding box of selected nodes\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const nodeId of nodeIds) {\n if (!graph.hasNode(nodeId)) continue;\n const attrs = graph.getNodeAttributes(nodeId);\n minX = Math.min(minX, attrs.x);\n minY = Math.min(minY, attrs.y);\n maxX = Math.max(maxX, attrs.x + (attrs.width || 200));\n maxY = Math.max(maxY, attrs.y + (attrs.height || 100));\n }\n\n // Position group node at bounding box origin with padding\n const padding = 20;\n if (graph.hasNode(groupNodeId)) {\n graph.setNodeAttribute(groupNodeId, 'x', minX - padding);\n graph.setNodeAttribute(groupNodeId, 'y', minY - padding - 30); // extra for header\n graph.setNodeAttribute(groupNodeId, 'width', maxX - minX + 2 * padding);\n graph.setNodeAttribute(groupNodeId, 'height', maxY - minY + 2 * padding + 30);\n }\n\n // Set parent for all nodes\n for (const nodeId of nodeIds) {\n if (nodeId !== groupNodeId && graph.hasNode(nodeId)) {\n graph.setNodeAttribute(nodeId, 'parentId', groupNodeId);\n }\n }\n set(graphUpdateVersionAtom, v => v + 1);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n});\n\n/**\n * Ungroup: remove parent from all children of a group node\n */\nexport const ungroupNodesAtom = atom(null, (get, set, groupId) => {\n set(pushHistoryAtom, 'Ungroup nodes');\n const graph = get(graphAtom);\n graph.forEachNode((nodeId, attrs) => {\n if (attrs.parentId === groupId) {\n graph.setNodeAttribute(nodeId, 'parentId', undefined);\n }\n });\n set(graphUpdateVersionAtom, v => v + 1);\n});\n\n// =============================================================================\n// Drag-to-Nest\n// =============================================================================\n\n/**\n * Nest dragged nodes into a target group node.\n * Sets parentId for each dragged node, then auto-resizes the target.\n */\nexport const nestNodesOnDropAtom = atom(null, (get, set, {\n nodeIds,\n targetId\n}) => {\n set(pushHistoryAtom, 'Nest nodes');\n for (const nodeId of nodeIds) {\n if (nodeId === targetId) continue;\n set(setNodeParentAtom, {\n nodeId,\n parentId: targetId\n });\n }\n set(autoResizeGroupAtom, targetId);\n});\n\n// =============================================================================\n// Descendants Helper\n// =============================================================================\n\n/**\n * Recursively collects all descendant node IDs of a group node.\n * Used by useNodeDrag to move all children when dragging a group.\n */\nexport function getNodeDescendants(graph, groupId) {\n const descendants = [];\n const stack = [groupId];\n while (stack.length > 0) {\n const current = stack.pop();\n graph.forEachNode((nodeId, attrs) => {\n if (attrs.parentId === current) {\n descendants.push(nodeId);\n stack.push(nodeId);\n }\n });\n }\n return descendants;\n}\n\n// =============================================================================\n// Edge Re-routing for Collapsed Groups\n// =============================================================================\n\n/**\n * Derived: maps each collapsed node to its outermost collapsed ancestor.\n * Used by visibleEdgeKeysAtom and edgeFamilyAtom to re-route edges\n * from hidden children to their visible group node.\n *\n * Only nodes that are inside a collapsed group appear in this map.\n * The value is always a visible group node (the outermost collapsed ancestor).\n */\nexport const collapsedEdgeRemapAtom = atom(get => {\n const collapsed = get(collapsedGroupsAtom);\n if (collapsed.size === 0) return new Map();\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n const remap = new Map();\n for (const nodeId of graph.nodes()) {\n let current = nodeId;\n let outermost = null;\n while (true) {\n if (!graph.hasNode(current)) break;\n const parent = graph.getNodeAttribute(current, 'parentId');\n if (!parent) break;\n if (collapsed.has(parent)) outermost = parent;\n current = parent;\n }\n if (outermost) remap.set(nodeId, outermost);\n }\n return remap;\n});\n\n// =============================================================================\n// Group Auto-resize\n// =============================================================================\n\n/**\n * Write atom: recomputes a group node's position and dimensions\n * to contain all its direct children with padding.\n */\nexport const autoResizeGroupAtom = atom(null, (get, set, groupId) => {\n const graph = get(graphAtom);\n if (!graph.hasNode(groupId)) return;\n const children = [];\n graph.forEachNode((nodeId, attrs) => {\n if (attrs.parentId === groupId) {\n children.push(nodeId);\n }\n });\n if (children.length === 0) return;\n const padding = 20;\n const headerHeight = 30;\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const childId of children) {\n const attrs = graph.getNodeAttributes(childId);\n minX = Math.min(minX, attrs.x);\n minY = Math.min(minY, attrs.y);\n maxX = Math.max(maxX, attrs.x + (attrs.width || 200));\n maxY = Math.max(maxY, attrs.y + (attrs.height || 100));\n }\n graph.setNodeAttribute(groupId, 'x', minX - padding);\n graph.setNodeAttribute(groupId, 'y', minY - padding - headerHeight);\n graph.setNodeAttribute(groupId, 'width', maxX - minX + 2 * padding);\n graph.setNodeAttribute(groupId, 'height', maxY - minY + 2 * padding + headerHeight);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n});\n\n// =============================================================================\n// Visibility Helper\n// =============================================================================\n\n/**\n * Check if a node should be hidden because it's inside a collapsed group.\n * Walks up the parent chain — if ANY ancestor is collapsed, the node is hidden.\n */\nexport function isNodeCollapsed(nodeId, getParentId, collapsed) {\n let current = nodeId;\n while (true) {\n const parentId = getParentId(current);\n if (!parentId) return false;\n if (collapsed.has(parentId)) return true;\n current = parentId;\n }\n}","/**\n * Canvas History Store — v2\n *\n * Delta-based undo/redo — replaces full-graph JSON.stringify snapshots.\n *\n * Performance improvement:\n * - Before: O(N) per operation (deep-clone all nodes + edges)\n * - After: O(1) for moves, O(K) for batch operations\n *\n * Each history entry stores forward + reverse deltas, not full snapshots.\n * Falls back to full snapshot for complex operations (graph import).\n *\n * Pure delta functions are in ./history-actions.ts\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { createDebug } from '../utils/debug';\n\n// Re-export types for backward compat\n\n// Re-export pure functions for backward compat\nexport { applyDelta, invertDelta, createSnapshot } from './history-actions';\nimport { applyDelta, invertDelta, createSnapshot } from './history-actions';\nconst debug = createDebug('history');\n\n// =============================================================================\n// Configuration\n// =============================================================================\n\n/** Maximum number of history entries to keep */\nconst MAX_HISTORY_SIZE = 50;\n\n// =============================================================================\n// Atoms\n// =============================================================================\n\nexport const historyStateAtom = atom({\n past: [],\n future: [],\n isApplying: false\n});\nexport const canUndoAtom = atom(get => {\n const history = get(historyStateAtom);\n return history.past.length > 0 && !history.isApplying;\n});\nexport const canRedoAtom = atom(get => {\n const history = get(historyStateAtom);\n return history.future.length > 0 && !history.isApplying;\n});\nexport const undoCountAtom = atom(get => get(historyStateAtom).past.length);\nexport const redoCountAtom = atom(get => get(historyStateAtom).future.length);\n\n// =============================================================================\n// Push Delta (replaces pushHistoryAtom's full-snapshot approach)\n// =============================================================================\n\n/**\n * Push a delta to history. Call AFTER making the change.\n * The delta describes what changed; the reverse is auto-computed.\n */\nexport const pushDeltaAtom = atom(null, (get, set, delta) => {\n const history = get(historyStateAtom);\n if (history.isApplying) return;\n const {\n label,\n ...cleanDelta\n } = delta;\n const entry = {\n forward: cleanDelta,\n reverse: invertDelta(cleanDelta),\n timestamp: Date.now(),\n label\n };\n const newPast = [...history.past, entry];\n if (newPast.length > MAX_HISTORY_SIZE) newPast.shift();\n set(historyStateAtom, {\n past: newPast,\n future: [],\n // Clear redo stack\n isApplying: false\n });\n debug('Pushed delta: %s (past: %d)', label || delta.type, newPast.length);\n});\n\n/**\n * Legacy: Push a full-graph snapshot to history.\n * Use for complex operations where computing deltas is impractical.\n * Call BEFORE making changes.\n */\nexport const pushHistoryAtom = atom(null, (get, set, label) => {\n const history = get(historyStateAtom);\n if (history.isApplying) return;\n const graph = get(graphAtom);\n const snapshot = createSnapshot(graph, label);\n\n // Store as a full-snapshot delta\n const forward = {\n type: 'full-snapshot',\n nodes: snapshot.nodes,\n edges: snapshot.edges\n };\n const entry = {\n forward,\n reverse: forward,\n // For full snapshots, reverse IS the current state\n timestamp: Date.now(),\n label\n };\n const newPast = [...history.past, entry];\n if (newPast.length > MAX_HISTORY_SIZE) newPast.shift();\n set(historyStateAtom, {\n past: newPast,\n future: [],\n isApplying: false\n });\n debug('Pushed snapshot: %s (past: %d)', label || 'unnamed', newPast.length);\n});\n\n// =============================================================================\n// Undo / Redo\n// =============================================================================\n\nexport const undoAtom = atom(null, (get, set) => {\n const history = get(historyStateAtom);\n if (history.past.length === 0 || history.isApplying) return false;\n set(historyStateAtom, {\n ...history,\n isApplying: true\n });\n try {\n const graph = get(graphAtom);\n const newPast = [...history.past];\n const entry = newPast.pop();\n\n // For full-snapshot entries, save current state before restoring\n let forwardForRedo = entry.forward;\n if (entry.reverse.type === 'full-snapshot') {\n const currentSnapshot = createSnapshot(graph, 'current');\n forwardForRedo = {\n type: 'full-snapshot',\n nodes: currentSnapshot.nodes,\n edges: currentSnapshot.edges\n };\n }\n const structuralChange = applyDelta(graph, entry.reverse);\n if (structuralChange) {\n set(graphAtom, graph);\n set(graphUpdateVersionAtom, v => v + 1);\n }\n set(nodePositionUpdateCounterAtom, c => c + 1);\n const redoEntry = {\n forward: forwardForRedo,\n reverse: entry.reverse,\n timestamp: entry.timestamp,\n label: entry.label\n };\n set(historyStateAtom, {\n past: newPast,\n future: [redoEntry, ...history.future],\n isApplying: false\n });\n debug('Undo: %s (past: %d, future: %d)', entry.label, newPast.length, history.future.length + 1);\n return true;\n } catch (error) {\n debug.error('Undo failed: %O', error);\n set(historyStateAtom, {\n ...history,\n isApplying: false\n });\n return false;\n }\n});\nexport const redoAtom = atom(null, (get, set) => {\n const history = get(historyStateAtom);\n if (history.future.length === 0 || history.isApplying) return false;\n set(historyStateAtom, {\n ...history,\n isApplying: true\n });\n try {\n const graph = get(graphAtom);\n const newFuture = [...history.future];\n const entry = newFuture.shift();\n\n // For full-snapshot entries, save current state before restoring\n let reverseForUndo = entry.reverse;\n if (entry.forward.type === 'full-snapshot') {\n const currentSnapshot = createSnapshot(graph, 'current');\n reverseForUndo = {\n type: 'full-snapshot',\n nodes: currentSnapshot.nodes,\n edges: currentSnapshot.edges\n };\n }\n const structuralChange = applyDelta(graph, entry.forward);\n if (structuralChange) {\n set(graphAtom, graph);\n set(graphUpdateVersionAtom, v => v + 1);\n }\n set(nodePositionUpdateCounterAtom, c => c + 1);\n const undoEntry = {\n forward: entry.forward,\n reverse: reverseForUndo,\n timestamp: entry.timestamp,\n label: entry.label\n };\n set(historyStateAtom, {\n past: [...history.past, undoEntry],\n future: newFuture,\n isApplying: false\n });\n debug('Redo: %s (past: %d, future: %d)', entry.label, history.past.length + 1, newFuture.length);\n return true;\n } catch (error) {\n debug.error('Redo failed: %O', error);\n set(historyStateAtom, {\n ...history,\n isApplying: false\n });\n return false;\n }\n});\nexport const clearHistoryAtom = atom(null, (_get, set) => {\n set(historyStateAtom, {\n past: [],\n future: [],\n isApplying: false\n });\n debug('History cleared');\n});\nexport const historyLabelsAtom = atom(get => {\n const history = get(historyStateAtom);\n return {\n past: history.past.map(e => e.label || 'Unnamed'),\n future: history.future.map(e => e.label || 'Unnamed')\n };\n});","/**\n * History Actions — Pure delta functions\n *\n * applyDelta, invertDelta, createSnapshot extracted from history-store.ts.\n * These are pure functions operating on Graphology graphs and delta objects.\n */\n\n// =============================================================================\n// Delta Application\n// =============================================================================\n\n/**\n * Apply a delta to the graph in-place.\n * Returns true if graph structure changed (needs version bump).\n */\nexport function applyDelta(graph, delta) {\n switch (delta.type) {\n case 'move-node':\n {\n if (!graph.hasNode(delta.nodeId)) return false;\n graph.setNodeAttribute(delta.nodeId, 'x', delta.to.x);\n graph.setNodeAttribute(delta.nodeId, 'y', delta.to.y);\n return false; // Position change, not structural\n }\n case 'resize-node':\n {\n if (!graph.hasNode(delta.nodeId)) return false;\n graph.setNodeAttribute(delta.nodeId, 'width', delta.to.width);\n graph.setNodeAttribute(delta.nodeId, 'height', delta.to.height);\n return false;\n }\n case 'add-node':\n {\n if (graph.hasNode(delta.nodeId)) return false;\n graph.addNode(delta.nodeId, delta.attributes);\n return true;\n }\n case 'remove-node':\n {\n if (!graph.hasNode(delta.nodeId)) return false;\n graph.dropNode(delta.nodeId); // Also removes connected edges\n return true;\n }\n case 'add-edge':\n {\n if (graph.hasEdge(delta.edgeId)) return false;\n if (!graph.hasNode(delta.source) || !graph.hasNode(delta.target)) return false;\n graph.addEdgeWithKey(delta.edgeId, delta.source, delta.target, delta.attributes);\n return true;\n }\n case 'remove-edge':\n {\n if (!graph.hasEdge(delta.edgeId)) return false;\n graph.dropEdge(delta.edgeId);\n return true;\n }\n case 'update-node-attr':\n {\n if (!graph.hasNode(delta.nodeId)) return false;\n graph.setNodeAttribute(delta.nodeId, delta.key, delta.to);\n return false;\n }\n case 'batch':\n {\n let structuralChange = false;\n for (const d of delta.deltas) {\n if (applyDelta(graph, d)) structuralChange = true;\n }\n return structuralChange;\n }\n case 'full-snapshot':\n {\n // Full graph restore — clear and rebuild\n graph.clear();\n for (const node of delta.nodes) {\n graph.addNode(node.id, node.attributes);\n }\n for (const edge of delta.edges) {\n if (graph.hasNode(edge.source) && graph.hasNode(edge.target)) {\n graph.addEdgeWithKey(edge.id, edge.source, edge.target, edge.attributes);\n }\n }\n return true;\n }\n }\n}\n\n/**\n * Invert a delta (for creating reverse operations).\n */\nexport function invertDelta(delta) {\n switch (delta.type) {\n case 'move-node':\n return {\n ...delta,\n from: delta.to,\n to: delta.from\n };\n case 'resize-node':\n return {\n ...delta,\n from: delta.to,\n to: delta.from\n };\n case 'add-node':\n return {\n type: 'remove-node',\n nodeId: delta.nodeId,\n attributes: delta.attributes,\n connectedEdges: []\n };\n case 'remove-node':\n {\n // Restore node AND its connected edges\n const batch = [{\n type: 'add-node',\n nodeId: delta.nodeId,\n attributes: delta.attributes\n }, ...delta.connectedEdges.map(e => ({\n type: 'add-edge',\n edgeId: e.id,\n source: e.source,\n target: e.target,\n attributes: e.attributes\n }))];\n return batch.length === 1 ? batch[0] : {\n type: 'batch',\n deltas: batch\n };\n }\n case 'add-edge':\n return {\n type: 'remove-edge',\n edgeId: delta.edgeId,\n source: delta.source,\n target: delta.target,\n attributes: delta.attributes\n };\n case 'remove-edge':\n return {\n type: 'add-edge',\n edgeId: delta.edgeId,\n source: delta.source,\n target: delta.target,\n attributes: delta.attributes\n };\n case 'update-node-attr':\n return {\n ...delta,\n from: delta.to,\n to: delta.from\n };\n case 'batch':\n return {\n type: 'batch',\n deltas: delta.deltas.map(invertDelta).reverse()\n };\n case 'full-snapshot':\n // Can't invert a full snapshot — caller handles this\n return delta;\n }\n}\n\n// =============================================================================\n// Helper: Create full snapshot (for complex operations)\n// =============================================================================\n\nexport function createSnapshot(graph, label) {\n const nodes = [];\n const edges = [];\n graph.forEachNode((nodeId, attributes) => {\n nodes.push({\n id: nodeId,\n attributes: {\n ...attributes\n }\n });\n });\n graph.forEachEdge((edgeId, attributes, source, target) => {\n edges.push({\n id: edgeId,\n source,\n target,\n attributes: {\n ...attributes\n }\n });\n });\n return {\n timestamp: Date.now(),\n label,\n nodes,\n edges\n };\n}","/**\n * Graph mutations\n *\n * Write atoms for graph CRUD operations, drag lifecycle,\n * edge animations, split/merge, and DB sync.\n */\n\nimport { atom } from 'jotai';\nimport Graph from 'graphology';\nimport { graphAtom, graphUpdateVersionAtom, graphOptions, currentGraphIdAtom, draggingNodeIdAtom, preDragNodeAttributesAtom } from './graph-store';\nimport { nodePositionAtomFamily, nodePositionUpdateCounterAtom, cleanupNodePositionAtom } from './graph-position';\nimport { highestZIndexAtom } from './graph-derived';\nimport { autoResizeGroupAtom } from './group-store';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('graph:mutations');\n\n// --- Node Action Atoms ---\n\n/**\n * Start dragging a node\n */\nexport const startNodeDragAtom = atom(null, (get, set, {\n nodeId\n}) => {\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) return;\n const currentAttributes = graph.getNodeAttributes(nodeId);\n set(preDragNodeAttributesAtom, JSON.parse(JSON.stringify(currentAttributes)));\n const currentHighestZIndex = get(highestZIndexAtom);\n const newZIndex = currentHighestZIndex + 1;\n graph.setNodeAttribute(nodeId, 'zIndex', newZIndex);\n set(draggingNodeIdAtom, nodeId);\n});\n\n/**\n * End dragging a node\n */\nexport const endNodeDragAtom = atom(null, (get, set, _payload) => {\n const currentDraggingId = get(draggingNodeIdAtom);\n if (currentDraggingId) {\n debug('Node %s drag ended', currentDraggingId);\n\n // Auto-resize parent group if the dragged node belongs to one\n const graph = get(graphAtom);\n if (graph.hasNode(currentDraggingId)) {\n const parentId = graph.getNodeAttribute(currentDraggingId, 'parentId');\n if (parentId) {\n set(autoResizeGroupAtom, parentId);\n }\n }\n }\n set(draggingNodeIdAtom, null);\n set(preDragNodeAttributesAtom, null);\n});\n\n/**\n * Optimistically delete a node from local graph\n */\nexport const optimisticDeleteNodeAtom = atom(null, (get, set, {\n nodeId\n}) => {\n const graph = get(graphAtom);\n if (graph.hasNode(nodeId)) {\n graph.dropNode(nodeId);\n set(cleanupNodePositionAtom, nodeId);\n set(graphAtom, graph.copy());\n debug('Optimistically deleted node %s', nodeId);\n }\n});\n\n/**\n * Optimistically delete an edge from local graph\n */\nexport const optimisticDeleteEdgeAtom = atom(null, (get, set, {\n edgeKey\n}) => {\n const graph = get(graphAtom);\n if (graph.hasEdge(edgeKey)) {\n graph.dropEdge(edgeKey);\n set(graphAtom, graph.copy());\n debug('Optimistically deleted edge %s', edgeKey);\n }\n});\n\n// --- Local Graph Mutations ---\n\n/**\n * Add a node directly to local graph\n */\nexport const addNodeToLocalGraphAtom = atom(null, (get, set, newNode) => {\n const graph = get(graphAtom);\n if (graph.hasNode(newNode.id)) {\n debug('Node %s already exists, skipping', newNode.id);\n return;\n }\n const uiProps = newNode.ui_properties || {};\n const attributes = {\n x: typeof uiProps.x === 'number' ? uiProps.x : Math.random() * 800,\n y: typeof uiProps.y === 'number' ? uiProps.y : Math.random() * 600,\n size: typeof uiProps.size === 'number' ? uiProps.size : 15,\n width: typeof uiProps.width === 'number' ? uiProps.width : 500,\n height: typeof uiProps.height === 'number' ? uiProps.height : 500,\n color: typeof uiProps.color === 'string' ? uiProps.color : '#ccc',\n label: newNode.label || newNode.node_type || newNode.id,\n zIndex: typeof uiProps.zIndex === 'number' ? uiProps.zIndex : 0,\n dbData: newNode\n };\n debug('Adding node %s to local graph at (%d, %d)', newNode.id, attributes.x, attributes.y);\n graph.addNode(newNode.id, attributes);\n // Position is derived from graph - just update graph and trigger re-render\n set(graphAtom, graph.copy());\n set(graphUpdateVersionAtom, v => v + 1);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n});\n\n// Re-export all edge and advanced atoms for backward compat\nexport { swapEdgeAtomicAtom, departingEdgesAtom, EDGE_ANIMATION_DURATION, removeEdgeWithAnimationAtom, editingEdgeLabelAtom, updateEdgeLabelAtom } from './graph-mutations-edges';\nexport { dropTargetNodeIdAtom, splitNodeAtom, mergeNodesAtom } from './graph-mutations-advanced';\n\n// --- DB Sync Atom ---\n\n/**\n * Load/sync graph data from database\n * Merges DB data with local state, preserving positions during drag\n */\nexport const loadGraphFromDbAtom = atom(null, (get, set, fetchedNodes, fetchedEdges) => {\n debug('========== START SYNC ==========');\n debug('Fetched nodes: %d, edges: %d', fetchedNodes.length, fetchedEdges.length);\n const currentGraphId = get(currentGraphIdAtom);\n\n // Validate data belongs to current graph\n if (fetchedNodes.length > 0 && fetchedNodes[0].graph_id !== currentGraphId) {\n debug('Skipping sync - data belongs to different graph');\n return;\n }\n const existingGraph = get(graphAtom);\n const isDragging = get(draggingNodeIdAtom) !== null;\n if (isDragging) {\n debug('Skipping sync - drag in progress');\n return;\n }\n\n // Detect graph switch\n const existingNodeIds = new Set(existingGraph.nodes());\n const fetchedNodeIds = new Set(fetchedNodes.map(n => n.id));\n const hasAnyCommonNodes = Array.from(existingNodeIds).some(id => fetchedNodeIds.has(id));\n let graph;\n if (hasAnyCommonNodes && existingNodeIds.size > 0) {\n debug('Merging DB data into existing graph');\n graph = existingGraph.copy();\n } else {\n debug('Creating fresh graph (graph switch detected)');\n graph = new Graph(graphOptions);\n }\n const fetchedEdgeIds = new Set(fetchedEdges.map(e => e.id));\n\n // Remove deleted nodes\n if (hasAnyCommonNodes && existingNodeIds.size > 0) {\n graph.forEachNode(nodeId => {\n if (!fetchedNodeIds.has(nodeId)) {\n debug('Removing deleted node: %s', nodeId);\n graph.dropNode(nodeId);\n nodePositionAtomFamily.remove(nodeId);\n }\n });\n }\n\n // Merge/add nodes\n fetchedNodes.forEach(node => {\n const uiProps = node.ui_properties || {};\n const newX = typeof uiProps.x === 'number' ? uiProps.x : Math.random() * 800;\n const newY = typeof uiProps.y === 'number' ? uiProps.y : Math.random() * 600;\n if (graph.hasNode(node.id)) {\n const currentAttrs = graph.getNodeAttributes(node.id);\n const attributes = {\n x: newX,\n y: newY,\n size: typeof uiProps.size === 'number' ? uiProps.size : currentAttrs.size,\n width: typeof uiProps.width === 'number' ? uiProps.width : currentAttrs.width ?? 500,\n height: typeof uiProps.height === 'number' ? uiProps.height : currentAttrs.height ?? 500,\n color: typeof uiProps.color === 'string' ? uiProps.color : currentAttrs.color,\n label: node.label || node.node_type || node.id,\n zIndex: typeof uiProps.zIndex === 'number' ? uiProps.zIndex : currentAttrs.zIndex,\n dbData: node\n };\n graph.replaceNodeAttributes(node.id, attributes);\n } else {\n const attributes = {\n x: newX,\n y: newY,\n size: typeof uiProps.size === 'number' ? uiProps.size : 15,\n width: typeof uiProps.width === 'number' ? uiProps.width : 500,\n height: typeof uiProps.height === 'number' ? uiProps.height : 500,\n color: typeof uiProps.color === 'string' ? uiProps.color : '#ccc',\n label: node.label || node.node_type || node.id,\n zIndex: typeof uiProps.zIndex === 'number' ? uiProps.zIndex : 0,\n dbData: node\n };\n graph.addNode(node.id, attributes);\n }\n });\n\n // Remove deleted edges\n graph.forEachEdge(edgeId => {\n if (!fetchedEdgeIds.has(edgeId)) {\n debug('Removing deleted edge: %s', edgeId);\n graph.dropEdge(edgeId);\n }\n });\n\n // Merge/add edges\n fetchedEdges.forEach(edge => {\n if (graph.hasNode(edge.source_node_id) && graph.hasNode(edge.target_node_id)) {\n const uiProps = edge.ui_properties || {};\n const attributes = {\n type: typeof uiProps.style === 'string' ? uiProps.style : 'solid',\n color: typeof uiProps.color === 'string' ? uiProps.color : '#999',\n label: edge.edge_type ?? undefined,\n weight: typeof uiProps.weight === 'number' ? uiProps.weight : 1,\n dbData: edge\n };\n if (graph.hasEdge(edge.id)) {\n graph.replaceEdgeAttributes(edge.id, attributes);\n } else {\n try {\n graph.addEdgeWithKey(edge.id, edge.source_node_id, edge.target_node_id, attributes);\n } catch (e) {\n debug('Failed to add edge %s: %o', edge.id, e);\n }\n }\n }\n });\n set(graphAtom, graph);\n set(graphUpdateVersionAtom, v => v + 1);\n debug('========== SYNC COMPLETE ==========');\n debug('Final graph: %d nodes, %d edges', graph.order, graph.size);\n});","/**\n * Graph Mutations — Edge Operations\n *\n * Edge CRUD, atomic swap, animation, and label editing atoms.\n * Split from graph-mutations.ts for modularity.\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { edgeFamilyAtom } from './graph-derived';\nimport { createDebug } from '../utils/debug';\nimport { prefersReducedMotionAtom } from './reduced-motion-store';\nconst debug = createDebug('graph:mutations:edges');\n\n// --- Edge CRUD ---\n\n/**\n * Add an edge directly to local graph\n */\nexport const addEdgeToLocalGraphAtom = atom(null, (get, set, newEdge) => {\n const graph = get(graphAtom);\n if (graph.hasNode(newEdge.source_node_id) && graph.hasNode(newEdge.target_node_id)) {\n const uiProps = newEdge.ui_properties || {};\n const attributes = {\n type: typeof uiProps.style === 'string' ? uiProps.style : 'solid',\n color: typeof uiProps.color === 'string' ? uiProps.color : '#999',\n label: newEdge.edge_type ?? undefined,\n weight: typeof uiProps.weight === 'number' ? uiProps.weight : 1,\n dbData: newEdge\n };\n if (!graph.hasEdge(newEdge.id)) {\n try {\n debug('Adding edge %s to local graph', newEdge.id);\n graph.addEdgeWithKey(newEdge.id, newEdge.source_node_id, newEdge.target_node_id, attributes);\n set(graphAtom, graph.copy());\n set(graphUpdateVersionAtom, v => v + 1);\n } catch (e) {\n debug('Failed to add edge %s: %o', newEdge.id, e);\n }\n }\n }\n});\n\n/**\n * Remove an edge from local graph\n */\nexport const removeEdgeFromLocalGraphAtom = atom(null, (get, set, edgeId) => {\n const graph = get(graphAtom);\n if (graph.hasEdge(edgeId)) {\n graph.dropEdge(edgeId);\n set(graphAtom, graph.copy());\n set(graphUpdateVersionAtom, v => v + 1);\n }\n});\n\n/**\n * Atomic swap of temp edge with real edge (prevents render flash)\n */\nexport const swapEdgeAtomicAtom = atom(null, (get, set, {\n tempEdgeId,\n newEdge\n}) => {\n const graph = get(graphAtom);\n if (graph.hasEdge(tempEdgeId)) {\n graph.dropEdge(tempEdgeId);\n }\n if (graph.hasNode(newEdge.source_node_id) && graph.hasNode(newEdge.target_node_id)) {\n const uiProps = newEdge.ui_properties || {};\n const attributes = {\n type: typeof uiProps.style === 'string' ? uiProps.style : 'solid',\n color: typeof uiProps.color === 'string' ? uiProps.color : '#999',\n label: newEdge.edge_type ?? undefined,\n weight: typeof uiProps.weight === 'number' ? uiProps.weight : 1,\n dbData: newEdge\n };\n if (!graph.hasEdge(newEdge.id)) {\n try {\n debug('Atomically swapping temp edge %s with real edge %s', tempEdgeId, newEdge.id);\n graph.addEdgeWithKey(newEdge.id, newEdge.source_node_id, newEdge.target_node_id, attributes);\n } catch (e) {\n debug('Failed to add edge %s: %o', newEdge.id, e);\n }\n }\n }\n set(graphAtom, graph.copy());\n set(graphUpdateVersionAtom, v => v + 1);\n});\n\n// --- Edge Animation State ---\n\n/**\n * Departing edges: snapshots of edges that have been removed from the graph\n * but are still being rendered with an exit animation.\n */\nexport const departingEdgesAtom = atom(new Map());\n\n/**\n * Edge animation duration in milliseconds\n */\nexport const EDGE_ANIMATION_DURATION = 300;\n\n/**\n * Remove an edge with a fade-out animation.\n * Snapshots the edge state, removes it from the graph, then cleans up\n * the departing entry after the animation duration.\n */\nexport const removeEdgeWithAnimationAtom = atom(null, (get, set, edgeKey) => {\n const edgeState = get(edgeFamilyAtom(edgeKey));\n if (edgeState) {\n const departing = new Map(get(departingEdgesAtom));\n departing.set(edgeKey, edgeState);\n set(departingEdgesAtom, departing);\n set(removeEdgeFromLocalGraphAtom, edgeKey);\n const duration = get(prefersReducedMotionAtom) ? 0 : EDGE_ANIMATION_DURATION;\n setTimeout(() => {\n const current = new Map(get(departingEdgesAtom));\n current.delete(edgeKey);\n set(departingEdgesAtom, current);\n }, duration);\n }\n});\n\n// --- Edge Label Editing ---\n\n/**\n * Edge key currently being edited (label inline editing).\n * null when no edge label is being edited.\n */\nexport const editingEdgeLabelAtom = atom(null);\n\n/**\n * Update an edge's label attribute\n */\nexport const updateEdgeLabelAtom = atom(null, (get, set, {\n edgeKey,\n label\n}) => {\n const graph = get(graphAtom);\n if (graph.hasEdge(edgeKey)) {\n graph.setEdgeAttribute(edgeKey, 'label', label || undefined);\n set(graphUpdateVersionAtom, v => v + 1);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n }\n});","/**\n * Reduced Motion Store\n *\n * Tracks the user's `prefers-reduced-motion` OS setting.\n * When enabled, animations (inertia, layout transitions, edge fades)\n * should be skipped or set to instant.\n */\n\nimport { atom } from 'jotai';\n\n/**\n * Whether the user prefers reduced motion.\n * Initialized from `matchMedia` and updated on changes.\n *\n * Components/hooks should read this atom to skip animations:\n * - Pan/zoom inertia → stop immediately\n * - Layout transitions → apply positions instantly\n * - Edge fade animations → duration = 0\n */\nexport const prefersReducedMotionAtom = atom(typeof window !== 'undefined' && typeof window.matchMedia === 'function' ? window.matchMedia('(prefers-reduced-motion: reduce)').matches : false);\n\n/**\n * Effect atom: subscribes to matchMedia changes.\n * Mount this once in CanvasProvider via useAtom.\n */\nexport const watchReducedMotionAtom = atom(null, (_get, set) => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return;\n const mql = window.matchMedia('(prefers-reduced-motion: reduce)');\n const handler = e => {\n set(prefersReducedMotionAtom, e.matches);\n };\n\n // Sync initial state\n set(prefersReducedMotionAtom, mql.matches);\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n});","/**\n * Graph Mutations — Advanced Operations\n *\n * Split/merge node atoms and drop-target state.\n * Split from graph-mutations.ts for modularity.\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom, currentGraphIdAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { pushHistoryAtom } from './history-store';\nimport { createDebug } from '../utils/debug';\nimport { addEdgeToLocalGraphAtom } from './graph-mutations-edges';\nimport { addNodeToLocalGraphAtom, optimisticDeleteNodeAtom } from './graph-mutations';\nconst debug = createDebug('graph:mutations:advanced');\n\n// --- Drop Target ---\n\n/**\n * ID of the node currently being hovered over as a drop target during drag.\n * Used by drag-to-nest: when a dragged node is released over a target,\n * the dragged node becomes a child of the target.\n */\nexport const dropTargetNodeIdAtom = atom(null);\n\n// --- Split Node ---\n\n/**\n * Split a node into two copies: original stays at position1, clone at position2.\n * All incident edges are duplicated so both copies have the same connections.\n */\nexport const splitNodeAtom = atom(null, (get, set, {\n nodeId,\n position1,\n position2\n}) => {\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) return;\n const attrs = graph.getNodeAttributes(nodeId);\n const graphId = get(currentGraphIdAtom) || attrs.dbData.graph_id;\n\n // Snapshot for undo (must be before any mutations)\n set(pushHistoryAtom, 'Split node');\n\n // Move original to position1 (before addNodeToLocalGraphAtom which calls graph.copy())\n graph.setNodeAttribute(nodeId, 'x', position1.x);\n graph.setNodeAttribute(nodeId, 'y', position1.y);\n\n // Collect edges before addNodeToLocalGraphAtom replaces graph ref\n const edges = [];\n graph.forEachEdge(nodeId, (_key, eAttrs, source, target) => {\n edges.push({\n source,\n target,\n attrs: eAttrs\n });\n });\n\n // Create clone\n const cloneId = `split-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const cloneDbNode = {\n ...attrs.dbData,\n id: cloneId,\n graph_id: graphId,\n ui_properties: {\n ...(attrs.dbData.ui_properties || {}),\n x: position2.x,\n y: position2.y\n },\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString()\n };\n set(addNodeToLocalGraphAtom, cloneDbNode);\n\n // Duplicate all edges to clone\n for (const edge of edges) {\n const newSource = edge.source === nodeId ? cloneId : edge.source;\n const newTarget = edge.target === nodeId ? cloneId : edge.target;\n set(addEdgeToLocalGraphAtom, {\n ...edge.attrs.dbData,\n id: `split-e-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n source_node_id: newSource,\n target_node_id: newTarget\n });\n }\n set(graphUpdateVersionAtom, v => v + 1);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n debug('Split node %s → clone %s', nodeId, cloneId);\n});\n\n// --- Merge Nodes ---\n\n/**\n * Merge multiple nodes into one. The first node in the array survives.\n * Edges from doomed nodes are re-routed to the survivor.\n * Edges between merged nodes are discarded (would be self-loops).\n */\nexport const mergeNodesAtom = atom(null, (get, set, {\n nodeIds\n}) => {\n if (nodeIds.length < 2) return;\n const graph = get(graphAtom);\n const [survivorId, ...doomed] = nodeIds;\n if (!graph.hasNode(survivorId)) return;\n\n // Snapshot for undo (must be before any mutations)\n set(pushHistoryAtom, `Merge ${nodeIds.length} nodes`);\n const doomedSet = new Set(doomed);\n for (const doomedId of doomed) {\n if (!graph.hasNode(doomedId)) continue;\n\n // Collect edges before deletion (dropNode removes them)\n const edges = [];\n graph.forEachEdge(doomedId, (_key, eAttrs, source, target) => {\n edges.push({\n source,\n target,\n attrs: eAttrs\n });\n });\n for (const edge of edges) {\n const newSource = doomedSet.has(edge.source) ? survivorId : edge.source;\n const newTarget = doomedSet.has(edge.target) ? survivorId : edge.target;\n // Skip self-loops (edges between merged nodes)\n if (newSource === newTarget) continue;\n set(addEdgeToLocalGraphAtom, {\n ...edge.attrs.dbData,\n id: `merge-e-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n source_node_id: newSource,\n target_node_id: newTarget\n });\n }\n\n // Delete doomed node (auto-removes its original edges)\n set(optimisticDeleteNodeAtom, {\n nodeId: doomedId\n });\n }\n set(graphUpdateVersionAtom, v => v + 1);\n debug('Merged nodes %o → survivor %s', nodeIds, survivorId);\n});","/**\n * Sync state management\n *\n * Tracks sync status, pending mutations, and mutation queue for retry.\n */\n\nimport { atom } from 'jotai';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('sync');\n\n// --- Core State Atoms ---\n\n/**\n * Current sync status\n */\nexport const syncStatusAtom = atom('synced');\n\n/**\n * Number of pending (in-flight) mutations\n */\nexport const pendingMutationsCountAtom = atom(0);\n\n/**\n * Network online status\n */\nexport const isOnlineAtom = atom(typeof navigator !== 'undefined' ? navigator.onLine : true);\n\n/**\n * Last sync error message\n */\nexport const lastSyncErrorAtom = atom(null);\n\n/**\n * Last successful sync timestamp\n */\nexport const lastSyncTimeAtom = atom(Date.now());\n\n/**\n * Queued mutations for retry\n */\nexport const mutationQueueAtom = atom([]);\n\n// --- Derived State ---\n\n/**\n * Combined sync state for easy consumption\n */\nexport const syncStateAtom = atom(get => ({\n status: get(syncStatusAtom),\n pendingMutations: get(pendingMutationsCountAtom),\n lastError: get(lastSyncErrorAtom),\n lastSyncTime: get(lastSyncTimeAtom),\n isOnline: get(isOnlineAtom),\n queuedMutations: get(mutationQueueAtom).length\n}));\n\n// --- Mutation Tracking Actions ---\n\n/**\n * Start tracking a mutation (increment counter)\n */\nexport const startMutationAtom = atom(null, (get, set) => {\n const currentCount = get(pendingMutationsCountAtom);\n const newCount = currentCount + 1;\n set(pendingMutationsCountAtom, newCount);\n debug('Mutation started. Pending count: %d -> %d', currentCount, newCount);\n if (newCount > 0 && get(syncStatusAtom) !== 'syncing') {\n set(syncStatusAtom, 'syncing');\n debug('Status -> syncing');\n }\n});\n\n/**\n * Complete a mutation (decrement counter)\n */\nexport const completeMutationAtom = atom(null, (get, set, success = true) => {\n const currentCount = get(pendingMutationsCountAtom);\n const newCount = Math.max(0, currentCount - 1);\n set(pendingMutationsCountAtom, newCount);\n debug('Mutation completed (success: %s). Pending count: %d -> %d', success, currentCount, newCount);\n if (success) {\n set(lastSyncTimeAtom, Date.now());\n if (newCount === 0) {\n set(lastSyncErrorAtom, null);\n }\n }\n\n // Update status if no more pending mutations\n if (newCount === 0) {\n const isOnline = get(isOnlineAtom);\n const hasError = get(lastSyncErrorAtom) !== null;\n if (hasError) {\n set(syncStatusAtom, 'error');\n debug('Status -> error');\n } else if (!isOnline) {\n set(syncStatusAtom, 'offline');\n debug('Status -> offline');\n } else {\n set(syncStatusAtom, 'synced');\n debug('Status -> synced');\n }\n }\n});\n\n/**\n * Track a mutation error\n */\nexport const trackMutationErrorAtom = atom(null, (_get, set, error) => {\n set(lastSyncErrorAtom, error);\n debug('Mutation failed: %s', error);\n});\n\n// --- Network Status ---\n\n/**\n * Set online/offline status\n */\nexport const setOnlineStatusAtom = atom(null, (get, set, isOnline) => {\n set(isOnlineAtom, isOnline);\n const pendingCount = get(pendingMutationsCountAtom);\n const hasError = get(lastSyncErrorAtom) !== null;\n const queueLength = get(mutationQueueAtom).length;\n if (pendingCount === 0) {\n if (hasError || queueLength > 0) {\n set(syncStatusAtom, 'error');\n } else {\n set(syncStatusAtom, isOnline ? 'synced' : 'offline');\n }\n }\n});\n\n// --- Mutation Queue ---\n\n/**\n * Add a mutation to the retry queue\n */\nexport const queueMutationAtom = atom(null, (get, set, mutation) => {\n const queue = get(mutationQueueAtom);\n const newMutation = {\n ...mutation,\n id: crypto.randomUUID(),\n timestamp: Date.now(),\n retryCount: 0,\n maxRetries: mutation.maxRetries ?? 3\n };\n const newQueue = [...queue, newMutation];\n set(mutationQueueAtom, newQueue);\n debug('Queued mutation: %s. Queue size: %d', mutation.type, newQueue.length);\n if (get(pendingMutationsCountAtom) === 0) {\n set(syncStatusAtom, 'error');\n }\n return newMutation.id;\n});\n\n/**\n * Remove a mutation from the queue\n */\nexport const dequeueMutationAtom = atom(null, (get, set, mutationId) => {\n const queue = get(mutationQueueAtom);\n const newQueue = queue.filter(m => m.id !== mutationId);\n set(mutationQueueAtom, newQueue);\n debug('Dequeued mutation: %s. Queue size: %d', mutationId, newQueue.length);\n if (newQueue.length === 0 && get(pendingMutationsCountAtom) === 0 && get(lastSyncErrorAtom) === null) {\n set(syncStatusAtom, get(isOnlineAtom) ? 'synced' : 'offline');\n }\n});\n\n/**\n * Increment retry count for a mutation\n */\nexport const incrementRetryCountAtom = atom(null, (get, set, mutationId) => {\n const queue = get(mutationQueueAtom);\n const newQueue = queue.map(m => m.id === mutationId ? {\n ...m,\n retryCount: m.retryCount + 1\n } : m);\n set(mutationQueueAtom, newQueue);\n});\n\n/**\n * Get the next mutation to retry\n */\nexport const getNextQueuedMutationAtom = atom(get => {\n const queue = get(mutationQueueAtom);\n return queue.find(m => m.retryCount < m.maxRetries) ?? null;\n});\n\n/**\n * Clear all queued mutations\n */\nexport const clearMutationQueueAtom = atom(null, (get, set) => {\n set(mutationQueueAtom, []);\n debug('Cleared mutation queue');\n if (get(pendingMutationsCountAtom) === 0 && get(lastSyncErrorAtom) === null) {\n set(syncStatusAtom, get(isOnlineAtom) ? 'synced' : 'offline');\n }\n});","/**\n * Interaction Store\n *\n * Manages canvas interaction modes (picking nodes, points, etc.)\n * and visual feedback during interactions.\n */\n\nimport { atom } from 'jotai';\n\n// =============================================================================\n// Input Mode Types\n// =============================================================================\n\n/**\n * A selectable option for 'select' type inputs.\n */\n\n/**\n * Input mode - controls how canvas interactions are routed.\n * When not 'normal', canvas clicks are intercepted for special handling.\n */\n\n// =============================================================================\n// Feedback Types\n// =============================================================================\n\n/**\n * Visual feedback state for the canvas overlay.\n */\n\n// =============================================================================\n// Input Mode Atoms\n// =============================================================================\n\n/**\n * Current input mode - controls how canvas interactions are routed.\n */\nexport const inputModeAtom = atom({\n type: 'normal'\n});\n\n/**\n * Keyboard interaction mode for arrow/space/enter behavior.\n */\nexport const keyboardInteractionModeAtom = atom('navigate');\n\n/**\n * Visual feedback state for overlays during interaction.\n */\nexport const interactionFeedbackAtom = atom(null);\n\n/**\n * Resolver for pending input values (used by command systems).\n */\nexport const pendingInputResolverAtom = atom(null);\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/**\n * Reset input mode to normal.\n */\nexport const resetInputModeAtom = atom(null, (_get, set) => {\n set(inputModeAtom, {\n type: 'normal'\n });\n set(interactionFeedbackAtom, null);\n set(pendingInputResolverAtom, null);\n});\n\n/**\n * Reset keyboard interaction mode back to navigation.\n */\nexport const resetKeyboardInteractionModeAtom = atom(null, (_get, set) => {\n set(keyboardInteractionModeAtom, 'navigate');\n});\n\n/**\n * Set keyboard interaction mode explicitly.\n */\nexport const setKeyboardInteractionModeAtom = atom(null, (_get, set, mode) => {\n set(keyboardInteractionModeAtom, mode);\n});\n\n/**\n * Set input mode for picking a node.\n */\nexport const startPickNodeAtom = atom(null, (_get, set, options) => {\n set(inputModeAtom, {\n type: 'pickNode',\n ...options\n });\n});\n\n/**\n * Set input mode for picking multiple nodes.\n */\nexport const startPickNodesAtom = atom(null, (_get, set, options) => {\n set(inputModeAtom, {\n type: 'pickNodes',\n ...options\n });\n});\n\n/**\n * Set input mode for picking a point on the canvas.\n */\nexport const startPickPointAtom = atom(null, (_get, set, options) => {\n set(inputModeAtom, {\n type: 'pickPoint',\n ...options\n });\n});\n\n/**\n * Provide input value (called when user picks a node/point).\n */\nexport const provideInputAtom = atom(null, (get, set, value) => {\n set(pendingInputResolverAtom, value);\n // Input mode is typically reset by the consumer after receiving the value\n});\n\n/**\n * Update feedback during interaction.\n */\nexport const updateInteractionFeedbackAtom = atom(null, (get, set, feedback) => {\n const current = get(interactionFeedbackAtom);\n set(interactionFeedbackAtom, {\n ...current,\n ...feedback\n });\n});\n\n// =============================================================================\n// Derived Atoms\n// =============================================================================\n\n/**\n * Whether canvas is in a picking mode (not normal).\n */\nexport const isPickingModeAtom = atom(get => {\n const mode = get(inputModeAtom);\n return mode.type !== 'normal';\n});\n\n/**\n * Whether currently picking a node.\n */\nexport const isPickNodeModeAtom = atom(get => {\n const mode = get(inputModeAtom);\n return mode.type === 'pickNode' || mode.type === 'pickNodes';\n});","/**\n * Locked Node Store\n *\n * Manages \"locking\" onto a node for detailed viewing/editing.\n * Triple-click on a node locks it, showing additional panels/pages.\n */\n\nimport { atom } from 'jotai';\nimport { uiNodesAtom } from './graph-derived';\n\n// =============================================================================\n// Locked Node Atoms\n// =============================================================================\n\n/**\n * Currently locked node ID (null = no node locked).\n */\nexport const lockedNodeIdAtom = atom(null);\n\n/**\n * Full node data for the locked node.\n */\nexport const lockedNodeDataAtom = atom(get => {\n const id = get(lockedNodeIdAtom);\n if (!id) return null;\n const nodes = get(uiNodesAtom);\n return nodes.find(n => n.id === id) || null;\n});\n\n/**\n * Current page index for locked node (0-based).\n */\nexport const lockedNodePageIndexAtom = atom(0);\n\n/**\n * Total number of pages available (set by app).\n */\nexport const lockedNodePageCountAtom = atom(1);\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/**\n * Lock onto a node (typically triggered by triple-click).\n * @param nodeId - The node ID to lock onto\n * @param nodeData - Optional node data (for app compatibility, not used internally)\n */\nexport const lockNodeAtom = atom(null, (_get, set, payload) => {\n set(lockedNodeIdAtom, payload.nodeId);\n set(lockedNodePageIndexAtom, 0); // Reset to first page\n});\n\n/**\n * Unlock the currently locked node.\n */\nexport const unlockNodeAtom = atom(null, (_get, set) => {\n set(lockedNodeIdAtom, null);\n});\n\n/**\n * Navigate to next page in locked node view.\n */\nexport const nextLockedPageAtom = atom(null, (get, set) => {\n const current = get(lockedNodePageIndexAtom);\n const pageCount = get(lockedNodePageCountAtom);\n set(lockedNodePageIndexAtom, (current + 1) % pageCount);\n});\n\n/**\n * Navigate to previous page in locked node view.\n */\nexport const prevLockedPageAtom = atom(null, (get, set) => {\n const current = get(lockedNodePageIndexAtom);\n const pageCount = get(lockedNodePageCountAtom);\n set(lockedNodePageIndexAtom, (current - 1 + pageCount) % pageCount);\n});\n\n/**\n * Go to specific page by index.\n */\nexport const goToLockedPageAtom = atom(null, (get, set, index) => {\n const pageCount = get(lockedNodePageCountAtom);\n if (index >= 0 && index < pageCount) {\n set(lockedNodePageIndexAtom, index);\n }\n});\n\n// =============================================================================\n// Derived Atoms\n// =============================================================================\n\n/**\n * Whether a node is currently locked.\n */\nexport const hasLockedNodeAtom = atom(get => get(lockedNodeIdAtom) !== null);","import { c as _c } from \"react/compiler-runtime\";\n/**\n * Node Type Registry\n *\n * Maps node types to their UI components.\n * Apps register their custom node components here.\n */\n\nimport React from 'react';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Props passed to node type components.\n */\n\n/**\n * A component that renders a specific node type.\n */\nimport { jsxs as _jsxs, jsx as _jsx } from \"react/jsx-runtime\";\n// =============================================================================\n// Registry\n// =============================================================================\n\nconst nodeTypeRegistry = new Map();\n\n/**\n * Register a component for a node type.\n *\n * @example\n * ```tsx\n * registerNodeType('widget', WidgetNodeComponent);\n * registerNodeType('data-source', DataSourceNodeComponent);\n * ```\n */\nexport function registerNodeType(nodeType, component) {\n nodeTypeRegistry.set(nodeType, component);\n}\n\n/**\n * Register multiple node types at once.\n *\n * @example\n * ```tsx\n * registerNodeTypes({\n * 'widget': WidgetNodeComponent,\n * 'data-source': DataSourceNodeComponent,\n * 'puck': PuckNodeComponent,\n * });\n * ```\n */\nexport function registerNodeTypes(types) {\n for (const [nodeType, component] of Object.entries(types)) {\n nodeTypeRegistry.set(nodeType, component);\n }\n}\n\n/**\n * Unregister a node type component.\n * Returns true if the type was registered and removed.\n */\nexport function unregisterNodeType(nodeType) {\n return nodeTypeRegistry.delete(nodeType);\n}\n\n/**\n * Get the component for a node type.\n * Returns undefined if no component is registered.\n */\nexport function getNodeTypeComponent(nodeType) {\n if (!nodeType) return undefined;\n return nodeTypeRegistry.get(nodeType);\n}\n\n/**\n * Check if a node type has a registered component.\n */\nexport function hasNodeTypeComponent(nodeType) {\n if (!nodeType) return false;\n return nodeTypeRegistry.has(nodeType);\n}\n\n/**\n * Get all registered node types.\n */\nexport function getRegisteredNodeTypes() {\n return Array.from(nodeTypeRegistry.keys());\n}\n\n/**\n * Clear all registered node types.\n * Useful for testing.\n */\nexport function clearNodeTypeRegistry() {\n nodeTypeRegistry.clear();\n}\n\n// =============================================================================\n// Default Fallback Component\n// =============================================================================\n\n/**\n * Default fallback component for unknown node types.\n */\nexport const FallbackNodeTypeComponent = t0 => {\n const $ = _c(11);\n const {\n nodeData\n } = t0;\n let t1;\n if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t1 = {\n padding: \"12px\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n color: \"#666\",\n fontSize: \"12px\"\n };\n $[0] = t1;\n } else {\n t1 = $[0];\n }\n const t2 = nodeData.dbData.node_type || \"none\";\n let t3;\n if ($[1] !== t2) {\n t3 = /*#__PURE__*/_jsxs(\"div\", {\n children: [\"Unknown type: \", t2]\n });\n $[1] = t2;\n $[2] = t3;\n } else {\n t3 = $[2];\n }\n let t4;\n if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t4 = {\n marginTop: \"4px\",\n opacity: 0.7\n };\n $[3] = t4;\n } else {\n t4 = $[3];\n }\n let t5;\n if ($[4] !== nodeData.id) {\n t5 = nodeData.id.substring(0, 8);\n $[4] = nodeData.id;\n $[5] = t5;\n } else {\n t5 = $[5];\n }\n let t6;\n if ($[6] !== t5) {\n t6 = /*#__PURE__*/_jsx(\"div\", {\n style: t4,\n children: t5\n });\n $[6] = t5;\n $[7] = t6;\n } else {\n t6 = $[7];\n }\n let t7;\n if ($[8] !== t3 || $[9] !== t6) {\n t7 = /*#__PURE__*/_jsxs(\"div\", {\n style: t1,\n children: [t3, t6]\n });\n $[8] = t3;\n $[9] = t6;\n $[10] = t7;\n } else {\n t7 = $[10];\n }\n return t7;\n};","/**\n * Toast Store\n *\n * Lightweight toast notification system for canvas operations.\n * Shows brief, non-interactive messages (e.g., \"Undo: Split node\").\n */\n\nimport { atom } from 'jotai';\n/** Current visible toast, or null */\nexport const canvasToastAtom = atom(null);\n\n/** Show a toast message that auto-clears after 2 seconds */\nexport const showToastAtom = atom(null, (_get, set, message) => {\n const id = `toast-${Date.now()}`;\n set(canvasToastAtom, {\n id,\n message,\n timestamp: Date.now()\n });\n setTimeout(() => {\n set(canvasToastAtom, current => current?.id === id ? null : current);\n }, 2000);\n});","/**\n * Snap-to-Grid Store\n *\n * Optional grid snapping for node positioning.\n * When enabled, nodes snap to the nearest grid point during drag.\n */\n\nimport { atom } from 'jotai';\n// =============================================================================\n// Configuration\n// =============================================================================\n\n/** Whether grid snapping is enabled */\nexport const snapEnabledAtom = atom(false);\n\n/** Grid size in pixels (default: 20) */\nexport const snapGridSizeAtom = atom(20);\n\n/** Whether snap is temporarily disabled (e.g. holding modifier key) */\nexport const snapTemporaryDisableAtom = atom(false);\n\n// =============================================================================\n// Derived\n// =============================================================================\n\n/** Whether snapping is currently active (enabled AND not temporarily disabled) */\nexport const isSnappingActiveAtom = atom(get => {\n return get(snapEnabledAtom) && !get(snapTemporaryDisableAtom);\n});\n\n// =============================================================================\n// Snap Functions (pure — no atoms, usable anywhere)\n// =============================================================================\n\n/**\n * Snap a position to the nearest grid point.\n */\nexport function snapToGrid(pos, gridSize) {\n return {\n x: Math.round(pos.x / gridSize) * gridSize,\n y: Math.round(pos.y / gridSize) * gridSize\n };\n}\n\n/**\n * Snap a position if snapping is active, otherwise return as-is.\n */\nexport function conditionalSnap(pos, gridSize, isActive) {\n return isActive ? snapToGrid(pos, gridSize) : pos;\n}\n\n/**\n * Get snap guide lines for the current position.\n * Returns the X and Y grid lines closest to the position.\n */\nexport function getSnapGuides(pos, gridSize, tolerance = 5) {\n const snappedX = Math.round(pos.x / gridSize) * gridSize;\n const snappedY = Math.round(pos.y / gridSize) * gridSize;\n return {\n x: Math.abs(pos.x - snappedX) < tolerance ? snappedX : null,\n y: Math.abs(pos.y - snappedY) < tolerance ? snappedY : null\n };\n}\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/** Toggle snap on/off */\nexport const toggleSnapAtom = atom(null, (get, set) => {\n set(snapEnabledAtom, !get(snapEnabledAtom));\n});\n\n/** Set grid size */\nexport const setGridSizeAtom = atom(null, (_get, set, size) => {\n set(snapGridSizeAtom, Math.max(5, Math.min(200, size)));\n});\n\n// =============================================================================\n// Alignment Guides (node-to-node snapping)\n// =============================================================================\n\n/** Whether node alignment guides are enabled */\nexport const snapAlignmentEnabledAtom = atom(true);\n\n/** Toggle alignment guides on/off */\nexport const toggleAlignmentGuidesAtom = atom(null, (get, set) => {\n set(snapAlignmentEnabledAtom, !get(snapAlignmentEnabledAtom));\n});\n\n/** Active alignment guides during drag — written by useNodeDrag, read by AlignmentGuides */\n\nexport const alignmentGuidesAtom = atom({\n verticalGuides: [],\n horizontalGuides: []\n});\n\n/** Clear alignment guides (call on drag end) */\nexport const clearAlignmentGuidesAtom = atom(null, (_get, set) => {\n set(alignmentGuidesAtom, {\n verticalGuides: [],\n horizontalGuides: []\n });\n});\n\n// =============================================================================\n// Alignment Functions (pure — no atoms, usable anywhere)\n// =============================================================================\n\n/**\n * Find alignment guides for a dragged node against a set of other nodes.\n * Checks center-X, left-edge, right-edge, center-Y, top-edge, bottom-edge.\n *\n * Returns arrays of X and Y world coordinates where guides should be drawn.\n *\n * @param dragged - The node being dragged (current position)\n * @param others - Other nodes to check alignment against\n * @param tolerance - Max distance in px to trigger a guide (default: 5)\n */\nexport function findAlignmentGuides(dragged, others, tolerance = 5) {\n const verticals = new Set();\n const horizontals = new Set();\n const dragCX = dragged.x + dragged.width / 2;\n const dragCY = dragged.y + dragged.height / 2;\n const dragRight = dragged.x + dragged.width;\n const dragBottom = dragged.y + dragged.height;\n for (const other of others) {\n const otherCX = other.x + other.width / 2;\n const otherCY = other.y + other.height / 2;\n const otherRight = other.x + other.width;\n const otherBottom = other.y + other.height;\n\n // Vertical guides (X alignment)\n if (Math.abs(dragCX - otherCX) < tolerance) verticals.add(otherCX); // center-center\n if (Math.abs(dragged.x - other.x) < tolerance) verticals.add(other.x); // left-left\n if (Math.abs(dragRight - otherRight) < tolerance) verticals.add(otherRight); // right-right\n if (Math.abs(dragged.x - otherRight) < tolerance) verticals.add(otherRight); // left-right\n if (Math.abs(dragRight - other.x) < tolerance) verticals.add(other.x); // right-left\n if (Math.abs(dragCX - other.x) < tolerance) verticals.add(other.x); // center-left\n if (Math.abs(dragCX - otherRight) < tolerance) verticals.add(otherRight); // center-right\n\n // Horizontal guides (Y alignment)\n if (Math.abs(dragCY - otherCY) < tolerance) horizontals.add(otherCY); // center-center\n if (Math.abs(dragged.y - other.y) < tolerance) horizontals.add(other.y); // top-top\n if (Math.abs(dragBottom - otherBottom) < tolerance) horizontals.add(otherBottom); // bottom-bottom\n if (Math.abs(dragged.y - otherBottom) < tolerance) horizontals.add(otherBottom); // top-bottom\n if (Math.abs(dragBottom - other.y) < tolerance) horizontals.add(other.y); // bottom-top\n if (Math.abs(dragCY - other.y) < tolerance) horizontals.add(other.y); // center-top\n if (Math.abs(dragCY - otherBottom) < tolerance) horizontals.add(otherBottom); // center-bottom\n }\n return {\n verticalGuides: Array.from(verticals),\n horizontalGuides: Array.from(horizontals)\n };\n}","/**\n * Canvas Event Types\n *\n * Type definitions for configurable canvas events.\n *\n * Extracted from settings-types.ts in v1.9.0.\n *\n * @since 1.9.0\n */\n\n// =============================================================================\n// Canvas Events\n// =============================================================================\n\n/**\n * All configurable canvas events that can trigger actions.\n */\nexport let CanvasEventType = /*#__PURE__*/function (CanvasEventType) {\n // Node events\n CanvasEventType[\"NodeClick\"] = \"node:click\";\n CanvasEventType[\"NodeDoubleClick\"] = \"node:double-click\";\n CanvasEventType[\"NodeTripleClick\"] = \"node:triple-click\";\n CanvasEventType[\"NodeRightClick\"] = \"node:right-click\";\n CanvasEventType[\"NodeLongPress\"] = \"node:long-press\";\n // Edge events\n CanvasEventType[\"EdgeClick\"] = \"edge:click\";\n CanvasEventType[\"EdgeDoubleClick\"] = \"edge:double-click\";\n CanvasEventType[\"EdgeRightClick\"] = \"edge:right-click\";\n // Background events\n CanvasEventType[\"BackgroundClick\"] = \"background:click\";\n CanvasEventType[\"BackgroundDoubleClick\"] = \"background:double-click\";\n CanvasEventType[\"BackgroundRightClick\"] = \"background:right-click\";\n CanvasEventType[\"BackgroundLongPress\"] = \"background:long-press\";\n return CanvasEventType;\n}({});\n\n/**\n * Metadata for each event type (for UI display).\n */\n\n/**\n * Registry of all event type metadata.\n */\nexport const EVENT_TYPE_INFO = {\n [CanvasEventType.NodeClick]: {\n type: CanvasEventType.NodeClick,\n label: 'Click Node',\n description: 'Triggered when clicking on a node',\n category: 'node'\n },\n [CanvasEventType.NodeDoubleClick]: {\n type: CanvasEventType.NodeDoubleClick,\n label: 'Double-click Node',\n description: 'Triggered when double-clicking on a node',\n category: 'node'\n },\n [CanvasEventType.NodeTripleClick]: {\n type: CanvasEventType.NodeTripleClick,\n label: 'Triple-click Node',\n description: 'Triggered when triple-clicking on a node',\n category: 'node'\n },\n [CanvasEventType.NodeRightClick]: {\n type: CanvasEventType.NodeRightClick,\n label: 'Right-click Node',\n description: 'Triggered when right-clicking on a node',\n category: 'node'\n },\n [CanvasEventType.NodeLongPress]: {\n type: CanvasEventType.NodeLongPress,\n label: 'Long-press Node',\n description: 'Triggered when long-pressing on a node (mobile/touch)',\n category: 'node'\n },\n [CanvasEventType.EdgeClick]: {\n type: CanvasEventType.EdgeClick,\n label: 'Click Edge',\n description: 'Triggered when clicking on an edge',\n category: 'edge'\n },\n [CanvasEventType.EdgeDoubleClick]: {\n type: CanvasEventType.EdgeDoubleClick,\n label: 'Double-click Edge',\n description: 'Triggered when double-clicking on an edge',\n category: 'edge'\n },\n [CanvasEventType.EdgeRightClick]: {\n type: CanvasEventType.EdgeRightClick,\n label: 'Right-click Edge',\n description: 'Triggered when right-clicking on an edge',\n category: 'edge'\n },\n [CanvasEventType.BackgroundClick]: {\n type: CanvasEventType.BackgroundClick,\n label: 'Click Background',\n description: 'Triggered when clicking on the canvas background',\n category: 'background'\n },\n [CanvasEventType.BackgroundDoubleClick]: {\n type: CanvasEventType.BackgroundDoubleClick,\n label: 'Double-click Background',\n description: 'Triggered when double-clicking on the canvas background',\n category: 'background'\n },\n [CanvasEventType.BackgroundRightClick]: {\n type: CanvasEventType.BackgroundRightClick,\n label: 'Right-click Background',\n description: 'Triggered when right-clicking on the canvas background',\n category: 'background'\n },\n [CanvasEventType.BackgroundLongPress]: {\n type: CanvasEventType.BackgroundLongPress,\n label: 'Long-press Background',\n description: 'Triggered when long-pressing on the canvas background (mobile/touch)',\n category: 'background'\n }\n};","/**\n * Canvas Action Types\n *\n * Action category enum, built-in action IDs, and action definition interfaces.\n *\n * Extracted from settings-types.ts in v1.9.0.\n *\n * @since 1.9.0\n */\n\n// =============================================================================\n// Action Categories\n// =============================================================================\n\n/**\n * Categories for grouping actions in the UI.\n */\nexport let ActionCategory = /*#__PURE__*/function (ActionCategory) {\n /** No action / disabled */\n ActionCategory[\"None\"] = \"none\";\n /** Selection-related actions */\n ActionCategory[\"Selection\"] = \"selection\";\n /** Viewport/navigation actions */\n ActionCategory[\"Viewport\"] = \"viewport\";\n /** Node manipulation actions */\n ActionCategory[\"Node\"] = \"node\";\n /** Layout and arrangement actions */\n ActionCategory[\"Layout\"] = \"layout\";\n /** History actions (undo/redo) */\n ActionCategory[\"History\"] = \"history\";\n /** User-defined custom actions */\n ActionCategory[\"Custom\"] = \"custom\";\n return ActionCategory;\n}({});\n\n// =============================================================================\n// Built-in Action IDs\n// =============================================================================\n\n/**\n * IDs for all built-in actions.\n * Using const assertion for type safety while allowing string comparison.\n */\nexport const BuiltInActionId = {\n // None\n None: 'none',\n // Selection\n SelectNode: 'select-node',\n SelectEdge: 'select-edge',\n AddToSelection: 'add-to-selection',\n ClearSelection: 'clear-selection',\n DeleteSelected: 'delete-selected',\n // Viewport\n FitToView: 'fit-to-view',\n FitAllToView: 'fit-all-to-view',\n CenterOnNode: 'center-on-node',\n ResetViewport: 'reset-viewport',\n // Node\n LockNode: 'lock-node',\n UnlockNode: 'unlock-node',\n ToggleLock: 'toggle-lock',\n OpenContextMenu: 'open-context-menu',\n SplitNode: 'split-node',\n GroupNodes: 'group-nodes',\n MergeNodes: 'merge-nodes',\n // Layout\n ApplyForceLayout: 'apply-force-layout',\n // History\n Undo: 'undo',\n Redo: 'redo',\n // Creation\n CreateNode: 'create-node'\n};\n\n// =============================================================================\n// Action Context\n// =============================================================================\n\n/**\n * Context passed to action handlers when executing.\n */\n\n/**\n * Options for creating an ActionContext via the context builder helpers.\n */\n\n// =============================================================================\n// Action Helpers\n// =============================================================================\n\n/**\n * Helper functions provided to action handlers.\n */\n\n// =============================================================================\n// Action Definition\n// =============================================================================\n\n/**\n * Full definition of an action that can be triggered by events.\n */","/**\n * Canvas Settings State Types\n *\n * Event-action mappings, presets, persisted state, and default mappings.\n *\n * Extracted from settings-types.ts in v1.9.0.\n *\n * @since 1.9.0\n */\n\nimport { CanvasEventType } from './event-types';\nimport { BuiltInActionId } from './action-types';\n\n// =============================================================================\n// Event-Action Mappings\n// =============================================================================\n\n/**\n * Mapping of events to action IDs.\n */\n\n// =============================================================================\n// Presets\n// =============================================================================\n\n/**\n * A settings preset with a name and full event-action mappings.\n */\n\n// =============================================================================\n// Persisted State\n// =============================================================================\n\n/**\n * The full settings state that gets persisted to localStorage.\n */\n\n// =============================================================================\n// Default Mappings\n// =============================================================================\n\n/**\n * Default event-action mappings (the \"Default\" preset).\n */\nexport const DEFAULT_MAPPINGS = {\n [CanvasEventType.NodeClick]: BuiltInActionId.None,\n [CanvasEventType.NodeDoubleClick]: BuiltInActionId.FitToView,\n [CanvasEventType.NodeTripleClick]: BuiltInActionId.ToggleLock,\n [CanvasEventType.NodeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.NodeLongPress]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.EdgeClick]: BuiltInActionId.SelectEdge,\n [CanvasEventType.EdgeDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.EdgeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.BackgroundClick]: BuiltInActionId.ClearSelection,\n [CanvasEventType.BackgroundDoubleClick]: BuiltInActionId.FitAllToView,\n [CanvasEventType.BackgroundRightClick]: BuiltInActionId.None,\n [CanvasEventType.BackgroundLongPress]: BuiltInActionId.CreateNode\n};","/**\n * Node & Selection Actions\n *\n * Registration functions for node-related and selection-related built-in actions.\n */\n\nimport { ActionCategory, BuiltInActionId } from './settings-types';\nimport { registerAction } from './action-registry';\nexport function registerSelectionActions() {\n registerAction({\n id: BuiltInActionId.SelectNode,\n label: 'Select Node',\n description: 'Select this node (replacing current selection)',\n category: ActionCategory.Selection,\n icon: 'pointer',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.selectNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.SelectEdge,\n label: 'Select Edge',\n description: 'Select this edge',\n category: ActionCategory.Selection,\n icon: 'git-commit',\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.edgeId) {\n helpers.selectEdge(context.edgeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.AddToSelection,\n label: 'Add to Selection',\n description: 'Add this node to the current selection',\n category: ActionCategory.Selection,\n icon: 'plus-square',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.addToSelection(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.ClearSelection,\n label: 'Clear Selection',\n description: 'Deselect all nodes',\n category: ActionCategory.Selection,\n icon: 'x-square',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n helpers.clearSelection();\n }\n });\n registerAction({\n id: BuiltInActionId.DeleteSelected,\n label: 'Delete Selected',\n description: 'Delete all selected nodes',\n category: ActionCategory.Selection,\n icon: 'trash-2',\n isBuiltIn: true,\n handler: async (_context, helpers) => {\n const selectedIds = helpers.getSelectedNodeIds();\n for (const nodeId of selectedIds) {\n await helpers.deleteNode(nodeId);\n }\n }\n });\n}\nexport function registerNodeActions() {\n registerAction({\n id: BuiltInActionId.LockNode,\n label: 'Lock Node',\n description: 'Prevent this node from being moved',\n category: ActionCategory.Node,\n icon: 'lock',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.lockNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.UnlockNode,\n label: 'Unlock Node',\n description: 'Allow this node to be moved',\n category: ActionCategory.Node,\n icon: 'unlock',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.unlockNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.ToggleLock,\n label: 'Toggle Lock',\n description: 'Toggle whether this node can be moved',\n category: ActionCategory.Node,\n icon: 'lock',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.toggleLock(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.OpenContextMenu,\n label: 'Open Context Menu',\n description: 'Show the context menu for this node',\n category: ActionCategory.Node,\n icon: 'more-vertical',\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (helpers.openContextMenu) {\n helpers.openContextMenu(context.screenPosition, context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.CreateNode,\n label: 'Create Node',\n description: 'Create a new node at this position',\n category: ActionCategory.Node,\n icon: 'plus',\n isBuiltIn: true,\n handler: async (context, helpers) => {\n if (helpers.createNode) {\n await helpers.createNode(context.worldPosition);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.SplitNode,\n label: 'Split Node',\n description: 'Split a node into two separate nodes',\n category: ActionCategory.Node,\n icon: 'split',\n isBuiltIn: true,\n handler: async (context, helpers) => {\n if (helpers.splitNode && context.nodeId) {\n await helpers.splitNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.GroupNodes,\n label: 'Group Nodes',\n description: 'Group selected nodes into a parent container',\n category: ActionCategory.Node,\n icon: 'group',\n isBuiltIn: true,\n handler: async (context, helpers) => {\n if (helpers.groupNodes) {\n await helpers.groupNodes(context.selectedNodeIds ?? helpers.getSelectedNodeIds());\n }\n }\n });\n registerAction({\n id: BuiltInActionId.MergeNodes,\n label: 'Merge Nodes',\n description: 'Merge selected nodes into one',\n category: ActionCategory.Node,\n icon: 'merge',\n isBuiltIn: true,\n handler: async (context, helpers) => {\n if (helpers.mergeNodes) {\n await helpers.mergeNodes(context.selectedNodeIds ?? helpers.getSelectedNodeIds());\n }\n }\n });\n}","/**\n * Viewport Actions\n *\n * Registration functions for viewport-related built-in actions.\n */\n\nimport { ActionCategory, BuiltInActionId } from './settings-types';\nimport { registerAction } from './action-registry';\nexport function registerViewportActions() {\n registerAction({\n id: BuiltInActionId.FitToView,\n label: 'Fit to View',\n description: 'Zoom and pan to fit this node in view',\n category: ActionCategory.Viewport,\n icon: 'maximize-2',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.centerOnNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.FitAllToView,\n label: 'Fit All to View',\n description: 'Zoom and pan to fit all nodes in view',\n category: ActionCategory.Viewport,\n icon: 'maximize',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n helpers.fitToBounds('graph');\n }\n });\n registerAction({\n id: BuiltInActionId.CenterOnNode,\n label: 'Center on Node',\n description: 'Center the viewport on this node',\n category: ActionCategory.Viewport,\n icon: 'crosshair',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.centerOnNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.ResetViewport,\n label: 'Reset Viewport',\n description: 'Reset zoom to 100% and center on origin',\n category: ActionCategory.Viewport,\n icon: 'home',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n helpers.resetViewport();\n }\n });\n}\nexport function registerHistoryActions() {\n registerAction({\n id: BuiltInActionId.Undo,\n label: 'Undo',\n description: 'Undo the last action',\n category: ActionCategory.History,\n icon: 'undo-2',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n if (helpers.canUndo()) {\n helpers.undo();\n }\n }\n });\n registerAction({\n id: BuiltInActionId.Redo,\n label: 'Redo',\n description: 'Redo the last undone action',\n category: ActionCategory.History,\n icon: 'redo-2',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n if (helpers.canRedo()) {\n helpers.redo();\n }\n }\n });\n registerAction({\n id: BuiltInActionId.ApplyForceLayout,\n label: 'Apply Force Layout',\n description: 'Automatically arrange nodes using force-directed layout',\n category: ActionCategory.Layout,\n icon: 'layout-grid',\n isBuiltIn: true,\n handler: async (_context, helpers) => {\n await helpers.applyForceLayout();\n }\n });\n}","/**\n * Built-in Actions\n *\n * All default action definitions. Registered automatically when\n * action-registry.ts is imported.\n *\n * Actions are split into separate modules:\n * - actions-node.ts — Selection and Node actions\n * - actions-viewport.ts — Viewport, History, and Layout actions\n */\n\nimport { BuiltInActionId, ActionCategory } from './settings-types';\nimport { registerAction } from './action-registry';\nimport { registerSelectionActions, registerNodeActions } from './actions-node';\nimport { registerViewportActions, registerHistoryActions } from './actions-viewport';\n\n/**\n * Register all built-in actions.\n * Called automatically when action-registry is imported.\n */\nexport function registerBuiltInActions() {\n // None - do nothing\n registerAction({\n id: BuiltInActionId.None,\n label: 'None',\n description: 'Do nothing',\n category: ActionCategory.None,\n icon: 'ban',\n isBuiltIn: true,\n handler: () => {\n // Intentionally empty\n }\n });\n registerSelectionActions();\n registerNodeActions();\n registerViewportActions();\n registerHistoryActions();\n}","/**\n * Action Registry\n *\n * Extensible registry for actions that can be triggered by canvas events.\n * Similar pattern to node-type-registry.ts - apps can register custom actions.\n */\n\nimport { ActionCategory } from './settings-types';\n\n// =============================================================================\n// Registry Storage\n// =============================================================================\n\nconst actionRegistry = new Map();\n\n// =============================================================================\n// Registry Functions\n// =============================================================================\n\n/**\n * Register a new action.\n * If an action with the same ID exists, it will be overwritten.\n */\nexport function registerAction(action) {\n actionRegistry.set(action.id, action);\n}\n\n/**\n * Get an action by ID.\n */\nexport function getAction(id) {\n return actionRegistry.get(id);\n}\n\n/**\n * Check if an action exists.\n */\nexport function hasAction(id) {\n return actionRegistry.has(id);\n}\n\n/**\n * Get all registered actions.\n */\nexport function getAllActions() {\n return Array.from(actionRegistry.values());\n}\n\n/**\n * Get actions by category.\n */\nexport function getActionsByCategory(category) {\n return getAllActions().filter(action => action.category === category);\n}\n\n/**\n * Unregister an action (mainly for custom actions).\n */\nexport function unregisterAction(id) {\n return actionRegistry.delete(id);\n}\n\n/**\n * Clear all actions (mainly for testing).\n */\nexport function clearActions() {\n actionRegistry.clear();\n}\n\n// =============================================================================\n// Built-in Actions — registered on first import\n// =============================================================================\n\nimport { registerBuiltInActions } from './built-in-actions';\nregisterBuiltInActions();\n\n// =============================================================================\n// Export Action Utilities\n// =============================================================================\n\n/**\n * Get all action categories with their actions, for UI rendering.\n */\nexport function getActionsByCategories() {\n const categoryLabels = {\n [ActionCategory.None]: 'None',\n [ActionCategory.Selection]: 'Selection',\n [ActionCategory.Viewport]: 'Viewport',\n [ActionCategory.Node]: 'Node',\n [ActionCategory.Layout]: 'Layout',\n [ActionCategory.History]: 'History',\n [ActionCategory.Custom]: 'Custom'\n };\n const categoryOrder = [ActionCategory.None, ActionCategory.Selection, ActionCategory.Viewport, ActionCategory.Node, ActionCategory.Layout, ActionCategory.History, ActionCategory.Custom];\n return categoryOrder.map(category => ({\n category,\n label: categoryLabels[category],\n actions: getActionsByCategory(category)\n })).filter(group => group.actions.length > 0);\n}","/**\n * Action Executor\n *\n * Executes actions by ID with the provided context and helpers.\n * This is the core execution logic, separate from React hooks.\n */\n\nimport { getAction } from './action-registry';\nimport { BuiltInActionId } from './settings-types';\nimport { selectedNodeIdsAtom, selectSingleNodeAtom, addNodesToSelectionAtom, clearSelectionAtom, selectEdgeAtom, clearEdgeSelectionAtom } from './selection-store';\nimport { resetViewportAtom, fitToBoundsAtom, centerOnNodeAtom } from './viewport-store';\nimport { lockedNodeIdAtom, lockNodeAtom, unlockNodeAtom } from './locked-node-store';\nimport { canUndoAtom, canRedoAtom, undoAtom, redoAtom } from './history-store';\nimport { FitToBoundsMode } from '../utils/layout';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('actions');\n\n// =============================================================================\n// Execution Result\n// =============================================================================\n\n// =============================================================================\n// Execute Action\n// =============================================================================\n\n/**\n * Execute an action by its ID.\n *\n * @param actionId - The ID of the action to execute\n * @param context - The context of the triggering event\n * @param helpers - Helper functions for manipulating canvas state\n * @returns Promise resolving to the execution result\n */\nexport async function executeAction(actionId, context, helpers) {\n // None action is a no-op\n if (actionId === BuiltInActionId.None) {\n return {\n success: true,\n actionId\n };\n }\n const action = getAction(actionId);\n if (!action) {\n debug.warn('Action not found: %s', actionId);\n return {\n success: false,\n actionId,\n error: new Error(`Action not found: ${actionId}`)\n };\n }\n\n // Check if action requires a node but none was provided\n if (action.requiresNode && !context.nodeId) {\n debug.warn('Action %s requires a node context', actionId);\n return {\n success: false,\n actionId,\n error: new Error(`Action ${actionId} requires a node context`)\n };\n }\n try {\n const result = action.handler(context, helpers);\n\n // Handle both sync and async handlers\n if (result instanceof Promise) {\n await result;\n }\n return {\n success: true,\n actionId\n };\n } catch (error) {\n debug.error('Error executing action %s: %O', actionId, error);\n return {\n success: false,\n actionId,\n error: error instanceof Error ? error : new Error(String(error))\n };\n }\n}\n\n// =============================================================================\n// Context Builder Helpers\n// =============================================================================\n\n/**\n * Create an ActionContext from a mouse event.\n */\nexport function createActionContext(eventType, screenEvent, worldPosition, options) {\n return {\n eventType,\n nodeId: options?.nodeId,\n nodeData: options?.nodeData,\n edgeId: options?.edgeId,\n edgeData: options?.edgeData,\n worldPosition,\n screenPosition: {\n x: screenEvent.clientX,\n y: screenEvent.clientY\n },\n modifiers: {\n shift: false,\n ctrl: false,\n alt: false,\n meta: false\n }\n };\n}\n\n/**\n * Create an ActionContext from a React mouse event.\n */\nexport function createActionContextFromReactEvent(eventType, event, worldPosition, options) {\n return {\n eventType,\n nodeId: options?.nodeId,\n nodeData: options?.nodeData,\n edgeId: options?.edgeId,\n edgeData: options?.edgeData,\n worldPosition,\n screenPosition: {\n x: event.clientX,\n y: event.clientY\n },\n modifiers: {\n shift: event.shiftKey,\n ctrl: event.ctrlKey,\n alt: event.altKey,\n meta: event.metaKey\n }\n };\n}\n\n/**\n * Create an ActionContext from a touch event (for long-press).\n */\nexport function createActionContextFromTouchEvent(eventType, touch, worldPosition, options) {\n return {\n eventType,\n nodeId: options?.nodeId,\n nodeData: options?.nodeData,\n edgeId: options?.edgeId,\n edgeData: options?.edgeData,\n worldPosition,\n screenPosition: {\n x: touch.clientX,\n y: touch.clientY\n },\n modifiers: {\n shift: false,\n ctrl: false,\n alt: false,\n meta: false\n }\n };\n}\n\n// =============================================================================\n// Headless Action Helpers Builder\n// =============================================================================\n\n/**\n * Build ActionHelpers from a raw Jotai store.\n * No React required — works in tests, CLI tools, and non-React integrations.\n */\nexport function buildActionHelpers(store, options = {}) {\n return {\n selectNode: nodeId => store.set(selectSingleNodeAtom, nodeId),\n addToSelection: nodeId => store.set(addNodesToSelectionAtom, [nodeId]),\n clearSelection: () => store.set(clearSelectionAtom),\n getSelectedNodeIds: () => Array.from(store.get(selectedNodeIdsAtom)),\n fitToBounds: (mode, padding) => {\n const fitMode = mode === 'graph' ? FitToBoundsMode.Graph : FitToBoundsMode.Selection;\n store.set(fitToBoundsAtom, {\n mode: fitMode,\n padding\n });\n },\n centerOnNode: nodeId => store.set(centerOnNodeAtom, nodeId),\n resetViewport: () => store.set(resetViewportAtom),\n lockNode: nodeId => store.set(lockNodeAtom, {\n nodeId\n }),\n unlockNode: _nodeId => store.set(unlockNodeAtom),\n toggleLock: nodeId => {\n const currentLockedId = store.get(lockedNodeIdAtom);\n if (currentLockedId === nodeId) {\n store.set(unlockNodeAtom);\n } else {\n store.set(lockNodeAtom, {\n nodeId\n });\n }\n },\n deleteNode: async nodeId => {\n if (options.onDeleteNode) {\n await options.onDeleteNode(nodeId);\n } else {\n debug.warn('deleteNode called but onDeleteNode callback not provided');\n }\n },\n isNodeLocked: nodeId => store.get(lockedNodeIdAtom) === nodeId,\n applyForceLayout: async () => {\n if (options.onApplyForceLayout) {\n await options.onApplyForceLayout();\n } else {\n debug.warn('applyForceLayout called but onApplyForceLayout callback not provided');\n }\n },\n undo: () => store.set(undoAtom),\n redo: () => store.set(redoAtom),\n canUndo: () => store.get(canUndoAtom),\n canRedo: () => store.get(canRedoAtom),\n selectEdge: edgeId => store.set(selectEdgeAtom, edgeId),\n clearEdgeSelection: () => store.set(clearEdgeSelectionAtom),\n openContextMenu: options.onOpenContextMenu,\n createNode: options.onCreateNode\n };\n}","/**\n * Canvas Settings Store\n *\n * Jotai atoms for managing canvas settings with localStorage persistence.\n * Uses atomWithStorage for automatic sync across tabs.\n *\n * Built-in presets and utility functions are in ./settings-presets.ts\n */\n\nimport { atom } from 'jotai';\nimport { atomWithStorage } from 'jotai/utils';\nimport { CanvasEventType, DEFAULT_MAPPINGS } from './settings-types';\nimport { createDebug } from '../utils/debug';\n\n// Re-export presets and utility for backward compat\nexport { BUILT_IN_PRESETS, getActionForEvent } from './settings-presets';\nimport { BUILT_IN_PRESETS } from './settings-presets';\nconst debug = createDebug('settings');\n\n// =============================================================================\n// Default State\n// =============================================================================\n\nconst DEFAULT_STATE = {\n mappings: DEFAULT_MAPPINGS,\n activePresetId: 'default',\n customPresets: [],\n isPanelOpen: false,\n virtualizationEnabled: true\n};\n\n// =============================================================================\n// Main Settings Atom (persisted)\n// =============================================================================\n\n/**\n * The main settings atom, persisted to localStorage.\n * All settings state is stored in a single atom for atomic updates.\n */\nexport const canvasSettingsAtom = atomWithStorage('@blinksgg/canvas/settings', DEFAULT_STATE);\n\n// =============================================================================\n// Derived Read-Only Atoms\n// =============================================================================\n\n/**\n * Current event-action mappings.\n */\nexport const eventMappingsAtom = atom(get => get(canvasSettingsAtom).mappings);\n\n/**\n * Currently active preset ID (null if mappings have been modified).\n */\nexport const activePresetIdAtom = atom(get => get(canvasSettingsAtom).activePresetId);\n\n/**\n * All presets (built-in + custom).\n */\nexport const allPresetsAtom = atom(get => {\n const state = get(canvasSettingsAtom);\n return [...BUILT_IN_PRESETS, ...state.customPresets];\n});\n\n/**\n * The currently active preset (if any).\n */\nexport const activePresetAtom = atom(get => {\n const presetId = get(activePresetIdAtom);\n if (!presetId) return null;\n const allPresets = get(allPresetsAtom);\n return allPresets.find(p => p.id === presetId) || null;\n});\n\n/**\n * Whether the settings panel is open.\n */\nexport const isPanelOpenAtom = atom(get => get(canvasSettingsAtom).isPanelOpen);\n\n/**\n * Whether viewport virtualization is enabled.\n * When true, only visible nodes/edges are rendered (better performance for large graphs).\n */\nexport const virtualizationEnabledAtom = atom(get => get(canvasSettingsAtom).virtualizationEnabled ?? true);\n\n/**\n * Whether current mappings differ from the active preset.\n */\nexport const hasUnsavedChangesAtom = atom(get => {\n const state = get(canvasSettingsAtom);\n const activePreset = get(activePresetAtom);\n if (!activePreset) return true;\n\n // Compare mappings\n const events = Object.values(CanvasEventType);\n return events.some(event => state.mappings[event] !== activePreset.mappings[event]);\n});\n\n// =============================================================================\n// Action Atoms (write-only)\n// =============================================================================\n\n/**\n * Set a single event-action mapping.\n */\nexport const setEventMappingAtom = atom(null, (get, set, {\n event,\n actionId\n}) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n mappings: {\n ...current.mappings,\n [event]: actionId\n },\n // Clear active preset since mappings have changed\n activePresetId: null\n });\n});\n\n/**\n * Apply a preset (copies its mappings to current).\n */\nexport const applyPresetAtom = atom(null, (get, set, presetId) => {\n const allPresets = get(allPresetsAtom);\n const preset = allPresets.find(p => p.id === presetId);\n if (!preset) {\n debug.warn('Preset not found: %s', presetId);\n return;\n }\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n mappings: {\n ...preset.mappings\n },\n activePresetId: presetId\n });\n});\n\n/**\n * Save current mappings as a new custom preset.\n */\nexport const saveAsPresetAtom = atom(null, (get, set, {\n name,\n description\n}) => {\n const current = get(canvasSettingsAtom);\n\n // Generate unique ID\n const id = `custom-${Date.now()}`;\n const newPreset = {\n id,\n name,\n description,\n mappings: {\n ...current.mappings\n },\n isBuiltIn: false\n };\n set(canvasSettingsAtom, {\n ...current,\n customPresets: [...current.customPresets, newPreset],\n activePresetId: id\n });\n return id;\n});\n\n/**\n * Update an existing custom preset with current mappings.\n */\nexport const updatePresetAtom = atom(null, (get, set, presetId) => {\n const current = get(canvasSettingsAtom);\n\n // Can only update custom presets\n const presetIndex = current.customPresets.findIndex(p => p.id === presetId);\n if (presetIndex === -1) {\n debug.warn('Cannot update preset: %s (not found or built-in)', presetId);\n return;\n }\n const updatedPresets = [...current.customPresets];\n updatedPresets[presetIndex] = {\n ...updatedPresets[presetIndex],\n mappings: {\n ...current.mappings\n }\n };\n set(canvasSettingsAtom, {\n ...current,\n customPresets: updatedPresets,\n activePresetId: presetId\n });\n});\n\n/**\n * Delete a custom preset.\n */\nexport const deletePresetAtom = atom(null, (get, set, presetId) => {\n const current = get(canvasSettingsAtom);\n\n // Can only delete custom presets\n const newCustomPresets = current.customPresets.filter(p => p.id !== presetId);\n if (newCustomPresets.length === current.customPresets.length) {\n debug.warn('Cannot delete preset: %s (not found or built-in)', presetId);\n return;\n }\n\n // If we deleted the active preset, switch to default\n const newActiveId = current.activePresetId === presetId ? 'default' : current.activePresetId;\n\n // If switching to default, also reset mappings\n const newMappings = newActiveId === 'default' ? DEFAULT_MAPPINGS : current.mappings;\n set(canvasSettingsAtom, {\n ...current,\n customPresets: newCustomPresets,\n activePresetId: newActiveId,\n mappings: newMappings\n });\n});\n\n/**\n * Reset to default settings.\n */\nexport const resetSettingsAtom = atom(null, (get, set) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n mappings: DEFAULT_MAPPINGS,\n activePresetId: 'default'\n });\n});\n\n/**\n * Toggle the settings panel open/closed.\n */\nexport const togglePanelAtom = atom(null, (get, set) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n isPanelOpen: !current.isPanelOpen\n });\n});\n\n/**\n * Set the panel open state directly.\n */\nexport const setPanelOpenAtom = atom(null, (get, set, isOpen) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n isPanelOpen: isOpen\n });\n});\n\n/**\n * Set virtualization enabled/disabled.\n */\nexport const setVirtualizationEnabledAtom = atom(null, (get, set, enabled) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n virtualizationEnabled: enabled\n });\n});\n\n/**\n * Toggle virtualization on/off.\n */\nexport const toggleVirtualizationAtom = atom(null, (get, set) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n virtualizationEnabled: !(current.virtualizationEnabled ?? true)\n });\n});","/**\n * Settings Presets & Utilities\n *\n * Built-in presets and utility functions extracted from settings-store.ts.\n */\n\nimport { CanvasEventType, DEFAULT_MAPPINGS, BuiltInActionId } from './settings-types';\n\n// =============================================================================\n// Built-in Presets\n// =============================================================================\n\nexport const BUILT_IN_PRESETS = [{\n id: 'default',\n name: 'Default',\n description: 'Standard canvas interactions',\n isBuiltIn: true,\n mappings: DEFAULT_MAPPINGS\n}, {\n id: 'minimal',\n name: 'Minimal',\n description: 'Only essential selection and context menu actions',\n isBuiltIn: true,\n mappings: {\n [CanvasEventType.NodeClick]: BuiltInActionId.None,\n [CanvasEventType.NodeDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.NodeTripleClick]: BuiltInActionId.None,\n [CanvasEventType.NodeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.NodeLongPress]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.EdgeClick]: BuiltInActionId.SelectEdge,\n [CanvasEventType.EdgeDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.EdgeRightClick]: BuiltInActionId.None,\n [CanvasEventType.BackgroundClick]: BuiltInActionId.ClearSelection,\n [CanvasEventType.BackgroundDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.BackgroundRightClick]: BuiltInActionId.None,\n [CanvasEventType.BackgroundLongPress]: BuiltInActionId.None\n }\n}, {\n id: 'power-user',\n name: 'Power User',\n description: 'Quick actions for experienced users',\n isBuiltIn: true,\n mappings: {\n [CanvasEventType.NodeClick]: BuiltInActionId.None,\n [CanvasEventType.NodeDoubleClick]: BuiltInActionId.ToggleLock,\n [CanvasEventType.NodeTripleClick]: BuiltInActionId.DeleteSelected,\n [CanvasEventType.NodeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.NodeLongPress]: BuiltInActionId.AddToSelection,\n [CanvasEventType.EdgeClick]: BuiltInActionId.SelectEdge,\n [CanvasEventType.EdgeDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.EdgeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.BackgroundClick]: BuiltInActionId.ClearSelection,\n [CanvasEventType.BackgroundDoubleClick]: BuiltInActionId.CreateNode,\n [CanvasEventType.BackgroundRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.BackgroundLongPress]: BuiltInActionId.ApplyForceLayout\n }\n}];\n\n// =============================================================================\n// Utility Functions\n// =============================================================================\n\n/**\n * Get the action ID for a specific event from mappings.\n */\nexport function getActionForEvent(mappings, event) {\n return mappings[event] || BuiltInActionId.None;\n}","/**\n * Canvas Serializer\n *\n * JSON export/import of the full canvas state: nodes, edges, positions,\n * groups, and viewport. Enables copy-paste between canvases, file-based\n * backup, and template workflows.\n *\n * All functions are pure and operate on a Jotai store — no React required.\n *\n * @since 1.3.0\n */\n\nimport Graph from 'graphology';\nimport { graphAtom, graphUpdateVersionAtom, graphOptions } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { zoomAtom, panAtom } from './viewport-store';\nimport { collapsedGroupsAtom } from './group-store';\n// =============================================================================\n// Snapshot Schema\n// =============================================================================\n\n/** Version of the snapshot schema. Bump on breaking format changes. */\nexport const SNAPSHOT_VERSION = 1;\n\n/**\n * Serialized node — portable representation of a single canvas node.\n */\n\n/**\n * Serialized edge — portable representation of a single canvas edge.\n */\n\n/**\n * Serialized group relationship.\n */\n\n/**\n * Complete canvas snapshot — portable JSON schema.\n */\n\n/**\n * Options for importing a snapshot.\n */\n\n/**\n * Result of snapshot validation.\n */\n\n// =============================================================================\n// Export\n// =============================================================================\n\n/**\n * Export the current canvas state to a portable JSON snapshot.\n *\n * Reads the Graphology graph, all node positions, group state, and viewport\n * from the given Jotai store.\n */\nexport function exportGraph(store, metadata) {\n const graph = store.get(graphAtom);\n const zoom = store.get(zoomAtom);\n const pan = store.get(panAtom);\n const collapsed = store.get(collapsedGroupsAtom);\n const nodes = [];\n const groups = [];\n const seenGroupParents = new Set();\n graph.forEachNode((nodeId, attrs) => {\n const a = attrs;\n nodes.push({\n id: nodeId,\n position: {\n x: a.x,\n y: a.y\n },\n dimensions: {\n width: a.width,\n height: a.height\n },\n size: a.size,\n color: a.color,\n zIndex: a.zIndex,\n label: a.label,\n parentId: a.parentId,\n dbData: a.dbData\n });\n if (a.parentId) {\n const key = `${nodeId}:${a.parentId}`;\n if (!seenGroupParents.has(key)) {\n seenGroupParents.add(key);\n groups.push({\n nodeId,\n parentId: a.parentId,\n isCollapsed: collapsed.has(a.parentId)\n });\n }\n }\n });\n const edges = [];\n graph.forEachEdge((key, attrs, source, target) => {\n const a = attrs;\n edges.push({\n key,\n sourceId: source,\n targetId: target,\n attributes: {\n weight: a.weight,\n type: a.type,\n color: a.color,\n label: a.label\n },\n dbData: a.dbData\n });\n });\n return {\n version: SNAPSHOT_VERSION,\n exportedAt: new Date().toISOString(),\n nodes,\n edges,\n groups,\n viewport: {\n zoom,\n pan: {\n ...pan\n }\n },\n metadata\n };\n}\n\n// =============================================================================\n// Import\n// =============================================================================\n\n/**\n * Import a snapshot into the Jotai store, rebuilding the full graph state.\n */\nexport function importGraph(store, snapshot, options = {}) {\n const {\n clearExisting = true,\n offsetPosition,\n remapIds = false\n } = options;\n\n // Build ID remap table if needed\n const idMap = new Map();\n if (remapIds) {\n for (const node of snapshot.nodes) {\n idMap.set(node.id, crypto.randomUUID());\n }\n for (const edge of snapshot.edges) {\n idMap.set(edge.key, crypto.randomUUID());\n }\n }\n const remap = id => idMap.get(id) ?? id;\n\n // Clear or reuse graph\n let graph;\n if (clearExisting) {\n graph = new Graph(graphOptions);\n } else {\n graph = store.get(graphAtom);\n }\n\n // Offset helper\n const ox = offsetPosition?.x ?? 0;\n const oy = offsetPosition?.y ?? 0;\n\n // Add nodes\n for (const node of snapshot.nodes) {\n const nodeId = remap(node.id);\n const parentId = node.parentId ? remap(node.parentId) : undefined;\n const dbData = remapIds ? {\n ...node.dbData,\n id: nodeId\n } : node.dbData;\n const attrs = {\n x: node.position.x + ox,\n y: node.position.y + oy,\n width: node.dimensions.width,\n height: node.dimensions.height,\n size: node.size,\n color: node.color,\n zIndex: node.zIndex,\n label: node.label,\n parentId,\n dbData\n };\n graph.addNode(nodeId, attrs);\n }\n\n // Add edges\n for (const edge of snapshot.edges) {\n const edgeKey = remap(edge.key);\n const sourceId = remap(edge.sourceId);\n const targetId = remap(edge.targetId);\n\n // Skip edges whose endpoints don't exist\n if (!graph.hasNode(sourceId) || !graph.hasNode(targetId)) continue;\n const dbData = remapIds ? {\n ...edge.dbData,\n id: edgeKey,\n source_node_id: sourceId,\n target_node_id: targetId\n } : edge.dbData;\n const attrs = {\n weight: edge.attributes.weight,\n type: edge.attributes.type,\n color: edge.attributes.color,\n label: edge.attributes.label,\n dbData\n };\n graph.addEdgeWithKey(edgeKey, sourceId, targetId, attrs);\n }\n\n // Apply graph to store\n store.set(graphAtom, graph);\n store.set(graphUpdateVersionAtom, v => v + 1);\n store.set(nodePositionUpdateCounterAtom, c => c + 1);\n\n // Restore collapsed groups\n const collapsedSet = new Set();\n for (const group of snapshot.groups) {\n if (group.isCollapsed) {\n collapsedSet.add(remap(group.parentId));\n }\n }\n store.set(collapsedGroupsAtom, collapsedSet);\n\n // Restore viewport\n store.set(zoomAtom, snapshot.viewport.zoom);\n store.set(panAtom, {\n ...snapshot.viewport.pan\n });\n}\n\n// =============================================================================\n// Validation\n// =============================================================================\n\n/**\n * Validate that an unknown value conforms to the CanvasSnapshot schema.\n * Performs runtime type checks on all required fields.\n */\nexport function validateSnapshot(data) {\n const errors = [];\n if (!data || typeof data !== 'object') {\n return {\n valid: false,\n errors: ['Snapshot must be a non-null object']\n };\n }\n const obj = data;\n\n // Version\n if (obj.version !== SNAPSHOT_VERSION) {\n errors.push(`Expected version ${SNAPSHOT_VERSION}, got ${String(obj.version)}`);\n }\n\n // exportedAt\n if (typeof obj.exportedAt !== 'string') {\n errors.push('Missing or invalid \"exportedAt\" (expected ISO string)');\n }\n\n // nodes\n if (!Array.isArray(obj.nodes)) {\n errors.push('Missing or invalid \"nodes\" (expected array)');\n } else {\n for (let i = 0; i < obj.nodes.length; i++) {\n const node = obj.nodes[i];\n if (!node || typeof node !== 'object') {\n errors.push(`nodes[${i}]: expected object`);\n continue;\n }\n if (typeof node.id !== 'string') errors.push(`nodes[${i}]: missing \"id\"`);\n if (!node.position || typeof node.position !== 'object') errors.push(`nodes[${i}]: missing \"position\"`);\n if (!node.dimensions || typeof node.dimensions !== 'object') errors.push(`nodes[${i}]: missing \"dimensions\"`);\n if (!node.dbData || typeof node.dbData !== 'object') errors.push(`nodes[${i}]: missing \"dbData\"`);\n }\n }\n\n // edges\n if (!Array.isArray(obj.edges)) {\n errors.push('Missing or invalid \"edges\" (expected array)');\n } else {\n for (let i = 0; i < obj.edges.length; i++) {\n const edge = obj.edges[i];\n if (!edge || typeof edge !== 'object') {\n errors.push(`edges[${i}]: expected object`);\n continue;\n }\n if (typeof edge.key !== 'string') errors.push(`edges[${i}]: missing \"key\"`);\n if (typeof edge.sourceId !== 'string') errors.push(`edges[${i}]: missing \"sourceId\"`);\n if (typeof edge.targetId !== 'string') errors.push(`edges[${i}]: missing \"targetId\"`);\n if (!edge.dbData || typeof edge.dbData !== 'object') errors.push(`edges[${i}]: missing \"dbData\"`);\n }\n }\n\n // groups\n if (!Array.isArray(obj.groups)) {\n errors.push('Missing or invalid \"groups\" (expected array)');\n }\n\n // viewport\n if (!obj.viewport || typeof obj.viewport !== 'object') {\n errors.push('Missing or invalid \"viewport\" (expected object)');\n } else {\n const vp = obj.viewport;\n if (typeof vp.zoom !== 'number') errors.push('viewport: missing \"zoom\"');\n if (!vp.pan || typeof vp.pan !== 'object') errors.push('viewport: missing \"pan\"');\n }\n return {\n valid: errors.length === 0,\n errors\n };\n}","/**\n * Clipboard state management\n *\n * Provides copy/cut/paste operations for nodes and edges.\n * Uses local-first approach - pasted nodes exist only in local graph until saved.\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom } from './graph-store';\nimport { addNodeToLocalGraphAtom, optimisticDeleteNodeAtom } from './graph-mutations';\nimport { addEdgeToLocalGraphAtom } from './graph-mutations-edges';\nimport { selectedNodeIdsAtom, addNodesToSelectionAtom, clearSelectionAtom } from './selection-store';\nimport { pushHistoryAtom } from './history-store';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('clipboard');\n\n// --- Types ---\n\n// --- Constants ---\n\n/** Default offset when pasting (diagonal from original) */\nexport const PASTE_OFFSET = {\n x: 50,\n y: 50\n};\n\n// --- Core Atoms ---\n\n/**\n * Clipboard data storage\n */\nexport const clipboardAtom = atom(null);\n\n/**\n * Whether clipboard has content\n */\nexport const hasClipboardContentAtom = atom(get => get(clipboardAtom) !== null);\n\n/**\n * Number of nodes in clipboard\n */\nexport const clipboardNodeCountAtom = atom(get => {\n const clipboard = get(clipboardAtom);\n return clipboard?.nodes.length ?? 0;\n});\n\n// --- Helper Functions ---\n\n/**\n * Calculate bounding box of nodes\n */\nfunction calculateBounds(nodes) {\n if (nodes.length === 0) {\n return {\n minX: 0,\n minY: 0,\n maxX: 0,\n maxY: 0\n };\n }\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const node of nodes) {\n minX = Math.min(minX, node.attrs.x);\n minY = Math.min(minY, node.attrs.y);\n maxX = Math.max(maxX, node.attrs.x + node.attrs.width);\n maxY = Math.max(maxY, node.attrs.y + node.attrs.height);\n }\n return {\n minX,\n minY,\n maxX,\n maxY\n };\n}\n\n/**\n * Generate a new unique ID for pasted nodes\n */\nfunction generatePasteId(index) {\n return `paste-${Date.now()}-${index}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n// --- Action Atoms ---\n\n/**\n * Copy selected nodes and their internal edges to clipboard\n */\nexport const copyToClipboardAtom = atom(null, (get, set, nodeIds) => {\n const selectedIds = nodeIds ?? Array.from(get(selectedNodeIdsAtom));\n if (selectedIds.length === 0) {\n debug('Nothing to copy - no nodes selected');\n return;\n }\n const graph = get(graphAtom);\n const selectedSet = new Set(selectedIds);\n const nodes = [];\n const edges = [];\n\n // Collect node data\n for (const nodeId of selectedIds) {\n if (!graph.hasNode(nodeId)) {\n debug('Node %s not found in graph, skipping', nodeId);\n continue;\n }\n const attrs = graph.getNodeAttributes(nodeId);\n nodes.push({\n attrs: {\n ...attrs\n },\n dbData: {\n ...attrs.dbData\n }\n });\n }\n\n // Collect edges where BOTH source and target are in selection\n graph.forEachEdge((edgeKey, attrs, source, target) => {\n if (selectedSet.has(source) && selectedSet.has(target)) {\n edges.push({\n source,\n target,\n attrs: {\n ...attrs\n },\n dbData: {\n ...attrs.dbData\n }\n });\n }\n });\n const bounds = calculateBounds(nodes);\n const clipboardData = {\n nodes,\n edges,\n bounds,\n timestamp: Date.now()\n };\n set(clipboardAtom, clipboardData);\n debug('Copied %d nodes and %d edges to clipboard', nodes.length, edges.length);\n});\n\n/**\n * Cut selected nodes (copy + delete from graph)\n * Pushes history for undo support.\n */\nexport const cutToClipboardAtom = atom(null, (get, set, nodeIds) => {\n const selectedIds = nodeIds ?? Array.from(get(selectedNodeIdsAtom));\n if (selectedIds.length === 0) return;\n\n // First copy to clipboard\n set(copyToClipboardAtom, selectedIds);\n\n // Push history so entire cut is undoable\n set(pushHistoryAtom, 'Cut nodes');\n\n // Delete each selected node (also removes connected edges)\n for (const nodeId of selectedIds) {\n set(optimisticDeleteNodeAtom, {\n nodeId\n });\n }\n set(clearSelectionAtom);\n debug('Cut %d nodes — copied to clipboard and deleted from graph', selectedIds.length);\n});\n\n/**\n * Paste clipboard content at an offset from original position\n */\nexport const pasteFromClipboardAtom = atom(null, (get, set, offset) => {\n const clipboard = get(clipboardAtom);\n if (!clipboard || clipboard.nodes.length === 0) {\n debug('Nothing to paste - clipboard empty');\n return [];\n }\n const pasteOffset = offset ?? PASTE_OFFSET;\n const graph = get(graphAtom);\n\n // Push history for undo support\n set(pushHistoryAtom, 'Paste nodes');\n\n // Map old IDs to new IDs\n const idMap = new Map();\n const newNodeIds = [];\n\n // Create new nodes\n for (let i = 0; i < clipboard.nodes.length; i++) {\n const nodeData = clipboard.nodes[i];\n const newId = generatePasteId(i);\n idMap.set(nodeData.dbData.id, newId);\n newNodeIds.push(newId);\n\n // Create new DBGraphNode with offset position\n const newDbNode = {\n ...nodeData.dbData,\n id: newId,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ui_properties: {\n ...(nodeData.dbData.ui_properties || {}),\n x: nodeData.attrs.x + pasteOffset.x,\n y: nodeData.attrs.y + pasteOffset.y\n }\n };\n debug('Pasting node %s -> %s at (%d, %d)', nodeData.dbData.id, newId, nodeData.attrs.x + pasteOffset.x, nodeData.attrs.y + pasteOffset.y);\n set(addNodeToLocalGraphAtom, newDbNode);\n }\n\n // Create new edges with remapped IDs\n for (const edgeData of clipboard.edges) {\n const newSourceId = idMap.get(edgeData.source);\n const newTargetId = idMap.get(edgeData.target);\n if (!newSourceId || !newTargetId) {\n debug('Edge %s: source or target not found in id map, skipping', edgeData.dbData.id);\n continue;\n }\n const newEdgeId = generatePasteId(clipboard.edges.indexOf(edgeData) + clipboard.nodes.length);\n const newDbEdge = {\n ...edgeData.dbData,\n id: newEdgeId,\n source_node_id: newSourceId,\n target_node_id: newTargetId,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString()\n };\n debug('Pasting edge %s -> %s (from %s to %s)', edgeData.dbData.id, newEdgeId, newSourceId, newTargetId);\n set(addEdgeToLocalGraphAtom, newDbEdge);\n }\n\n // Select the newly pasted nodes\n set(clearSelectionAtom);\n set(addNodesToSelectionAtom, newNodeIds);\n debug('Pasted %d nodes and %d edges', newNodeIds.length, clipboard.edges.length);\n return newNodeIds;\n});\n\n/**\n * Duplicate selected nodes in place with offset\n * Shorthand for copy + paste\n */\nexport const duplicateSelectionAtom = atom(null, (get, set) => {\n set(copyToClipboardAtom);\n return set(pasteFromClipboardAtom);\n});\n\n/**\n * Clear clipboard content\n */\nexport const clearClipboardAtom = atom(null, (_get, set) => {\n set(clipboardAtom, null);\n debug('Clipboard cleared');\n});","/**\n * Virtualization state management\n *\n * Provides viewport-based culling to only render visible nodes and edges.\n * Uses a SpatialGrid index for O(visible) node lookups instead of O(N) scans.\n * Improves performance for large graphs (100+ nodes).\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom, edgeCreationAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { nodeKeysAtom, edgeKeysAtom } from './graph-derived';\nimport { panAtom, zoomAtom, viewportRectAtom } from './viewport-store';\nimport { virtualizationEnabledAtom } from './settings-store';\nimport { collapsedEdgeRemapAtom } from './group-store';\nimport { SpatialGrid } from './spatial-index';\nimport { canvasMark } from './perf';\n\n// --- Configuration ---\n\n/**\n * Buffer in world-space pixels beyond viewport edges.\n * Nodes within this buffer are still rendered for smooth panning.\n */\nexport const VIRTUALIZATION_BUFFER = 200;\n\n// Re-export for backwards compatibility\nexport { virtualizationEnabledAtom } from './settings-store';\n\n// --- Spatial Index ---\n\n/**\n * Spatial grid index rebuilt on graph structure changes.\n * Incrementally updated on position changes via the update path.\n */\nexport const spatialIndexAtom = atom(get => {\n get(graphUpdateVersionAtom);\n get(nodePositionUpdateCounterAtom);\n const graph = get(graphAtom);\n const grid = new SpatialGrid(500);\n graph.forEachNode((nodeId, attrs) => {\n const a = attrs;\n grid.insert(nodeId, a.x, a.y, a.width || 200, a.height || 100);\n });\n return grid;\n});\n\n// --- Visible Bounds ---\n\n/**\n * Calculate visible bounds in world coordinates.\n * Includes buffer for smooth panning.\n */\nexport const visibleBoundsAtom = atom(get => {\n const viewport = get(viewportRectAtom);\n const pan = get(panAtom);\n const zoom = get(zoomAtom);\n if (!viewport || zoom === 0) {\n return null;\n }\n const buffer = VIRTUALIZATION_BUFFER;\n return {\n minX: (-buffer - pan.x) / zoom,\n minY: (-buffer - pan.y) / zoom,\n maxX: (viewport.width + buffer - pan.x) / zoom,\n maxY: (viewport.height + buffer - pan.y) / zoom\n };\n});\n\n// --- Node Visibility ---\n\n/**\n * Node keys filtered to only those visible in viewport.\n * Uses SpatialGrid.query() for O(visible) performance when enabled.\n * Falls back to all nodes when virtualization disabled or bounds unavailable.\n */\nexport const visibleNodeKeysAtom = atom(get => {\n const end = canvasMark('virtualization-cull');\n const enabled = get(virtualizationEnabledAtom);\n const allKeys = get(nodeKeysAtom);\n if (!enabled) {\n end();\n return allKeys;\n }\n const bounds = get(visibleBoundsAtom);\n if (!bounds) {\n end();\n return allKeys;\n }\n const grid = get(spatialIndexAtom);\n const visibleSet = grid.query(bounds);\n\n // Return keys in original order (preserves rendering order)\n const result = allKeys.filter(k => visibleSet.has(k));\n end();\n return result;\n});\n\n// --- Edge Visibility ---\n\n/**\n * Edge keys filtered to only those where both endpoints are visible.\n * Temp edge during creation is always included.\n *\n * When groups are collapsed, edges to/from collapsed children are re-routed\n * to the group node. Internal edges (both endpoints in the same collapsed group)\n * are hidden.\n */\nexport const visibleEdgeKeysAtom = atom(get => {\n const enabled = get(virtualizationEnabledAtom);\n const allEdgeKeys = get(edgeKeysAtom);\n const edgeCreation = get(edgeCreationAtom);\n const remap = get(collapsedEdgeRemapAtom);\n\n // Always include temp edge if creating\n const tempEdgeKey = edgeCreation.isCreating ? 'temp-creating-edge' : null;\n\n // Depend on graph changes\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n\n // Filter edges: resolve effective endpoints through remap\n const filteredEdges = allEdgeKeys.filter(edgeKey => {\n const source = graph.source(edgeKey);\n const target = graph.target(edgeKey);\n const effectiveSource = remap.get(source) ?? source;\n const effectiveTarget = remap.get(target) ?? target;\n\n // Hide internal edges (both endpoints map to the same collapsed group)\n if (effectiveSource === effectiveTarget) return false;\n return true;\n });\n if (!enabled) {\n return tempEdgeKey ? [...filteredEdges, tempEdgeKey] : filteredEdges;\n }\n\n // Get visible node set for O(1) lookup\n const visibleNodeKeys = get(visibleNodeKeysAtom);\n const visibleNodeSet = new Set(visibleNodeKeys);\n const visibleEdges = filteredEdges.filter(edgeKey => {\n const source = graph.source(edgeKey);\n const target = graph.target(edgeKey);\n const effectiveSource = remap.get(source) ?? source;\n const effectiveTarget = remap.get(target) ?? target;\n\n // Edge visible if both effective endpoints are visible\n return visibleNodeSet.has(effectiveSource) && visibleNodeSet.has(effectiveTarget);\n });\n return tempEdgeKey ? [...visibleEdges, tempEdgeKey] : visibleEdges;\n});\n\n// --- Metrics ---\n\n/**\n * Virtualization metrics for debugging/monitoring.\n */\nexport const virtualizationMetricsAtom = atom(get => {\n const enabled = get(virtualizationEnabledAtom);\n const totalNodes = get(nodeKeysAtom).length;\n const totalEdges = get(edgeKeysAtom).length;\n const visibleNodes = get(visibleNodeKeysAtom).length;\n const visibleEdges = get(visibleEdgeKeysAtom).length;\n const bounds = get(visibleBoundsAtom);\n return {\n enabled,\n totalNodes,\n totalEdges,\n visibleNodes,\n visibleEdges,\n culledNodes: totalNodes - visibleNodes,\n culledEdges: totalEdges - visibleEdges,\n bounds\n };\n});","/**\n * Spatial Grid Index\n *\n * Fixed-cell grid for O(visible + bucket) viewport culling.\n * Replaces the O(N) linear scan in visibleNodeKeysAtom.\n *\n * Default cell size is 500 world-space pixels — chosen to balance\n * bucket count vs. false positives for typical node sizes (200–500px).\n */\n\nexport class SpatialGrid {\n /** cell key → set of node IDs in that cell */\n cells = new Map();\n /** node ID → entry data (for update/remove) */\n entries = new Map();\n constructor(cellSize = 500) {\n this.cellSize = cellSize;\n }\n\n /** Number of tracked entries */\n get size() {\n return this.entries.size;\n }\n cellKey(cx, cy) {\n return `${cx},${cy}`;\n }\n getCellRange(x, y, w, h) {\n const cs = this.cellSize;\n return {\n minCX: Math.floor(x / cs),\n minCY: Math.floor(y / cs),\n maxCX: Math.floor((x + w) / cs),\n maxCY: Math.floor((y + h) / cs)\n };\n }\n\n /**\n * Insert a node into the index.\n * If the node already exists, it is updated.\n */\n insert(id, x, y, width, height) {\n if (this.entries.has(id)) {\n this.update(id, x, y, width, height);\n return;\n }\n const entry = {\n id,\n x,\n y,\n width,\n height\n };\n this.entries.set(id, entry);\n const {\n minCX,\n minCY,\n maxCX,\n maxCY\n } = this.getCellRange(x, y, width, height);\n for (let cx = minCX; cx <= maxCX; cx++) {\n for (let cy = minCY; cy <= maxCY; cy++) {\n const key = this.cellKey(cx, cy);\n let cell = this.cells.get(key);\n if (!cell) {\n cell = new Set();\n this.cells.set(key, cell);\n }\n cell.add(id);\n }\n }\n }\n\n /**\n * Update a node's position/dimensions.\n */\n update(id, x, y, width, height) {\n const prev = this.entries.get(id);\n if (!prev) {\n this.insert(id, x, y, width, height);\n return;\n }\n\n // Quick check: if cell range didn't change, just update entry\n const prevRange = this.getCellRange(prev.x, prev.y, prev.width, prev.height);\n const newRange = this.getCellRange(x, y, width, height);\n prev.x = x;\n prev.y = y;\n prev.width = width;\n prev.height = height;\n if (prevRange.minCX === newRange.minCX && prevRange.minCY === newRange.minCY && prevRange.maxCX === newRange.maxCX && prevRange.maxCY === newRange.maxCY) {\n return; // Same cells, no grid update needed\n }\n\n // Remove from old cells\n for (let cx = prevRange.minCX; cx <= prevRange.maxCX; cx++) {\n for (let cy = prevRange.minCY; cy <= prevRange.maxCY; cy++) {\n const key = this.cellKey(cx, cy);\n const cell = this.cells.get(key);\n if (cell) {\n cell.delete(id);\n if (cell.size === 0) this.cells.delete(key);\n }\n }\n }\n\n // Add to new cells\n for (let cx = newRange.minCX; cx <= newRange.maxCX; cx++) {\n for (let cy = newRange.minCY; cy <= newRange.maxCY; cy++) {\n const key = this.cellKey(cx, cy);\n let cell = this.cells.get(key);\n if (!cell) {\n cell = new Set();\n this.cells.set(key, cell);\n }\n cell.add(id);\n }\n }\n }\n\n /**\n * Remove a node from the index.\n */\n remove(id) {\n const entry = this.entries.get(id);\n if (!entry) return;\n const {\n minCX,\n minCY,\n maxCX,\n maxCY\n } = this.getCellRange(entry.x, entry.y, entry.width, entry.height);\n for (let cx = minCX; cx <= maxCX; cx++) {\n for (let cy = minCY; cy <= maxCY; cy++) {\n const key = this.cellKey(cx, cy);\n const cell = this.cells.get(key);\n if (cell) {\n cell.delete(id);\n if (cell.size === 0) this.cells.delete(key);\n }\n }\n }\n this.entries.delete(id);\n }\n\n /**\n * Query all node IDs whose bounding box overlaps the given bounds.\n * Returns a Set for O(1) membership checks.\n */\n query(bounds) {\n const result = new Set();\n const {\n minCX,\n minCY,\n maxCX,\n maxCY\n } = this.getCellRange(bounds.minX, bounds.minY, bounds.maxX - bounds.minX, bounds.maxY - bounds.minY);\n for (let cx = minCX; cx <= maxCX; cx++) {\n for (let cy = minCY; cy <= maxCY; cy++) {\n const cell = this.cells.get(this.cellKey(cx, cy));\n if (!cell) continue;\n for (const id of cell) {\n if (result.has(id)) continue;\n\n // AABB intersection test against actual entry bounds\n const entry = this.entries.get(id);\n const entryRight = entry.x + entry.width;\n const entryBottom = entry.y + entry.height;\n if (entry.x <= bounds.maxX && entryRight >= bounds.minX && entry.y <= bounds.maxY && entryBottom >= bounds.minY) {\n result.add(id);\n }\n }\n }\n }\n return result;\n }\n\n /**\n * Clear all entries.\n */\n clear() {\n this.cells.clear();\n this.entries.clear();\n }\n\n /**\n * Check if a node is tracked.\n */\n has(id) {\n return this.entries.has(id);\n }\n}","/**\n * Input Store\n *\n * Jotai atoms tracking active pointers, input sources, and device capabilities.\n * Components read these atoms to adapt behavior per input source.\n *\n * Key derived atoms:\n * - `primaryInputSourceAtom` — the last-used input source ('finger' | 'pencil' | 'mouse')\n * - `isStylusActiveAtom` — true when a pen pointer is currently down\n * - `isMultiTouchAtom` — true when 2+ fingers are touching\n */\n\nimport { atom } from 'jotai';\nimport { detectInputCapabilities } from './input-classifier';\n\n// =============================================================================\n// Core Atoms\n// =============================================================================\n\n/**\n * Map of all currently active (down) pointers.\n * Updated on pointer down/up/cancel events.\n */\nexport const activePointersAtom = atom(new Map());\n\n/**\n * The primary/last-used input source.\n * Updated whenever a pointer goes down — the most recent source wins.\n * Defaults to 'mouse' on desktop, 'finger' on mobile.\n */\nexport const primaryInputSourceAtom = atom('mouse');\n\n/**\n * Device input capabilities.\n * Initialized once on mount, updated when stylus is first detected.\n */\nexport const inputCapabilitiesAtom = atom(detectInputCapabilities());\n\n// =============================================================================\n// Derived Atoms\n// =============================================================================\n\n/**\n * Whether a stylus/pen is currently touching the screen.\n * When true, finger touches should be routed to pan/zoom only (palm rejection).\n */\nexport const isStylusActiveAtom = atom(get => {\n const pointers = get(activePointersAtom);\n for (const [, pointer] of pointers) {\n if (pointer.source === 'pencil') return true;\n }\n return false;\n});\n\n/**\n * Whether multiple fingers are currently touching.\n * When true, the gesture is likely a pinch or two-finger pan.\n */\nexport const isMultiTouchAtom = atom(get => {\n const pointers = get(activePointersAtom);\n let fingerCount = 0;\n for (const [, pointer] of pointers) {\n if (pointer.source === 'finger') fingerCount++;\n }\n return fingerCount > 1;\n});\n\n/**\n * Count of active finger pointers.\n */\nexport const fingerCountAtom = atom(get => {\n const pointers = get(activePointersAtom);\n let count = 0;\n for (const [, pointer] of pointers) {\n if (pointer.source === 'finger') count++;\n }\n return count;\n});\n\n/**\n * Whether the device primarily uses touch (tablet/phone).\n * Used for showing/hiding touch-specific UI (e.g., ViewportControls).\n */\nexport const isTouchDeviceAtom = atom(get => {\n const caps = get(inputCapabilitiesAtom);\n return caps.hasTouch;\n});\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/**\n * Register a pointer down event.\n * Updates active pointers and primary input source.\n */\nexport const pointerDownAtom = atom(null, (get, set, pointer) => {\n const pointers = new Map(get(activePointersAtom));\n pointers.set(pointer.pointerId, pointer);\n set(activePointersAtom, pointers);\n set(primaryInputSourceAtom, pointer.source);\n\n // Auto-detect stylus capability on first pen event\n if (pointer.source === 'pencil') {\n const caps = get(inputCapabilitiesAtom);\n if (!caps.hasStylus) {\n set(inputCapabilitiesAtom, {\n ...caps,\n hasStylus: true\n });\n }\n }\n});\n\n/**\n * Unregister a pointer up/cancel event.\n */\nexport const pointerUpAtom = atom(null, (get, set, pointerId) => {\n const pointers = new Map(get(activePointersAtom));\n pointers.delete(pointerId);\n set(activePointersAtom, pointers);\n});\n\n/**\n * Clear all active pointers.\n * Call on blur or visibility change to prevent stuck pointers.\n */\nexport const clearPointersAtom = atom(null, (_get, set) => {\n set(activePointersAtom, new Map());\n});","/**\n * Selection Path Store\n *\n * Manages the active lasso/rect selection path during drag operations.\n * The gesture resolver already returns 'lasso-select' and 'rect-select' intents;\n * this store tracks the drawn path and resolves which nodes fall inside it.\n */\n\nimport { atom } from 'jotai';\nimport { uiNodesAtom } from './graph-derived';\nimport { selectedNodeIdsAtom } from './selection-store';\n\n// --- Types ---\n\n// --- Core Atoms ---\n\n/** The active selection path, or null when not selecting */\nexport const selectionPathAtom = atom(null);\n\n/** Whether a selection drag is currently in progress */\nexport const isSelectingAtom = atom(get => get(selectionPathAtom) !== null);\n\n// --- Actions ---\n\n/** Start a new selection path */\nexport const startSelectionAtom = atom(null, (_get, set, {\n type,\n point\n}) => {\n set(selectionPathAtom, {\n type,\n points: [point]\n });\n});\n\n/** Add a point to the current selection path */\nexport const updateSelectionAtom = atom(null, (get, set, point) => {\n const current = get(selectionPathAtom);\n if (!current) return;\n if (current.type === 'rect') {\n // For rect, keep only start point + current point\n set(selectionPathAtom, {\n ...current,\n points: [current.points[0], point]\n });\n } else {\n // For lasso, append the point\n set(selectionPathAtom, {\n ...current,\n points: [...current.points, point]\n });\n }\n});\n\n/** Cancel the active selection drag without changing selection. */\nexport const cancelSelectionAtom = atom(null, (_get, set) => {\n set(selectionPathAtom, null);\n});\n\n/** End selection: compute intersecting nodes, update selection, clear path */\nexport const endSelectionAtom = atom(null, (get, set) => {\n const path = get(selectionPathAtom);\n if (!path || path.points.length < 2) {\n set(selectionPathAtom, null);\n return;\n }\n const nodes = get(uiNodesAtom);\n const selectedIds = [];\n if (path.type === 'rect') {\n const [p1, p2] = [path.points[0], path.points[path.points.length - 1]];\n const minX = Math.min(p1.x, p2.x);\n const maxX = Math.max(p1.x, p2.x);\n const minY = Math.min(p1.y, p2.y);\n const maxY = Math.max(p1.y, p2.y);\n for (const node of nodes) {\n // AABB intersection: node overlaps selection rect\n const nodeRight = node.position.x + (node.width ?? 200);\n const nodeBottom = node.position.y + (node.height ?? 100);\n if (node.position.x < maxX && nodeRight > minX && node.position.y < maxY && nodeBottom > minY) {\n selectedIds.push(node.id);\n }\n }\n } else {\n // Lasso: point-in-polygon test on node center\n const polygon = path.points;\n for (const node of nodes) {\n const cx = node.position.x + (node.width ?? 200) / 2;\n const cy = node.position.y + (node.height ?? 100) / 2;\n if (pointInPolygon(cx, cy, polygon)) {\n selectedIds.push(node.id);\n }\n }\n }\n\n // Set selection to the intersecting nodes\n set(selectedNodeIdsAtom, new Set(selectedIds));\n set(selectionPathAtom, null);\n});\n\n// --- Derived: selection rect bounds (for rendering) ---\n\n/** For rect mode, compute the bounding box */\nexport const selectionRectAtom = atom(get => {\n const path = get(selectionPathAtom);\n if (!path || path.type !== 'rect' || path.points.length < 2) return null;\n const [p1, p2] = [path.points[0], path.points[path.points.length - 1]];\n return {\n x: Math.min(p1.x, p2.x),\n y: Math.min(p1.y, p2.y),\n width: Math.abs(p2.x - p1.x),\n height: Math.abs(p2.y - p1.y)\n };\n});\n\n// --- Utilities ---\n\n/**\n * Ray-casting point-in-polygon test.\n * Returns true if (px, py) is inside the polygon defined by points.\n */\nexport function pointInPolygon(px, py, polygon) {\n let inside = false;\n const n = polygon.length;\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const xi = polygon[i].x;\n const yi = polygon[i].y;\n const xj = polygon[j].x;\n const yj = polygon[j].y;\n if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}","/**\n * Search Store\n *\n * Node and edge search with fuzzy multi-token matching.\n * Provides text search across node labels/types/IDs and edge labels/types\n * with result navigation and visual filter mode.\n */\n\nimport { atom } from 'jotai';\nimport { uiNodesAtom } from './graph-derived';\nimport { graphAtom, graphUpdateVersionAtom } from './graph-store';\nimport { centerOnNodeAtom } from './viewport-store';\nimport { selectSingleNodeAtom } from './selection-store';\n\n// =============================================================================\n// Search Query\n// =============================================================================\n\n/**\n * Current search query string.\n * Empty string = no active search.\n */\nexport const searchQueryAtom = atom('');\n\n/**\n * Set search query\n */\nexport const setSearchQueryAtom = atom(null, (_get, set, query) => {\n set(searchQueryAtom, query);\n set(highlightedSearchIndexAtom, 0);\n});\n\n/**\n * Clear search\n */\nexport const clearSearchAtom = atom(null, (_get, set) => {\n set(searchQueryAtom, '');\n set(highlightedSearchIndexAtom, 0);\n});\n\n// =============================================================================\n// Fuzzy Matching\n// =============================================================================\n\n/**\n * Check if ALL tokens in the query appear (in any order) within the haystack.\n * Tokens are split by whitespace. Each token must match as a substring.\n *\n * @example\n * fuzzyMatch(\"inp typ\", \"Input Type Node\") → true\n * fuzzyMatch(\"xyz\", \"Input Type Node\") → false\n */\nexport function fuzzyMatch(query, ...haystacks) {\n const tokens = query.toLowerCase().split(/\\s+/).filter(Boolean);\n if (tokens.length === 0) return false;\n const combined = haystacks.join(' ').toLowerCase();\n return tokens.every(token => combined.includes(token));\n}\n\n// =============================================================================\n// Node Search Results\n// =============================================================================\n\n/**\n * Derived: set of node IDs matching the current search query.\n * Uses fuzzy multi-token matching on label, node_type, and id.\n */\nexport const searchResultsAtom = atom(get => {\n const query = get(searchQueryAtom).trim();\n if (!query) return new Set();\n const nodes = get(uiNodesAtom);\n const matches = new Set();\n for (const node of nodes) {\n if (fuzzyMatch(query, node.label || '', node.dbData.node_type || '', node.id)) {\n matches.add(node.id);\n }\n }\n return matches;\n});\n\n/**\n * Derived: ordered array of matching node IDs (for navigation)\n */\nexport const searchResultsArrayAtom = atom(get => {\n return Array.from(get(searchResultsAtom));\n});\n\n/**\n * Derived: count of search results\n */\nexport const searchResultCountAtom = atom(get => {\n return get(searchResultsAtom).size;\n});\n\n// =============================================================================\n// Edge Search Results\n// =============================================================================\n\n/**\n * Derived: set of edge keys matching the current search query.\n * Matches on edge label, edge_type, and edge id.\n */\nexport const searchEdgeResultsAtom = atom(get => {\n const query = get(searchQueryAtom).trim();\n if (!query) return new Set();\n\n // Depend on graph version for reactivity\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n const matches = new Set();\n graph.forEachEdge((edgeKey, attrs) => {\n const label = attrs.label || '';\n const edgeType = attrs.dbData?.edge_type || '';\n if (fuzzyMatch(query, label, edgeType, edgeKey)) {\n matches.add(edgeKey);\n }\n });\n return matches;\n});\n\n/**\n * Derived: count of matching edges\n */\nexport const searchEdgeResultCountAtom = atom(get => {\n return get(searchEdgeResultsAtom).size;\n});\n\n// =============================================================================\n// Combined\n// =============================================================================\n\n/**\n * Whether a search filter is currently active\n */\nexport const isFilterActiveAtom = atom(get => {\n return get(searchQueryAtom).trim().length > 0;\n});\n\n/**\n * Total count of matching nodes + edges\n */\nexport const searchTotalResultCountAtom = atom(get => {\n return get(searchResultCountAtom) + get(searchEdgeResultCountAtom);\n});\n\n// =============================================================================\n// Result Navigation\n// =============================================================================\n\n/**\n * Index of the currently highlighted search result\n */\nexport const highlightedSearchIndexAtom = atom(0);\n\n/**\n * Navigate to the next search result\n */\nexport const nextSearchResultAtom = atom(null, (get, set) => {\n const results = get(searchResultsArrayAtom);\n if (results.length === 0) return;\n const currentIndex = get(highlightedSearchIndexAtom);\n const nextIndex = (currentIndex + 1) % results.length;\n set(highlightedSearchIndexAtom, nextIndex);\n const nodeId = results[nextIndex];\n set(centerOnNodeAtom, nodeId);\n set(selectSingleNodeAtom, nodeId);\n});\n\n/**\n * Navigate to the previous search result\n */\nexport const prevSearchResultAtom = atom(null, (get, set) => {\n const results = get(searchResultsArrayAtom);\n if (results.length === 0) return;\n const currentIndex = get(highlightedSearchIndexAtom);\n const prevIndex = (currentIndex - 1 + results.length) % results.length;\n set(highlightedSearchIndexAtom, prevIndex);\n const nodeId = results[prevIndex];\n set(centerOnNodeAtom, nodeId);\n set(selectSingleNodeAtom, nodeId);\n});\n\n/**\n * Get the currently highlighted node ID\n */\nexport const highlightedSearchNodeIdAtom = atom(get => {\n const results = get(searchResultsArrayAtom);\n if (results.length === 0) return null;\n const index = get(highlightedSearchIndexAtom);\n return results[index] ?? null;\n});","/**\n * Gesture Rules — Defaults, Labels & Merge\n *\n * Default gesture rule definitions and merge utilities.\n * Split from gesture-rules.ts for modularity.\n */\n\n// =============================================================================\n// Label Generation\n// =============================================================================\n\nconst MODIFIER_KEYS = ['shift', 'ctrl', 'alt', 'meta'];\nconst SOURCE_LABELS = {\n mouse: 'Mouse',\n pencil: 'Pencil',\n finger: 'Touch'\n};\nconst GESTURE_LABELS = {\n tap: 'Tap',\n 'double-tap': 'Double-tap',\n 'triple-tap': 'Triple-tap',\n drag: 'Drag',\n 'long-press': 'Long-press',\n 'right-click': 'Right-click',\n pinch: 'Pinch',\n scroll: 'Scroll'\n};\nconst TARGET_LABELS = {\n node: 'node',\n edge: 'edge',\n port: 'port',\n 'resize-handle': 'resize handle',\n background: 'background'\n};\nconst BUTTON_LABELS = {\n 0: 'Left',\n 1: 'Middle',\n 2: 'Right'\n};\n\n/**\n * Generate a human-readable label from a gesture pattern.\n */\nexport function formatRuleLabel(pattern) {\n const parts = [];\n\n // Modifiers first\n if (pattern.modifiers) {\n const mods = MODIFIER_KEYS.filter(k => pattern.modifiers[k]).map(k => k.charAt(0).toUpperCase() + k.slice(1));\n if (mods.length) parts.push(mods.join('+'));\n }\n\n // Button (only for non-left)\n if (pattern.button !== undefined && pattern.button !== 0) {\n parts.push(BUTTON_LABELS[pattern.button]);\n }\n\n // Source\n if (pattern.source) {\n parts.push(SOURCE_LABELS[pattern.source]);\n }\n\n // Gesture\n if (pattern.gesture) {\n parts.push(GESTURE_LABELS[pattern.gesture] ?? pattern.gesture);\n }\n\n // Target\n if (pattern.target) {\n parts.push('on ' + (TARGET_LABELS[pattern.target] ?? pattern.target));\n }\n if (parts.length === 0) return 'Any gesture';\n\n // Join with spaces, but use \" + \" before gesture if modifiers present\n if (pattern.modifiers) {\n const modCount = MODIFIER_KEYS.filter(k => pattern.modifiers[k]).length;\n if (modCount > 0 && parts.length > modCount) {\n const modPart = parts.slice(0, 1).join('');\n const rest = parts.slice(1).join(' ').toLowerCase();\n return `${modPart} + ${rest}`;\n }\n }\n return parts.join(' ');\n}\n\n// =============================================================================\n// Merge Utilities\n// =============================================================================\n\n/**\n * Merge consumer-provided rules with defaults.\n * Consumer rules override defaults with the same ID.\n * Consumer rules without matching IDs are appended.\n */\nexport function mergeRules(defaults, overrides) {\n const overrideMap = new Map(overrides.map(r => [r.id, r]));\n const result = [];\n\n // Apply overrides to matching defaults\n for (const rule of defaults) {\n const override = overrideMap.get(rule.id);\n if (override) {\n result.push(override);\n overrideMap.delete(rule.id);\n } else {\n result.push(rule);\n }\n }\n\n // Append remaining overrides (new rules)\n for (const rule of overrideMap.values()) {\n result.push(rule);\n }\n return result;\n}\n\n// =============================================================================\n// Default Rules\n// =============================================================================\n\n/**\n * Default gesture rules that replicate the current canvas behavior.\n */\nexport const DEFAULT_GESTURE_RULES = [\n// ── Tap gestures ──────────────────────────────────────────────\n{\n id: 'tap-node',\n pattern: {\n gesture: 'tap',\n target: 'node'\n },\n actionId: 'select-node'\n}, {\n id: 'tap-edge',\n pattern: {\n gesture: 'tap',\n target: 'edge'\n },\n actionId: 'select-edge'\n}, {\n id: 'tap-port',\n pattern: {\n gesture: 'tap',\n target: 'port'\n },\n actionId: 'select-node'\n}, {\n id: 'tap-bg',\n pattern: {\n gesture: 'tap',\n target: 'background'\n },\n actionId: 'clear-selection'\n},\n// ── Double-tap ────────────────────────────────────────────────\n{\n id: 'dtap-node',\n pattern: {\n gesture: 'double-tap',\n target: 'node'\n },\n actionId: 'fit-to-view'\n}, {\n id: 'dtap-bg',\n pattern: {\n gesture: 'double-tap',\n target: 'background'\n },\n actionId: 'fit-all-to-view'\n},\n// ── Triple-tap ────────────────────────────────────────────────\n{\n id: 'ttap-node',\n pattern: {\n gesture: 'triple-tap',\n target: 'node'\n },\n actionId: 'toggle-lock'\n},\n// ── Left-button drag ──────────────────────────────────────────\n{\n id: 'drag-node',\n pattern: {\n gesture: 'drag',\n target: 'node'\n },\n actionId: 'move-node'\n}, {\n id: 'drag-port',\n pattern: {\n gesture: 'drag',\n target: 'port'\n },\n actionId: 'create-edge'\n}, {\n id: 'drag-bg-finger',\n pattern: {\n gesture: 'drag',\n target: 'background',\n source: 'finger'\n },\n actionId: 'pan'\n}, {\n id: 'drag-bg-mouse',\n pattern: {\n gesture: 'drag',\n target: 'background',\n source: 'mouse'\n },\n actionId: 'pan'\n}, {\n id: 'drag-bg-pencil',\n pattern: {\n gesture: 'drag',\n target: 'background',\n source: 'pencil'\n },\n actionId: 'lasso-select'\n},\n// ── Shift+drag overrides ──────────────────────────────────────\n{\n id: 'shift-drag-bg',\n pattern: {\n gesture: 'drag',\n target: 'background',\n modifiers: {\n shift: true\n }\n },\n actionId: 'rect-select'\n},\n// ── Right-click tap (context menu) ────────────────────────────\n{\n id: 'rc-node',\n pattern: {\n gesture: 'tap',\n target: 'node',\n button: 2\n },\n actionId: 'open-context-menu'\n}, {\n id: 'rc-edge',\n pattern: {\n gesture: 'tap',\n target: 'edge',\n button: 2\n },\n actionId: 'open-context-menu'\n}, {\n id: 'rc-bg',\n pattern: {\n gesture: 'tap',\n target: 'background',\n button: 2\n },\n actionId: 'open-context-menu'\n},\n// ── Long-press ────────────────────────────────────────────────\n{\n id: 'lp-node',\n pattern: {\n gesture: 'long-press',\n target: 'node'\n },\n actionId: 'open-context-menu'\n}, {\n id: 'lp-bg-finger',\n pattern: {\n gesture: 'long-press',\n target: 'background',\n source: 'finger'\n },\n actionId: 'create-node'\n},\n// ── Right-button drag (defaults to none — consumers override) ─\n{\n id: 'rdrag-node',\n pattern: {\n gesture: 'drag',\n target: 'node',\n button: 2\n },\n actionId: 'none'\n}, {\n id: 'rdrag-bg',\n pattern: {\n gesture: 'drag',\n target: 'background',\n button: 2\n },\n actionId: 'none'\n},\n// ── Middle-button drag (defaults to none) ─────────────────────\n{\n id: 'mdrag-node',\n pattern: {\n gesture: 'drag',\n target: 'node',\n button: 1\n },\n actionId: 'none'\n}, {\n id: 'mdrag-bg',\n pattern: {\n gesture: 'drag',\n target: 'background',\n button: 1\n },\n actionId: 'none'\n},\n// ── Zoom ──────────────────────────────────────────────────────\n{\n id: 'pinch-bg',\n pattern: {\n gesture: 'pinch',\n target: 'background'\n },\n actionId: 'zoom'\n}, {\n id: 'scroll-any',\n pattern: {\n gesture: 'scroll'\n },\n actionId: 'zoom'\n},\n// ── Split ─────────────────────────────────────────────────────\n{\n id: 'pinch-node',\n pattern: {\n gesture: 'pinch',\n target: 'node'\n },\n actionId: 'split-node'\n}];","/**\n * Gesture Rules — Composable Event System\n *\n * A rule-based gesture resolution engine where ANY combination of\n * (button x modifier x source x gesture x target) can be mapped to any action.\n *\n * Resolution works by scoring each rule's pattern against the current gesture\n * descriptor. The most specific match wins, with automatic fallback to\n * less-specific rules.\n *\n * Types are in ./gesture-rules-types.ts\n * Defaults + labels + merge are in ./gesture-rules-defaults.ts\n */\n\n// Re-export all types for backward compat\n\n// Re-export defaults, labels, merge for backward compat\nexport { DEFAULT_GESTURE_RULES, mergeRules, formatRuleLabel } from './gesture-rules-defaults';\n\n// Re-export the index type\n\n// =============================================================================\n// Specificity Scoring\n// =============================================================================\n\nconst MODIFIER_KEYS = ['shift', 'ctrl', 'alt', 'meta'];\n\n/**\n * Calculate how specifically a pattern matches a descriptor.\n *\n * Returns -1 if the pattern does NOT match.\n * Returns 0+ for a match, where higher = more specific.\n *\n * Scoring:\n * gesture: +32 (most important dimension)\n * target: +16\n * modifiers: +8 per matching modifier flag\n * source: +4\n * button: +2\n */\nexport function matchSpecificity(pattern, desc) {\n let score = 0;\n if (pattern.gesture !== undefined) {\n if (pattern.gesture !== desc.gesture) return -1;\n score += 32;\n }\n if (pattern.target !== undefined) {\n if (pattern.target !== desc.target) return -1;\n score += 16;\n }\n if (pattern.source !== undefined) {\n if (pattern.source !== desc.source) return -1;\n score += 4;\n }\n if (pattern.button !== undefined) {\n if (pattern.button !== (desc.button ?? 0)) return -1;\n score += 2;\n }\n if (pattern.modifiers !== undefined) {\n const dm = desc.modifiers ?? {};\n for (const key of MODIFIER_KEYS) {\n const required = pattern.modifiers[key];\n if (required === undefined) continue;\n const actual = dm[key] ?? false;\n if (required !== actual) return -1;\n score += 8;\n }\n }\n return score;\n}\n\n// =============================================================================\n// Resolver\n// =============================================================================\n\n/** Sentinel rule for palm-rejected gestures */\nconst PALM_REJECTION_RULE = {\n id: '__palm-rejection__',\n pattern: {},\n actionId: 'none',\n label: 'Palm rejection'\n};\n\n/**\n * Resolve a gesture descriptor against a rule set.\n *\n * 1. Apply palm rejection (finger + stylus active → remap)\n * 2. Score every rule against the (possibly transformed) descriptor\n * 3. Pick highest specificity; break ties with rule.priority\n * 4. Return resolved action or null if no match\n */\nexport function resolveGesture(desc, rules, options) {\n const palmRejection = options?.palmRejection !== false;\n\n // Palm rejection: when stylus is active, finger touches become\n // navigation-only (taps → none, drags on nodes → pan)\n if (palmRejection && desc.isStylusActive && desc.source === 'finger') {\n if (desc.gesture === 'tap' || desc.gesture === 'long-press' || desc.gesture === 'double-tap' || desc.gesture === 'triple-tap') {\n return {\n actionId: 'none',\n rule: PALM_REJECTION_RULE,\n score: Infinity\n };\n }\n if (desc.gesture === 'drag' && desc.target !== 'background') {\n // Re-resolve as background pan\n return resolveGesture({\n ...desc,\n target: 'background',\n isStylusActive: false\n }, rules, {\n palmRejection: false\n });\n }\n }\n let best = null;\n for (const rule of rules) {\n const specificity = matchSpecificity(rule.pattern, desc);\n if (specificity < 0) continue;\n\n // Combine specificity with priority for final score\n const effectiveScore = specificity * 1000 + (rule.priority ?? 0);\n if (!best || effectiveScore > best.score) {\n best = {\n actionId: rule.actionId,\n rule,\n score: effectiveScore\n };\n }\n }\n return best;\n}\n\n// =============================================================================\n// Rule Index (for fast lookup)\n// =============================================================================\n\nexport function buildRuleIndex(rules) {\n const buckets = new Map();\n const wildcardRules = [];\n for (const rule of rules) {\n const key = rule.pattern.gesture;\n if (key === undefined) {\n wildcardRules.push(rule);\n } else {\n const bucket = buckets.get(key);\n if (bucket) {\n bucket.push(rule);\n } else {\n buckets.set(key, [rule]);\n }\n }\n }\n\n // Pre-concatenate wildcard rules into each gesture bucket\n const index = new Map();\n if (wildcardRules.length > 0) {\n for (const [key, bucket] of buckets) {\n index.set(key, bucket.concat(wildcardRules));\n }\n index.set('__wildcard__', wildcardRules);\n } else {\n for (const [key, bucket] of buckets) {\n index.set(key, bucket);\n }\n }\n return index;\n}\n\n/**\n * Resolve using an indexed rule set (faster for large rule sets).\n */\nexport function resolveGestureIndexed(desc, index, options) {\n const rules = index.get(desc.gesture) ?? index.get('__wildcard__') ?? [];\n return resolveGesture(desc, rules, options);\n}","/**\n * Gesture Rule Store\n *\n * Jotai atoms for managing gesture rules with localStorage persistence.\n * Provides CRUD operations and an indexed lookup for fast resolution.\n */\n\nimport { atom } from 'jotai';\nimport { atomWithStorage } from 'jotai/utils';\nimport { DEFAULT_GESTURE_RULES, buildRuleIndex, mergeRules } from './gesture-rules';\n\n// =============================================================================\n// Persisted State\n// =============================================================================\n\nconst DEFAULT_RULE_STATE = {\n customRules: [],\n palmRejection: true\n};\n\n/**\n * Persisted gesture rule settings.\n * Only stores user customizations — defaults are applied at runtime.\n */\nexport const gestureRuleSettingsAtom = atomWithStorage('canvas-gesture-rules', DEFAULT_RULE_STATE);\n\n// =============================================================================\n// Runtime Rules (merged defaults + custom)\n// =============================================================================\n\n/**\n * Consumer-provided rule overrides (set via Canvas props).\n * These are NOT persisted — they come from the component tree.\n */\nexport const consumerGestureRulesAtom = atom([]);\n\n/**\n * The effective rule set: defaults + persisted custom + consumer overrides.\n * Consumer rules take highest priority (applied last).\n */\nexport const gestureRulesAtom = atom(get => {\n const settings = get(gestureRuleSettingsAtom);\n const consumerRules = get(consumerGestureRulesAtom);\n\n // Layer 1: Start with defaults\n // Layer 2: Apply persisted user customizations\n let rules = mergeRules(DEFAULT_GESTURE_RULES, settings.customRules);\n // Layer 3: Apply consumer-provided overrides\n if (consumerRules.length > 0) {\n rules = mergeRules(rules, consumerRules);\n }\n return rules;\n});\n\n/**\n * Indexed rule set for fast resolution.\n * Recomputes only when rules change.\n */\nexport const gestureRuleIndexAtom = atom(get => {\n return buildRuleIndex(get(gestureRulesAtom));\n});\n\n/**\n * Palm rejection toggle.\n */\nexport const palmRejectionEnabledAtom = atom(get => get(gestureRuleSettingsAtom).palmRejection, (get, set, enabled) => {\n const current = get(gestureRuleSettingsAtom);\n set(gestureRuleSettingsAtom, {\n ...current,\n palmRejection: enabled\n });\n});\n\n// =============================================================================\n// CRUD Atoms\n// =============================================================================\n\n/**\n * Add or replace a custom gesture rule.\n * If a rule with the same ID exists, it's replaced.\n */\nexport const addGestureRuleAtom = atom(null, (get, set, rule) => {\n const current = get(gestureRuleSettingsAtom);\n const existing = current.customRules.findIndex(r => r.id === rule.id);\n const newRules = [...current.customRules];\n if (existing >= 0) {\n newRules[existing] = rule;\n } else {\n newRules.push(rule);\n }\n set(gestureRuleSettingsAtom, {\n ...current,\n customRules: newRules\n });\n});\n\n/**\n * Remove a custom gesture rule by ID.\n */\nexport const removeGestureRuleAtom = atom(null, (get, set, ruleId) => {\n const current = get(gestureRuleSettingsAtom);\n set(gestureRuleSettingsAtom, {\n ...current,\n customRules: current.customRules.filter(r => r.id !== ruleId)\n });\n});\n\n/**\n * Update an existing custom gesture rule.\n */\nexport const updateGestureRuleAtom = atom(null, (get, set, {\n id,\n updates\n}) => {\n const current = get(gestureRuleSettingsAtom);\n const index = current.customRules.findIndex(r => r.id === id);\n if (index < 0) return;\n const newRules = [...current.customRules];\n newRules[index] = {\n ...newRules[index],\n ...updates\n };\n set(gestureRuleSettingsAtom, {\n ...current,\n customRules: newRules\n });\n});\n\n/**\n * Reset all custom rules (revert to defaults).\n */\nexport const resetGestureRulesAtom = atom(null, (get, set) => {\n const current = get(gestureRuleSettingsAtom);\n set(gestureRuleSettingsAtom, {\n ...current,\n customRules: []\n });\n});","/**\n * External Keyboard Store\n *\n * Detects whether an external keyboard is connected to a touch device.\n * When detected, modifier-key actions become available via keyboard\n * shortcuts, so the TouchActionButton can be hidden.\n *\n * Detection: On touch devices, the first physical key event (not\n * on-screen keyboard) sets `hasExternalKeyboardAtom` to true.\n * Only meaningful when `isTouchDeviceAtom` is true — on desktop,\n * keyboard is always assumed.\n */\n\nimport { atom } from 'jotai';\n\n/**\n * Whether an external keyboard has been detected on a touch device.\n * Set to true on first `keydown` event on a touch-capable device.\n */\nexport const hasExternalKeyboardAtom = atom(false);\n\n/**\n * Effect atom: listens for keydown events on touch devices.\n * Once detected, stops listening (permanent for the session).\n */\nexport const watchExternalKeyboardAtom = atom(null, (get, set) => {\n if (typeof window === 'undefined') return;\n const handler = e => {\n // Ignore virtual keyboard keys (typically modifier-only events)\n // A real keyboard sends identifiable key values\n if (e.key && e.key.length === 1 || ['Tab', 'Escape', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {\n set(hasExternalKeyboardAtom, true);\n window.removeEventListener('keydown', handler);\n }\n };\n window.addEventListener('keydown', handler);\n return () => window.removeEventListener('keydown', handler);\n});","/**\n * Command Registry\n *\n * Singleton class for managing all available commands.\n * Commands can be registered by the canvas package (built-ins)\n * or by consuming apps (custom commands).\n */\n\n/**\n * Command Registry - Singleton class for managing all available commands.\n *\n * Usage:\n * ```typescript\n * import { commandRegistry } from '@blinksgg/canvas';\n *\n * // Register a command\n * commandRegistry.register(myCommand);\n *\n * // Get a command by name or alias\n * const cmd = commandRegistry.get('createNode'); // or 'cn'\n *\n * // Search commands\n * const results = commandRegistry.search('node');\n * ```\n */\nclass CommandRegistry {\n commands = new Map();\n aliases = new Map(); // alias -> command name\n\n /**\n * Register a command with the registry.\n * @param command The command definition to register\n * @throws Error if command name or alias already exists\n */\n register(command) {\n if (this.commands.has(command.name)) {\n throw new Error(`Command \"${command.name}\" is already registered`);\n }\n this.commands.set(command.name, command);\n\n // Register aliases\n if (command.aliases) {\n for (const alias of command.aliases) {\n if (this.aliases.has(alias)) {\n throw new Error(`Alias \"${alias}\" is already registered for command \"${this.aliases.get(alias)}\"`);\n }\n if (this.commands.has(alias)) {\n throw new Error(`Alias \"${alias}\" conflicts with existing command name`);\n }\n this.aliases.set(alias, command.name);\n }\n }\n }\n\n /**\n * Unregister a command by name.\n * @param name The command name to remove\n */\n unregister(name) {\n const command = this.commands.get(name);\n if (command) {\n // Remove aliases\n if (command.aliases) {\n for (const alias of command.aliases) {\n this.aliases.delete(alias);\n }\n }\n this.commands.delete(name);\n }\n }\n\n /**\n * Get a command by name or alias.\n * @param nameOrAlias Command name or alias\n * @returns The command definition or undefined if not found\n */\n get(nameOrAlias) {\n // Check if it's a direct command name\n const direct = this.commands.get(nameOrAlias);\n if (direct) return direct;\n\n // Check if it's an alias\n const commandName = this.aliases.get(nameOrAlias);\n if (commandName) {\n return this.commands.get(commandName);\n }\n return undefined;\n }\n\n /**\n * Check if a command exists by name or alias.\n * @param nameOrAlias Command name or alias\n */\n has(nameOrAlias) {\n return this.commands.has(nameOrAlias) || this.aliases.has(nameOrAlias);\n }\n\n /**\n * Search for commands matching a query.\n * Searches command names, aliases, and descriptions.\n * @param query Search query (case-insensitive)\n * @returns Array of matching commands, sorted by relevance\n */\n search(query) {\n if (!query.trim()) {\n return this.all();\n }\n const lowerQuery = query.toLowerCase().trim();\n const results = [];\n const commands = Array.from(this.commands.values());\n for (const command of commands) {\n let score = 0;\n\n // Exact name match (highest priority)\n if (command.name.toLowerCase() === lowerQuery) {\n score = 100;\n }\n // Name starts with query\n else if (command.name.toLowerCase().startsWith(lowerQuery)) {\n score = 80;\n }\n // Name contains query\n else if (command.name.toLowerCase().includes(lowerQuery)) {\n score = 60;\n }\n // Alias exact match\n else if (command.aliases?.some(a => a.toLowerCase() === lowerQuery)) {\n score = 90;\n }\n // Alias starts with query\n else if (command.aliases?.some(a => a.toLowerCase().startsWith(lowerQuery))) {\n score = 70;\n }\n // Alias contains query\n else if (command.aliases?.some(a => a.toLowerCase().includes(lowerQuery))) {\n score = 50;\n }\n // Description contains query\n else if (command.description.toLowerCase().includes(lowerQuery)) {\n score = 30;\n }\n if (score > 0) {\n results.push({\n command,\n score\n });\n }\n }\n\n // Sort by score (descending), then alphabetically\n return results.sort((a, b) => b.score - a.score || a.command.name.localeCompare(b.command.name)).map(r => r.command);\n }\n\n /**\n * Get all registered commands.\n * @returns Array of all commands, sorted alphabetically by name\n */\n all() {\n return Array.from(this.commands.values()).sort((a, b) => a.name.localeCompare(b.name));\n }\n\n /**\n * Get commands by category.\n * @param category The category to filter by\n * @returns Array of commands in the category\n */\n byCategory(category) {\n return this.all().filter(cmd => cmd.category === category);\n }\n\n /**\n * Get all available categories.\n * @returns Array of unique categories\n */\n categories() {\n const categories = new Set();\n const commands = Array.from(this.commands.values());\n for (const command of commands) {\n categories.add(command.category);\n }\n return Array.from(categories).sort();\n }\n\n /**\n * Get the count of registered commands.\n */\n get size() {\n return this.commands.size;\n }\n\n /**\n * Clear all registered commands.\n * Useful for testing.\n */\n clear() {\n this.commands.clear();\n this.aliases.clear();\n }\n\n /**\n * Get a serializable list of commands for API responses.\n */\n toJSON() {\n return this.all().map(cmd => ({\n name: cmd.name,\n aliases: cmd.aliases || [],\n description: cmd.description,\n category: cmd.category,\n inputs: cmd.inputs.map(input => ({\n name: input.name,\n type: input.type,\n prompt: input.prompt,\n required: input.required !== false\n }))\n }));\n }\n}\n\n// Singleton instance\nexport const commandRegistry = new CommandRegistry();\n\n// Default export for convenience\nexport default commandRegistry;\n\n// Helper function for registering commands\nexport function registerCommand(command) {\n commandRegistry.register(command);\n}","/**\n * Plugin Registry\n *\n * Central registry for canvas plugins. Handles:\n * - Registration with dependency resolution\n * - Conflict detection across all subsystems\n * - Atomic registration (all-or-nothing)\n * - Cleanup on unregister\n */\n\nimport { PluginError } from './plugin-types';\nimport { registerNodeTypes, unregisterNodeType } from './node-type-registry';\nimport { registerAction as registerEventAction, unregisterAction as unregisterEventAction } from './action-registry';\nimport { registerAction as registerGestureAction, unregisterAction as unregisterGestureAction } from '../gestures/dispatcher';\nimport { commandRegistry } from '../commands/registry';\nimport { registerEdgePathCalculator, unregisterEdgePathCalculator } from '../utils/edge-path-registry';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('plugins');\n\n// =============================================================================\n// Registry\n// =============================================================================\n\nconst plugins = new Map();\n\n/**\n * Register a plugin. All capabilities are registered atomically.\n *\n * @throws {PluginError} ALREADY_REGISTERED — plugin ID already in use\n * @throws {PluginError} MISSING_DEPENDENCY — required plugin not registered\n * @throws {PluginError} CONFLICT — duplicate node type, action, command, or calculator\n *\n * @example\n * ```ts\n * registerPlugin({\n * id: 'my-plugin',\n * name: 'My Plugin',\n * nodeTypes: { 'custom': CustomNode },\n * commands: [myCommand],\n * });\n * ```\n */\nexport function registerPlugin(plugin) {\n debug('Registering plugin: %s', plugin.id);\n\n // 1. Check not already registered\n if (plugins.has(plugin.id)) {\n throw new PluginError('Plugin is already registered', plugin.id, 'ALREADY_REGISTERED');\n }\n\n // 2. Check dependencies\n if (plugin.dependencies) {\n for (const depId of plugin.dependencies) {\n if (!plugins.has(depId)) {\n throw new PluginError(`Missing dependency: \"${depId}\"`, plugin.id, 'MISSING_DEPENDENCY');\n }\n }\n }\n\n // 3. Check for conflicts before registering anything\n detectConflicts(plugin);\n\n // 4. Register all capabilities\n const cleanups = [];\n try {\n // Node types\n if (plugin.nodeTypes) {\n const nodeTypeNames = Object.keys(plugin.nodeTypes);\n registerNodeTypes(plugin.nodeTypes);\n cleanups.push(() => {\n for (const name of nodeTypeNames) {\n unregisterNodeType(name);\n }\n });\n }\n\n // Edge path calculators\n if (plugin.edgePathCalculators) {\n for (const [name, calc] of Object.entries(plugin.edgePathCalculators)) {\n registerEdgePathCalculator(name, calc);\n cleanups.push(() => unregisterEdgePathCalculator(name));\n }\n }\n\n // Gesture action handlers\n if (plugin.actionHandlers) {\n for (const [actionId, handler] of Object.entries(plugin.actionHandlers)) {\n registerGestureAction(actionId, handler);\n cleanups.push(() => unregisterGestureAction(actionId));\n }\n }\n\n // Gesture contexts are stored on the plugin — consumers read them\n // via getPluginGestureContexts() and merge them into the mapping index.\n\n // Commands\n if (plugin.commands) {\n for (const cmd of plugin.commands) {\n commandRegistry.register(cmd);\n cleanups.push(() => commandRegistry.unregister(cmd.name));\n }\n }\n\n // Event-action definitions\n if (plugin.actions) {\n for (const action of plugin.actions) {\n registerEventAction(action);\n cleanups.push(() => unregisterEventAction(action.id));\n }\n }\n\n // 5. Lifecycle hook\n let lifecycleCleanup = null;\n if (plugin.onRegister) {\n const ctx = makePluginContext(plugin.id);\n try {\n const result = plugin.onRegister(ctx);\n if (typeof result === 'function') {\n lifecycleCleanup = result;\n }\n } catch (err) {\n // Rollback all registrations on lifecycle error\n for (const cleanup of cleanups.reverse()) {\n try {\n cleanup();\n } catch {/* swallow cleanup errors */}\n }\n throw new PluginError(`onRegister failed: ${err instanceof Error ? err.message : String(err)}`, plugin.id, 'LIFECYCLE_ERROR');\n }\n }\n\n // 6. Store registration\n plugins.set(plugin.id, {\n plugin,\n cleanup: () => {\n for (const cleanup of cleanups.reverse()) {\n try {\n cleanup();\n } catch {/* swallow cleanup errors */}\n }\n if (lifecycleCleanup) {\n try {\n lifecycleCleanup();\n } catch {/* swallow */}\n }\n },\n registeredAt: Date.now()\n });\n debug('Plugin registered: %s (%d node types, %d commands, %d actions)', plugin.id, Object.keys(plugin.nodeTypes ?? {}).length, plugin.commands?.length ?? 0, plugin.actions?.length ?? 0);\n } catch (err) {\n if (err instanceof PluginError) throw err;\n // Rollback on unexpected error\n for (const cleanup of cleanups.reverse()) {\n try {\n cleanup();\n } catch {/* swallow */}\n }\n throw err;\n }\n}\n\n/**\n * Unregister a plugin and clean up all its registrations.\n *\n * @throws {PluginError} NOT_FOUND — plugin not registered\n * @throws {PluginError} CONFLICT — other plugins depend on this one\n */\nexport function unregisterPlugin(pluginId) {\n const registration = plugins.get(pluginId);\n if (!registration) {\n throw new PluginError('Plugin is not registered', pluginId, 'NOT_FOUND');\n }\n\n // Check no other plugin depends on this one\n for (const [otherId, other] of plugins) {\n if (other.plugin.dependencies?.includes(pluginId)) {\n throw new PluginError(`Cannot unregister: plugin \"${otherId}\" depends on it`, pluginId, 'CONFLICT');\n }\n }\n\n // Run cleanup\n if (registration.cleanup) {\n registration.cleanup();\n }\n plugins.delete(pluginId);\n debug('Plugin unregistered: %s', pluginId);\n}\n\n// =============================================================================\n// Queries\n// =============================================================================\n\n/** Get a registered plugin by ID */\nexport function getPlugin(id) {\n return plugins.get(id)?.plugin;\n}\n\n/** Check if a plugin is registered */\nexport function hasPlugin(id) {\n return plugins.has(id);\n}\n\n/** Get all registered plugins */\nexport function getAllPlugins() {\n return Array.from(plugins.values()).map(r => r.plugin);\n}\n\n/** Get all registered plugin IDs */\nexport function getPluginIds() {\n return Array.from(plugins.keys());\n}\n\n/**\n * Get all gesture contexts contributed by plugins.\n * Used by GestureProvider to merge plugin contexts into the mapping index.\n */\nexport function getPluginGestureContexts() {\n const contexts = [];\n for (const registration of plugins.values()) {\n if (registration.plugin.gestureContexts) {\n contexts.push(...registration.plugin.gestureContexts);\n }\n }\n return contexts;\n}\n\n/** Clear all plugins. Mainly for testing. */\nexport function clearPlugins() {\n // Unregister in reverse order (respect dependencies)\n const ids = Array.from(plugins.keys()).reverse();\n for (const id of ids) {\n const reg = plugins.get(id);\n if (reg?.cleanup) {\n try {\n reg.cleanup();\n } catch {/* swallow */}\n }\n plugins.delete(id);\n }\n debug('All plugins cleared');\n}\n\n// =============================================================================\n// Conflict Detection\n// =============================================================================\n\nfunction detectConflicts(plugin) {\n // Check command name conflicts\n if (plugin.commands) {\n for (const cmd of plugin.commands) {\n if (commandRegistry.has(cmd.name)) {\n throw new PluginError(`Command \"${cmd.name}\" is already registered`, plugin.id, 'CONFLICT');\n }\n }\n }\n\n // Check edge path calculator conflicts\n if (plugin.edgePathCalculators) {\n for (const name of Object.keys(plugin.edgePathCalculators)) {\n // Built-in types are fine to shadow (plugin overrides)\n // Only conflict with other plugins\n for (const [otherId, other] of plugins) {\n if (other.plugin.edgePathCalculators?.[name]) {\n throw new PluginError(`Edge path calculator \"${name}\" already registered by plugin \"${otherId}\"`, plugin.id, 'CONFLICT');\n }\n }\n }\n }\n\n // Check node type conflicts between plugins\n if (plugin.nodeTypes) {\n for (const nodeType of Object.keys(plugin.nodeTypes)) {\n for (const [otherId, other] of plugins) {\n if (other.plugin.nodeTypes?.[nodeType]) {\n throw new PluginError(`Node type \"${nodeType}\" already registered by plugin \"${otherId}\"`, plugin.id, 'CONFLICT');\n }\n }\n }\n }\n\n // Check action handler conflicts between plugins\n if (plugin.actionHandlers) {\n for (const actionId of Object.keys(plugin.actionHandlers)) {\n for (const [otherId, other] of plugins) {\n if (other.plugin.actionHandlers?.[actionId]) {\n throw new PluginError(`Action handler \"${actionId}\" already registered by plugin \"${otherId}\"`, plugin.id, 'CONFLICT');\n }\n }\n }\n }\n}\n\n// =============================================================================\n// Internal Helpers\n// =============================================================================\n\nfunction makePluginContext(pluginId) {\n return {\n pluginId,\n getPlugin,\n hasPlugin\n };\n}","/**\n * Command Store — Action Atoms\n *\n * Action atoms and helper functions for managing the command line.\n * Core state atoms are in ./store-atoms.ts.\n */\n\nimport { atom } from 'jotai';\nimport { commandRegistry } from './registry';\n\n// Re-export all state atoms for backward compat\nexport { inputModeAtom, commandLineVisibleAtom, commandLineStateAtom, commandFeedbackAtom, commandHistoryAtom, selectedSuggestionIndexAtom, pendingInputResolverAtom, isCommandActiveAtom, currentInputAtom, commandProgressAtom } from './store-atoms';\n\n// Import for internal use\nimport { inputModeAtom, commandLineVisibleAtom, commandLineStateAtom, commandFeedbackAtom, commandHistoryAtom, selectedSuggestionIndexAtom, pendingInputResolverAtom } from './store-atoms';\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/**\n * Open the command line and enter search mode.\n */\nexport const openCommandLineAtom = atom(null, (get, set) => {\n set(commandLineVisibleAtom, true);\n set(commandLineStateAtom, {\n phase: 'searching',\n query: '',\n suggestions: commandRegistry.all()\n });\n set(selectedSuggestionIndexAtom, 0);\n});\n\n/**\n * Close the command line and reset state.\n */\nexport const closeCommandLineAtom = atom(null, (get, set) => {\n set(commandLineVisibleAtom, false);\n set(commandLineStateAtom, {\n phase: 'idle'\n });\n set(inputModeAtom, {\n type: 'normal'\n });\n set(commandFeedbackAtom, null);\n set(pendingInputResolverAtom, null);\n});\n\n/**\n * Update search query and suggestions.\n */\nexport const updateSearchQueryAtom = atom(null, (get, set, query) => {\n const suggestions = commandRegistry.search(query);\n set(commandLineStateAtom, {\n phase: 'searching',\n query,\n suggestions\n });\n set(selectedSuggestionIndexAtom, 0); // Reset selection on query change\n});\n\n/**\n * Select a command and start collecting inputs.\n */\nexport const selectCommandAtom = atom(null, (get, set, command) => {\n // Add to history\n const history = get(commandHistoryAtom);\n const newHistory = [command.name, ...history.filter(h => h !== command.name)].slice(0, 50);\n set(commandHistoryAtom, newHistory);\n\n // If command has no inputs, execute immediately\n if (command.inputs.length === 0) {\n set(commandLineStateAtom, {\n phase: 'executing',\n command\n });\n return;\n }\n\n // Start collecting inputs\n set(commandLineStateAtom, {\n phase: 'collecting',\n command,\n inputIndex: 0,\n collected: {}\n });\n\n // Set input mode for first input\n const firstInput = command.inputs[0];\n set(inputModeAtom, inputDefToMode(firstInput));\n});\n\n/**\n * Provide a value for the current input and advance to next.\n */\nexport const provideInputAtom = atom(null, (get, set, value) => {\n const state = get(commandLineStateAtom);\n if (state.phase !== 'collecting') return;\n const {\n command,\n inputIndex,\n collected\n } = state;\n const currentInput = command.inputs[inputIndex];\n\n // Validate if validator exists\n if (currentInput.validate) {\n const result = currentInput.validate(value, collected);\n if (result !== true) {\n set(commandLineStateAtom, {\n phase: 'error',\n message: typeof result === 'string' ? result : `Invalid value for ${currentInput.name}`\n });\n return;\n }\n }\n\n // Add to collected inputs\n const newCollected = {\n ...collected,\n [currentInput.name]: value\n };\n\n // Check if there are more inputs\n if (inputIndex < command.inputs.length - 1) {\n const nextInputIndex = inputIndex + 1;\n const nextInput = command.inputs[nextInputIndex];\n set(commandLineStateAtom, {\n phase: 'collecting',\n command,\n inputIndex: nextInputIndex,\n collected: newCollected\n });\n\n // Set input mode for next input\n set(inputModeAtom, inputDefToMode(nextInput, newCollected));\n\n // Update feedback\n if (command.feedback) {\n const feedback = command.feedback(newCollected, nextInput);\n if (feedback) {\n // Convert CommandFeedback to FeedbackState\n const feedbackState = {\n hoveredNodeId: feedback.highlightNodeId,\n ghostNode: feedback.ghostNode,\n crosshair: feedback.crosshair,\n // Handle previewEdge conversion - toCursor variant needs cursorWorldPos\n previewEdge: feedback.previewEdge && 'to' in feedback.previewEdge ? {\n from: feedback.previewEdge.from,\n to: feedback.previewEdge.to\n } : undefined\n };\n set(commandFeedbackAtom, feedbackState);\n } else {\n set(commandFeedbackAtom, null);\n }\n }\n } else {\n // All inputs collected, ready to execute\n set(commandLineStateAtom, {\n phase: 'collecting',\n command,\n inputIndex: inputIndex,\n collected: newCollected\n });\n\n // Signal that we're ready to execute (the executor will handle this)\n set(inputModeAtom, {\n type: 'normal'\n });\n }\n});\n\n/**\n * Skip the current optional input and use default value.\n */\nexport const skipInputAtom = atom(null, (get, set) => {\n const state = get(commandLineStateAtom);\n if (state.phase !== 'collecting') return;\n const {\n command,\n inputIndex\n } = state;\n const currentInput = command.inputs[inputIndex];\n\n // Can only skip optional inputs\n if (currentInput.required !== false) {\n return;\n }\n\n // Use default value\n const value = currentInput.default;\n set(provideInputAtom, value);\n});\n\n/**\n * Go back to the previous input.\n */\nexport const goBackInputAtom = atom(null, (get, set) => {\n const state = get(commandLineStateAtom);\n if (state.phase !== 'collecting') return;\n const {\n command,\n inputIndex,\n collected\n } = state;\n if (inputIndex === 0) {\n // Go back to search\n set(commandLineStateAtom, {\n phase: 'searching',\n query: command.name,\n suggestions: [command]\n });\n set(inputModeAtom, {\n type: 'normal'\n });\n return;\n }\n\n // Go to previous input\n const prevInputIndex = inputIndex - 1;\n const prevInput = command.inputs[prevInputIndex];\n\n // Remove the previous value from collected\n const newCollected = {\n ...collected\n };\n delete newCollected[prevInput.name];\n set(commandLineStateAtom, {\n phase: 'collecting',\n command,\n inputIndex: prevInputIndex,\n collected: newCollected\n });\n set(inputModeAtom, inputDefToMode(prevInput, newCollected));\n});\n\n/**\n * Set error state.\n */\nexport const setCommandErrorAtom = atom(null, (get, set, message) => {\n set(commandLineStateAtom, {\n phase: 'error',\n message\n });\n set(inputModeAtom, {\n type: 'normal'\n });\n});\n\n/**\n * Clear error and go back to idle.\n */\nexport const clearCommandErrorAtom = atom(null, (get, set) => {\n set(commandLineStateAtom, {\n phase: 'idle'\n });\n});\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Convert an InputDefinition to an InputMode.\n */\nfunction inputDefToMode(input, collected) {\n switch (input.type) {\n case 'point':\n return {\n type: 'pickPoint',\n prompt: input.prompt,\n snapToGrid: input.snapToGrid\n };\n case 'node':\n return {\n type: 'pickNode',\n prompt: input.prompt,\n filter: input.filter ? node => input.filter(node, collected || {}) : undefined\n };\n case 'nodes':\n return {\n type: 'pickNodes',\n prompt: input.prompt,\n filter: input.filter ? node => input.filter(node, collected || {}) : undefined\n };\n case 'select':\n return {\n type: 'select',\n prompt: input.prompt,\n options: input.options || []\n };\n case 'text':\n case 'number':\n case 'color':\n case 'boolean':\n default:\n return {\n type: 'text',\n prompt: input.prompt\n };\n }\n}","/**\n * Command Store — State Atoms\n *\n * Core state and derived atoms for the command line system.\n * Action atoms live in ./store.ts.\n */\n\nimport { atom } from 'jotai';\nimport { atomWithStorage } from 'jotai/utils';\n// =============================================================================\n// Core State Atoms\n// =============================================================================\n\n/**\n * Input mode - controls how canvas interactions are routed.\n * When type is not 'normal', canvas clicks are intercepted by the command system.\n */\nexport const inputModeAtom = atom({\n type: 'normal'\n});\n\n/**\n * Whether the command line UI is visible.\n */\nexport const commandLineVisibleAtom = atom(false);\n\n/**\n * Command line state machine.\n */\nexport const commandLineStateAtom = atom({\n phase: 'idle'\n});\n\n/**\n * Visual feedback state for the canvas overlay.\n */\nexport const commandFeedbackAtom = atom(null);\n\n/**\n * Command history (persisted to localStorage).\n */\nexport const commandHistoryAtom = atomWithStorage('canvas-command-history', []);\n\n/**\n * Currently selected suggestion index for keyboard navigation.\n */\nexport const selectedSuggestionIndexAtom = atom(0);\n\n// =============================================================================\n// Input Resolution\n// =============================================================================\n\n/**\n * Resolver for pending input. Used to communicate between canvas and command system.\n */\nexport const pendingInputResolverAtom = atom(null);\n\n// =============================================================================\n// Derived Atoms\n// =============================================================================\n\n/**\n * Whether a command is currently being executed or inputs collected.\n */\nexport const isCommandActiveAtom = atom(get => {\n const state = get(commandLineStateAtom);\n return state.phase === 'collecting' || state.phase === 'executing';\n});\n\n/**\n * Current input definition (if collecting).\n */\nexport const currentInputAtom = atom(get => {\n const state = get(commandLineStateAtom);\n if (state.phase !== 'collecting') return null;\n return state.command.inputs[state.inputIndex];\n});\n\n/**\n * Progress through current command (e.g., \"2/3\").\n */\nexport const commandProgressAtom = atom(get => {\n const state = get(commandLineStateAtom);\n if (state.phase !== 'collecting') return null;\n return {\n current: state.inputIndex + 1,\n total: state.command.inputs.length\n };\n});","/**\n * Modifier Helpers\n *\n * Pure utility functions for gesture state queries — repeat detection,\n * selection lookup, subject resolution.\n *\n * Extracted from input-action-helpers.ts in v1.6.0.\n *\n * @since 1.6.0\n */\n\nimport { draggingNodeIdAtom, edgeCreationAtom, focusedNodeIdAtom, selectedEdgeIdAtom, selectedNodeIdsAtom, clearSelectionAtom, clearEdgeSelectionAtom } from '../core';\nimport { isKeyInputEvent } from './types';\n\n/**\n * Whether the keyboard event is a held-down repeat.\n */\nexport function isRepeatBlocked(event) {\n return isKeyInputEvent(event) && event.repeat;\n}\n\n/**\n * Get array of currently selected node IDs.\n */\nexport function getSelectedNodeIds(store) {\n return Array.from(store.get(selectedNodeIdsAtom));\n}\n\n/**\n * Clear both node and edge selection.\n */\nexport function clearSelectionState(store) {\n store.set(clearSelectionAtom);\n store.set(clearEdgeSelectionAtom);\n}\n\n/**\n * Resolve the best node ID to use for focus-based operations.\n */\nexport function resolveFocusableNodeId(store) {\n const focusedNodeId = store.get(focusedNodeIdAtom);\n if (focusedNodeId) return focusedNodeId;\n const selected = getSelectedNodeIds(store);\n return selected[0] ?? null;\n}\n\n/**\n * Determine what entity the current gesture targets.\n */\nexport function getCurrentSubject(store) {\n const draggingNodeId = store.get(draggingNodeIdAtom);\n if (draggingNodeId) return {\n kind: 'node',\n nodeId: draggingNodeId\n };\n const edgeCreation = store.get(edgeCreationAtom);\n if (edgeCreation.isCreating && edgeCreation.sourceNodeId) {\n return {\n kind: 'node',\n nodeId: edgeCreation.sourceNodeId\n };\n }\n const focusedNodeId = resolveFocusableNodeId(store);\n if (focusedNodeId) return {\n kind: 'node',\n nodeId: focusedNodeId\n };\n const selectedEdgeId = store.get(selectedEdgeIdAtom);\n if (selectedEdgeId) return {\n kind: 'edge',\n edgeId: selectedEdgeId\n };\n return {\n kind: 'background'\n };\n}\n\n/**\n * Fill in the subject on key InputEvents if not already set.\n */\nexport function updateKeySubject(event, store) {\n if (event.kind === 'key' && event.subject === undefined) {\n event.subject = getCurrentSubject(store);\n }\n}","/**\n * Gesture Classification — Navigation\n *\n * Pure navigation functions for keyboard-based node traversal:\n * findNearestNode, cycleFocus, navigateFocus, activateFocusedNode.\n *\n * Extracted from input-action-helpers.ts in v1.6.0.\n *\n * @since 1.6.0\n */\n\nimport { focusedNodeIdAtom, selectSingleNodeAtom, setFocusedNodeAtom, setKeyboardInteractionModeAtom, uiNodesAtom } from '../core';\nimport { resolveFocusableNodeId } from './modifier-helpers';\n/**\n * Find the nearest node in a given direction from the current focus.\n */\nexport function findNearestNode(currentNodeId, store, direction) {\n const nodes = store.get(uiNodesAtom);\n if (nodes.length === 0) return null;\n if (!currentNodeId) {\n const sorted = [...nodes].sort((a, b) => a.position.y - b.position.y || a.position.x - b.position.x);\n return sorted[0]?.id ?? null;\n }\n const currentNode = nodes.find(node => node.id === currentNodeId);\n if (!currentNode) return nodes[0]?.id ?? null;\n const cx = currentNode.position.x + (currentNode.width ?? 200) / 2;\n const cy = currentNode.position.y + (currentNode.height ?? 100) / 2;\n let bestId = null;\n let bestScore = Number.POSITIVE_INFINITY;\n for (const candidate of nodes) {\n if (candidate.id === currentNode.id) continue;\n const nx = candidate.position.x + (candidate.width ?? 200) / 2;\n const ny = candidate.position.y + (candidate.height ?? 100) / 2;\n const dx = nx - cx;\n const dy = ny - cy;\n let isValid = false;\n switch (direction) {\n case 'right':\n isValid = dx > 0;\n break;\n case 'left':\n isValid = dx < 0;\n break;\n case 'down':\n isValid = dy > 0;\n break;\n case 'up':\n isValid = dy < 0;\n break;\n }\n if (!isValid) continue;\n const dist = Math.sqrt(dx * dx + dy * dy);\n const isHorizontal = direction === 'left' || direction === 'right';\n const perpendicularDistance = isHorizontal ? Math.abs(dy) : Math.abs(dx);\n const score = dist + perpendicularDistance * 0.5;\n if (score < bestScore) {\n bestScore = score;\n bestId = candidate.id;\n }\n }\n return bestId;\n}\n\n/**\n * Cycle focus to the next/previous node by z-index order.\n */\nexport function cycleFocus(store, direction) {\n const nodes = store.get(uiNodesAtom);\n if (nodes.length === 0) return;\n const focusedNodeId = store.get(focusedNodeIdAtom);\n const sorted = [...nodes].sort((a, b) => a.zIndex - b.zIndex);\n const currentIdx = focusedNodeId ? sorted.findIndex(node => node.id === focusedNodeId) : -1;\n const nextIdx = direction === -1 ? currentIdx <= 0 ? sorted.length - 1 : currentIdx - 1 : (currentIdx + 1) % sorted.length;\n store.set(setFocusedNodeAtom, sorted[nextIdx].id);\n}\n\n/**\n * Navigate focus to the nearest node in a direction.\n */\nexport function navigateFocus(store, direction) {\n const nextId = findNearestNode(resolveFocusableNodeId(store), store, direction);\n if (nextId) {\n store.set(setFocusedNodeAtom, nextId);\n }\n}\n\n/**\n * Activate the focused node — select it and optionally enter manipulate mode.\n */\nexport function activateFocusedNode(store, enterManipulate) {\n const focusedNodeId = resolveFocusableNodeId(store);\n if (!focusedNodeId) return;\n store.set(setFocusedNodeAtom, focusedNodeId);\n store.set(selectSingleNodeAtom, focusedNodeId);\n if (enterManipulate) {\n store.set(setKeyboardInteractionModeAtom, 'manipulate');\n }\n}","/**\n * Input Action Helpers\n *\n * Pure store-based helper functions used by useRegisterInputActions.\n * These are extracted for testability — each function operates on a\n * Jotai store without React dependencies.\n */\n\nimport { addNodesToSelectionAtom, cancelSelectionAtom, clearEdgeSelectionAtom, clearSelectionAtom, copyToClipboardAtom, draggingNodeIdAtom, edgeCreationAtom, endNodeDragAtom, focusedNodeIdAtom, graphAtom, nodeKeysAtom, nodePositionUpdateCounterAtom, optimisticDeleteEdgeAtom, optimisticDeleteNodeAtom, provideInputAtom, pushHistoryAtom, resetInputModeAtom, selectSingleNodeAtom, selectedEdgeIdAtom, selectedNodeIdsAtom, setFocusedNodeAtom, resetKeyboardInteractionModeAtom, toggleNodeInSelectionAtom } from '../core';\nimport { isFilterActiveAtom, clearSearchAtom } from '../core/search-store';\nimport { inputModeAtom, keyboardInteractionModeAtom } from '../core/interaction-store';\nimport { selectionPathAtom } from '../core/selection-path-store';\nimport { commandLineVisibleAtom, closeCommandLineAtom } from '../commands/store';\n// Re-export extracted modules for backward compat\nexport { isRepeatBlocked, getSelectedNodeIds, clearSelectionState, resolveFocusableNodeId, getCurrentSubject, updateKeySubject } from './modifier-helpers';\nimport { getSelectedNodeIds, clearSelectionState, updateKeySubject } from './modifier-helpers';\nexport { findNearestNode, cycleFocus, navigateFocus, activateFocusedNode } from './gesture-classification';\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nexport const EMPTY_EDGE_CREATION = {\n isCreating: false,\n sourceNodeId: null,\n sourceNodePosition: null,\n targetPosition: null,\n hoveredTargetNodeId: null,\n sourceHandle: null,\n targetHandle: null,\n sourcePort: null,\n targetPort: null,\n snappedTargetPosition: null\n};\n\n// =============================================================================\n// Mutations\n// =============================================================================\n\nexport function nudgeSelection(store, dx, dy, label) {\n const selected = getSelectedNodeIds(store);\n if (selected.length === 0) {\n const focused = store.get(focusedNodeIdAtom);\n if (focused) {\n store.set(selectSingleNodeAtom, focused);\n }\n }\n const nodeIds = getSelectedNodeIds(store);\n if (nodeIds.length === 0) return;\n const graph = store.get(graphAtom).copy();\n store.set(pushHistoryAtom, label);\n for (const nodeId of nodeIds) {\n if (!graph.hasNode(nodeId)) continue;\n const x = graph.getNodeAttribute(nodeId, 'x');\n const y = graph.getNodeAttribute(nodeId, 'y');\n graph.setNodeAttribute(nodeId, 'x', x + dx);\n graph.setNodeAttribute(nodeId, 'y', y + dy);\n }\n store.set(graphAtom, graph);\n store.set(nodePositionUpdateCounterAtom, count => count + 1);\n}\nexport function deleteSelection(store) {\n const selectedEdgeId = store.get(selectedEdgeIdAtom);\n if (selectedEdgeId) {\n store.set(optimisticDeleteEdgeAtom, {\n edgeKey: selectedEdgeId\n });\n store.set(clearEdgeSelectionAtom);\n }\n const selectedNodeIds = getSelectedNodeIds(store);\n if (selectedNodeIds.length === 0) return;\n store.set(pushHistoryAtom, selectedNodeIds.length > 1 ? `Delete ${selectedNodeIds.length} nodes` : 'Delete node');\n const focusedNodeId = store.get(focusedNodeIdAtom);\n for (const nodeId of selectedNodeIds) {\n store.set(optimisticDeleteNodeAtom, {\n nodeId\n });\n }\n if (focusedNodeId && selectedNodeIds.includes(focusedNodeId)) {\n store.set(setFocusedNodeAtom, null);\n }\n store.set(clearSelectionAtom);\n}\nexport function cutSelection(store) {\n const selectedNodeIds = getSelectedNodeIds(store);\n if (selectedNodeIds.length === 0) return;\n store.set(copyToClipboardAtom, selectedNodeIds);\n deleteSelection(store);\n}\n\n// =============================================================================\n// Interaction State\n// =============================================================================\n\nexport function cancelActiveInteraction(store) {\n let didCancel = false;\n if (store.get(draggingNodeIdAtom) !== null) {\n store.set(endNodeDragAtom);\n didCancel = true;\n }\n if (store.get(edgeCreationAtom).isCreating) {\n store.set(edgeCreationAtom, EMPTY_EDGE_CREATION);\n didCancel = true;\n }\n if (store.get(inputModeAtom).type === 'pickPoint' || store.get(inputModeAtom).type === 'pickNode' || store.get(inputModeAtom).type === 'pickNodes') {\n store.set(resetInputModeAtom);\n didCancel = true;\n }\n const selectionPath = store.get(selectionPathAtom);\n if (selectionPath !== null) {\n store.set(cancelSelectionAtom);\n didCancel = true;\n }\n return didCancel;\n}\nexport function escapeInput(store) {\n if (cancelActiveInteraction(store)) return;\n if (store.get(keyboardInteractionModeAtom) === 'manipulate') {\n store.set(resetKeyboardInteractionModeAtom);\n return;\n }\n if (store.get(isFilterActiveAtom)) {\n store.set(clearSearchAtom);\n return;\n }\n if (store.get(commandLineVisibleAtom)) {\n store.set(closeCommandLineAtom);\n return;\n }\n if (store.get(selectedNodeIdsAtom).size > 0 || store.get(selectedEdgeIdAtom) !== null) {\n clearSelectionState(store);\n }\n}\n\n// =============================================================================\n// Pick Mode\n// =============================================================================\n\nexport function resolvePickNode(event, store) {\n updateKeySubject(event, store);\n if (event.subject?.kind !== 'node') return;\n if (store.get(inputModeAtom).type === 'pickNodes') {\n store.set(toggleNodeInSelectionAtom, event.subject.nodeId);\n store.set(setFocusedNodeAtom, event.subject.nodeId);\n return;\n }\n store.set(provideInputAtom, event.subject.nodeId);\n store.set(resetInputModeAtom);\n}\nexport function finishPickNodes(store) {\n store.set(provideInputAtom, getSelectedNodeIds(store));\n store.set(resetInputModeAtom);\n}\nexport function resolvePickPoint(event, store) {\n if (event.kind !== 'pointer') return;\n store.set(provideInputAtom, event.worldPosition);\n store.set(resetInputModeAtom);\n}\nexport function selectAll(store) {\n clearSelectionState(store);\n store.set(addNodesToSelectionAtom, store.get(nodeKeysAtom));\n}","/**\n * useCanvasGestures — Main viewport gesture hook\n *\n * Wires @use-gesture/react → recognize → resolve → dispatch.\n *\n * Responsibilities:\n * - Pointer tracking (down/up/cancel) via input-store\n * - Tap/double-tap/long-press via TimedStateRunner\n * - Drag intent resolution via mapper\n * - Pan with inertia (delegated to useInertia)\n * - Pinch zoom with inertia + snap-to-100%\n * - Wheel zoom\n * - Lasso / rect-select routing\n * - pointercancel + visibilitychange cleanup\n *\n * Guard context is built by useGuardContext.\n * Inertia is managed by useInertia.\n */\n\nimport { useRef, useEffect, useMemo } from 'react';\nimport { useAtom, useSetAtom, useAtomValue } from 'jotai';\nimport { useGesture } from '@use-gesture/react';\nimport { zoomAtom, panAtom, viewportRectAtom, screenToWorldAtom } from '../core/viewport-store';\nimport { clearSelectionAtom, selectedNodeIdsAtom } from '../core/selection-store';\nimport { classifyPointer } from '../core/input-classifier';\nimport { pointerDownAtom, pointerUpAtom, primaryInputSourceAtom, clearPointersAtom } from '../core/input-store';\nimport { prefersReducedMotionAtom } from '../core/reduced-motion-store';\nimport { startSelectionAtom, updateSelectionAtom, endSelectionAtom } from '../core/selection-path-store';\nimport { extractModifiers } from './normalize';\nimport { TimedStateRunner } from './timed-state-runner';\nimport { buildMappingIndex, resolve } from './mapper';\nimport { dispatch } from './dispatcher';\nimport { PALM_REJECTION_CONTEXT, DEFAULT_CONTEXT } from './contexts';\nimport { useGuardContext } from './useGuardContext';\nimport { useInertia, INERTIA_MIN_SPEED } from './useInertia';\nimport { createWheelHandler } from './useWheelZoom';\nimport { createPinchHandlers } from './usePinchZoom';\nimport { NO_HELD_KEYS, NO_MODIFIERS } from './types';\n\n// =============================================================================\n// Config\n// =============================================================================\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useCanvasGestures({\n ref,\n minZoom = 0.1,\n maxZoom = 5,\n zoomSensitivity = 0.0015,\n enablePan = true,\n enableZoom = true,\n mappingIndex: externalIndex,\n contexts: extraContexts,\n palmRejection = true,\n onAction,\n heldKeys = NO_HELD_KEYS\n}) {\n // --- Jotai atoms ---\n const [panVals, setPan] = useAtom(panAtom);\n const [zoomVal, setZoom] = useAtom(zoomAtom);\n const setViewportRect = useSetAtom(viewportRectAtom);\n const selectedNodeIds = useAtomValue(selectedNodeIdsAtom);\n const clearSelection = useSetAtom(clearSelectionAtom);\n const screenToWorld = useAtomValue(screenToWorldAtom);\n\n // Input tracking\n const setPointerDown = useSetAtom(pointerDownAtom);\n const setPointerUp = useSetAtom(pointerUpAtom);\n const clearPointers = useSetAtom(clearPointersAtom);\n const primaryInputSource = useAtomValue(primaryInputSourceAtom);\n const reducedMotion = useAtomValue(prefersReducedMotionAtom);\n\n // Selection path (lasso / rect-select)\n const startSelection = useSetAtom(startSelectionAtom);\n const updateSelection = useSetAtom(updateSelectionAtom);\n const endSelection = useSetAtom(endSelectionAtom);\n\n // --- Extracted hooks ---\n const guardRef = useGuardContext(heldKeys);\n const inertia = useInertia();\n\n // --- Refs (mutable, no re-renders) ---\n const panStartRef = useRef({\n x: 0,\n y: 0\n });\n const dragOriginatedOnBg = useRef(false);\n const dragSourceRef = useRef('mouse');\n const buttonRef = useRef(0);\n const dragIntentRef = useRef('none');\n\n // Timed state (tap counting / long-press)\n const timedRunner = useRef(new TimedStateRunner());\n\n // --- Build mapping index (use external if provided) ---\n const internalIndex = useMemo(() => {\n const ctxList = [];\n if (palmRejection) ctxList.push(PALM_REJECTION_CONTEXT);\n if (extraContexts) ctxList.push(...extraContexts);\n ctxList.push(DEFAULT_CONTEXT);\n return buildMappingIndex(ctxList);\n }, [palmRejection, extraContexts]);\n const mappingIndex = externalIndex ?? internalIndex;\n\n // --- Helpers ---\n\n const isBackgroundTarget = target => {\n if (!ref.current || !target) return false;\n const child = ref.current.firstChild;\n return target === ref.current || target === child;\n };\n const makeGestureEvent = (type, phase, subject, screenX, screenY, extra) => {\n const worldPos = screenToWorld(screenX, screenY);\n return {\n kind: 'pointer',\n type,\n phase,\n subject,\n source: dragSourceRef.current,\n button: buttonRef.current,\n modifiers: NO_MODIFIERS,\n heldKeys,\n screenPosition: {\n x: screenX,\n y: screenY\n },\n worldPosition: worldPos,\n ...extra\n };\n };\n const resolveAndDispatch = event => {\n const resolution = resolve(event, mappingIndex, guardRef.current);\n if (resolution) {\n dispatch(event, resolution);\n onAction?.(event, resolution);\n }\n return resolution;\n };\n\n // --- Timed state emit handler (for async timer-based gestures like long-press) ---\n useEffect(() => {\n const runner = timedRunner.current;\n runner.onEmit = _gestureType => {\n // Long-press fires asynchronously from the timer.\n // Position is captured at pointer-down time via the onPointerDown handler.\n };\n return () => {\n runner.destroy();\n };\n }, []);\n\n // --- Viewport resize observer ---\n useEffect(() => {\n const el = ref.current;\n if (!el) {\n setViewportRect(null);\n return;\n }\n setViewportRect(el.getBoundingClientRect());\n const observer = new ResizeObserver(entries => {\n for (const entry of entries) {\n setViewportRect(entry.contentRect);\n }\n });\n observer.observe(el);\n return () => {\n observer.unobserve(el);\n observer.disconnect();\n };\n }, [setViewportRect]);\n\n // --- Cleanup on unmount ---\n useEffect(() => {\n return () => {\n inertia.cancelAll();\n timedRunner.current.destroy();\n };\n }, []);\n\n // --- Visibility change: clear pointers + cancel inertia ---\n useEffect(() => {\n const handleVisChange = () => {\n if (document.hidden) {\n inertia.cancelAll();\n clearPointers();\n timedRunner.current.feed('cancel');\n }\n };\n document.addEventListener('visibilitychange', handleVisChange);\n return () => document.removeEventListener('visibilitychange', handleVisChange);\n }, [clearPointers]);\n\n // ==========================================================================\n // @use-gesture binding\n // ==========================================================================\n\n useGesture({\n onPointerDown: state => {\n if (!ref.current) {\n dragOriginatedOnBg.current = false;\n return;\n }\n const pe = state.event;\n const classified = classifyPointer(pe);\n setPointerDown(classified);\n dragSourceRef.current = classified.source;\n buttonRef.current = pe.button ?? 0;\n\n // Cancel inertia on new touch\n inertia.cancelAll();\n if (isBackgroundTarget(state.event.target)) {\n dragOriginatedOnBg.current = true;\n\n // Feed timed state machine for tap/long-press tracking\n timedRunner.current.feed('down');\n\n // Wire the long-press timer emit\n const startX = pe.clientX;\n const startY = pe.clientY;\n timedRunner.current.onEmit = gestureType => {\n if (gestureType === 'long-press') {\n const worldPos_0 = screenToWorld(startX, startY);\n const event_0 = makeGestureEvent('long-press', 'instant', {\n kind: 'background'\n }, startX, startY, {\n modifiers: extractModifiers(pe),\n worldPosition: worldPos_0\n });\n resolveAndDispatch(event_0);\n }\n };\n } else {\n dragOriginatedOnBg.current = false;\n }\n },\n onPointerUp: state_0 => {\n const pe_0 = state_0.event;\n setPointerUp(pe_0.pointerId);\n },\n onDragStart: ({\n event: event_1\n }) => {\n if (!dragOriginatedOnBg.current) return;\n const pe_1 = event_1;\n const modifiers = pe_1 ? extractModifiers(pe_1) : NO_MODIFIERS;\n\n // Resolve drag intent once at start\n const gestureEvent = makeGestureEvent('drag', 'start', {\n kind: 'background'\n }, pe_1?.clientX ?? 0, pe_1?.clientY ?? 0, {\n modifiers\n });\n const resolution_0 = resolve(gestureEvent, mappingIndex, guardRef.current);\n dragIntentRef.current = resolution_0?.actionId ?? 'none';\n if (dragIntentRef.current === 'pan' && enablePan) {\n panStartRef.current = {\n ...panVals\n };\n inertia.panSampler.reset();\n } else if (dragIntentRef.current === 'lasso-select' || dragIntentRef.current === 'rect-select') {\n const worldPos_1 = screenToWorld(pe_1?.clientX ?? 0, pe_1?.clientY ?? 0);\n startSelection({\n type: dragIntentRef.current === 'lasso-select' ? 'lasso' : 'rect',\n point: worldPos_1\n });\n }\n\n // Dispatch the start phase\n if (resolution_0) {\n dispatch(gestureEvent, resolution_0);\n onAction?.(gestureEvent, resolution_0);\n }\n },\n onDrag: ({\n movement: [mx, my],\n tap,\n active,\n pinching,\n event: event_2,\n velocity: [vx, vy],\n direction: [dx, dy]\n }) => {\n if (tap && dragOriginatedOnBg.current) {\n // Tap on background — the timed runner tracks tap counting.\n const emitted = timedRunner.current.feed('up');\n const pe_2 = event_2;\n const modifiers_0 = extractModifiers(pe_2);\n const tapType = emitted ?? 'tap';\n const gestureEvent_0 = makeGestureEvent(tapType, 'instant', {\n kind: 'background'\n }, pe_2.clientX, pe_2.clientY, {\n modifiers: modifiers_0\n });\n const resolution_1 = resolve(gestureEvent_0, mappingIndex, guardRef.current);\n if (resolution_1) {\n dispatch(gestureEvent_0, resolution_1);\n onAction?.(gestureEvent_0, resolution_1);\n } else {\n clearSelection();\n }\n return;\n }\n if (!tap && active && !pinching && dragOriginatedOnBg.current) {\n // Cancel long-press on drag movement\n timedRunner.current.feed('move-beyond-threshold');\n const intent = dragIntentRef.current;\n if (intent === 'pan' && enablePan) {\n setPan({\n x: panStartRef.current.x + mx,\n y: panStartRef.current.y + my\n });\n const now = performance.now();\n inertia.panSampler.sample(vx * dx, vy * dy, now);\n } else if (intent === 'lasso-select' || intent === 'rect-select') {\n const pe_3 = event_2;\n const worldPos_2 = screenToWorld(pe_3.clientX, pe_3.clientY);\n updateSelection(worldPos_2);\n }\n }\n },\n onDragEnd: () => {\n timedRunner.current.feed('up');\n const intent_0 = dragIntentRef.current;\n if (intent_0 === 'lasso-select' || intent_0 === 'rect-select') {\n endSelection();\n }\n\n // Pan inertia for finger drags (skip if reduced motion)\n if (!reducedMotion && dragOriginatedOnBg.current && dragSourceRef.current === 'finger' && intent_0 === 'pan') {\n const avg = inertia.panSampler.average();\n const speed = Math.sqrt(avg.x ** 2 + avg.y ** 2);\n if (speed > INERTIA_MIN_SPEED) {\n inertia.startPanInertia(avg, setPan);\n }\n }\n dragOriginatedOnBg.current = false;\n dragIntentRef.current = 'none';\n inertia.panSampler.reset();\n },\n onWheel: createWheelHandler({\n ref,\n minZoom,\n maxZoom,\n zoomSensitivity,\n enableZoom,\n zoom: zoomVal,\n pan: panVals,\n selectedNodeIds,\n setZoom,\n setPan\n }),\n ...createPinchHandlers({\n ref,\n minZoom,\n maxZoom,\n enableZoom,\n reducedMotion,\n zoom: zoomVal,\n pan: panVals,\n setZoom,\n setPan,\n inertia\n })\n }, {\n target: ref,\n eventOptions: {\n passive: false,\n capture: true\n },\n drag: {\n filterTaps: true,\n tapsThreshold: primaryInputSource === 'finger' ? 10 : 5,\n pointer: {\n touch: true,\n keys: false,\n capture: false,\n buttons: -1\n }\n },\n wheel: {},\n pinch: {\n scaleBounds: () => ({\n min: minZoom,\n max: maxZoom\n }),\n from: () => [zoomVal, 0]\n }\n });\n}","/**\n * useGuardContext — Guard context hook\n *\n * Reads all atoms needed for the gesture guard context and returns\n * a ref that is updated every render. The ref is stable and safe\n * to read inside useGesture callbacks without stale closure issues.\n */\n\nimport { useRef } from 'react';\nimport { useAtomValue } from 'jotai';\nimport { selectedNodeIdsAtom, focusedNodeIdAtom } from '../core/selection-store';\nimport { draggingNodeIdAtom, edgeCreationAtom } from '../core/graph-store';\nimport { isStylusActiveAtom, fingerCountAtom } from '../core/input-store';\nimport { inputModeAtom, keyboardInteractionModeAtom } from '../core/interaction-store';\nimport { selectionPathAtom } from '../core/selection-path-store';\nimport { isFilterActiveAtom } from '../core/search-store';\nimport { commandLineVisibleAtom } from '../commands/store';\nimport { NO_HELD_KEYS } from './types';\nexport function useGuardContext(heldKeys = NO_HELD_KEYS) {\n const isStylusActive = useAtomValue(isStylusActiveAtom);\n const fingerCount = useAtomValue(fingerCountAtom);\n const draggingNodeId = useAtomValue(draggingNodeIdAtom);\n const focusedNodeId = useAtomValue(focusedNodeIdAtom);\n const selectedNodeIds = useAtomValue(selectedNodeIdsAtom);\n const inputMode = useAtomValue(inputModeAtom);\n const keyboardInteractionMode = useAtomValue(keyboardInteractionModeAtom);\n const selectionPath = useAtomValue(selectionPathAtom);\n const edgeCreation = useAtomValue(edgeCreationAtom);\n const isSearchActive = useAtomValue(isFilterActiveAtom);\n const commandLineVisible = useAtomValue(commandLineVisibleAtom);\n const guardRef = useRef({\n isStylusActive: false,\n fingerCount: 0,\n isDragging: false,\n isResizing: false,\n isSplitting: false,\n inputMode: {\n type: 'normal'\n },\n keyboardInteractionMode: 'navigate',\n selectedNodeIds: new Set(),\n focusedNodeId: null,\n isSearchActive: false,\n commandLineVisible: false,\n heldKeys: NO_HELD_KEYS,\n custom: {}\n });\n guardRef.current = {\n isStylusActive,\n fingerCount,\n isDragging: draggingNodeId !== null,\n isResizing: false,\n isSplitting: false,\n inputMode,\n keyboardInteractionMode,\n selectedNodeIds,\n focusedNodeId,\n isSearchActive,\n commandLineVisible,\n heldKeys,\n custom: {\n isSelecting: selectionPath !== null,\n isCreatingEdge: edgeCreation.isCreating\n }\n };\n return guardRef;\n}","/**\n * useInertia — Pan & zoom inertia management\n *\n * Encapsulates the rAF animation loops, VelocitySamplers, and\n * pinch tracking refs used by useCanvasGestures. Returns stable\n * functions for starting/cancelling inertia and recording samples.\n */\n\nimport { useRef, useEffect } from 'react';\nimport { PanInertia, ZoomInertia, VelocitySampler } from './inertia';\n// =============================================================================\n// Constants\n// =============================================================================\n\nexport const ZOOM_SNAP_THRESHOLD = 0.03;\nexport const INERTIA_MIN_SPEED = 2;\nconst VELOCITY_SAMPLE_COUNT = 5;\n\n// =============================================================================\n// Types\n// =============================================================================\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nexport function snapZoom(z) {\n return Math.abs(z - 1.0) < ZOOM_SNAP_THRESHOLD ? 1.0 : z;\n}\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useInertia() {\n const panInertiaRef = useRef(null);\n const zoomInertiaRef = useRef(null);\n const panSamplerRef = useRef(new VelocitySampler(VELOCITY_SAMPLE_COUNT));\n const zoomSamplerRef = useRef(new VelocitySampler(VELOCITY_SAMPLE_COUNT));\n const pinchPrevOrigin = useRef(null);\n const lastPinchZoom = useRef(null);\n const cancelPan = () => {\n if (panInertiaRef.current) {\n cancelAnimationFrame(panInertiaRef.current.anim);\n panInertiaRef.current = null;\n }\n };\n const cancelZoom = () => {\n if (zoomInertiaRef.current) {\n cancelAnimationFrame(zoomInertiaRef.current.anim);\n zoomInertiaRef.current = null;\n }\n };\n const cancelAll = () => {\n cancelPan();\n cancelZoom();\n };\n const startPanInertia = (velocity, setPan) => {\n cancelPan();\n const engine = new PanInertia(velocity);\n const animate = () => {\n const tick = engine.tick();\n if (!tick) {\n panInertiaRef.current = null;\n return;\n }\n setPan(prev => ({\n x: prev.x + tick.x,\n y: prev.y + tick.y\n }));\n panInertiaRef.current.anim = requestAnimationFrame(animate);\n };\n panInertiaRef.current = {\n anim: requestAnimationFrame(animate),\n engine\n };\n };\n const startZoomInertia = (velocity_0, origin, currentZoom, minZoom, maxZoom, setZoom, setPan_0) => {\n cancelZoom();\n const engine_0 = new ZoomInertia(velocity_0, origin);\n const animate_0 = () => {\n const tick_0 = engine_0.tick(currentZoom);\n if (!tick_0) {\n zoomInertiaRef.current = null;\n return;\n }\n setZoom(prevZoom => {\n const newZoom = Math.max(minZoom, Math.min(maxZoom, prevZoom + tick_0.delta));\n setPan_0(prevPan => {\n const worldX = (tick_0.origin.x - prevPan.x) / prevZoom;\n const worldY = (tick_0.origin.y - prevPan.y) / prevZoom;\n return {\n x: tick_0.origin.x - worldX * newZoom,\n y: tick_0.origin.y - worldY * newZoom\n };\n });\n return snapZoom(newZoom);\n });\n zoomInertiaRef.current.anim = requestAnimationFrame(animate_0);\n };\n zoomInertiaRef.current = {\n anim: requestAnimationFrame(animate_0),\n engine: engine_0\n };\n };\n\n // Cleanup on unmount\n useEffect(() => cancelAll, []);\n return {\n startPanInertia,\n startZoomInertia,\n cancelAll,\n cancelPan,\n cancelZoom,\n panSampler: panSamplerRef.current,\n zoomSampler: zoomSamplerRef.current,\n pinchPrevOrigin,\n lastPinchZoom\n };\n}","/**\n * useWheelZoom — Wheel zoom handler extracted from useCanvasGestures\n *\n * Pure function returning an `onWheel` callback for @use-gesture/react.\n * Handles:\n * - Zoom calculation with configurable sensitivity\n * - Snap-to-100% via snapZoom\n * - Min/max bounds clamping\n * - Scroll passthrough for scrollable content inside selected nodes\n *\n * @since 1.3.0\n */\n\nimport { snapZoom } from './useInertia';\n\n// =============================================================================\n// Config\n// =============================================================================\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Creates an onWheel handler for use with @use-gesture/react.\n *\n * Extracted from useCanvasGestures to enable independent testing\n * and reuse in custom gesture compositions.\n */\nexport function createWheelHandler(config) {\n return ({\n event,\n pinching,\n delta: [, dy],\n memo\n }) => {\n if (memo === true || pinching || !config.enableZoom || !config.ref.current) return;\n\n // Check scrollable element inside selected node\n const target = event.target;\n const noDrag = target.closest('[data-no-drag=\"true\"]');\n if (noDrag) {\n const draggableNode = target.closest('[data-draggable-node=\"true\"]');\n if (draggableNode) {\n const nodeId = draggableNode.getAttribute('data-node-id');\n if (nodeId && config.selectedNodeIds.has(nodeId)) {\n let el = target;\n while (el && noDrag.contains(el)) {\n if (el.scrollHeight > el.clientHeight) {\n const atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 1;\n const atTop = el.scrollTop <= 1;\n if (!atBottom && dy > 0 || !atTop && dy < 0 || atBottom && dy < 0 || atTop && dy > 0) {\n return;\n }\n }\n el = el.parentElement;\n }\n }\n }\n }\n event.preventDefault();\n const rect = config.ref.current.getBoundingClientRect();\n const mouseX = event.clientX - rect.left;\n const mouseY = event.clientY - rect.top;\n const worldX = (mouseX - config.pan.x) / config.zoom;\n const worldY = (mouseY - config.pan.y) / config.zoom;\n const zoomDelta = -dy * config.zoomSensitivity * config.zoom;\n const newZoom = snapZoom(Math.max(config.minZoom, Math.min(config.maxZoom, config.zoom + zoomDelta)));\n config.setZoom(newZoom);\n config.setPan({\n x: mouseX - worldX * newZoom,\n y: mouseY - worldY * newZoom\n });\n };\n}","/**\n * usePinchZoom — Pinch zoom handlers extracted from useCanvasGestures\n *\n * Pure function returning `onPinchStart`, `onPinch`, `onPinchEnd` callbacks\n * for @use-gesture/react. Handles:\n * - Simultaneous pan during pinch (finger midpoint tracking)\n * - Zoom velocity sampling for inertia\n * - Snap-to-100% via snapZoom\n * - Inertia trigger on pinch end\n *\n * @since 1.3.0\n */\n\nimport { snapZoom } from './useInertia';\n\n// =============================================================================\n// Config\n// =============================================================================\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Creates onPinchStart, onPinch, onPinchEnd handlers for use with @use-gesture/react.\n *\n * Extracted from useCanvasGestures to enable independent testing\n * and reuse in custom gesture compositions.\n */\nexport function createPinchHandlers(config) {\n const onPinchStart = ({\n origin: [ox, oy]\n }) => {\n if (!config.enableZoom || !config.ref.current) return true;\n config.inertia.cancelAll();\n config.inertia.pinchPrevOrigin.current = {\n x: ox,\n y: oy\n };\n config.inertia.zoomSampler.reset();\n config.inertia.lastPinchZoom.current = {\n zoom: config.zoom,\n t: performance.now()\n };\n return false;\n };\n const onPinch = ({\n offset: [d],\n origin: [ox, oy],\n event,\n memo\n }) => {\n if (memo === true || !config.enableZoom || !config.ref.current) return;\n event.preventDefault();\n const rect = config.ref.current.getBoundingClientRect();\n const pinchX = ox - rect.left;\n const pinchY = oy - rect.top;\n\n // Simultaneous pan\n let pdx = 0;\n let pdy = 0;\n if (config.inertia.pinchPrevOrigin.current) {\n pdx = ox - config.inertia.pinchPrevOrigin.current.x;\n pdy = oy - config.inertia.pinchPrevOrigin.current.y;\n }\n config.inertia.pinchPrevOrigin.current = {\n x: ox,\n y: oy\n };\n const worldX = (pinchX - config.pan.x) / config.zoom;\n const worldY = (pinchY - config.pan.y) / config.zoom;\n const newZoom = snapZoom(Math.max(config.minZoom, Math.min(config.maxZoom, d)));\n\n // Track zoom velocity\n const now = performance.now();\n if (config.inertia.lastPinchZoom.current) {\n const dt = (now - config.inertia.lastPinchZoom.current.t) / 1000;\n if (dt > 0) {\n const v = (newZoom - config.inertia.lastPinchZoom.current.zoom) / dt;\n config.inertia.zoomSampler.sample(v, 0, now);\n }\n }\n config.inertia.lastPinchZoom.current = {\n zoom: newZoom,\n t: now\n };\n config.setZoom(newZoom);\n config.setPan({\n x: pinchX - worldX * newZoom + pdx,\n y: pinchY - worldY * newZoom + pdy\n });\n };\n const onPinchEnd = () => {\n const avg = config.inertia.zoomSampler.average();\n const perFrameV = avg.x / 60;\n if (!config.reducedMotion && Math.abs(perFrameV) > 0.001 && config.ref.current) {\n const rect = config.ref.current.getBoundingClientRect();\n const origin = config.inertia.pinchPrevOrigin.current ?? {\n x: rect.width / 2,\n y: rect.height / 2\n };\n config.inertia.startZoomInertia(perFrameV, {\n x: origin.x - rect.left,\n y: origin.y - rect.top\n }, config.zoom, config.minZoom, config.maxZoom, config.setZoom, config.setPan);\n }\n config.inertia.pinchPrevOrigin.current = null;\n config.inertia.zoomSampler.reset();\n config.inertia.lastPinchZoom.current = null;\n };\n return {\n onPinchStart,\n onPinch,\n onPinchEnd\n };\n}","/**\n * useNodeGestures — Node-level gesture recognition hook\n *\n * Replaces the inline click counting, touch long-press timers, and\n * context menu handling in Node.tsx. Produces gesture events that\n * route through the v2 pipeline (resolve → dispatch).\n *\n * Drag mechanics stay in useNodeDrag — this hook handles:\n * - tap / double-tap / triple-tap (via TimedStateRunner)\n * - right-click (tap with button=2)\n * - long-press (finger/pencil only)\n * - hover enter/leave\n *\n * Returns event handler props to spread on the node DOM element.\n */\n\nimport { useRef, useEffect } from 'react';\nimport { useAtomValue } from 'jotai';\nimport { screenToWorldAtom } from '../core/viewport-store';\nimport { isStylusActiveAtom, fingerCountAtom } from '../core/input-store';\nimport { inputModeAtom, keyboardInteractionModeAtom } from '../core/interaction-store';\nimport { focusedNodeIdAtom, selectedNodeIdsAtom } from '../core/selection-store';\nimport { draggingNodeIdAtom, edgeCreationAtom } from '../core/graph-store';\nimport { isFilterActiveAtom } from '../core/search-store';\nimport { selectionPathAtom } from '../core/selection-path-store';\nimport { commandLineVisibleAtom } from '../commands/store';\nimport { classifyPointer } from '../core/input-classifier';\nimport { TimedStateRunner } from './timed-state-runner';\nimport { extractModifiers } from './normalize';\nimport { resolve } from './mapper';\nimport { dispatch } from './dispatcher';\nimport { NO_HELD_KEYS, NO_MODIFIERS } from './types';\nexport function useNodeGestures({\n nodeId,\n mappingIndex,\n onAction,\n heldKeys = NO_HELD_KEYS\n}) {\n const screenToWorld = useAtomValue(screenToWorldAtom);\n const isStylusActive = useAtomValue(isStylusActiveAtom);\n const fingerCount = useAtomValue(fingerCountAtom);\n const inputMode = useAtomValue(inputModeAtom);\n const keyboardInteractionMode = useAtomValue(keyboardInteractionModeAtom);\n const selectedNodeIds = useAtomValue(selectedNodeIdsAtom);\n const focusedNodeId = useAtomValue(focusedNodeIdAtom);\n const draggingNodeId = useAtomValue(draggingNodeIdAtom);\n const edgeCreation = useAtomValue(edgeCreationAtom);\n const selectionPath = useAtomValue(selectionPathAtom);\n const isSearchActive = useAtomValue(isFilterActiveAtom);\n const commandLineVisible = useAtomValue(commandLineVisibleAtom);\n const runner = useRef(new TimedStateRunner());\n const sourceRef = useRef('mouse');\n const buttonRef = useRef(0);\n const posRef = useRef({\n x: 0,\n y: 0\n });\n const modifiersRef = useRef(NO_MODIFIERS);\n // Track whether a right-button drag happened (suppress context menu)\n const rightDragSeen = useRef(false);\n\n // Guard context ref — kept fresh each render\n const guardRef = useRef({\n isStylusActive: false,\n fingerCount: 0,\n isDragging: false,\n isResizing: false,\n isSplitting: false,\n inputMode: {\n type: 'normal'\n },\n keyboardInteractionMode: 'navigate',\n selectedNodeIds: new Set(),\n focusedNodeId: null,\n isSearchActive: false,\n commandLineVisible: false,\n heldKeys: NO_HELD_KEYS,\n custom: {}\n });\n guardRef.current = {\n isStylusActive,\n fingerCount,\n isDragging: draggingNodeId !== null,\n isResizing: false,\n isSplitting: false,\n inputMode,\n keyboardInteractionMode,\n selectedNodeIds,\n focusedNodeId,\n isSearchActive,\n commandLineVisible,\n heldKeys,\n custom: {}\n };\n guardRef.current.custom = {\n isSelecting: selectionPath !== null,\n isCreatingEdge: edgeCreation.isCreating\n };\n\n // Cleanup\n useEffect(() => {\n return () => runner.current.destroy();\n }, []);\n const resolveAndDispatch = event => {\n const resolution = resolve(event, mappingIndex, guardRef.current);\n if (resolution) {\n dispatch(event, resolution);\n onAction?.(event, resolution);\n }\n return resolution;\n };\n const makeEvent = (type, phase, screenX, screenY) => {\n const worldPos = screenToWorld(screenX, screenY);\n return {\n kind: 'pointer',\n type,\n phase,\n subject: {\n kind: 'node',\n nodeId\n },\n source: sourceRef.current,\n button: buttonRef.current,\n modifiers: modifiersRef.current,\n heldKeys,\n screenPosition: {\n x: screenX,\n y: screenY\n },\n worldPosition: worldPos\n };\n };\n\n // Wire timer-based emits (long-press)\n useEffect(() => {\n runner.current.onEmit = gestureType => {\n if (gestureType === 'long-press') {\n const event_0 = makeEvent('long-press', 'instant', posRef.current.x, posRef.current.y);\n resolveAndDispatch(event_0);\n }\n };\n });\n const onPointerDown = e => {\n const classified = classifyPointer(e.nativeEvent);\n sourceRef.current = classified.source;\n buttonRef.current = e.button ?? 0;\n posRef.current = {\n x: e.clientX,\n y: e.clientY\n };\n modifiersRef.current = extractModifiers(e);\n rightDragSeen.current = false;\n runner.current.feed('down');\n };\n const onPointerUp = e_0 => {\n const emitted = runner.current.feed('up');\n if (emitted) {\n // Synchronous tap emit — build and resolve\n const event_1 = makeEvent(emitted, 'instant', e_0.clientX, e_0.clientY);\n resolveAndDispatch(event_1);\n }\n };\n const onPointerCancel = _e => {\n runner.current.feed('cancel');\n };\n const onContextMenu = e_1 => {\n // Always prevent default — we handle right-click through the pipeline\n e_1.preventDefault();\n e_1.stopPropagation();\n\n // If a right-drag was in progress, suppress the context menu\n if (rightDragSeen.current) {\n rightDragSeen.current = false;\n return;\n }\n\n // Right-click is handled as tap with button=2 via the timed state\n // machine's 'up' event. If the runner already emitted a tap,\n // it was dispatched in onPointerUp. If not (e.g., contextmenu\n // fires without paired pointer events on some browsers), we\n // fire a synthetic tap here as a fallback.\n const event_2 = makeEvent('tap', 'instant', e_1.clientX, e_1.clientY);\n event_2.button = 2;\n event_2.modifiers = extractModifiers(e_1);\n resolveAndDispatch(event_2);\n };\n return {\n onPointerDown,\n onPointerUp,\n onPointerCancel,\n onContextMenu\n };\n}","import { c as _c } from \"react/compiler-runtime\";\n/**\n * useInputSystem — Consumer hook for the shared input pipeline\n *\n * Provides a stable API for:\n * - Pushing / removing MappingContexts at runtime\n * - Reading the current mapping index\n * - Configuring palm rejection\n *\n * All context state is managed via useState.\n * Context sync belongs in hooks (Design Decision 5), not effectful atoms.\n */\n\nimport { useState } from 'react';\nimport { buildMappingIndex } from './mapper';\nimport { ACTIVE_INTERACTION_CONTEXT, DEFAULT_CONTEXT, KEYBOARD_MANIPULATE_CONTEXT, KEYBOARD_NAVIGATE_CONTEXT, PALM_REJECTION_CONTEXT, SEARCH_CONTEXT } from './contexts';\nimport { NO_HELD_KEYS } from './types';\nexport function useInputSystem(t0) {\n const $ = _c(19);\n const config = t0 === undefined ? {} : t0;\n const {\n contexts: staticContexts,\n palmRejection: t1\n } = config;\n const initialPR = t1 === undefined ? true : t1;\n let t2;\n if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t2 = [];\n $[0] = t2;\n } else {\n t2 = $[0];\n }\n const [dynamicContexts, setDynamicContexts] = useState(t2);\n const [palmRejection, setPalmRejection] = useState(initialPR);\n const [heldKeys, setHeldKeys] = useState(NO_HELD_KEYS);\n const all = [];\n if (palmRejection) {\n all.push(PALM_REJECTION_CONTEXT);\n }\n all.push(ACTIVE_INTERACTION_CONTEXT, SEARCH_CONTEXT, KEYBOARD_MANIPULATE_CONTEXT, KEYBOARD_NAVIGATE_CONTEXT);\n if (staticContexts) {\n all.push(...staticContexts);\n }\n all.push(...dynamicContexts);\n all.push(DEFAULT_CONTEXT);\n const mappingIndex = buildMappingIndex(all);\n let t3;\n if ($[1] !== setDynamicContexts) {\n t3 = ctx => {\n setDynamicContexts(prev => {\n const filtered = prev.filter(c => c.id !== ctx.id);\n return [...filtered, ctx];\n });\n };\n $[1] = setDynamicContexts;\n $[2] = t3;\n } else {\n t3 = $[2];\n }\n const pushContext = t3;\n let t4;\n if ($[3] !== setDynamicContexts) {\n t4 = id => {\n setDynamicContexts(prev_0 => prev_0.filter(c_0 => c_0.id !== id));\n };\n $[3] = setDynamicContexts;\n $[4] = t4;\n } else {\n t4 = $[4];\n }\n const removeContext = t4;\n let t5;\n if ($[5] !== setDynamicContexts) {\n t5 = (id_0, enabled) => {\n setDynamicContexts(prev_1 => prev_1.map(c_1 => c_1.id === id_0 ? {\n ...c_1,\n enabled\n } : c_1));\n };\n $[5] = setDynamicContexts;\n $[6] = t5;\n } else {\n t5 = $[6];\n }\n const setContextEnabled = t5;\n let t6;\n if ($[7] !== setHeldKeys) {\n t6 = () => {\n setHeldKeys(NO_HELD_KEYS);\n };\n $[7] = setHeldKeys;\n $[8] = t6;\n } else {\n t6 = $[8];\n }\n const clearHeldKeys = t6;\n let t7;\n if ($[9] !== clearHeldKeys || $[10] !== heldKeys || $[11] !== mappingIndex || $[12] !== palmRejection || $[13] !== pushContext || $[14] !== removeContext || $[15] !== setContextEnabled || $[16] !== setHeldKeys || $[17] !== setPalmRejection) {\n t7 = {\n mappingIndex,\n pushContext,\n removeContext,\n setContextEnabled,\n palmRejection,\n setPalmRejection,\n heldKeys,\n setHeldKeys,\n clearHeldKeys\n };\n $[9] = clearHeldKeys;\n $[10] = heldKeys;\n $[11] = mappingIndex;\n $[12] = palmRejection;\n $[13] = pushContext;\n $[14] = removeContext;\n $[15] = setContextEnabled;\n $[16] = setHeldKeys;\n $[17] = setPalmRejection;\n $[18] = t7;\n } else {\n t7 = $[18];\n }\n return t7;\n}\nexport const useGestureSystem = useInputSystem;","import { c as _c } from \"react/compiler-runtime\";\n/**\n * useInputModeGestureContext — Syncs input mode → mapping context\n *\n * When the interaction store's inputModeAtom changes, this hook\n * pushes/removes the corresponding MappingContext from the gesture system.\n *\n * This follows Design Decision 5: context sync belongs in hooks.\n */\n\nimport { useEffect } from 'react';\nimport { useAtomValue } from 'jotai';\nimport { inputModeAtom } from '../core/interaction-store';\nimport { INPUT_MODE_CONTEXTS } from './contexts';\nconst INPUT_MODE_CONTEXT_PREFIX = 'input-mode:';\n\n/**\n * Sync the current input mode to a gesture mapping context.\n * Call this once at the Canvas level, passing the gesture system API.\n */\nexport function useInputModeGestureContext(inputSystem) {\n const $ = _c(4);\n const inputMode = useAtomValue(inputModeAtom);\n let t0;\n let t1;\n if ($[0] !== inputMode.type || $[1] !== inputSystem) {\n t0 = () => {\n const modeType = inputMode.type;\n const ctx = INPUT_MODE_CONTEXTS[modeType] ?? null;\n if (ctx) {\n inputSystem.pushContext(ctx);\n } else {\n for (const key of Object.keys(INPUT_MODE_CONTEXTS)) {\n const existing = INPUT_MODE_CONTEXTS[key];\n if (existing) {\n inputSystem.removeContext(existing.id);\n }\n }\n }\n return () => {\n if (ctx) {\n inputSystem.removeContext(ctx.id);\n }\n };\n };\n t1 = [inputMode.type, inputSystem];\n $[0] = inputMode.type;\n $[1] = inputSystem;\n $[2] = t0;\n $[3] = t1;\n } else {\n t0 = $[2];\n t1 = $[3];\n }\n useEffect(t0, t1);\n}","import { c as _c } from \"react/compiler-runtime\";\n/**\n * useRegisterInputActions — Action registration hook\n *\n * Registers all built-in input actions (selection, clipboard, navigation,\n * commands, etc.) into the gesture dispatcher. Business logic lives in\n * ./input-action-helpers.ts for testability.\n */\n\nimport { useEffect } from 'react';\nimport { useStore } from 'jotai';\nimport { copyToClipboardAtom, duplicateSelectionAtom, fitToBoundsAtom, lockedNodeIdAtom, lockNodeAtom, mergeNodesAtom, pasteFromClipboardAtom, selectEdgeAtom, selectSingleNodeAtom, setFocusedNodeAtom, toggleNodeInSelectionAtom, unlockNodeAtom, undoAtom, redoAtom, centerOnNodeAtom, resetKeyboardInteractionModeAtom, resetInputModeAtom } from '../core';\nimport { openCommandLineAtom } from '../commands/store';\nimport { nextSearchResultAtom, prevSearchResultAtom } from '../core/search-store';\nimport { registerAction, unregisterAction } from './dispatcher';\nimport { isRepeatBlocked, getSelectedNodeIds, clearSelectionState, updateKeySubject, navigateFocus, cycleFocus, activateFocusedNode, nudgeSelection, deleteSelection, cutSelection, cancelActiveInteraction, escapeInput, resolvePickNode, finishPickNodes, resolvePickPoint, selectAll } from './input-action-helpers';\nfunction register(actionId, handler) {\n registerAction(actionId, handler);\n return () => unregisterAction(actionId);\n}\nexport function useRegisterInputActions() {\n const $ = _c(3);\n const store = useStore();\n let t0;\n let t1;\n if ($[0] !== store) {\n t0 = () => {\n const unregister = [register(\"select-node\", event => {\n updateKeySubject(event, store);\n if (event.subject?.kind !== \"node\") {\n return;\n }\n store.set(setFocusedNodeAtom, event.subject.nodeId);\n if (event.kind === \"key\") {\n store.set(selectSingleNodeAtom, event.subject.nodeId);\n }\n }), register(\"select-edge\", event_0 => {\n updateKeySubject(event_0, store);\n if (event_0.subject?.kind !== \"edge\") {\n return;\n }\n store.set(selectEdgeAtom, event_0.subject.edgeId);\n }), register(\"toggle-selection\", event_1 => {\n updateKeySubject(event_1, store);\n if (event_1.subject?.kind !== \"node\") {\n return;\n }\n store.set(setFocusedNodeAtom, event_1.subject.nodeId);\n if (event_1.kind === \"key\") {\n store.set(toggleNodeInSelectionAtom, event_1.subject.nodeId);\n }\n }), register(\"clear-selection\", () => {\n clearSelectionState(store);\n }), register(\"select-all\", event_2 => {\n if (isRepeatBlocked(event_2)) {\n return;\n }\n selectAll(store);\n }), register(\"fit-to-view\", event_3 => {\n updateKeySubject(event_3, store);\n if (event_3.subject?.kind === \"node\") {\n store.set(centerOnNodeAtom, event_3.subject.nodeId);\n }\n }), register(\"fit-all-to-view\", () => {\n store.set(fitToBoundsAtom, {\n mode: \"graph\"\n });\n }), register(\"toggle-lock\", event_4 => {\n updateKeySubject(event_4, store);\n if (event_4.subject?.kind !== \"node\") {\n return;\n }\n if (store.get(lockedNodeIdAtom) === event_4.subject.nodeId) {\n store.set(unlockNodeAtom);\n } else {\n store.set(lockNodeAtom, {\n nodeId: event_4.subject.nodeId\n });\n }\n }), register(\"open-command-line\", event_5 => {\n if (isRepeatBlocked(event_5)) {\n return;\n }\n store.set(openCommandLineAtom);\n }), register(\"open-search\", event_6 => {\n if (isRepeatBlocked(event_6)) {\n return;\n }\n store.set(openCommandLineAtom);\n }), register(\"search-next-result\", () => {\n store.set(nextSearchResultAtom);\n }), register(\"search-prev-result\", () => {\n store.set(prevSearchResultAtom);\n }), register(\"copy-selection\", event_7 => {\n if (isRepeatBlocked(event_7)) {\n return;\n }\n const selectedNodeIds = getSelectedNodeIds(store);\n if (selectedNodeIds.length > 0) {\n store.set(copyToClipboardAtom, selectedNodeIds);\n }\n }), register(\"cut-selection\", event_8 => {\n if (isRepeatBlocked(event_8)) {\n return;\n }\n cutSelection(store);\n }), register(\"paste-selection\", event_9 => {\n if (isRepeatBlocked(event_9)) {\n return;\n }\n store.set(pasteFromClipboardAtom);\n }), register(\"duplicate-selection\", event_10 => {\n if (isRepeatBlocked(event_10)) {\n return;\n }\n store.set(duplicateSelectionAtom);\n }), register(\"merge-selection\", event_11 => {\n if (isRepeatBlocked(event_11)) {\n return;\n }\n const nodeIds = getSelectedNodeIds(store);\n if (nodeIds.length >= 2) {\n store.set(mergeNodesAtom, {\n nodeIds\n });\n }\n }), register(\"delete-selection\", event_12 => {\n if (isRepeatBlocked(event_12)) {\n return;\n }\n deleteSelection(store);\n }), register(\"undo\", event_13 => {\n if (isRepeatBlocked(event_13)) {\n return;\n }\n store.set(undoAtom);\n }), register(\"redo\", event_14 => {\n if (isRepeatBlocked(event_14)) {\n return;\n }\n store.set(redoAtom);\n }), register(\"cancel-active-input\", () => {\n cancelActiveInteraction(store);\n }), register(\"escape-input\", () => {\n escapeInput(store);\n }), register(\"navigate-focus-up\", () => {\n navigateFocus(store, \"up\");\n }), register(\"navigate-focus-down\", () => {\n navigateFocus(store, \"down\");\n }), register(\"navigate-focus-left\", () => {\n navigateFocus(store, \"left\");\n }), register(\"navigate-focus-right\", () => {\n navigateFocus(store, \"right\");\n }), register(\"cycle-focus-forward\", event_15 => {\n if (isRepeatBlocked(event_15)) {\n return;\n }\n cycleFocus(store, 1);\n }), register(\"cycle-focus-backward\", event_16 => {\n if (isRepeatBlocked(event_16)) {\n return;\n }\n cycleFocus(store, -1);\n }), register(\"activate-focused-node\", event_17 => {\n if (isRepeatBlocked(event_17)) {\n return;\n }\n activateFocusedNode(store, false);\n }), register(\"enter-keyboard-manipulate-mode\", event_18 => {\n if (isRepeatBlocked(event_18)) {\n return;\n }\n activateFocusedNode(store, true);\n }), register(\"exit-keyboard-manipulate-mode\", () => {\n store.set(resetKeyboardInteractionModeAtom);\n }), register(\"nudge-selection-up\", () => {\n nudgeSelection(store, 0, -10, \"Nudge selection\");\n }), register(\"nudge-selection-down\", () => {\n nudgeSelection(store, 0, 10, \"Nudge selection\");\n }), register(\"nudge-selection-left\", () => {\n nudgeSelection(store, -10, 0, \"Nudge selection\");\n }), register(\"nudge-selection-right\", () => {\n nudgeSelection(store, 10, 0, \"Nudge selection\");\n }), register(\"nudge-selection-up-large\", () => {\n nudgeSelection(store, 0, -50, \"Nudge selection\");\n }), register(\"nudge-selection-down-large\", () => {\n nudgeSelection(store, 0, 50, \"Nudge selection\");\n }), register(\"nudge-selection-left-large\", () => {\n nudgeSelection(store, -50, 0, \"Nudge selection\");\n }), register(\"nudge-selection-right-large\", () => {\n nudgeSelection(store, 50, 0, \"Nudge selection\");\n }), register(\"resolve-pick-node\", event_19 => {\n resolvePickNode(event_19, store);\n }), register(\"finish-pick-nodes\", () => {\n finishPickNodes(store);\n }), register(\"resolve-pick-point\", event_20 => {\n resolvePickPoint(event_20, store);\n }), register(\"cancel-pick\", () => {\n store.set(resetInputModeAtom);\n })];\n return () => {\n for (const cleanup of unregister) {\n cleanup();\n }\n };\n };\n t1 = [store];\n $[0] = store;\n $[1] = t0;\n $[2] = t1;\n } else {\n t0 = $[1];\n t1 = $[2];\n }\n useEffect(t0, t1);\n}","/**\n * InputProvider — React context for the shared input system\n *\n * Holds the shared mapping index, action callback, and the single\n * keyboard listener for the active canvas instance.\n */\n\nimport React, { createContext, useContext, useEffect, useRef, useState } from 'react';\nimport { useStore } from 'jotai';\nimport { dispatch } from './dispatcher';\nimport { resolve } from './mapper';\nimport { useInputModeGestureContext } from './useInputModeGestureContext';\nimport { useRegisterInputActions } from './useRegisterInputActions';\nimport { useInputSystem } from './useGestureSystem';\nimport { isEditableTarget, applyHeldKeyDelta, getCurrentSubject, getSubjectPosition, buildGuardContext } from './gesture-provider-utils';\n\n// Re-export utilities for consumers\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport { isEditableTarget, setHeldKeyValue, applyHeldKeyDelta, getCurrentSubject, getSubjectPosition, buildGuardContext } from './gesture-provider-utils';\n// Singleton: keyboard focus routing uses \"last focused wins\" across all\n// InputProvider instances in the page. This is intentional — only one\n// canvas should handle keyboard events at a time.\nlet nextOwnerId = 1;\nlet activeOwnerId = null;\nconst InputContext = /*#__PURE__*/createContext(null);\n// Pure utility functions moved to gesture-provider-utils.ts in v1.8.0\n\nexport function InputProvider({\n children,\n gestureConfig,\n onAction\n}) {\n const store = useStore();\n const system = useInputSystem({\n contexts: gestureConfig?.contexts,\n palmRejection: gestureConfig?.palmRejection ?? true\n });\n useInputModeGestureContext(system);\n useRegisterInputActions();\n const [ownerId] = useState(() => nextOwnerId++);\n const [canvasRoot, setCanvasRoot] = useState(null);\n const rootRef = useRef(null);\n const systemRef = useRef(system);\n systemRef.current = system;\n const registerCanvasRoot = node => {\n rootRef.current = node;\n setCanvasRoot(node);\n };\n useEffect(() => {\n const root = canvasRoot;\n if (!root) {\n return;\n }\n const activate = event => {\n activeOwnerId = ownerId;\n if (!isEditableTarget(event.target)) {\n root.focus({\n preventScroll: true\n });\n }\n };\n root.addEventListener('pointerdown', activate, true);\n root.addEventListener('focusin', activate, true);\n return () => {\n root.removeEventListener('pointerdown', activate, true);\n root.removeEventListener('focusin', activate, true);\n if (activeOwnerId === ownerId) {\n activeOwnerId = null;\n }\n };\n }, [canvasRoot, ownerId]);\n useEffect(() => {\n const handleKeyboard = nativeEvent => {\n if (activeOwnerId !== ownerId) {\n return;\n }\n const root_0 = rootRef.current;\n if (!root_0 || !root_0.isConnected) {\n return;\n }\n const currentSystem = systemRef.current;\n const editableTarget = isEditableTarget(nativeEvent.target);\n const shouldTrackHeldKey = nativeEvent.type === 'keyup' || !nativeEvent.isComposing && !editableTarget;\n const nextHeldKeys = shouldTrackHeldKey ? applyHeldKeyDelta(nativeEvent, currentSystem.heldKeys) : currentSystem.heldKeys;\n if (nextHeldKeys !== currentSystem.heldKeys) {\n currentSystem.setHeldKeys(nextHeldKeys);\n }\n if (nativeEvent.isComposing || editableTarget) {\n return;\n }\n const subject = getCurrentSubject(store);\n const {\n screenPosition,\n worldPosition\n } = getSubjectPosition(store, root_0, subject);\n const inputEvent = {\n kind: 'key',\n phase: nativeEvent.type === 'keydown' ? 'down' : 'up',\n key: nativeEvent.key,\n code: nativeEvent.code,\n repeat: nativeEvent.repeat,\n modifiers: {\n shift: nativeEvent.shiftKey,\n ctrl: nativeEvent.ctrlKey,\n alt: nativeEvent.altKey,\n meta: nativeEvent.metaKey\n },\n heldKeys: nextHeldKeys,\n subject,\n screenPosition,\n worldPosition,\n originalEvent: nativeEvent\n };\n const resolution = resolve(inputEvent, currentSystem.mappingIndex, buildGuardContext(store, {\n heldKeys: nextHeldKeys\n }));\n if (!resolution) {\n return;\n }\n nativeEvent.preventDefault();\n dispatch(inputEvent, resolution);\n onAction?.(inputEvent, resolution);\n };\n const clearHeldKeys = () => {\n systemRef.current.clearHeldKeys();\n };\n window.addEventListener('keydown', handleKeyboard, true);\n window.addEventListener('keyup', handleKeyboard, true);\n window.addEventListener('blur', clearHeldKeys);\n document.addEventListener('visibilitychange', clearHeldKeys);\n return () => {\n window.removeEventListener('keydown', handleKeyboard, true);\n window.removeEventListener('keyup', handleKeyboard, true);\n window.removeEventListener('blur', clearHeldKeys);\n document.removeEventListener('visibilitychange', clearHeldKeys);\n };\n }, [onAction, ownerId, store]);\n return /*#__PURE__*/_jsx(InputContext.Provider, {\n value: {\n system,\n onAction,\n registerCanvasRoot\n },\n children: children\n });\n}\nexport function useInputContext() {\n const ctx = useContext(InputContext);\n if (!ctx) {\n throw new Error(\"useInputContext must be used within an InputProvider\");\n }\n return ctx;\n}\nexport const GestureProvider = InputProvider;\nexport const useGestureContext = useInputContext;","/**\n * GestureProvider Utilities\n *\n * Pure functions extracted from GestureProvider.tsx for testability.\n * No React dependencies — all functions operate on plain objects or DOM elements.\n *\n * @since 1.8.0\n */\n\nimport { draggingNodeIdAtom, edgeCreationAtom, fingerCountAtom, focusedNodeIdAtom, inputModeAtom, isStylusActiveAtom, keyboardInteractionModeAtom, screenToWorldAtom, selectedNodeIdsAtom, uiNodesAtom, worldToScreenAtom } from '../core';\nimport { isFilterActiveAtom } from '../core/search-store';\nimport { selectionPathAtom } from '../core/selection-path-store';\nimport { commandLineVisibleAtom } from '../commands/store';\n\n// =============================================================================\n// Editable Target Detection\n// =============================================================================\n\n/**\n * Check whether a DOM target is an editable element (input, textarea,\n * contenteditable, or marked with data-no-canvas-keyboard).\n */\nexport function isEditableTarget(target) {\n if (!(target instanceof HTMLElement)) {\n return false;\n }\n if (target.isContentEditable) {\n return true;\n }\n const editable = target.closest('input, textarea, [contenteditable=\"true\"], [data-no-canvas-keyboard=\"true\"]');\n return editable !== null;\n}\n\n// =============================================================================\n// Held Keys State Management\n// =============================================================================\n\n/**\n * Immutably set a single key's held state. Returns the same object\n * reference if nothing changed (for React bailout).\n */\nexport function setHeldKeyValue(current, key, isHeld) {\n const previous = current[key] ?? false;\n if (previous === isHeld) {\n return current;\n }\n const next = {\n ...current\n };\n if (isHeld) {\n next[key] = true;\n } else {\n delete next[key];\n }\n return next;\n}\n\n/**\n * Apply a keyboard event to the held-keys state.\n * Returns same reference if nothing changed.\n */\nexport function applyHeldKeyDelta(event, current) {\n const isHeld = event.type === 'keydown';\n const nextByKey = setHeldKeyValue(current.byKey, event.key, isHeld);\n const nextByCode = setHeldKeyValue(current.byCode, event.code, isHeld);\n if (nextByKey === current.byKey && nextByCode === current.byCode) {\n return current;\n }\n return {\n byKey: nextByKey,\n byCode: nextByCode\n };\n}\n\n// =============================================================================\n// Subject Resolution\n// =============================================================================\n\n/**\n * Determine the current gesture subject from store state.\n */\nexport function getCurrentSubject(store) {\n const draggingNodeId = store.get(draggingNodeIdAtom);\n if (draggingNodeId) {\n return {\n kind: 'node',\n nodeId: draggingNodeId\n };\n }\n const edgeCreation = store.get(edgeCreationAtom);\n if (edgeCreation.isCreating && edgeCreation.sourceNodeId) {\n return {\n kind: 'node',\n nodeId: edgeCreation.sourceNodeId\n };\n }\n const focusedNodeId = store.get(focusedNodeIdAtom);\n if (focusedNodeId) {\n return {\n kind: 'node',\n nodeId: focusedNodeId\n };\n }\n return {\n kind: 'background'\n };\n}\n\n/**\n * Get screen and world positions for a gesture subject.\n */\nexport function getSubjectPosition(store, root, subject) {\n const worldToScreen = store.get(worldToScreenAtom);\n if (subject.kind === 'node') {\n const node = store.get(uiNodesAtom).find(entry => entry.id === subject.nodeId);\n if (!node) {\n return {};\n }\n const worldPosition = {\n x: node.position.x + (node.width ?? 200) / 2,\n y: node.position.y + (node.height ?? 100) / 2\n };\n return {\n worldPosition,\n screenPosition: worldToScreen(worldPosition.x, worldPosition.y)\n };\n }\n if (subject.kind === 'background' && root) {\n const rect = root.getBoundingClientRect();\n const screenPosition = {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2\n };\n return {\n screenPosition,\n worldPosition: store.get(screenToWorldAtom)(screenPosition.x, screenPosition.y)\n };\n }\n return {};\n}\n\n// =============================================================================\n// Guard Context\n// =============================================================================\n\n/**\n * Build the guard context object used for gesture resolution.\n */\nexport function buildGuardContext(store, system) {\n const heldKeys = 'heldKeys' in system ? system.heldKeys : system;\n const edgeCreation = store.get(edgeCreationAtom);\n return {\n isStylusActive: store.get(isStylusActiveAtom),\n fingerCount: store.get(fingerCountAtom),\n isDragging: store.get(draggingNodeIdAtom) !== null,\n isResizing: false,\n isSplitting: false,\n inputMode: store.get(inputModeAtom),\n keyboardInteractionMode: store.get(keyboardInteractionModeAtom),\n selectedNodeIds: store.get(selectedNodeIdsAtom),\n focusedNodeId: store.get(focusedNodeIdAtom),\n isSearchActive: store.get(isFilterActiveAtom),\n commandLineVisible: store.get(commandLineVisibleAtom),\n heldKeys,\n custom: {\n isSelecting: store.get(selectionPathAtom) !== null,\n isCreatingEdge: edgeCreation.isCreating\n }\n };\n}"],"mappings":";;;;;AAWO,IAAM,eAAe,OAAO,OAAO;AAAA,EACxC,OAAO;AAAA,EACP,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AACR,CAAC;AACM,IAAM,eAAe,OAAO,OAAO;AAAA,EACxC,OAAO,OAAO,OAAO,CAAC,CAAC;AAAA,EACvB,QAAQ,OAAO,OAAO,CAAC,CAAC;AAC1B,CAAC;AAuBM,SAAS,gBAAgB,OAAO;AACrC,SAAO,MAAM,SAAS;AACxB;AACO,SAAS,sBAAsB,OAAO;AAC3C,SAAO,MAAM,SAAS;AACxB;;;ACZO,SAAS,gBAAgB,GAAG;AACjC,QAAM,SAAS,oBAAoB,EAAE,WAAW;AAChD,SAAO;AAAA,IACL;AAAA,IACA,WAAW,EAAE;AAAA,IACb,UAAU,EAAE;AAAA,IACZ,OAAO,EAAE;AAAA,IACT,OAAO,EAAE;AAAA,IACT,WAAW,EAAE;AAAA,IACb,gBAAgB,EAAE;AAAA,EACpB;AACF;AAKA,SAAS,oBAAoB,aAAa;AACxC,UAAQ,aAAa;AAAA,IACnB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AAEE,aAAO;AAAA,EACX;AACF;AAaO,SAAS,0BAA0B;AACxC,MAAI,OAAO,WAAW,aAAa;AAEjC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,MACX,UAAU;AAAA,MACV,kBAAkB;AAAA,IACpB;AAAA,EACF;AACA,QAAM,WAAW,kBAAkB,UAAU,UAAU,iBAAiB;AAGxE,QAAM,qBAAqB,OAAO,OAAO,eAAe;AACxD,QAAM,mBAAmB,qBAAqB,OAAO,WAAW,mBAAmB,EAAE,UAAU;AAC/F,QAAM,iBAAiB,qBAAqB,OAAO,WAAW,iBAAiB,EAAE,UAAU;AAI3F,QAAM,WAAW,kBAAkB,CAAC;AACpC,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA;AAAA,IAEX;AAAA,IACA;AAAA,EACF;AACF;;;AC3FO,SAAS,iBAAiB,GAAG;AAClC,MAAI,CAAC,EAAE,YAAY,CAAC,EAAE,WAAW,CAAC,EAAE,UAAU,CAAC,EAAE,SAAS;AACxD,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,OAAO,EAAE;AAAA,IACT,MAAM,EAAE;AAAA,IACR,KAAK,EAAE;AAAA,IACP,MAAM,EAAE;AAAA,EACV;AACF;AAKA,SAAS,YAAY,KAAK;AACxB,MAAI,QAAQ,EAAG,QAAO;AACtB,MAAI,QAAQ,EAAG,QAAO;AACtB,SAAO;AACT;AAKA,SAAS,uBAAuB,MAAM;AACpC,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAKO,SAAS,iBAAiB,GAAG;AAClC,QAAM,aAAa,gBAAgB,CAAC;AACpC,SAAO;AAAA,IACL,WAAW,EAAE;AAAA,IACb,WAAW,uBAAuB,EAAE,IAAI;AAAA,IACxC,QAAQ,WAAW;AAAA,IACnB,QAAQ,YAAY,EAAE,MAAM;AAAA,IAC5B,WAAW,iBAAiB,CAAC;AAAA,IAC7B,SAAS,EAAE;AAAA,IACX,SAAS,EAAE;AAAA,IACX,UAAU,EAAE;AAAA,IACZ,WAAW,EAAE;AAAA,EACf;AACF;;;AC/CO,IAAM,mBAAmB;AACzB,IAAM,eAAe;AAGrB,IAAM,wBAAwB;AAC9B,IAAM,8BAA8B;AACpC,IAAM,OAAO;AAAA,EAClB,KAAK;AAAA,EACL,UAAU;AACZ;AACA,IAAM,iBAAiB;AAAA,EACrB,aAAa;AAAA,EACb,kBAAkB;AACpB;AAMO,SAAS,WAAW,OAAO,OAAO,SAAS,gBAAgB;AAChE,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,OAAO,OAAO,MAAM;AAAA,IAC7B,KAAK;AACH,aAAO,KAAK,OAAO,MAAM;AAAA,IAC3B,KAAK;AACH,aAAO,aAAa,KAAK;AAAA,IAC3B,KAAK;AACH,aAAO,SAAS;AAAA,IAClB,KAAK;AACH,aAAO,iBAAiB,KAAK;AAAA,IAC/B,KAAK;AACH,aAAO,cAAc;AAAA,IACvB;AACE,aAAO;AAAA,QACL;AAAA,MACF;AAAA,EACJ;AACF;AACA,SAAS,OAAO,OAAO,QAAQ;AAC7B,UAAQ,MAAM,KAAK;AAAA,IACjB,KAAK;AACH,aAAO;AAAA,QACL,OAAO;AAAA,UACL,KAAK;AAAA,UACL,UAAU;AAAA,QACZ;AAAA,QACA,aAAa;AAAA,QACb,eAAe;AAAA,UACb,IAAI;AAAA,UACJ,SAAS,OAAO;AAAA,QAClB;AAAA,MACF;AAAA,IACF,KAAK;AAEH,aAAO;AAAA,QACL,OAAO;AAAA,UACL,KAAK;AAAA,UACL,UAAU,MAAM;AAAA,QAClB;AAAA,QACA,aAAa;AAAA,QACb,eAAe;AAAA,UACb,IAAI;AAAA,UACJ,SAAS,OAAO;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AACE,aAAO;AAAA,QACL;AAAA,MACF;AAAA,EACJ;AACF;AACA,SAAS,KAAK,OAAO,QAAQ;AAC3B,MAAI,MAAM,QAAQ,WAAW;AAE3B,QAAI,MAAM,QAAQ,gBAAgB;AAChC,aAAO;AAAA,QACL,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACA,QAAM,WAAW,MAAM,WAAW;AAClC,QAAM,OAAO,gBAAgB,QAAQ;AACrC,SAAO;AAAA,IACL,OAAO;AAAA,MACL,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,eAAe;AAAA,MACb,IAAI;AAAA,MACJ,SAAS,OAAO;AAAA,IAClB;AAAA,EACF;AACF;AACA,SAAS,aAAa,OAAO;AAC3B,MAAI,MAAM,QAAQ,WAAW;AAC3B,WAAO;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,EACF;AACF;AACA,SAAS,WAAW;AAClB,SAAO;AAAA,IACL,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AACF;AACA,SAAS,iBAAiB,OAAO;AAC/B,MAAI,MAAM,QAAQ,WAAW;AAC3B,WAAO;AAAA,MACL,OAAO;AAAA,QACL,KAAK;AAAA,QACL,UAAU;AAAA,MACZ;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,EACF;AACF;AACA,SAAS,gBAAgB;AACvB,SAAO;AAAA,IACL,OAAO;AAAA,EACT;AACF;AACA,SAAS,gBAAgB,OAAO;AAC9B,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;;;ACzJO,IAAM,mBAAN,MAAuB;AAAA,EAK5B,YAAY,QAAQ;AAJpB,iCAAQ;AACR,kCAAS,oBAAI,IAAI;AAEjB;AAAA,kCAAS;AAEP,SAAK,SAAS;AAAA,MACZ,aAAa,QAAQ,eAAe;AAAA,MACpC,kBAAkB,QAAQ,oBAAoB;AAAA,IAChD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,OAAO;AACV,WAAO,KAAK,MAAM,KAAK;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,MAAM;AACR,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA,EAGA,UAAU;AACR,eAAW,SAAS,KAAK,OAAO,OAAO,GAAG;AACxC,mBAAa,KAAK;AAAA,IACpB;AACA,SAAK,OAAO,MAAM;AAClB,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EAChB;AAAA,EACA,MAAM,OAAO;AACX,UAAM,SAAS,WAAW,KAAK,OAAO,OAAO,KAAK,MAAM;AACxD,SAAK,QAAQ,OAAO;AACpB,QAAI,OAAO,aAAa;AACtB,YAAM,QAAQ,KAAK,OAAO,IAAI,OAAO,WAAW;AAChD,UAAI,UAAU,QAAW;AACvB,qBAAa,KAAK;AAClB,aAAK,OAAO,OAAO,OAAO,WAAW;AAAA,MACvC;AAAA,IACF;AACA,QAAI,OAAO,eAAe;AACxB,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF,IAAI,OAAO;AAEX,YAAM,WAAW,KAAK,OAAO,IAAI,EAAE;AACnC,UAAI,aAAa,QAAW;AAC1B,qBAAa,QAAQ;AAAA,MACvB;AACA,WAAK,OAAO,IAAI,IAAI,WAAW,MAAM;AACnC,aAAK,OAAO,OAAO,EAAE;AACrB,cAAM,aAAa,SAAS,EAAE;AAC9B,cAAM,cAAc,WAAW,KAAK,OAAO,YAAY,KAAK,MAAM;AAClE,aAAK,QAAQ,YAAY;AACzB,YAAI,YAAY,MAAM;AACpB,eAAK,SAAS,YAAY,IAAI;AAAA,QAChC;AAAA,MACF,GAAG,OAAO,CAAC;AAAA,IACb;AACA,WAAO,OAAO;AAAA,EAChB;AACF;;;AC9DA,IAAM,aAAa;AACnB,IAAM,YAAY;AAClB,IAAM,aAAa;AACnB,IAAM,gBAAgB;AACtB,IAAM,0BAA0B;AAChC,IAAM,0BAA0B;AAChC,IAAM,0BAA0B;AAChC,IAAM,0BAA0B;AAChC,IAAM,eAAe;AACrB,IAAM,eAAe;AAMd,SAAS,YAAY,SAAS,OAAO;AAC1C,MAAI,QAAQ;AAGZ,MAAI,QAAQ,SAAS,QAAW;AAC9B,UAAM,aAAa,gBAAgB,KAAK,IAAI,QAAQ;AACpD,QAAI,QAAQ,SAAS,WAAY,QAAO;AAAA,EAC1C;AAGA,MAAI,QAAQ,SAAS,QAAW;AAC9B,QAAI,CAAC,sBAAsB,KAAK,KAAK,QAAQ,SAAS,MAAM,KAAM,QAAO;AACzE,aAAS;AAAA,EACX;AAGA,MAAI,QAAQ,gBAAgB,QAAW;AACrC,QAAI,MAAM,YAAY,UAAa,QAAQ,gBAAgB,MAAM,QAAQ,KAAM,QAAO;AACtF,aAAS;AAAA,EACX;AAGA,MAAI,QAAQ,UAAU,UAAa,QAAQ,UAAU,MAAM,OAAO;AAChE,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,WAAW,QAAW;AAChC,QAAI,CAAC,sBAAsB,KAAK,EAAG,QAAO;AAC1C,QAAI,QAAQ,WAAW,MAAM,OAAQ,QAAO;AAC5C,aAAS;AAAA,EACX;AAGA,MAAI,QAAQ,WAAW,QAAW;AAChC,QAAI,CAAC,sBAAsB,KAAK,EAAG,QAAO;AAC1C,QAAI,QAAQ,WAAW,MAAM,OAAQ,QAAO;AAC5C,aAAS;AAAA,EACX;AAGA,MAAI,QAAQ,QAAQ,QAAW;AAC7B,QAAI,CAAC,gBAAgB,KAAK,KAAK,QAAQ,QAAQ,MAAM,IAAK,QAAO;AACjE,aAAS;AAAA,EACX;AACA,MAAI,QAAQ,SAAS,QAAW;AAC9B,QAAI,CAAC,gBAAgB,KAAK,KAAK,QAAQ,SAAS,MAAM,KAAM,QAAO;AACnE,aAAS;AAAA,EACX;AAGA,MAAI,QAAQ,cAAc,QAAW;AACnC,UAAM,KAAK,cAAc,QAAQ,WAAW,MAAM,SAAS;AAC3D,QAAI,OAAO,GAAI,QAAO;AACtB,aAAS;AAAA,EACX;AAGA,MAAI,QAAQ,aAAa,QAAW;AAClC,UAAM,KAAK,aAAa,QAAQ,UAAU,MAAM,QAAQ;AACxD,QAAI,OAAO,GAAI,QAAO;AACtB,aAAS;AAAA,EACX;AACA,SAAO;AACT;AAQA,SAAS,cAAc,SAAS,QAAQ;AACtC,MAAI,QAAQ;AACZ,QAAM,OAAO,CAAC,SAAS,QAAQ,OAAO,MAAM;AAC5C,aAAW,OAAO,MAAM;AACtB,UAAM,WAAW,QAAQ,GAAG;AAC5B,QAAI,aAAa,OAAW;AAC5B,QAAI,aAAa,OAAO,GAAG,EAAG,QAAO;AACrC,aAAS,WAAW,0BAA0B;AAAA,EAChD;AACA,MAAI,QAAQ,QAAQ;AAClB,UAAM,eAAe,OAAO,UAAU,CAAC;AACvC,eAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,QAAQ,MAAM,GAAG;AAC5D,YAAM,YAAY,aAAa,GAAG,KAAK;AACvC,UAAI,aAAa,UAAW,QAAO;AACnC,eAAS,WAAW,0BAA0B;AAAA,IAChD;AAAA,EACF;AACA,SAAO;AACT;AACA,SAAS,aAAa,SAAS,QAAQ;AACrC,MAAI,QAAQ;AACZ,aAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,QAAQ,SAAS,CAAC,CAAC,GAAG;AACjE,UAAM,YAAY,OAAO,MAAM,GAAG,KAAK;AACvC,QAAI,aAAa,UAAW,QAAO;AACnC,aAAS,WAAW,0BAA0B;AAAA,EAChD;AACA,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,QAAQ,UAAU,CAAC,CAAC,GAAG;AACnE,UAAM,YAAY,OAAO,OAAO,IAAI,KAAK;AACzC,QAAI,aAAa,UAAW,QAAO;AACnC,aAAS,WAAW,0BAA0B;AAAA,EAChD;AACA,SAAO;AACT;;;ACvHA,IAAM,WAAW;AACjB,SAAS,oBAAoB,SAAS;AACpC,QAAM;AAAA,IACJ;AAAA,EACF,IAAI;AACJ,MAAI,QAAQ,SAAS,QAAW;AAC9B,WAAO,WAAW,QAAQ,IAAI;AAAA,EAChC;AACA,MAAI,QAAQ,SAAS,SAAS,QAAQ,QAAQ,UAAa,QAAQ,SAAS,QAAW;AACrF,WAAO,QAAQ,UAAU,UAAU,QAAQ,UAAU,OAAO,OAAO,QAAQ,KAAK,KAAK;AAAA,EACvF;AACA,SAAO;AACT;AACA,SAAS,kBAAkB,OAAO;AAChC,SAAO,gBAAgB,KAAK,IAAI,OAAO,MAAM,KAAK,KAAK,WAAW,MAAM,IAAI;AAC9E;AAMO,SAAS,aAAa,KAAK;AAChC,QAAM,QAAQ,oBAAI,IAAI;AACtB,QAAM,YAAY,CAAC;AACnB,aAAW,WAAW,IAAI,UAAU;AAClC,UAAM,MAAM,oBAAoB,OAAO;AACvC,QAAI,QAAQ,MAAM;AAChB,gBAAU,KAAK,OAAO;AAAA,IACxB,OAAO;AACL,UAAI,SAAS,MAAM,IAAI,GAAG;AAC1B,UAAI,CAAC,QAAQ;AACX,iBAAS,CAAC;AACV,cAAM,IAAI,KAAK,MAAM;AAAA,MACvB;AACA,aAAO,KAAK,OAAO;AAAA,IACrB;AAAA,EACF;AACA,QAAM,UAAU,oBAAI,IAAI;AACxB,aAAW,CAAC,KAAK,MAAM,KAAK,OAAO;AACjC,YAAQ,IAAI,KAAK,MAAM;AAAA,EACzB;AACA,MAAI,UAAU,SAAS,GAAG;AACxB,YAAQ,IAAI,UAAU,SAAS;AAAA,EACjC;AACA,SAAO;AAAA,IACL,WAAW,IAAI;AAAA,IACf,UAAU,IAAI;AAAA,IACd,SAAS,IAAI;AAAA,IACb;AAAA,EACF;AACF;AAYO,SAAS,kBAAkB,UAAU;AAC1C,SAAO,SAAS,IAAI,YAAY,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAC1E;AAmBO,SAAS,QAAQ,OAAO,OAAO,OAAO;AAC3C,MAAI,SAAS;AACb,aAAW,OAAO,OAAO;AACvB,QAAI,CAAC,IAAI,QAAS;AAClB,UAAM,SAAS,IAAI,QAAQ,IAAI,kBAAkB,KAAK,CAAC;AACvD,UAAM,iBAAiB,IAAI,QAAQ,IAAI,QAAQ;AAC/C,QAAI,CAAC,UAAU,CAAC,eAAgB;AAChC,QAAI,YAAY;AAChB,QAAI,cAAc;AAClB,eAAW,WAAW,CAAC,GAAI,UAAU,CAAC,GAAI,GAAI,kBAAkB,CAAC,CAAE,GAAG;AACpE,YAAM,QAAQ,YAAY,QAAQ,SAAS,KAAK;AAChD,UAAI,UAAU,GAAI;AAClB,UAAI,QAAQ,QAAQ,CAAC,QAAQ,KAAK,KAAK,EAAG;AAC1C,UAAI,QAAQ,WAAW;AACrB,oBAAY;AACZ,sBAAc;AAAA,MAChB;AAAA,IACF;AACA,QAAI,gBAAgB,MAAM;AACxB,YAAM,SAAS;AAAA,QACb,UAAU,YAAY;AAAA,QACtB,SAAS;AAAA,QACT,WAAW,IAAI;AAAA,QACf,OAAO;AAAA,QACP,UAAU,YAAY,iBAAiB;AAAA,MACzC;AACA,UAAI,OAAO,UAAU;AACnB,eAAO;AAAA,MACT;AAGA,UAAI,WAAW,MAAM;AACnB,iBAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;AC9HO,IAAM,iBAAiB;AAAA,EAC5B,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,IACT,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,kBAAkB,CAAC,IAAI;AAAA,IACxC,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,kBAAkB,CAAC,IAAI;AAAA,IACxC,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,CAAC;AACH;AAMO,IAAM,8BAA8B;AAAA,EACzC,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,IACT,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,CAAC;AACH;AACO,IAAM,4BAA4B;AAAA,EACvC,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,IACT,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,4BAA4B;AAAA,IAC7C,cAAc;AAAA,EAChB,CAAC;AACH;;;AC5SO,IAAM,mBAAmB;AAAA;AAAA,EAEhC;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,QACR,QAAQ;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,IACR;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,EACZ;AAAC;;;ACvLD,IAAM,oBAAoB,SAAO,CAAC,IAAI;AAM/B,IAAM,oBAAoB;AAAA,EAAC;AAAA,IAChC,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAC;;;AC9UM,IAAM,kBAAkB;AAAA,EAC7B,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC,GAAG,kBAAkB,GAAG,iBAAiB;AACtD;AAMO,IAAM,oBAAoB;AAAA,EAC/B,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,IACT,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,CAAC;AACH;AACO,IAAM,qBAAqB;AAAA,EAChC,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,IACT,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,CAAC;AACH;AACO,IAAM,qBAAqB;AAAA,EAChC,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,IACT,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,IACR;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,EAChB,CAAC;AACH;AAMO,IAAM,sBAAsB;AAAA,EACjC,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AAAA,EACX,MAAM;AAAA,EACN,QAAQ;AACV;;;AClHO,IAAM,yBAAyB;AAAA,EACpC,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,IACT,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,GAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI;AAAA,IACjB,cAAc;AAAA,EAChB,CAAC;AACH;AAMO,IAAM,6BAA6B;AAAA,EACxC,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,IACT,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAO,IAAI,cAAc,IAAI,eAAe,QAAQ,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,OAAO,cAAc;AAAA,IACtH,cAAc;AAAA,EAChB,CAAC;AACH;;;AChFA,IAAM,WAAW,oBAAI,IAAI;AAKlB,SAAS,eAAe,UAAU,SAAS;AAChD,WAAS,IAAI,UAAU,OAAO;AAChC;AAKO,SAAS,iBAAiB,UAAU;AACzC,WAAS,OAAO,QAAQ;AAC1B;AAKO,SAAS,WAAW,UAAU;AACnC,SAAO,SAAS,IAAI,QAAQ;AAC9B;AAKO,SAAS,gBAAgB;AAC9B,WAAS,MAAM;AACjB;AAaO,SAAS,SAAS,OAAO,YAAY;AAC1C,MAAI,WAAW,aAAa,OAAQ,QAAO;AAC3C,QAAM,UAAU,SAAS,IAAI,WAAW,QAAQ;AAChD,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,OAAO,YAAY,YAAY;AAEjC,QAAI,gBAAgB,KAAK,KAAK,MAAM,UAAU,UAAU,CAAC,gBAAgB,KAAK,MAAM,MAAM,UAAU,WAAW,MAAM,UAAU,YAAY;AACzI,cAAQ,KAAK;AAAA,IACf;AACA,WAAO;AAAA,EACT;AAGA,aAAW,SAAS,MAAM,OAAO,KAAK;AACtC,SAAO;AACT;AACA,SAAS,WAAW,SAAS,OAAO,OAAO;AACzC,MAAI,gBAAgB,KAAK,GAAG;AAC1B,kBAAc,SAAS,OAAO,KAAK;AACnC;AAAA,EACF;AACA,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,cAAQ,UAAU,KAAK;AACvB;AAAA,IACF,KAAK;AACH,cAAQ,SAAS,KAAK;AACtB;AAAA,IACF,KAAK;AACH,cAAQ,QAAQ,KAAK;AACrB;AAAA,IACF,KAAK;AACH,cAAQ,YAAY,KAAK;AACzB;AAAA,IACF,KAAK;AACH,cAAQ,WAAW,KAAK;AACxB;AAAA,EACJ;AACF;AACA,SAAS,cAAc,SAAS,OAAO,OAAO;AAC5C,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,cAAQ,SAAS,KAAK;AACtB;AAAA,IACF,KAAK;AACH,cAAQ,OAAO,KAAK;AACpB;AAAA,EACJ;AACF;;;AC3FO,IAAM,eAAe;AACrB,IAAM,gBAAgB;AACtB,IAAM,eAAe;AACrB,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAU9B,IAAM,kBAAN,MAAsB;AAAA,EAE3B,YAAY,aAAa,uBAAuB;AADhD,mCAAU,CAAC;AAET,SAAK,aAAa;AAAA,EACpB;AAAA,EACA,OAAO,IAAI,IAAI,GAAG;AAChB,QAAI,KAAK,QAAQ,UAAU,KAAK,YAAY;AAC1C,WAAK,QAAQ,MAAM;AAAA,IACrB;AACA,SAAK,QAAQ,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EACA,UAAU;AACR,UAAM,IAAI,KAAK,QAAQ;AACvB,QAAI,MAAM,EAAG,QAAO;AAAA,MAClB,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AACA,QAAI,KAAK;AACT,QAAI,KAAK;AACT,eAAW,KAAK,KAAK,SAAS;AAC5B,YAAM,EAAE;AACR,YAAM,EAAE;AAAA,IACV;AACA,WAAO;AAAA,MACL,GAAG,KAAK;AAAA,MACR,GAAG,KAAK;AAAA,IACV;AAAA,EACF;AAAA,EACA,QAAQ;AACN,SAAK,QAAQ,SAAS;AAAA,EACxB;AACF;AAMO,IAAM,aAAN,MAAiB;AAAA,EACtB,YAAY,UAAU,WAAW,cAAc,cAAc,cAAc;AACzE,SAAK,WAAW;AAChB,SAAK,cAAc;AACnB,SAAK,KAAK,SAAS;AACnB,SAAK,KAAK,SAAS;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO;AACL,SAAK,MAAM,KAAK;AAChB,SAAK,MAAM,KAAK;AAChB,QAAI,KAAK,IAAI,KAAK,EAAE,IAAI,KAAK,eAAe,KAAK,IAAI,KAAK,EAAE,IAAI,KAAK,aAAa;AAChF,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,GAAG,KAAK;AAAA,MACR,GAAG,KAAK;AAAA,IACV;AAAA,EACF;AACF;AAMO,IAAM,cAAN,MAAkB;AAAA,EACvB,YAAY,UAAU,QAAQ,WAAW,eAAe,cAAc,cAAc,gBAAgB,qBAAqB;AACvH,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,cAAc;AACnB,SAAK,gBAAgB;AACrB,SAAK,IAAI;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,aAAa;AAChB,SAAK,KAAK,KAAK;AACf,QAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa;AAEvC,UAAI,KAAK,IAAI,cAAc,CAAC,IAAI,KAAK,eAAe;AAClD,cAAM,YAAY,IAAI;AACtB,eAAO,KAAK,IAAI,SAAS,IAAI,OAAQ;AAAA,UACnC,OAAO;AAAA,UACP,QAAQ,KAAK;AAAA,QACf,IAAI;AAAA,MACN;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AACF;;;ACpHA,SAAS,YAAY;AACrB,OAAO,WAAW;AAGX,IAAM,eAAe;AAAA,EAC1B,MAAM;AAAA,EACN,OAAO;AAAA,EACP,gBAAgB;AAClB;AAOO,IAAM,qBAAqB,KAAK,IAAI;AAKpC,IAAM,YAAY,KAAK,IAAI,MAAM,YAAY,CAAC;AAK9C,IAAM,yBAAyB,KAAK,CAAC;AAIrC,IAAM,mBAAmB,KAAK;AAAA,EACnC,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,uBAAuB;AACzB,CAAC;AAIM,IAAM,qBAAqB,KAAK,IAAI;AACpC,IAAM,4BAA4B,KAAK,IAAI;;;ACjDlD,SAAS,QAAAA,aAAY;AACrB,SAAS,kBAAkB;AAC3B,OAAOC,YAAW;;;ACIlB,OAAO,kBAAkB;AACzB,IAAM,YAAY;AAYX,SAAS,YAAY,QAAQ;AAClC,QAAM,OAAO,aAAa,GAAG,SAAS,IAAI,MAAM,EAAE;AAClD,QAAM,OAAO,aAAa,GAAG,SAAS,IAAI,MAAM,OAAO;AACvD,QAAM,QAAQ,aAAa,GAAG,SAAS,IAAI,MAAM,QAAQ;AAGzD,OAAK,UAAU;AACf,QAAM,UAAU;AAGhB,OAAK,MAAM,QAAQ,KAAK,KAAK,OAAO;AACpC,QAAM,MAAM,QAAQ,MAAM,KAAK,OAAO;AAGtC,QAAM,UAAU,OAAO,OAAO,MAAM;AAAA,IAClC;AAAA,IACA;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGO,IAAM,QAAQ;AAAA,EACnB,OAAO;AAAA,IACL,MAAM,YAAY,YAAY;AAAA,IAC9B,MAAM,YAAY,YAAY;AAAA,IAC9B,MAAM,YAAY,YAAY;AAAA,EAChC;AAAA,EACA,IAAI;AAAA,IACF,WAAW,YAAY,cAAc;AAAA,IACrC,MAAM,YAAY,SAAS;AAAA,IAC3B,QAAQ,YAAY,WAAW;AAAA,EACjC;AAAA,EACA,MAAM;AAAA,IACJ,QAAQ,YAAY,aAAa;AAAA,IACjC,WAAW,YAAY,gBAAgB;AAAA,IACvC,OAAO,YAAY,YAAY;AAAA,EACjC;AAAA,EACA,UAAU,YAAY,UAAU;AAClC;;;ACxDO,IAAM,uBAAuB,oBAAI,IAAI;AA6BrC,SAAS,2BAA2B;AACzC,uBAAqB,MAAM;AAC7B;;;AC5BA,SAAS,QAAAC,aAAY;AAMd,IAAM,kBAAkBA,MAAK,KAAK;AAIzC,IAAI,WAAW;AAMR,SAAS,eAAe,SAAS;AACtC,aAAW;AACb;AAGA,IAAI,OAAO,WAAW,aAAa;AACjC,SAAO,eAAe;AACxB;AAQO,SAAS,WAAW,MAAM;AAC/B,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,WAAW,UAAU,IAAI;AAC/B,MAAI;AACF,gBAAY,KAAK,QAAQ;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO,MAAM;AACX,QAAI;AACF,kBAAY,QAAQ,UAAU,IAAI,IAAI,QAAQ;AAAA,IAChD,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AACA,SAAS,QAAQ;AAAC;;;AH7ClB,IAAMC,SAAQ,YAAY,gBAAgB;AAQ1C,IAAM,wBAAwB,oBAAI,QAAQ;AAC1C,SAAS,iBAAiB,OAAO;AAC/B,MAAI,QAAQ,sBAAsB,IAAI,KAAK;AAC3C,MAAI,CAAC,OAAO;AACV,YAAQ,oBAAI,IAAI;AAChB,0BAAsB,IAAI,OAAO,KAAK;AAAA,EACxC;AACA,SAAO;AACT;AAOO,IAAM,gCAAgCC,MAAK,CAAC;AAM5C,IAAM,yBAAyB,WAAW,YAAUA,MAAK,SAAO;AACrE,MAAI,6BAA6B;AACjC,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AACA,QAAM,IAAI,MAAM,iBAAiB,QAAQ,GAAG;AAC5C,QAAM,IAAI,MAAM,iBAAiB,QAAQ,GAAG;AAG5C,QAAM,QAAQ,iBAAiB,KAAK;AACpC,QAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,MAAI,QAAQ,KAAK,MAAM,KAAK,KAAK,MAAM,GAAG;AACxC,WAAO;AAAA,EACT;AACA,QAAM,MAAM;AAAA,IACV;AAAA,IACA;AAAA,EACF;AACA,QAAM,IAAI,QAAQ,GAAG;AACrB,SAAO;AACT,CAAC,CAAC;AAKK,IAAM,yBAAyBA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EAC1D;AAAA,EACA;AACF,MAAM;AACJ,QAAM,MAAM,WAAW,YAAY;AACnC,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,IAAAD,OAAM,mCAAmC,QAAQ,QAAQ;AACzD,UAAM,iBAAiB,QAAQ,KAAK,SAAS,CAAC;AAC9C,UAAM,iBAAiB,QAAQ,KAAK,SAAS,CAAC;AAE9C,QAAI,+BAA+B,OAAK,IAAI,CAAC;AAAA,EAC/C;AACA,MAAI;AACN,CAAC;AAMM,IAAM,0BAA0BC,MAAK,MAAM,CAAC,KAAK,MAAM,WAAW;AACvE,yBAAuB,OAAO,MAAM;AACpC,QAAM,QAAQ,IAAI,SAAS;AAC3B,mBAAiB,KAAK,EAAE,OAAO,MAAM;AACrC,EAAAD,OAAM,sCAAsC,MAAM;AACpD,CAAC;AAMM,IAAM,8BAA8BC,MAAK,MAAM,CAAC,KAAK,SAAS;AACnE,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,UAAU,MAAM,MAAM;AAC5B,UAAQ,QAAQ,YAAU;AACxB,2BAAuB,OAAO,MAAM;AAAA,EACtC,CAAC;AACD,wBAAsB,OAAO,KAAK;AAClC,EAAAD,OAAM,6BAA6B,QAAQ,MAAM;AACnD,CAAC;AAKM,IAAM,yBAAyBC,MAAK,MAAM,CAAC,KAAK,QAAQ;AAC7D,EAAAD,OAAM,2BAA2B;AACjC,MAAI,2BAA2B;AAC/B,2BAAyB;AACzB,QAAM,aAAa,IAAIE,OAAM,YAAY;AACzC,MAAI,WAAW,UAAU;AACzB,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACxC,CAAC;;;AIpHD,SAAS,QAAAC,aAAY;AACrB,SAAS,cAAAC,mBAAkB;;;ACF3B,SAAS,QAAAC,aAAY;;;ACArB,SAAS,QAAAC,aAAY;AAErB,IAAMC,SAAQ,YAAY,WAAW;AAO9B,IAAM,sBAAsBC,MAAK,oBAAI,IAAI,CAAC;AAK1C,IAAM,qBAAqBA,MAAK,IAAI;AAQpC,IAAM,qCAAqCA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACtE;AAAA,EACA;AACF,MAAM;AACJ,QAAM,mBAAmB,IAAI,mBAAmB;AAChD,EAAAD,OAAM,mEAAmE,QAAQ,gBAAgB,MAAM,KAAK,gBAAgB,CAAC;AAG7H,MAAI,oBAAoB,IAAI;AAC5B,MAAI,gBAAgB;AAClB,UAAM,eAAe,IAAI,IAAI,gBAAgB;AAC7C,QAAI,aAAa,IAAI,MAAM,GAAG;AAC5B,mBAAa,OAAO,MAAM;AAAA,IAC5B,OAAO;AACL,mBAAa,IAAI,MAAM;AAAA,IACzB;AACA,IAAAA,OAAM,yCAAyC,MAAM,KAAK,YAAY,CAAC;AACvE,QAAI,qBAAqB,YAAY;AAAA,EACvC,OAAO;AAGL,QAAI,CAAC,iBAAiB,IAAI,MAAM,GAAG;AACjC,MAAAA,OAAM,wCAAwC,MAAM;AACpD,UAAI,qBAAqB,oBAAI,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,IAC5C,OAAO;AACL,MAAAA,OAAM,gDAAgD;AAAA,IACxD;AAAA,EACF;AACF,CAAC;AAKM,IAAM,uBAAuBC,MAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AACnE,EAAAD,OAAM,wBAAwB,MAAM;AACpC,MAAI,oBAAoB,IAAI;AAC5B,MAAI,WAAW,QAAQ,WAAW,QAAW;AAC3C,IAAAA,OAAM,oBAAoB;AAC1B,QAAI,qBAAqB,oBAAI,IAAI,CAAC;AAAA,EACpC,OAAO;AACL,UAAM,mBAAmB,IAAI,mBAAmB;AAChD,QAAI,iBAAiB,IAAI,MAAM,KAAK,iBAAiB,SAAS,GAAG;AAC/D;AAAA,IACF;AACA,QAAI,qBAAqB,oBAAI,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,EAC5C;AACF,CAAC;AAKM,IAAM,4BAA4BC,MAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AACxE,QAAM,mBAAmB,IAAI,mBAAmB;AAChD,QAAM,eAAe,IAAI,IAAI,gBAAgB;AAC7C,MAAI,aAAa,IAAI,MAAM,GAAG;AAC5B,iBAAa,OAAO,MAAM;AAAA,EAC5B,OAAO;AACL,iBAAa,IAAI,MAAM;AAAA,EACzB;AACA,MAAI,qBAAqB,YAAY;AACvC,CAAC;AAKM,IAAM,qBAAqBA,MAAK,MAAM,CAAC,MAAM,QAAQ;AAC1D,EAAAD,OAAM,gBAAgB;AACtB,MAAI,qBAAqB,oBAAI,IAAI,CAAC;AACpC,CAAC;AAKM,IAAM,0BAA0BC,MAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AACvE,QAAM,mBAAmB,IAAI,mBAAmB;AAChD,QAAM,eAAe,IAAI,IAAI,gBAAgB;AAC7C,aAAW,UAAU,SAAS;AAC5B,iBAAa,IAAI,MAAM;AAAA,EACzB;AACA,MAAI,qBAAqB,YAAY;AACvC,CAAC;AAKM,IAAM,+BAA+BA,MAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AAC5E,QAAM,mBAAmB,IAAI,mBAAmB;AAChD,QAAM,eAAe,IAAI,IAAI,gBAAgB;AAC7C,aAAW,UAAU,SAAS;AAC5B,iBAAa,OAAO,MAAM;AAAA,EAC5B;AACA,MAAI,qBAAqB,YAAY;AACvC,CAAC;AAKM,IAAM,iBAAiBA,MAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AAC7D,MAAI,oBAAoB,MAAM;AAC9B,MAAI,WAAW,MAAM;AACnB,QAAI,qBAAqB,oBAAI,IAAI,CAAC;AAAA,EACpC;AACF,CAAC;AAKM,IAAM,yBAAyBA,MAAK,MAAM,CAAC,MAAM,QAAQ;AAC9D,MAAI,oBAAoB,IAAI;AAC9B,CAAC;AASM,IAAM,oBAAoBA,MAAK,IAAI;AAKnC,IAAM,qBAAqBA,MAAK,MAAM,CAAC,MAAM,KAAK,WAAW;AAClE,MAAI,mBAAmB,MAAM;AAC/B,CAAC;AAKM,IAAM,qBAAqBA,MAAK,SAAO,IAAI,iBAAiB,MAAM,IAAI;AAOtE,IAAM,yBAAyBA,MAAK,SAAO,IAAI,mBAAmB,EAAE,IAAI;AAKxE,IAAM,mBAAmBA,MAAK,SAAO,IAAI,mBAAmB,EAAE,OAAO,CAAC;;;ACjJtE,IAAI,kBAA+B,0BAAUC,kBAAiB;AAEnE,EAAAA,iBAAgB,OAAO,IAAI;AAE3B,EAAAA,iBAAgB,WAAW,IAAI;AAC/B,SAAOA;AACT,GAAE,CAAC,CAAC;AAmBG,IAAM,kBAAkB,WAAS;AACtC,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,MACH,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,EACF;AACA,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,UAAQ,KAAK,CAAC,CAAC;AAClD,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,UAAQ,KAAK,CAAC,CAAC;AAClD,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,UAAQ,KAAK,IAAI,KAAK,KAAK,CAAC;AAC/D,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,UAAQ,KAAK,IAAI,KAAK,MAAM,CAAC;AAChE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,EACjB;AACF;;;AFzDO,IAAM,WAAWC,MAAK,CAAC;AAKvB,IAAM,UAAUA,MAAK;AAAA,EAC1B,GAAG;AAAA,EACH,GAAG;AACL,CAAC;AAKM,IAAM,mBAAmBA,MAAK,IAAI;AAOlC,IAAM,oBAAoBA,MAAK,SAAO;AAC3C,SAAO,CAAC,SAAS,YAAY;AAC3B,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,OAAO,IAAI,QAAQ;AACzB,UAAM,OAAO,IAAI,gBAAgB;AACjC,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,IACF;AACA,UAAM,YAAY,UAAU,KAAK;AACjC,UAAM,YAAY,UAAU,KAAK;AACjC,WAAO;AAAA,MACL,IAAI,YAAY,IAAI,KAAK;AAAA,MACzB,IAAI,YAAY,IAAI,KAAK;AAAA,IAC3B;AAAA,EACF;AACF,CAAC;AAKM,IAAM,oBAAoBA,MAAK,SAAO;AAC3C,SAAO,CAAC,QAAQ,WAAW;AACzB,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,OAAO,IAAI,QAAQ;AACzB,UAAM,OAAO,IAAI,gBAAgB;AACjC,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,IACF;AACA,WAAO;AAAA,MACL,GAAG,SAAS,OAAO,IAAI,IAAI,KAAK;AAAA,MAChC,GAAG,SAAS,OAAO,IAAI,IAAI,KAAK;AAAA,IAClC;AAAA,EACF;AACF,CAAC;AAOM,IAAM,cAAcA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,cAAc,IAAI,QAAQ;AAChC,QAAM,MAAM,IAAI,OAAO;AACvB,QAAM,OAAO,IAAI,gBAAgB;AAGjC,QAAM,UAAU,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;AAC/C,MAAI,YAAY,UAAa,YAAY,UAAa,MAAM;AAE1D,UAAM,YAAY,UAAU,KAAK;AACjC,UAAM,YAAY,UAAU,KAAK;AACjC,UAAM,UAAU,YAAY,IAAI,KAAK;AACrC,UAAM,UAAU,YAAY,IAAI,KAAK;AACrC,UAAM,UAAU,YAAY,SAAS;AACrC,UAAM,UAAU,YAAY,SAAS;AACrC,QAAI,SAAS;AAAA,MACX,GAAG;AAAA,MACH,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AACA,MAAI,UAAU,OAAO;AACvB,CAAC;AAKM,IAAM,oBAAoBA,MAAK,MAAM,CAAC,MAAM,QAAQ;AACzD,MAAI,UAAU,CAAC;AACf,MAAI,SAAS;AAAA,IACX,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AACH,CAAC;AAiBM,IAAM,kBAAkBA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACnD;AAAA,EACA,UAAU;AACZ,MAAM;AACJ,QAAM,iBAAiB,OAAO,SAAS,WAAW,SAAS,UAAU,gBAAgB,QAAQ,gBAAgB,YAAY;AACzH,QAAM,eAAe,IAAI,gBAAgB;AACzC,MAAI,CAAC,gBAAgB,aAAa,SAAS,KAAK,aAAa,UAAU,EAAG;AAG1E,MAAI,6BAA6B;AACjC,MAAI;AACJ,MAAI,mBAAmB,gBAAgB,OAAO;AAC5C,UAAM,QAAQ,IAAI,SAAS;AAC3B,UAAM,QAAQ,MAAM,MAAM,EAAE,IAAI,UAAQ;AACtC,YAAM,QAAQ,MAAM,kBAAkB,IAAI;AAC1C,aAAO;AAAA,QACL,GAAG,MAAM;AAAA,QACT,GAAG,MAAM;AAAA,QACT,OAAO,MAAM,SAAS;AAAA,QACtB,QAAQ,MAAM,UAAU;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,aAAS,gBAAgB,KAAK;AAAA,EAChC,OAAO;AACL,UAAM,cAAc,IAAI,mBAAmB;AAC3C,UAAM,WAAW,IAAI,WAAW;AAChC,UAAM,gBAAgB,SAAS,OAAO,OAAK,YAAY,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,QAAM;AAAA,MAC1E,GAAG,EAAE,SAAS;AAAA,MACd,GAAG,EAAE,SAAS;AAAA,MACd,OAAO,EAAE,SAAS;AAAA,MAClB,QAAQ,EAAE,UAAU;AAAA,IACtB,EAAE;AACF,aAAS,gBAAgB,aAAa;AAAA,EACxC;AACA,MAAI,OAAO,SAAS,KAAK,OAAO,UAAU,EAAG;AAC7C,QAAM,UAAU,KAAK,IAAI,GAAG,aAAa,QAAQ,IAAI,CAAC;AACtD,QAAM,UAAU,KAAK,IAAI,GAAG,aAAa,SAAS,IAAI,CAAC;AACvD,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,SAAS,SAAS,OAAO,CAAC;AACnE,QAAM,OAAO,KAAK,IAAI,GAAG,aAAa,QAAQ,IAAI,WAAW;AAC7D,QAAM,OAAO,KAAK,IAAI,GAAG,aAAa,SAAS,IAAI,WAAW;AAC9D,QAAM,QAAQ,KAAK,IAAI,OAAO,OAAO,OAAO,OAAO,OAAO,MAAM;AAChE,MAAI,SAAS,KAAK,CAAC,SAAS,KAAK,EAAG;AACpC,MAAI,UAAU,KAAK;AACnB,QAAM,UAAU,OAAO,QAAQ;AAC/B,QAAM,UAAU,OAAO,SAAS;AAChC,QAAM,SAAS,eAAe,OAAO,WAAW;AAChD,QAAM,SAAS,eAAe,OAAO,WAAW;AAChD,MAAI,SAAS;AAAA,IACX,GAAG,SAAS,OAAO,IAAI;AAAA,IACvB,GAAG,SAAS,OAAO,IAAI;AAAA,EACzB,CAAC;AACH,CAAC;AAKM,IAAM,mBAAmBA,MAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AAC/D,QAAM,QAAQ,IAAI,WAAW;AAC7B,QAAM,OAAO,MAAM,KAAK,OAAK,EAAE,OAAO,MAAM;AAC5C,MAAI,CAAC,KAAM;AACX,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,EACX,IAAI;AACJ,QAAM,OAAO,IAAI,QAAQ;AACzB,QAAM,UAAU,IAAI,QAAQ;AAC5B,QAAM,UAAU,IAAI,SAAS;AAC7B,QAAM,OAAO,IAAI,gBAAgB;AACjC,QAAM,YAAY,OAAO,KAAK,QAAQ,IAAI;AAC1C,QAAM,aAAa,OAAO,KAAK,SAAS,IAAI;AAC5C,MAAI,SAAS;AAAA,IACX,GAAG,YAAY,UAAU;AAAA,IACzB,GAAG,aAAa,UAAU;AAAA,EAC5B,CAAC;AACH,CAAC;AAcM,IAAM,sBAAsBC,MAAK,IAAI;AAGrC,IAAM,6BAA6BA,MAAK,CAAC;AAGzC,IAAM,0BAA0BA,MAAK,SAAO;AACjD,QAAM,WAAW,IAAI,0BAA0B;AAC/C,SAAO,WAAW,KAAK,WAAW;AACpC,CAAC;AAKM,IAAM,0BAA0BA,MAAK,IAAI;AAMzC,IAAM,wBAAwBA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACzD;AAAA,EACA;AAAA,EACA,WAAW;AACb,MAAM;AACJ,QAAM,QAAQ,IAAI,WAAW;AAC7B,QAAM,OAAO,MAAM,KAAK,OAAK,EAAE,OAAO,MAAM;AAC5C,MAAI,CAAC,KAAM;AACX,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,EACX,IAAI;AACJ,QAAM,UAAU,IAAI,QAAQ;AAC5B,QAAM,UAAU,IAAI,SAAS;AAC7B,QAAM,OAAO,IAAI,gBAAgB;AACjC,QAAM,YAAY,OAAO,KAAK,QAAQ,IAAI;AAC1C,QAAM,aAAa,OAAO,KAAK,SAAS,IAAI;AAC5C,QAAM,YAAY,cAAc,IAAI,QAAQ;AAC5C,QAAM,YAAY;AAAA,IAChB,GAAG,YAAY,UAAU;AAAA,IACzB,GAAG,aAAa,UAAU;AAAA,EAC5B;AACA,MAAI,qBAAqB,MAAM;AAC/B,MAAI,yBAAyB;AAAA,IAC3B,YAAY;AAAA,IACZ;AAAA,IACA,WAAW,IAAI,QAAQ;AAAA,IACvB,UAAU;AAAA,MACR,GAAG,IAAI,OAAO;AAAA,IAChB;AAAA,IACA;AAAA,IACA,WAAW,YAAY,IAAI;AAAA,EAC7B,CAAC;AACH,CAAC;AAMM,IAAM,yBAAyBA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EAC1D;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AACb,MAAM;AACJ,QAAM,eAAe,IAAI,gBAAgB;AACzC,MAAI,CAAC,gBAAgB,aAAa,SAAS,KAAK,aAAa,UAAU,EAAG;AAC1E,MAAI,6BAA6B;AACjC,MAAI;AACJ,MAAI,SAAS,SAAS;AACpB,UAAM,QAAQ,IAAI,SAAS;AAC3B,UAAM,QAAQ,MAAM,MAAM,EAAE,IAAI,UAAQ;AACtC,YAAM,QAAQ,MAAM,kBAAkB,IAAI;AAC1C,aAAO;AAAA,QACL,GAAG,MAAM;AAAA,QACT,GAAG,MAAM;AAAA,QACT,OAAO,MAAM,SAAS;AAAA,QACtB,QAAQ,MAAM,UAAU;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,aAAS,gBAAgB,KAAK;AAAA,EAChC,OAAO;AACL,UAAM,cAAc,IAAI,mBAAmB;AAC3C,UAAM,WAAW,IAAI,WAAW;AAChC,UAAM,gBAAgB,SAAS,OAAO,OAAK,YAAY,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,QAAM;AAAA,MAC1E,GAAG,EAAE,SAAS;AAAA,MACd,GAAG,EAAE,SAAS;AAAA,MACd,OAAO,EAAE,SAAS;AAAA,MAClB,QAAQ,EAAE,UAAU;AAAA,IACtB,EAAE;AACF,aAAS,gBAAgB,aAAa;AAAA,EACxC;AACA,MAAI,OAAO,SAAS,KAAK,OAAO,UAAU,EAAG;AAC7C,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,SAAS,aAAa,QAAQ,IAAI,GAAG,aAAa,SAAS,IAAI,CAAC,CAAC;AAC1G,QAAM,OAAO,KAAK,IAAI,GAAG,aAAa,QAAQ,IAAI,WAAW;AAC7D,QAAM,OAAO,KAAK,IAAI,GAAG,aAAa,SAAS,IAAI,WAAW;AAC9D,QAAM,QAAQ,KAAK,IAAI,OAAO,OAAO,OAAO,OAAO,OAAO,MAAM;AAChE,MAAI,SAAS,KAAK,CAAC,SAAS,KAAK,EAAG;AACpC,QAAM,UAAU,OAAO,QAAQ;AAC/B,QAAM,UAAU,OAAO,SAAS;AAChC,QAAM,SAAS,eAAe,OAAO,WAAW;AAChD,QAAM,SAAS,eAAe,OAAO,WAAW;AAChD,QAAM,YAAY;AAAA,IAChB,GAAG,SAAS,OAAO,IAAI;AAAA,IACvB,GAAG,SAAS,OAAO,IAAI;AAAA,EACzB;AACA,MAAI,yBAAyB;AAAA,IAC3B,YAAY;AAAA,IACZ;AAAA,IACA,WAAW,IAAI,QAAQ;AAAA,IACvB,UAAU;AAAA,MACR,GAAG,IAAI,OAAO;AAAA,IAChB;AAAA,IACA;AAAA,IACA,WAAW,YAAY,IAAI;AAAA,EAC7B,CAAC;AACH,CAAC;;;AG3UD,SAAS,QAAAC,aAAY;;;ACQrB,SAAS,QAAAC,aAAY;;;ACAd,SAAS,WAAW,OAAO,OAAO;AACvC,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,aACH;AACE,UAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,EAAG,QAAO;AACzC,YAAM,iBAAiB,MAAM,QAAQ,KAAK,MAAM,GAAG,CAAC;AACpD,YAAM,iBAAiB,MAAM,QAAQ,KAAK,MAAM,GAAG,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IACF,KAAK,eACH;AACE,UAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,EAAG,QAAO;AACzC,YAAM,iBAAiB,MAAM,QAAQ,SAAS,MAAM,GAAG,KAAK;AAC5D,YAAM,iBAAiB,MAAM,QAAQ,UAAU,MAAM,GAAG,MAAM;AAC9D,aAAO;AAAA,IACT;AAAA,IACF,KAAK,YACH;AACE,UAAI,MAAM,QAAQ,MAAM,MAAM,EAAG,QAAO;AACxC,YAAM,QAAQ,MAAM,QAAQ,MAAM,UAAU;AAC5C,aAAO;AAAA,IACT;AAAA,IACF,KAAK,eACH;AACE,UAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,EAAG,QAAO;AACzC,YAAM,SAAS,MAAM,MAAM;AAC3B,aAAO;AAAA,IACT;AAAA,IACF,KAAK,YACH;AACE,UAAI,MAAM,QAAQ,MAAM,MAAM,EAAG,QAAO;AACxC,UAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC,MAAM,QAAQ,MAAM,MAAM,EAAG,QAAO;AACzE,YAAM,eAAe,MAAM,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,UAAU;AAC/E,aAAO;AAAA,IACT;AAAA,IACF,KAAK,eACH;AACE,UAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,EAAG,QAAO;AACzC,YAAM,SAAS,MAAM,MAAM;AAC3B,aAAO;AAAA,IACT;AAAA,IACF,KAAK,oBACH;AACE,UAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,EAAG,QAAO;AACzC,YAAM,iBAAiB,MAAM,QAAQ,MAAM,KAAK,MAAM,EAAE;AACxD,aAAO;AAAA,IACT;AAAA,IACF,KAAK,SACH;AACE,UAAI,mBAAmB;AACvB,iBAAW,KAAK,MAAM,QAAQ;AAC5B,YAAI,WAAW,OAAO,CAAC,EAAG,oBAAmB;AAAA,MAC/C;AACA,aAAO;AAAA,IACT;AAAA,IACF,KAAK,iBACH;AAEE,YAAM,MAAM;AACZ,iBAAW,QAAQ,MAAM,OAAO;AAC9B,cAAM,QAAQ,KAAK,IAAI,KAAK,UAAU;AAAA,MACxC;AACA,iBAAW,QAAQ,MAAM,OAAO;AAC9B,YAAI,MAAM,QAAQ,KAAK,MAAM,KAAK,MAAM,QAAQ,KAAK,MAAM,GAAG;AAC5D,gBAAM,eAAe,KAAK,IAAI,KAAK,QAAQ,KAAK,QAAQ,KAAK,UAAU;AAAA,QACzE;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACJ;AACF;AAKO,SAAS,YAAY,OAAO;AACjC,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM,MAAM;AAAA,QACZ,IAAI,MAAM;AAAA,MACZ;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM,MAAM;AAAA,QACZ,IAAI,MAAM;AAAA,MACZ;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,QACd,YAAY,MAAM;AAAA,QAClB,gBAAgB,CAAC;AAAA,MACnB;AAAA,IACF,KAAK,eACH;AAEE,YAAM,QAAQ,CAAC;AAAA,QACb,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,QACd,YAAY,MAAM;AAAA,MACpB,GAAG,GAAG,MAAM,eAAe,IAAI,QAAM;AAAA,QACnC,MAAM;AAAA,QACN,QAAQ,EAAE;AAAA,QACV,QAAQ,EAAE;AAAA,QACV,QAAQ,EAAE;AAAA,QACV,YAAY,EAAE;AAAA,MAChB,EAAE,CAAC;AACH,aAAO,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI;AAAA,QACrC,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,QACd,QAAQ,MAAM;AAAA,QACd,QAAQ,MAAM;AAAA,QACd,YAAY,MAAM;AAAA,MACpB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,QACd,QAAQ,MAAM;AAAA,QACd,QAAQ,MAAM;AAAA,QACd,YAAY,MAAM;AAAA,MACpB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM,MAAM;AAAA,QACZ,IAAI,MAAM;AAAA,MACZ;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM,OAAO,IAAI,WAAW,EAAE,QAAQ;AAAA,MAChD;AAAA,IACF,KAAK;AAEH,aAAO;AAAA,EACX;AACF;AAMO,SAAS,eAAe,OAAO,OAAO;AAC3C,QAAM,QAAQ,CAAC;AACf,QAAM,QAAQ,CAAC;AACf,QAAM,YAAY,CAAC,QAAQ,eAAe;AACxC,UAAM,KAAK;AAAA,MACT,IAAI;AAAA,MACJ,YAAY;AAAA,QACV,GAAG;AAAA,MACL;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACD,QAAM,YAAY,CAAC,QAAQ,YAAY,QAAQ,WAAW;AACxD,UAAM,KAAK;AAAA,MACT,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA,YAAY;AAAA,QACV,GAAG;AAAA,MACL;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACD,SAAO;AAAA,IACL,WAAW,KAAK,IAAI;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ADzKA,IAAMC,SAAQ,YAAY,SAAS;AAOnC,IAAM,mBAAmB;AAMlB,IAAM,mBAAmBC,MAAK;AAAA,EACnC,MAAM,CAAC;AAAA,EACP,QAAQ,CAAC;AAAA,EACT,YAAY;AACd,CAAC;AACM,IAAM,cAAcA,MAAK,SAAO;AACrC,QAAM,UAAU,IAAI,gBAAgB;AACpC,SAAO,QAAQ,KAAK,SAAS,KAAK,CAAC,QAAQ;AAC7C,CAAC;AACM,IAAM,cAAcA,MAAK,SAAO;AACrC,QAAM,UAAU,IAAI,gBAAgB;AACpC,SAAO,QAAQ,OAAO,SAAS,KAAK,CAAC,QAAQ;AAC/C,CAAC;AACM,IAAM,gBAAgBA,MAAK,SAAO,IAAI,gBAAgB,EAAE,KAAK,MAAM;AACnE,IAAM,gBAAgBA,MAAK,SAAO,IAAI,gBAAgB,EAAE,OAAO,MAAM;AAUrE,IAAM,gBAAgBA,MAAK,MAAM,CAAC,KAAK,KAAK,UAAU;AAC3D,QAAM,UAAU,IAAI,gBAAgB;AACpC,MAAI,QAAQ,WAAY;AACxB,QAAM;AAAA,IACJ;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AACJ,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,IACT,SAAS,YAAY,UAAU;AAAA,IAC/B,WAAW,KAAK,IAAI;AAAA,IACpB;AAAA,EACF;AACA,QAAM,UAAU,CAAC,GAAG,QAAQ,MAAM,KAAK;AACvC,MAAI,QAAQ,SAAS,iBAAkB,SAAQ,MAAM;AACrD,MAAI,kBAAkB;AAAA,IACpB,MAAM;AAAA,IACN,QAAQ,CAAC;AAAA;AAAA,IAET,YAAY;AAAA,EACd,CAAC;AACD,EAAAD,OAAM,+BAA+B,SAAS,MAAM,MAAM,QAAQ,MAAM;AAC1E,CAAC;AAOM,IAAM,kBAAkBC,MAAK,MAAM,CAAC,KAAK,KAAK,UAAU;AAC7D,QAAM,UAAU,IAAI,gBAAgB;AACpC,MAAI,QAAQ,WAAY;AACxB,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,WAAW,eAAe,OAAO,KAAK;AAG5C,QAAM,UAAU;AAAA,IACd,MAAM;AAAA,IACN,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,EAClB;AACA,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,SAAS;AAAA;AAAA,IAET,WAAW,KAAK,IAAI;AAAA,IACpB;AAAA,EACF;AACA,QAAM,UAAU,CAAC,GAAG,QAAQ,MAAM,KAAK;AACvC,MAAI,QAAQ,SAAS,iBAAkB,SAAQ,MAAM;AACrD,MAAI,kBAAkB;AAAA,IACpB,MAAM;AAAA,IACN,QAAQ,CAAC;AAAA,IACT,YAAY;AAAA,EACd,CAAC;AACD,EAAAD,OAAM,kCAAkC,SAAS,WAAW,QAAQ,MAAM;AAC5E,CAAC;AAMM,IAAM,WAAWC,MAAK,MAAM,CAAC,KAAK,QAAQ;AAC/C,QAAM,UAAU,IAAI,gBAAgB;AACpC,MAAI,QAAQ,KAAK,WAAW,KAAK,QAAQ,WAAY,QAAO;AAC5D,MAAI,kBAAkB;AAAA,IACpB,GAAG;AAAA,IACH,YAAY;AAAA,EACd,CAAC;AACD,MAAI;AACF,UAAM,QAAQ,IAAI,SAAS;AAC3B,UAAM,UAAU,CAAC,GAAG,QAAQ,IAAI;AAChC,UAAM,QAAQ,QAAQ,IAAI;AAG1B,QAAI,iBAAiB,MAAM;AAC3B,QAAI,MAAM,QAAQ,SAAS,iBAAiB;AAC1C,YAAM,kBAAkB,eAAe,OAAO,SAAS;AACvD,uBAAiB;AAAA,QACf,MAAM;AAAA,QACN,OAAO,gBAAgB;AAAA,QACvB,OAAO,gBAAgB;AAAA,MACzB;AAAA,IACF;AACA,UAAM,mBAAmB,WAAW,OAAO,MAAM,OAAO;AACxD,QAAI,kBAAkB;AACpB,UAAI,WAAW,KAAK;AACpB,UAAI,wBAAwB,OAAK,IAAI,CAAC;AAAA,IACxC;AACA,QAAI,+BAA+B,OAAK,IAAI,CAAC;AAC7C,UAAM,YAAY;AAAA,MAChB,SAAS;AAAA,MACT,SAAS,MAAM;AAAA,MACf,WAAW,MAAM;AAAA,MACjB,OAAO,MAAM;AAAA,IACf;AACA,QAAI,kBAAkB;AAAA,MACpB,MAAM;AAAA,MACN,QAAQ,CAAC,WAAW,GAAG,QAAQ,MAAM;AAAA,MACrC,YAAY;AAAA,IACd,CAAC;AACD,IAAAD,OAAM,mCAAmC,MAAM,OAAO,QAAQ,QAAQ,QAAQ,OAAO,SAAS,CAAC;AAC/F,WAAO;AAAA,EACT,SAAS,OAAO;AACd,IAAAA,OAAM,MAAM,mBAAmB,KAAK;AACpC,QAAI,kBAAkB;AAAA,MACpB,GAAG;AAAA,MACH,YAAY;AAAA,IACd,CAAC;AACD,WAAO;AAAA,EACT;AACF,CAAC;AACM,IAAM,WAAWC,MAAK,MAAM,CAAC,KAAK,QAAQ;AAC/C,QAAM,UAAU,IAAI,gBAAgB;AACpC,MAAI,QAAQ,OAAO,WAAW,KAAK,QAAQ,WAAY,QAAO;AAC9D,MAAI,kBAAkB;AAAA,IACpB,GAAG;AAAA,IACH,YAAY;AAAA,EACd,CAAC;AACD,MAAI;AACF,UAAM,QAAQ,IAAI,SAAS;AAC3B,UAAM,YAAY,CAAC,GAAG,QAAQ,MAAM;AACpC,UAAM,QAAQ,UAAU,MAAM;AAG9B,QAAI,iBAAiB,MAAM;AAC3B,QAAI,MAAM,QAAQ,SAAS,iBAAiB;AAC1C,YAAM,kBAAkB,eAAe,OAAO,SAAS;AACvD,uBAAiB;AAAA,QACf,MAAM;AAAA,QACN,OAAO,gBAAgB;AAAA,QACvB,OAAO,gBAAgB;AAAA,MACzB;AAAA,IACF;AACA,UAAM,mBAAmB,WAAW,OAAO,MAAM,OAAO;AACxD,QAAI,kBAAkB;AACpB,UAAI,WAAW,KAAK;AACpB,UAAI,wBAAwB,OAAK,IAAI,CAAC;AAAA,IACxC;AACA,QAAI,+BAA+B,OAAK,IAAI,CAAC;AAC7C,UAAM,YAAY;AAAA,MAChB,SAAS,MAAM;AAAA,MACf,SAAS;AAAA,MACT,WAAW,MAAM;AAAA,MACjB,OAAO,MAAM;AAAA,IACf;AACA,QAAI,kBAAkB;AAAA,MACpB,MAAM,CAAC,GAAG,QAAQ,MAAM,SAAS;AAAA,MACjC,QAAQ;AAAA,MACR,YAAY;AAAA,IACd,CAAC;AACD,IAAAD,OAAM,mCAAmC,MAAM,OAAO,QAAQ,KAAK,SAAS,GAAG,UAAU,MAAM;AAC/F,WAAO;AAAA,EACT,SAAS,OAAO;AACd,IAAAA,OAAM,MAAM,mBAAmB,KAAK;AACpC,QAAI,kBAAkB;AAAA,MACpB,GAAG;AAAA,MACH,YAAY;AAAA,IACd,CAAC;AACD,WAAO;AAAA,EACT;AACF,CAAC;AACM,IAAM,mBAAmBC,MAAK,MAAM,CAAC,MAAM,QAAQ;AACxD,MAAI,kBAAkB;AAAA,IACpB,MAAM,CAAC;AAAA,IACP,QAAQ,CAAC;AAAA,IACT,YAAY;AAAA,EACd,CAAC;AACD,EAAAD,OAAM,iBAAiB;AACzB,CAAC;AACM,IAAM,oBAAoBC,MAAK,SAAO;AAC3C,QAAM,UAAU,IAAI,gBAAgB;AACpC,SAAO;AAAA,IACL,MAAM,QAAQ,KAAK,IAAI,OAAK,EAAE,SAAS,SAAS;AAAA,IAChD,QAAQ,QAAQ,OAAO,IAAI,OAAK,EAAE,SAAS,SAAS;AAAA,EACtD;AACF,CAAC;;;AD3NM,IAAM,sBAAsBC,MAAK,oBAAI,IAAI,CAAC;AAK1C,IAAM,0BAA0BA,MAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AACvE,QAAM,UAAU,IAAI,mBAAmB;AACvC,QAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,MAAI,KAAK,IAAI,OAAO,GAAG;AACrB,SAAK,OAAO,OAAO;AAAA,EACrB,OAAO;AACL,SAAK,IAAI,OAAO;AAAA,EAClB;AACA,MAAI,qBAAqB,IAAI;AAC/B,CAAC;AAKM,IAAM,oBAAoBA,MAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AACjE,QAAM,UAAU,IAAI,mBAAmB;AACvC,MAAI,CAAC,QAAQ,IAAI,OAAO,GAAG;AACzB,UAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,SAAK,IAAI,OAAO;AAChB,QAAI,qBAAqB,IAAI;AAAA,EAC/B;AACF,CAAC;AAKM,IAAM,kBAAkBA,MAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AAC/D,QAAM,UAAU,IAAI,mBAAmB;AACvC,MAAI,QAAQ,IAAI,OAAO,GAAG;AACxB,UAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,SAAK,OAAO,OAAO;AACnB,QAAI,qBAAqB,IAAI;AAAA,EAC/B;AACF,CAAC;AASM,IAAM,mBAAmBA,MAAK,SAAO;AAC1C,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,SAAO,cAAY;AACjB,UAAM,WAAW,CAAC;AAClB,UAAM,YAAY,CAAC,QAAQ,UAAU;AACnC,UAAI,MAAM,aAAa,UAAU;AAC/B,iBAAS,KAAK,MAAM;AAAA,MACtB;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AACF,CAAC;AAKM,IAAM,iBAAiBA,MAAK,SAAO;AACxC,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,SAAO,YAAU;AACf,QAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO;AACnC,WAAO,MAAM,iBAAiB,QAAQ,UAAU;AAAA,EAClD;AACF,CAAC;AAKM,IAAM,kBAAkBA,MAAK,SAAO;AACzC,QAAM,cAAc,IAAI,gBAAgB;AACxC,SAAO,YAAU,YAAY,MAAM,EAAE,SAAS;AAChD,CAAC;AAKM,IAAM,sBAAsBA,MAAK,SAAO;AAC7C,QAAM,cAAc,IAAI,gBAAgB;AACxC,SAAO,aAAW,YAAY,OAAO,EAAE;AACzC,CAAC;AASM,IAAM,oBAAoBA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACrD;AAAA,EACA;AACF,MAAM;AACJ,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG;AAG5B,MAAI,UAAU;AACZ,QAAI,aAAa,OAAQ;AAEzB,QAAI,UAAU;AACd,WAAO,SAAS;AACd,UAAI,YAAY,OAAQ;AACxB,UAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAC7B,gBAAU,MAAM,iBAAiB,SAAS,UAAU;AAAA,IACtD;AAAA,EACF;AACA,QAAM,iBAAiB,QAAQ,YAAY,QAAQ;AACnD,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACxC,CAAC;AAKM,IAAM,uBAAuBA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACxD;AAAA,EACA;AACF,MAAM;AACJ,aAAW,UAAU,SAAS;AAC5B,QAAI,mBAAmB;AAAA,MACrB;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AACF,CAAC;AAKM,IAAM,sBAAsBA,MAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AAClE,MAAI,mBAAmB;AAAA,IACrB;AAAA,IACA,UAAU;AAAA,EACZ,CAAC;AACH,CAAC;AAQM,IAAM,yBAAyBA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EAC1D;AAAA,EACA;AACF,MAAM;AACJ,MAAI,iBAAiB,SAAS,QAAQ,MAAM,QAAQ;AACpD,QAAM,QAAQ,IAAI,SAAS;AAG3B,MAAI,OAAO,UACT,OAAO,UACP,OAAO,WACP,OAAO;AACT,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,MAAM,QAAQ,MAAM,EAAG;AAC5B,UAAM,QAAQ,MAAM,kBAAkB,MAAM;AAC5C,WAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,WAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,WAAO,KAAK,IAAI,MAAM,MAAM,KAAK,MAAM,SAAS,IAAI;AACpD,WAAO,KAAK,IAAI,MAAM,MAAM,KAAK,MAAM,UAAU,IAAI;AAAA,EACvD;AAGA,QAAM,UAAU;AAChB,MAAI,MAAM,QAAQ,WAAW,GAAG;AAC9B,UAAM,iBAAiB,aAAa,KAAK,OAAO,OAAO;AACvD,UAAM,iBAAiB,aAAa,KAAK,OAAO,UAAU,EAAE;AAC5D,UAAM,iBAAiB,aAAa,SAAS,OAAO,OAAO,IAAI,OAAO;AACtE,UAAM,iBAAiB,aAAa,UAAU,OAAO,OAAO,IAAI,UAAU,EAAE;AAAA,EAC9E;AAGA,aAAW,UAAU,SAAS;AAC5B,QAAI,WAAW,eAAe,MAAM,QAAQ,MAAM,GAAG;AACnD,YAAM,iBAAiB,QAAQ,YAAY,WAAW;AAAA,IACxD;AAAA,EACF;AACA,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACtC,MAAI,+BAA+B,OAAK,IAAI,CAAC;AAC/C,CAAC;AAKM,IAAM,mBAAmBA,MAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AAChE,MAAI,iBAAiB,eAAe;AACpC,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,YAAY,CAAC,QAAQ,UAAU;AACnC,QAAI,MAAM,aAAa,SAAS;AAC9B,YAAM,iBAAiB,QAAQ,YAAY,MAAS;AAAA,IACtD;AAAA,EACF,CAAC;AACD,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACxC,CAAC;AAUM,IAAM,sBAAsBA,MAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACvD;AAAA,EACA;AACF,MAAM;AACJ,MAAI,iBAAiB,YAAY;AACjC,aAAW,UAAU,SAAS;AAC5B,QAAI,WAAW,SAAU;AACzB,QAAI,mBAAmB;AAAA,MACrB;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AACA,MAAI,qBAAqB,QAAQ;AACnC,CAAC;AAqCM,IAAM,yBAAyBC,MAAK,SAAO;AAChD,QAAM,YAAY,IAAI,mBAAmB;AACzC,MAAI,UAAU,SAAS,EAAG,QAAO,oBAAI,IAAI;AACzC,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,QAAQ,oBAAI,IAAI;AACtB,aAAW,UAAU,MAAM,MAAM,GAAG;AAClC,QAAI,UAAU;AACd,QAAI,YAAY;AAChB,WAAO,MAAM;AACX,UAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAC7B,YAAM,SAAS,MAAM,iBAAiB,SAAS,UAAU;AACzD,UAAI,CAAC,OAAQ;AACb,UAAI,UAAU,IAAI,MAAM,EAAG,aAAY;AACvC,gBAAU;AAAA,IACZ;AACA,QAAI,UAAW,OAAM,IAAI,QAAQ,SAAS;AAAA,EAC5C;AACA,SAAO;AACT,CAAC;AAUM,IAAM,sBAAsBA,MAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AACnE,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAC7B,QAAM,WAAW,CAAC;AAClB,QAAM,YAAY,CAAC,QAAQ,UAAU;AACnC,QAAI,MAAM,aAAa,SAAS;AAC9B,eAAS,KAAK,MAAM;AAAA,IACtB;AAAA,EACF,CAAC;AACD,MAAI,SAAS,WAAW,EAAG;AAC3B,QAAM,UAAU;AAChB,QAAM,eAAe;AACrB,MAAI,OAAO,UACT,OAAO,UACP,OAAO,WACP,OAAO;AACT,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,MAAM,kBAAkB,OAAO;AAC7C,WAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,WAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,WAAO,KAAK,IAAI,MAAM,MAAM,KAAK,MAAM,SAAS,IAAI;AACpD,WAAO,KAAK,IAAI,MAAM,MAAM,KAAK,MAAM,UAAU,IAAI;AAAA,EACvD;AACA,QAAM,iBAAiB,SAAS,KAAK,OAAO,OAAO;AACnD,QAAM,iBAAiB,SAAS,KAAK,OAAO,UAAU,YAAY;AAClE,QAAM,iBAAiB,SAAS,SAAS,OAAO,OAAO,IAAI,OAAO;AAClE,QAAM,iBAAiB,SAAS,UAAU,OAAO,OAAO,IAAI,UAAU,YAAY;AAClF,MAAI,+BAA+B,OAAK,IAAI,CAAC;AAC/C,CAAC;;;AJ9TM,IAAM,oBAAoBC,MAAK,SAAO;AAC3C,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,OAAO;AACX,QAAM,YAAY,CAAC,OAAO,eAAe;AACvC,QAAI,WAAW,SAAS,MAAM;AAC5B,aAAO,WAAW;AAAA,IACpB;AAAA,EACF,CAAC;AACD,SAAO;AACT,CAAC;AAQD,IAAM,sBAAsB,oBAAI,QAAQ;AACjC,IAAM,cAAcA,MAAK,SAAO;AACrC,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,oBAAoB,IAAI,kBAAkB;AAChD,QAAM,YAAY,IAAI,mBAAmB;AACzC,QAAM,QAAQ,CAAC;AACf,QAAM,YAAY,CAAC,QAAQ,eAAe;AAExC,QAAI,UAAU,OAAO,GAAG;AACtB,UAAI,UAAU;AACd,UAAI,SAAS;AACb,aAAO,MAAM;AACX,YAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAC7B,cAAM,MAAM,MAAM,kBAAkB,OAAO,EAAE;AAC7C,YAAI,CAAC,IAAK;AACV,YAAI,UAAU,IAAI,GAAG,GAAG;AACtB,mBAAS;AACT;AAAA,QACF;AACA,kBAAU;AAAA,MACZ;AACA,UAAI,OAAQ;AAAA,IACd;AACA,UAAM,WAAW,IAAI,uBAAuB,MAAM,CAAC;AACnD,UAAM,KAAK;AAAA,MACT,GAAG;AAAA,MACH,IAAI;AAAA,MACJ;AAAA,MACA,YAAY,WAAW;AAAA,IACzB,CAAC;AAAA,EACH,CAAC;AAGD,QAAM,OAAO,oBAAoB,IAAI,KAAK,KAAK,CAAC;AAChD,MAAI,MAAM,WAAW,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,MAAM,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,EAAE,aAAa,KAAK,CAAC,EAAE,YAAY,EAAE,eAAe,KAAK,CAAC,EAAE,UAAU,GAAG;AACxJ,WAAO;AAAA,EACT;AACA,sBAAoB,IAAI,OAAO,KAAK;AACpC,SAAO;AACT,CAAC;AAKM,IAAM,eAAeA,MAAK,SAAO;AACtC,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,SAAO,MAAM,MAAM;AACrB,CAAC;AAKM,IAAM,iBAAiBC,YAAW,YAAUD,MAAK,SAAO;AAC7D,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,WAAO;AAAA,EACT;AACA,QAAM,aAAa,MAAM,kBAAkB,MAAM;AACjD,QAAM,WAAW,IAAI,uBAAuB,MAAM,CAAC;AACnD,QAAM,oBAAoB,IAAI,kBAAkB;AAChD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,IAAI;AAAA,IACJ;AAAA,IACA,YAAY,WAAW;AAAA,EACzB;AACF,CAAC,GAAG,CAAC,GAAG,MAAM,MAAM,CAAC;AAOd,IAAM,eAAeA,MAAK,SAAO;AACtC,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,SAAO,MAAM,MAAM;AACrB,CAAC;AAKM,IAAM,2BAA2BA,MAAK,SAAO;AAClD,QAAM,OAAO,IAAI,YAAY;AAC7B,QAAM,eAAe,IAAI,gBAAgB;AACzC,MAAI,aAAa,YAAY;AAC3B,WAAO,CAAC,GAAG,MAAM,oBAAoB;AAAA,EACvC;AACA,SAAO;AACT,CAAC;AAQD,IAAM,oBAAoB,oBAAI,QAAQ;AACtC,SAAS,aAAa,OAAO;AAC3B,MAAI,QAAQ,kBAAkB,IAAI,KAAK;AACvC,MAAI,CAAC,OAAO;AACV,YAAQ,oBAAI,IAAI;AAChB,sBAAkB,IAAI,OAAO,KAAK;AAAA,EACpC;AACA,SAAO;AACT;AACO,IAAM,iBAAiBC,YAAW,SAAOD,MAAK,SAAO;AAK1D,MAAI,sBAAsB;AAC1B,MAAI,QAAQ,sBAAsB;AAChC,UAAM,oBAAoB,IAAI,gBAAgB;AAC9C,UAAME,SAAQ,IAAI,SAAS;AAC3B,QAAI,kBAAkB,cAAc,kBAAkB,gBAAgB,kBAAkB,gBAAgB;AACtG,YAAM,kBAAkBA,OAAM,kBAAkB,kBAAkB,YAAY;AAC9E,YAAM,qBAAqB,IAAI,uBAAuB,kBAAkB,YAAY,CAAC;AACrF,YAAM,MAAM,IAAI,OAAO;AACvB,YAAM,OAAO,IAAI,QAAQ;AACzB,YAAM,eAAe,IAAI,gBAAgB;AACzC,UAAI,mBAAmB,cAAc;AACnC,cAAM,SAAS,kBAAkB,eAAe,IAAI,aAAa;AACjE,cAAM,SAAS,kBAAkB,eAAe,IAAI,aAAa;AACjE,cAAM,gBAAgB,SAAS,IAAI,KAAK;AACxC,cAAM,gBAAgB,SAAS,IAAI,KAAK;AACxC,cAAM,WAAW;AAAA,UACf,KAAK;AAAA,UACL,UAAU,kBAAkB;AAAA,UAC5B,UAAU;AAAA,UACV,gBAAgB;AAAA,UAChB,gBAAgB;AAAA,YACd,GAAG;AAAA,YACH,GAAG;AAAA,UACL;AAAA,UACA,gBAAgB,gBAAgB;AAAA,UAChC,iBAAiB,gBAAgB;AAAA,UACjC,kBAAkB,gBAAgB;AAAA,UAClC,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,UACjB,kBAAkB;AAAA,UAClB,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,QAAQ;AAAA,YACN,IAAI;AAAA,YACJ,UAAU,IAAI,kBAAkB,KAAK;AAAA,YACrC,gBAAgB,kBAAkB;AAAA,YAClC,gBAAgB;AAAA,YAChB,WAAW;AAAA,YACX,kBAAkB;AAAA,YAClB,eAAe;AAAA,YACf,MAAM;AAAA,YACN,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,YACnC,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,UACrC;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,CAAC,MAAM,QAAQ,GAAG,GAAG;AACvB,iBAAa,KAAK,EAAE,OAAO,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,WAAW,MAAM,OAAO,GAAG;AACjC,QAAM,WAAW,MAAM,OAAO,GAAG;AACjC,QAAM,aAAa,MAAM,kBAAkB,GAAG;AAI9C,QAAM,QAAQ,IAAI,sBAAsB;AACxC,QAAM,oBAAoB,MAAM,IAAI,QAAQ,KAAK;AACjD,QAAM,oBAAoB,MAAM,IAAI,QAAQ,KAAK;AACjD,MAAI,CAAC,MAAM,QAAQ,iBAAiB,KAAK,CAAC,MAAM,QAAQ,iBAAiB,GAAG;AAC1E,iBAAa,KAAK,EAAE,OAAO,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,mBAAmB,MAAM,kBAAkB,iBAAiB;AAClE,QAAM,mBAAmB,MAAM,kBAAkB,iBAAiB;AAClE,QAAM,iBAAiB,IAAI,uBAAuB,iBAAiB,CAAC;AACpE,QAAM,iBAAiB,IAAI,uBAAuB,iBAAiB,CAAC;AACpE,MAAI,oBAAoB,kBAAkB;AACxC,UAAM,OAAO;AAAA,MACX,GAAG;AAAA,MACH;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,gBAAgB,iBAAiB;AAAA,MACjC,gBAAgB,iBAAiB;AAAA,MACjC,iBAAiB,iBAAiB,SAAS,iBAAiB;AAAA,MAC5D,kBAAkB,iBAAiB,UAAU,iBAAiB;AAAA,MAC9D,iBAAiB,iBAAiB,SAAS,iBAAiB;AAAA,MAC5D,kBAAkB,iBAAiB,UAAU,iBAAiB;AAAA,IAChE;AAGA,UAAM,YAAY,aAAa,KAAK;AACpC,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,QAAQ,KAAK,mBAAmB,KAAK,kBAAkB,KAAK,mBAAmB,KAAK,kBAAkB,KAAK,aAAa,KAAK,YAAY,KAAK,aAAa,KAAK,YAAY,KAAK,SAAS,KAAK,QAAQ,KAAK,UAAU,KAAK,SAAS,KAAK,WAAW,KAAK,UAAU,KAAK,UAAU,KAAK,SAAS,KAAK,mBAAmB,KAAK,kBAAkB,KAAK,mBAAmB,KAAK,kBAAkB,KAAK,oBAAoB,KAAK,mBAAmB,KAAK,qBAAqB,KAAK,oBAAoB,KAAK,oBAAoB,KAAK,mBAAmB,KAAK,qBAAqB,KAAK,kBAAkB;AACtkB,aAAO;AAAA,IACT;AACA,cAAU,IAAI,KAAK,IAAI;AACvB,WAAO;AAAA,EACT;AACA,eAAa,KAAK,EAAE,OAAO,GAAG;AAC9B,SAAO;AACT,CAAC,GAAG,CAAC,GAAG,MAAM,MAAM,CAAC;;;AOrPrB,SAAS,QAAAC,cAAY;AACrB,OAAOC,YAAW;;;ACDlB,SAAS,QAAAC,cAAY;;;ACCrB,SAAS,QAAAC,aAAY;AAWd,IAAM,2BAA2BA,MAAK,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,aAAa,OAAO,WAAW,kCAAkC,EAAE,UAAU,KAAK;AAMtL,IAAM,yBAAyBA,MAAK,MAAM,CAAC,MAAM,QAAQ;AAC9D,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,WAAY;AAC9E,QAAM,MAAM,OAAO,WAAW,kCAAkC;AAChE,QAAM,UAAU,OAAK;AACnB,QAAI,0BAA0B,EAAE,OAAO;AAAA,EACzC;AAGA,MAAI,0BAA0B,IAAI,OAAO;AACzC,MAAI,iBAAiB,UAAU,OAAO;AACtC,SAAO,MAAM,IAAI,oBAAoB,UAAU,OAAO;AACxD,CAAC;;;ADvBD,IAAMC,SAAQ,YAAY,uBAAuB;AAO1C,IAAM,0BAA0BC,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AACvE,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,MAAM,QAAQ,QAAQ,cAAc,KAAK,MAAM,QAAQ,QAAQ,cAAc,GAAG;AAClF,UAAM,UAAU,QAAQ,iBAAiB,CAAC;AAC1C,UAAM,aAAa;AAAA,MACjB,MAAM,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,MAC1D,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,MAC3D,OAAO,QAAQ,aAAa;AAAA,MAC5B,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AAAA,MAC9D,QAAQ;AAAA,IACV;AACA,QAAI,CAAC,MAAM,QAAQ,QAAQ,EAAE,GAAG;AAC9B,UAAI;AACF,QAAAD,OAAM,iCAAiC,QAAQ,EAAE;AACjD,cAAM,eAAe,QAAQ,IAAI,QAAQ,gBAAgB,QAAQ,gBAAgB,UAAU;AAC3F,YAAI,WAAW,MAAM,KAAK,CAAC;AAC3B,YAAI,wBAAwB,OAAK,IAAI,CAAC;AAAA,MACxC,SAAS,GAAG;AACV,QAAAA,OAAM,6BAA6B,QAAQ,IAAI,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAKM,IAAM,+BAA+BC,OAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AAC3E,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,UAAM,SAAS,MAAM;AACrB,QAAI,WAAW,MAAM,KAAK,CAAC;AAC3B,QAAI,wBAAwB,OAAK,IAAI,CAAC;AAAA,EACxC;AACF,CAAC;AAKM,IAAM,qBAAqBA,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACtD;AAAA,EACA;AACF,MAAM;AACJ,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,MAAM,QAAQ,UAAU,GAAG;AAC7B,UAAM,SAAS,UAAU;AAAA,EAC3B;AACA,MAAI,MAAM,QAAQ,QAAQ,cAAc,KAAK,MAAM,QAAQ,QAAQ,cAAc,GAAG;AAClF,UAAM,UAAU,QAAQ,iBAAiB,CAAC;AAC1C,UAAM,aAAa;AAAA,MACjB,MAAM,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,MAC1D,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,MAC3D,OAAO,QAAQ,aAAa;AAAA,MAC5B,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AAAA,MAC9D,QAAQ;AAAA,IACV;AACA,QAAI,CAAC,MAAM,QAAQ,QAAQ,EAAE,GAAG;AAC9B,UAAI;AACF,QAAAD,OAAM,sDAAsD,YAAY,QAAQ,EAAE;AAClF,cAAM,eAAe,QAAQ,IAAI,QAAQ,gBAAgB,QAAQ,gBAAgB,UAAU;AAAA,MAC7F,SAAS,GAAG;AACV,QAAAA,OAAM,6BAA6B,QAAQ,IAAI,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW,MAAM,KAAK,CAAC;AAC3B,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACxC,CAAC;AAQM,IAAM,qBAAqBC,OAAK,oBAAI,IAAI,CAAC;AAKzC,IAAM,0BAA0B;AAOhC,IAAM,8BAA8BA,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AAC3E,QAAM,YAAY,IAAI,eAAe,OAAO,CAAC;AAC7C,MAAI,WAAW;AACb,UAAM,YAAY,IAAI,IAAI,IAAI,kBAAkB,CAAC;AACjD,cAAU,IAAI,SAAS,SAAS;AAChC,QAAI,oBAAoB,SAAS;AACjC,QAAI,8BAA8B,OAAO;AACzC,UAAM,WAAW,IAAI,wBAAwB,IAAI,IAAI;AACrD,eAAW,MAAM;AACf,YAAM,UAAU,IAAI,IAAI,IAAI,kBAAkB,CAAC;AAC/C,cAAQ,OAAO,OAAO;AACtB,UAAI,oBAAoB,OAAO;AAAA,IACjC,GAAG,QAAQ;AAAA,EACb;AACF,CAAC;AAQM,IAAM,uBAAuBA,OAAK,IAAI;AAKtC,IAAM,sBAAsBA,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACvD;AAAA,EACA;AACF,MAAM;AACJ,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,UAAM,iBAAiB,SAAS,SAAS,SAAS,MAAS;AAC3D,QAAI,wBAAwB,OAAK,IAAI,CAAC;AACtC,QAAI,+BAA+B,OAAK,IAAI,CAAC;AAAA,EAC/C;AACF,CAAC;;;AEzID,SAAS,QAAAC,cAAY;AAOrB,IAAMC,SAAQ,YAAY,0BAA0B;AAS7C,IAAM,uBAAuBC,OAAK,IAAI;AAQtC,IAAM,gBAAgBA,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG;AAC5B,QAAM,QAAQ,MAAM,kBAAkB,MAAM;AAC5C,QAAM,UAAU,IAAI,kBAAkB,KAAK,MAAM,OAAO;AAGxD,MAAI,iBAAiB,YAAY;AAGjC,QAAM,iBAAiB,QAAQ,KAAK,UAAU,CAAC;AAC/C,QAAM,iBAAiB,QAAQ,KAAK,UAAU,CAAC;AAG/C,QAAM,QAAQ,CAAC;AACf,QAAM,YAAY,QAAQ,CAAC,MAAM,QAAQ,QAAQ,WAAW;AAC1D,UAAM,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AAAA,EACH,CAAC;AAGD,QAAM,UAAU,SAAS,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAC7E,QAAM,cAAc;AAAA,IAClB,GAAG,MAAM;AAAA,IACT,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,eAAe;AAAA,MACb,GAAI,MAAM,OAAO,iBAAiB,CAAC;AAAA,MACnC,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACf;AAAA,IACA,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACnC,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,EACrC;AACA,MAAI,yBAAyB,WAAW;AAGxC,aAAW,QAAQ,OAAO;AACxB,UAAM,YAAY,KAAK,WAAW,SAAS,UAAU,KAAK;AAC1D,UAAM,YAAY,KAAK,WAAW,SAAS,UAAU,KAAK;AAC1D,QAAI,yBAAyB;AAAA,MAC3B,GAAG,KAAK,MAAM;AAAA,MACd,IAAI,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,MACnE,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH;AACA,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACtC,MAAI,+BAA+B,OAAK,IAAI,CAAC;AAC7C,EAAAD,OAAM,iCAA4B,QAAQ,OAAO;AACnD,CAAC;AASM,IAAM,iBAAiBC,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EAClD;AACF,MAAM;AACJ,MAAI,QAAQ,SAAS,EAAG;AACxB,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,CAAC,YAAY,GAAG,MAAM,IAAI;AAChC,MAAI,CAAC,MAAM,QAAQ,UAAU,EAAG;AAGhC,MAAI,iBAAiB,SAAS,QAAQ,MAAM,QAAQ;AACpD,QAAM,YAAY,IAAI,IAAI,MAAM;AAChC,aAAW,YAAY,QAAQ;AAC7B,QAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG;AAG9B,UAAM,QAAQ,CAAC;AACf,UAAM,YAAY,UAAU,CAAC,MAAM,QAAQ,QAAQ,WAAW;AAC5D,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AACD,eAAW,QAAQ,OAAO;AACxB,YAAM,YAAY,UAAU,IAAI,KAAK,MAAM,IAAI,aAAa,KAAK;AACjE,YAAM,YAAY,UAAU,IAAI,KAAK,MAAM,IAAI,aAAa,KAAK;AAEjE,UAAI,cAAc,UAAW;AAC7B,UAAI,yBAAyB;AAAA,QAC3B,GAAG,KAAK,MAAM;AAAA,QACd,IAAI,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,QACnE,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH;AAGA,QAAI,0BAA0B;AAAA,MAC5B,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AACA,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACtC,EAAAD,OAAM,sCAAiC,SAAS,UAAU;AAC5D,CAAC;;;AH9HD,IAAME,SAAQ,YAAY,iBAAiB;AAOpC,IAAM,oBAAoBC,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACrD;AACF,MAAM;AACJ,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG;AAC5B,QAAM,oBAAoB,MAAM,kBAAkB,MAAM;AACxD,MAAI,2BAA2B,KAAK,MAAM,KAAK,UAAU,iBAAiB,CAAC,CAAC;AAC5E,QAAM,uBAAuB,IAAI,iBAAiB;AAClD,QAAM,YAAY,uBAAuB;AACzC,QAAM,iBAAiB,QAAQ,UAAU,SAAS;AAClD,MAAI,oBAAoB,MAAM;AAChC,CAAC;AAKM,IAAM,kBAAkBA,OAAK,MAAM,CAAC,KAAK,KAAK,aAAa;AAChE,QAAM,oBAAoB,IAAI,kBAAkB;AAChD,MAAI,mBAAmB;AACrB,IAAAD,OAAM,sBAAsB,iBAAiB;AAG7C,UAAM,QAAQ,IAAI,SAAS;AAC3B,QAAI,MAAM,QAAQ,iBAAiB,GAAG;AACpC,YAAM,WAAW,MAAM,iBAAiB,mBAAmB,UAAU;AACrE,UAAI,UAAU;AACZ,YAAI,qBAAqB,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACA,MAAI,oBAAoB,IAAI;AAC5B,MAAI,2BAA2B,IAAI;AACrC,CAAC;AAKM,IAAM,2BAA2BC,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EAC5D;AACF,MAAM;AACJ,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,UAAM,SAAS,MAAM;AACrB,QAAI,yBAAyB,MAAM;AACnC,QAAI,WAAW,MAAM,KAAK,CAAC;AAC3B,IAAAD,OAAM,kCAAkC,MAAM;AAAA,EAChD;AACF,CAAC;AAKM,IAAM,2BAA2BC,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EAC5D;AACF,MAAM;AACJ,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,UAAM,SAAS,OAAO;AACtB,QAAI,WAAW,MAAM,KAAK,CAAC;AAC3B,IAAAD,OAAM,kCAAkC,OAAO;AAAA,EACjD;AACF,CAAC;AAOM,IAAM,0BAA0BC,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AACvE,QAAM,QAAQ,IAAI,SAAS;AAC3B,MAAI,MAAM,QAAQ,QAAQ,EAAE,GAAG;AAC7B,IAAAD,OAAM,oCAAoC,QAAQ,EAAE;AACpD;AAAA,EACF;AACA,QAAM,UAAU,QAAQ,iBAAiB,CAAC;AAC1C,QAAM,aAAa;AAAA,IACjB,GAAG,OAAO,QAAQ,MAAM,WAAW,QAAQ,IAAI,KAAK,OAAO,IAAI;AAAA,IAC/D,GAAG,OAAO,QAAQ,MAAM,WAAW,QAAQ,IAAI,KAAK,OAAO,IAAI;AAAA,IAC/D,MAAM,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAAA,IACxD,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,IAC3D,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AAAA,IAC9D,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,IAC3D,OAAO,QAAQ,SAAS,QAAQ,aAAa,QAAQ;AAAA,IACrD,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AAAA,IAC9D,QAAQ;AAAA,EACV;AACA,EAAAA,OAAM,6CAA6C,QAAQ,IAAI,WAAW,GAAG,WAAW,CAAC;AACzF,QAAM,QAAQ,QAAQ,IAAI,UAAU;AAEpC,MAAI,WAAW,MAAM,KAAK,CAAC;AAC3B,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACtC,MAAI,+BAA+B,OAAK,IAAI,CAAC;AAC/C,CAAC;AAYM,IAAM,sBAAsBC,OAAK,MAAM,CAAC,KAAK,KAAK,cAAc,iBAAiB;AACtF,EAAAD,OAAM,kCAAkC;AACxC,EAAAA,OAAM,gCAAgC,aAAa,QAAQ,aAAa,MAAM;AAC9E,QAAM,iBAAiB,IAAI,kBAAkB;AAG7C,MAAI,aAAa,SAAS,KAAK,aAAa,CAAC,EAAE,aAAa,gBAAgB;AAC1E,IAAAA,OAAM,iDAAiD;AACvD;AAAA,EACF;AACA,QAAM,gBAAgB,IAAI,SAAS;AACnC,QAAM,aAAa,IAAI,kBAAkB,MAAM;AAC/C,MAAI,YAAY;AACd,IAAAA,OAAM,kCAAkC;AACxC;AAAA,EACF;AAGA,QAAM,kBAAkB,IAAI,IAAI,cAAc,MAAM,CAAC;AACrD,QAAM,iBAAiB,IAAI,IAAI,aAAa,IAAI,OAAK,EAAE,EAAE,CAAC;AAC1D,QAAM,oBAAoB,MAAM,KAAK,eAAe,EAAE,KAAK,QAAM,eAAe,IAAI,EAAE,CAAC;AACvF,MAAI;AACJ,MAAI,qBAAqB,gBAAgB,OAAO,GAAG;AACjD,IAAAA,OAAM,qCAAqC;AAC3C,YAAQ,cAAc,KAAK;AAAA,EAC7B,OAAO;AACL,IAAAA,OAAM,8CAA8C;AACpD,YAAQ,IAAIE,OAAM,YAAY;AAAA,EAChC;AACA,QAAM,iBAAiB,IAAI,IAAI,aAAa,IAAI,OAAK,EAAE,EAAE,CAAC;AAG1D,MAAI,qBAAqB,gBAAgB,OAAO,GAAG;AACjD,UAAM,YAAY,YAAU;AAC1B,UAAI,CAAC,eAAe,IAAI,MAAM,GAAG;AAC/B,QAAAF,OAAM,6BAA6B,MAAM;AACzC,cAAM,SAAS,MAAM;AACrB,+BAAuB,OAAO,MAAM;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AAGA,eAAa,QAAQ,UAAQ;AAC3B,UAAM,UAAU,KAAK,iBAAiB,CAAC;AACvC,UAAM,OAAO,OAAO,QAAQ,MAAM,WAAW,QAAQ,IAAI,KAAK,OAAO,IAAI;AACzE,UAAM,OAAO,OAAO,QAAQ,MAAM,WAAW,QAAQ,IAAI,KAAK,OAAO,IAAI;AACzE,QAAI,MAAM,QAAQ,KAAK,EAAE,GAAG;AAC1B,YAAM,eAAe,MAAM,kBAAkB,KAAK,EAAE;AACpD,YAAM,aAAa;AAAA,QACjB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,MAAM,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO,aAAa;AAAA,QACrE,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,aAAa,SAAS;AAAA,QACjF,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS,aAAa,UAAU;AAAA,QACrF,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,aAAa;AAAA,QACxE,OAAO,KAAK,SAAS,KAAK,aAAa,KAAK;AAAA,QAC5C,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS,aAAa;AAAA,QAC3E,QAAQ;AAAA,MACV;AACA,YAAM,sBAAsB,KAAK,IAAI,UAAU;AAAA,IACjD,OAAO;AACL,YAAM,aAAa;AAAA,QACjB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,MAAM,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAAA,QACxD,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,QAC3D,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AAAA,QAC9D,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,QAC3D,OAAO,KAAK,SAAS,KAAK,aAAa,KAAK;AAAA,QAC5C,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AAAA,QAC9D,QAAQ;AAAA,MACV;AACA,YAAM,QAAQ,KAAK,IAAI,UAAU;AAAA,IACnC;AAAA,EACF,CAAC;AAGD,QAAM,YAAY,YAAU;AAC1B,QAAI,CAAC,eAAe,IAAI,MAAM,GAAG;AAC/B,MAAAA,OAAM,6BAA6B,MAAM;AACzC,YAAM,SAAS,MAAM;AAAA,IACvB;AAAA,EACF,CAAC;AAGD,eAAa,QAAQ,UAAQ;AAC3B,QAAI,MAAM,QAAQ,KAAK,cAAc,KAAK,MAAM,QAAQ,KAAK,cAAc,GAAG;AAC5E,YAAM,UAAU,KAAK,iBAAiB,CAAC;AACvC,YAAM,aAAa;AAAA,QACjB,MAAM,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,QAC1D,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,QAC3D,OAAO,KAAK,aAAa;AAAA,QACzB,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AAAA,QAC9D,QAAQ;AAAA,MACV;AACA,UAAI,MAAM,QAAQ,KAAK,EAAE,GAAG;AAC1B,cAAM,sBAAsB,KAAK,IAAI,UAAU;AAAA,MACjD,OAAO;AACL,YAAI;AACF,gBAAM,eAAe,KAAK,IAAI,KAAK,gBAAgB,KAAK,gBAAgB,UAAU;AAAA,QACpF,SAAS,GAAG;AACV,UAAAA,OAAM,6BAA6B,KAAK,IAAI,CAAC;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,MAAI,WAAW,KAAK;AACpB,MAAI,wBAAwB,OAAK,IAAI,CAAC;AACtC,EAAAA,OAAM,qCAAqC;AAC3C,EAAAA,OAAM,mCAAmC,MAAM,OAAO,MAAM,IAAI;AAClE,CAAC;;;AItOD,SAAS,QAAAG,cAAY;AAErB,IAAMC,SAAQ,YAAY,MAAM;AAOzB,IAAM,iBAAiBC,OAAK,QAAQ;AAKpC,IAAM,4BAA4BA,OAAK,CAAC;AAKxC,IAAM,eAAeA,OAAK,OAAO,cAAc,cAAc,UAAU,SAAS,IAAI;AAKpF,IAAM,oBAAoBA,OAAK,IAAI;AAKnC,IAAM,mBAAmBA,OAAK,KAAK,IAAI,CAAC;AAKxC,IAAM,oBAAoBA,OAAK,CAAC,CAAC;AAOjC,IAAM,gBAAgBA,OAAK,UAAQ;AAAA,EACxC,QAAQ,IAAI,cAAc;AAAA,EAC1B,kBAAkB,IAAI,yBAAyB;AAAA,EAC/C,WAAW,IAAI,iBAAiB;AAAA,EAChC,cAAc,IAAI,gBAAgB;AAAA,EAClC,UAAU,IAAI,YAAY;AAAA,EAC1B,iBAAiB,IAAI,iBAAiB,EAAE;AAC1C,EAAE;AAOK,IAAM,oBAAoBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AACxD,QAAM,eAAe,IAAI,yBAAyB;AAClD,QAAM,WAAW,eAAe;AAChC,MAAI,2BAA2B,QAAQ;AACvC,EAAAD,OAAM,6CAA6C,cAAc,QAAQ;AACzE,MAAI,WAAW,KAAK,IAAI,cAAc,MAAM,WAAW;AACrD,QAAI,gBAAgB,SAAS;AAC7B,IAAAA,OAAM,mBAAmB;AAAA,EAC3B;AACF,CAAC;AAKM,IAAM,uBAAuBC,OAAK,MAAM,CAAC,KAAK,KAAK,UAAU,SAAS;AAC3E,QAAM,eAAe,IAAI,yBAAyB;AAClD,QAAM,WAAW,KAAK,IAAI,GAAG,eAAe,CAAC;AAC7C,MAAI,2BAA2B,QAAQ;AACvC,EAAAD,OAAM,6DAA6D,SAAS,cAAc,QAAQ;AAClG,MAAI,SAAS;AACX,QAAI,kBAAkB,KAAK,IAAI,CAAC;AAChC,QAAI,aAAa,GAAG;AAClB,UAAI,mBAAmB,IAAI;AAAA,IAC7B;AAAA,EACF;AAGA,MAAI,aAAa,GAAG;AAClB,UAAM,WAAW,IAAI,YAAY;AACjC,UAAM,WAAW,IAAI,iBAAiB,MAAM;AAC5C,QAAI,UAAU;AACZ,UAAI,gBAAgB,OAAO;AAC3B,MAAAA,OAAM,iBAAiB;AAAA,IACzB,WAAW,CAAC,UAAU;AACpB,UAAI,gBAAgB,SAAS;AAC7B,MAAAA,OAAM,mBAAmB;AAAA,IAC3B,OAAO;AACL,UAAI,gBAAgB,QAAQ;AAC5B,MAAAA,OAAM,kBAAkB;AAAA,IAC1B;AAAA,EACF;AACF,CAAC;AAKM,IAAM,yBAAyBC,OAAK,MAAM,CAAC,MAAM,KAAK,UAAU;AACrE,MAAI,mBAAmB,KAAK;AAC5B,EAAAD,OAAM,uBAAuB,KAAK;AACpC,CAAC;AAOM,IAAM,sBAAsBC,OAAK,MAAM,CAAC,KAAK,KAAK,aAAa;AACpE,MAAI,cAAc,QAAQ;AAC1B,QAAM,eAAe,IAAI,yBAAyB;AAClD,QAAM,WAAW,IAAI,iBAAiB,MAAM;AAC5C,QAAM,cAAc,IAAI,iBAAiB,EAAE;AAC3C,MAAI,iBAAiB,GAAG;AACtB,QAAI,YAAY,cAAc,GAAG;AAC/B,UAAI,gBAAgB,OAAO;AAAA,IAC7B,OAAO;AACL,UAAI,gBAAgB,WAAW,WAAW,SAAS;AAAA,IACrD;AAAA,EACF;AACF,CAAC;AAOM,IAAM,oBAAoBA,OAAK,MAAM,CAAC,KAAK,KAAK,aAAa;AAClE,QAAM,QAAQ,IAAI,iBAAiB;AACnC,QAAM,cAAc;AAAA,IAClB,GAAG;AAAA,IACH,IAAI,OAAO,WAAW;AAAA,IACtB,WAAW,KAAK,IAAI;AAAA,IACpB,YAAY;AAAA,IACZ,YAAY,SAAS,cAAc;AAAA,EACrC;AACA,QAAM,WAAW,CAAC,GAAG,OAAO,WAAW;AACvC,MAAI,mBAAmB,QAAQ;AAC/B,EAAAD,OAAM,uCAAuC,SAAS,MAAM,SAAS,MAAM;AAC3E,MAAI,IAAI,yBAAyB,MAAM,GAAG;AACxC,QAAI,gBAAgB,OAAO;AAAA,EAC7B;AACA,SAAO,YAAY;AACrB,CAAC;AAKM,IAAM,sBAAsBC,OAAK,MAAM,CAAC,KAAK,KAAK,eAAe;AACtE,QAAM,QAAQ,IAAI,iBAAiB;AACnC,QAAM,WAAW,MAAM,OAAO,OAAK,EAAE,OAAO,UAAU;AACtD,MAAI,mBAAmB,QAAQ;AAC/B,EAAAD,OAAM,yCAAyC,YAAY,SAAS,MAAM;AAC1E,MAAI,SAAS,WAAW,KAAK,IAAI,yBAAyB,MAAM,KAAK,IAAI,iBAAiB,MAAM,MAAM;AACpG,QAAI,gBAAgB,IAAI,YAAY,IAAI,WAAW,SAAS;AAAA,EAC9D;AACF,CAAC;AAKM,IAAM,0BAA0BC,OAAK,MAAM,CAAC,KAAK,KAAK,eAAe;AAC1E,QAAM,QAAQ,IAAI,iBAAiB;AACnC,QAAM,WAAW,MAAM,IAAI,OAAK,EAAE,OAAO,aAAa;AAAA,IACpD,GAAG;AAAA,IACH,YAAY,EAAE,aAAa;AAAA,EAC7B,IAAI,CAAC;AACL,MAAI,mBAAmB,QAAQ;AACjC,CAAC;AAKM,IAAM,4BAA4BA,OAAK,SAAO;AACnD,QAAM,QAAQ,IAAI,iBAAiB;AACnC,SAAO,MAAM,KAAK,OAAK,EAAE,aAAa,EAAE,UAAU,KAAK;AACzD,CAAC;AAKM,IAAM,yBAAyBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC7D,MAAI,mBAAmB,CAAC,CAAC;AACzB,EAAAD,OAAM,wBAAwB;AAC9B,MAAI,IAAI,yBAAyB,MAAM,KAAK,IAAI,iBAAiB,MAAM,MAAM;AAC3E,QAAI,gBAAgB,IAAI,YAAY,IAAI,WAAW,SAAS;AAAA,EAC9D;AACF,CAAC;;;AC7LD,SAAS,QAAAE,cAAY;AA8Bd,IAAM,gBAAgBA,OAAK;AAAA,EAChC,MAAM;AACR,CAAC;AAKM,IAAM,8BAA8BA,OAAK,UAAU;AAKnD,IAAM,0BAA0BA,OAAK,IAAI;AAKzC,IAAM,2BAA2BA,OAAK,IAAI;AAS1C,IAAM,qBAAqBA,OAAK,MAAM,CAAC,MAAM,QAAQ;AAC1D,MAAI,eAAe;AAAA,IACjB,MAAM;AAAA,EACR,CAAC;AACD,MAAI,yBAAyB,IAAI;AACjC,MAAI,0BAA0B,IAAI;AACpC,CAAC;AAKM,IAAM,mCAAmCA,OAAK,MAAM,CAAC,MAAM,QAAQ;AACxE,MAAI,6BAA6B,UAAU;AAC7C,CAAC;AAKM,IAAM,iCAAiCA,OAAK,MAAM,CAAC,MAAM,KAAK,SAAS;AAC5E,MAAI,6BAA6B,IAAI;AACvC,CAAC;AAKM,IAAM,oBAAoBA,OAAK,MAAM,CAAC,MAAM,KAAK,YAAY;AAClE,MAAI,eAAe;AAAA,IACjB,MAAM;AAAA,IACN,GAAG;AAAA,EACL,CAAC;AACH,CAAC;AAKM,IAAM,qBAAqBA,OAAK,MAAM,CAAC,MAAM,KAAK,YAAY;AACnE,MAAI,eAAe;AAAA,IACjB,MAAM;AAAA,IACN,GAAG;AAAA,EACL,CAAC;AACH,CAAC;AAKM,IAAM,qBAAqBA,OAAK,MAAM,CAAC,MAAM,KAAK,YAAY;AACnE,MAAI,eAAe;AAAA,IACjB,MAAM;AAAA,IACN,GAAG;AAAA,EACL,CAAC;AACH,CAAC;AAKM,IAAM,mBAAmBA,OAAK,MAAM,CAAC,KAAK,KAAK,UAAU;AAC9D,MAAI,0BAA0B,KAAK;AAErC,CAAC;AAKM,IAAM,gCAAgCA,OAAK,MAAM,CAAC,KAAK,KAAK,aAAa;AAC9E,QAAM,UAAU,IAAI,uBAAuB;AAC3C,MAAI,yBAAyB;AAAA,IAC3B,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AACH,CAAC;AASM,IAAM,oBAAoBA,OAAK,SAAO;AAC3C,QAAM,OAAO,IAAI,aAAa;AAC9B,SAAO,KAAK,SAAS;AACvB,CAAC;AAKM,IAAM,qBAAqBA,OAAK,SAAO;AAC5C,QAAM,OAAO,IAAI,aAAa;AAC9B,SAAO,KAAK,SAAS,cAAc,KAAK,SAAS;AACnD,CAAC;;;ACjJD,SAAS,QAAAC,cAAY;AAUd,IAAM,mBAAmBC,OAAK,IAAI;AAKlC,IAAM,qBAAqBA,OAAK,SAAO;AAC5C,QAAM,KAAK,IAAI,gBAAgB;AAC/B,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,QAAQ,IAAI,WAAW;AAC7B,SAAO,MAAM,KAAK,OAAK,EAAE,OAAO,EAAE,KAAK;AACzC,CAAC;AAKM,IAAM,0BAA0BA,OAAK,CAAC;AAKtC,IAAM,0BAA0BA,OAAK,CAAC;AAWtC,IAAM,eAAeA,OAAK,MAAM,CAAC,MAAM,KAAK,YAAY;AAC7D,MAAI,kBAAkB,QAAQ,MAAM;AACpC,MAAI,yBAAyB,CAAC;AAChC,CAAC;AAKM,IAAM,iBAAiBA,OAAK,MAAM,CAAC,MAAM,QAAQ;AACtD,MAAI,kBAAkB,IAAI;AAC5B,CAAC;AAKM,IAAM,qBAAqBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AACzD,QAAM,UAAU,IAAI,uBAAuB;AAC3C,QAAM,YAAY,IAAI,uBAAuB;AAC7C,MAAI,0BAA0B,UAAU,KAAK,SAAS;AACxD,CAAC;AAKM,IAAM,qBAAqBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AACzD,QAAM,UAAU,IAAI,uBAAuB;AAC3C,QAAM,YAAY,IAAI,uBAAuB;AAC7C,MAAI,0BAA0B,UAAU,IAAI,aAAa,SAAS;AACpE,CAAC;AAKM,IAAM,qBAAqBA,OAAK,MAAM,CAAC,KAAK,KAAK,UAAU;AAChE,QAAM,YAAY,IAAI,uBAAuB;AAC7C,MAAI,SAAS,KAAK,QAAQ,WAAW;AACnC,QAAI,yBAAyB,KAAK;AAAA,EACpC;AACF,CAAC;AASM,IAAM,oBAAoBA,OAAK,SAAO,IAAI,gBAAgB,MAAM,IAAI;;;AC/F3E,SAAS,KAAK,UAAU;AAQxB,OAAO,WAAW;AAalB,SAAS,QAAQ,OAAO,OAAO,YAAY;;;ACd3C,SAAS,QAAAC,cAAY;AAEd,IAAM,kBAAkBA,OAAK,IAAI;AAGjC,IAAM,gBAAgBA,OAAK,MAAM,CAAC,MAAM,KAAK,YAAY;AAC9D,QAAM,KAAK,SAAS,KAAK,IAAI,CAAC;AAC9B,MAAI,iBAAiB;AAAA,IACnB;AAAA,IACA;AAAA,IACA,WAAW,KAAK,IAAI;AAAA,EACtB,CAAC;AACD,aAAW,MAAM;AACf,QAAI,iBAAiB,aAAW,SAAS,OAAO,KAAK,OAAO,OAAO;AAAA,EACrE,GAAG,GAAI;AACT,CAAC;;;ACfD,SAAS,QAAAC,cAAY;AAMd,IAAM,kBAAkBA,OAAK,KAAK;AAGlC,IAAM,mBAAmBA,OAAK,EAAE;AAGhC,IAAM,2BAA2BA,OAAK,KAAK;AAO3C,IAAM,uBAAuBA,OAAK,SAAO;AAC9C,SAAO,IAAI,eAAe,KAAK,CAAC,IAAI,wBAAwB;AAC9D,CAAC;AAyCM,IAAM,iBAAiBC,OAAK,MAAM,CAAC,KAAK,QAAQ;AACrD,MAAI,iBAAiB,CAAC,IAAI,eAAe,CAAC;AAC5C,CAAC;AAGM,IAAM,kBAAkBA,OAAK,MAAM,CAAC,MAAM,KAAK,SAAS;AAC7D,MAAI,kBAAkB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC;AACxD,CAAC;AAOM,IAAM,2BAA2BA,OAAK,IAAI;AAG1C,IAAM,4BAA4BA,OAAK,MAAM,CAAC,KAAK,QAAQ;AAChE,MAAI,0BAA0B,CAAC,IAAI,wBAAwB,CAAC;AAC9D,CAAC;AAIM,IAAM,sBAAsBA,OAAK;AAAA,EACtC,gBAAgB,CAAC;AAAA,EACjB,kBAAkB,CAAC;AACrB,CAAC;AAGM,IAAM,2BAA2BA,OAAK,MAAM,CAAC,MAAM,QAAQ;AAChE,MAAI,qBAAqB;AAAA,IACvB,gBAAgB,CAAC;AAAA,IACjB,kBAAkB,CAAC;AAAA,EACrB,CAAC;AACH,CAAC;;;ACtFM,IAAI,kBAA+B,0BAAUC,kBAAiB;AAEnE,EAAAA,iBAAgB,WAAW,IAAI;AAC/B,EAAAA,iBAAgB,iBAAiB,IAAI;AACrC,EAAAA,iBAAgB,iBAAiB,IAAI;AACrC,EAAAA,iBAAgB,gBAAgB,IAAI;AACpC,EAAAA,iBAAgB,eAAe,IAAI;AAEnC,EAAAA,iBAAgB,WAAW,IAAI;AAC/B,EAAAA,iBAAgB,iBAAiB,IAAI;AACrC,EAAAA,iBAAgB,gBAAgB,IAAI;AAEpC,EAAAA,iBAAgB,iBAAiB,IAAI;AACrC,EAAAA,iBAAgB,uBAAuB,IAAI;AAC3C,EAAAA,iBAAgB,sBAAsB,IAAI;AAC1C,EAAAA,iBAAgB,qBAAqB,IAAI;AACzC,SAAOA;AACT,GAAE,CAAC,CAAC;AASG,IAAM,kBAAkB;AAAA,EAC7B,CAAC,gBAAgB,SAAS,GAAG;AAAA,IAC3B,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,eAAe,GAAG;AAAA,IACjC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,eAAe,GAAG;AAAA,IACjC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,cAAc,GAAG;AAAA,IAChC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,aAAa,GAAG;AAAA,IAC/B,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,SAAS,GAAG;AAAA,IAC3B,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,eAAe,GAAG;AAAA,IACjC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,cAAc,GAAG;AAAA,IAChC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,eAAe,GAAG;AAAA,IACjC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,qBAAqB,GAAG;AAAA,IACvC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,oBAAoB,GAAG;AAAA,IACtC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,gBAAgB,mBAAmB,GAAG;AAAA,IACrC,MAAM,gBAAgB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AACF;;;ACnGO,IAAI,iBAA8B,0BAAUC,iBAAgB;AAEjE,EAAAA,gBAAe,MAAM,IAAI;AAEzB,EAAAA,gBAAe,WAAW,IAAI;AAE9B,EAAAA,gBAAe,UAAU,IAAI;AAE7B,EAAAA,gBAAe,MAAM,IAAI;AAEzB,EAAAA,gBAAe,QAAQ,IAAI;AAE3B,EAAAA,gBAAe,SAAS,IAAI;AAE5B,EAAAA,gBAAe,QAAQ,IAAI;AAC3B,SAAOA;AACT,GAAE,CAAC,CAAC;AAUG,IAAM,kBAAkB;AAAA;AAAA,EAE7B,MAAM;AAAA;AAAA,EAEN,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAEhB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA;AAAA,EAEf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA;AAAA,EAEZ,kBAAkB;AAAA;AAAA,EAElB,MAAM;AAAA,EACN,MAAM;AAAA;AAAA,EAEN,YAAY;AACd;;;AC5BO,IAAM,mBAAmB;AAAA,EAC9B,CAAC,gBAAgB,SAAS,GAAG,gBAAgB;AAAA,EAC7C,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,EACnD,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,EACnD,CAAC,gBAAgB,cAAc,GAAG,gBAAgB;AAAA,EAClD,CAAC,gBAAgB,aAAa,GAAG,gBAAgB;AAAA,EACjD,CAAC,gBAAgB,SAAS,GAAG,gBAAgB;AAAA,EAC7C,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,EACnD,CAAC,gBAAgB,cAAc,GAAG,gBAAgB;AAAA,EAClD,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,EACnD,CAAC,gBAAgB,qBAAqB,GAAG,gBAAgB;AAAA,EACzD,CAAC,gBAAgB,oBAAoB,GAAG,gBAAgB;AAAA,EACxD,CAAC,gBAAgB,mBAAmB,GAAG,gBAAgB;AACzD;;;ACjDO,SAAS,2BAA2B;AACzC,EAAAC,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,cAAc;AAAA,IACd,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,WAAW,QAAQ,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,WAAW,QAAQ,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,cAAc;AAAA,IACd,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,eAAe,QAAQ,MAAM;AAAA,MACvC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,CAAC,UAAU,YAAY;AAC9B,cAAQ,eAAe;AAAA,IACzB;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,OAAO,UAAU,YAAY;AACpC,YAAM,cAAc,QAAQ,mBAAmB;AAC/C,iBAAW,UAAU,aAAa;AAChC,cAAM,QAAQ,WAAW,MAAM;AAAA,MACjC;AAAA,IACF;AAAA,EACF,CAAC;AACH;AACO,SAAS,sBAAsB;AACpC,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,cAAc;AAAA,IACd,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,SAAS,QAAQ,MAAM;AAAA,MACjC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,cAAc;AAAA,IACd,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,WAAW,QAAQ,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,cAAc;AAAA,IACd,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,WAAW,QAAQ,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,iBAAiB;AAC3B,gBAAQ,gBAAgB,QAAQ,gBAAgB,QAAQ,MAAM;AAAA,MAChE;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,OAAO,SAAS,YAAY;AACnC,UAAI,QAAQ,YAAY;AACtB,cAAM,QAAQ,WAAW,QAAQ,aAAa;AAAA,MAChD;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,OAAO,SAAS,YAAY;AACnC,UAAI,QAAQ,aAAa,QAAQ,QAAQ;AACvC,cAAM,QAAQ,UAAU,QAAQ,MAAM;AAAA,MACxC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,OAAO,SAAS,YAAY;AACnC,UAAI,QAAQ,YAAY;AACtB,cAAM,QAAQ,WAAW,QAAQ,mBAAmB,QAAQ,mBAAmB,CAAC;AAAA,MAClF;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,OAAO,SAAS,YAAY;AACnC,UAAI,QAAQ,YAAY;AACtB,cAAM,QAAQ,WAAW,QAAQ,mBAAmB,QAAQ,mBAAmB,CAAC;AAAA,MAClF;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AChLO,SAAS,0BAA0B;AACxC,EAAAC,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,cAAc;AAAA,IACd,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,aAAa,QAAQ,MAAM;AAAA,MACrC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,CAAC,UAAU,YAAY;AAC9B,cAAQ,YAAY,OAAO;AAAA,IAC7B;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,cAAc;AAAA,IACd,WAAW;AAAA,IACX,SAAS,CAAC,SAAS,YAAY;AAC7B,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,aAAa,QAAQ,MAAM;AAAA,MACrC;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,CAAC,UAAU,YAAY;AAC9B,cAAQ,cAAc;AAAA,IACxB;AAAA,EACF,CAAC;AACH;AACO,SAAS,yBAAyB;AACvC,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,CAAC,UAAU,YAAY;AAC9B,UAAI,QAAQ,QAAQ,GAAG;AACrB,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,CAAC,UAAU,YAAY;AAC9B,UAAI,QAAQ,QAAQ,GAAG;AACrB,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AACD,EAAAA,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,OAAO,UAAU,YAAY;AACpC,YAAM,QAAQ,iBAAiB;AAAA,IACjC;AAAA,EACF,CAAC;AACH;;;AC9EO,SAAS,yBAAyB;AAEvC,EAAAC,gBAAe;AAAA,IACb,IAAI,gBAAgB;AAAA,IACpB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,eAAe;AAAA,IACzB,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,MAAM;AAAA,IAEf;AAAA,EACF,CAAC;AACD,2BAAyB;AACzB,sBAAoB;AACpB,0BAAwB;AACxB,yBAAuB;AACzB;;;ACxBA,IAAM,iBAAiB,oBAAI,IAAI;AAUxB,SAASC,gBAAe,QAAQ;AACrC,iBAAe,IAAI,OAAO,IAAI,MAAM;AACtC;AAiDA,uBAAuB;;;AC3DvB,IAAMC,SAAQ,YAAY,SAAS;;;ACNnC,SAAS,QAAAC,cAAY;AACrB,SAAS,uBAAuB;;;ACEzB,IAAM,mBAAmB,CAAC;AAAA,EAC/B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AACZ,GAAG;AAAA,EACD,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA,IACR,CAAC,gBAAgB,SAAS,GAAG,gBAAgB;AAAA,IAC7C,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,IACnD,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,IACnD,CAAC,gBAAgB,cAAc,GAAG,gBAAgB;AAAA,IAClD,CAAC,gBAAgB,aAAa,GAAG,gBAAgB;AAAA,IACjD,CAAC,gBAAgB,SAAS,GAAG,gBAAgB;AAAA,IAC7C,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,IACnD,CAAC,gBAAgB,cAAc,GAAG,gBAAgB;AAAA,IAClD,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,IACnD,CAAC,gBAAgB,qBAAqB,GAAG,gBAAgB;AAAA,IACzD,CAAC,gBAAgB,oBAAoB,GAAG,gBAAgB;AAAA,IACxD,CAAC,gBAAgB,mBAAmB,GAAG,gBAAgB;AAAA,EACzD;AACF,GAAG;AAAA,EACD,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA,IACR,CAAC,gBAAgB,SAAS,GAAG,gBAAgB;AAAA,IAC7C,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,IACnD,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,IACnD,CAAC,gBAAgB,cAAc,GAAG,gBAAgB;AAAA,IAClD,CAAC,gBAAgB,aAAa,GAAG,gBAAgB;AAAA,IACjD,CAAC,gBAAgB,SAAS,GAAG,gBAAgB;AAAA,IAC7C,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,IACnD,CAAC,gBAAgB,cAAc,GAAG,gBAAgB;AAAA,IAClD,CAAC,gBAAgB,eAAe,GAAG,gBAAgB;AAAA,IACnD,CAAC,gBAAgB,qBAAqB,GAAG,gBAAgB;AAAA,IACzD,CAAC,gBAAgB,oBAAoB,GAAG,gBAAgB;AAAA,IACxD,CAAC,gBAAgB,mBAAmB,GAAG,gBAAgB;AAAA,EACzD;AACF,CAAC;;;ADvCD,IAAMC,UAAQ,YAAY,UAAU;AAMpC,IAAM,gBAAgB;AAAA,EACpB,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,eAAe,CAAC;AAAA,EAChB,aAAa;AAAA,EACb,uBAAuB;AACzB;AAUO,IAAM,qBAAqB,gBAAgB,6BAA6B,aAAa;AASrF,IAAM,oBAAoBC,OAAK,SAAO,IAAI,kBAAkB,EAAE,QAAQ;AAKtE,IAAM,qBAAqBA,OAAK,SAAO,IAAI,kBAAkB,EAAE,cAAc;AAK7E,IAAM,iBAAiBA,OAAK,SAAO;AACxC,QAAM,QAAQ,IAAI,kBAAkB;AACpC,SAAO,CAAC,GAAG,kBAAkB,GAAG,MAAM,aAAa;AACrD,CAAC;AAKM,IAAM,mBAAmBA,OAAK,SAAO;AAC1C,QAAM,WAAW,IAAI,kBAAkB;AACvC,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,aAAa,IAAI,cAAc;AACrC,SAAO,WAAW,KAAK,OAAK,EAAE,OAAO,QAAQ,KAAK;AACpD,CAAC;AAKM,IAAM,kBAAkBA,OAAK,SAAO,IAAI,kBAAkB,EAAE,WAAW;AAMvE,IAAM,4BAA4BA,OAAK,SAAO,IAAI,kBAAkB,EAAE,yBAAyB,IAAI;AAKnG,IAAM,wBAAwBA,OAAK,SAAO;AAC/C,QAAM,QAAQ,IAAI,kBAAkB;AACpC,QAAM,eAAe,IAAI,gBAAgB;AACzC,MAAI,CAAC,aAAc,QAAO;AAG1B,QAAM,SAAS,OAAO,OAAO,eAAe;AAC5C,SAAO,OAAO,KAAK,WAAS,MAAM,SAAS,KAAK,MAAM,aAAa,SAAS,KAAK,CAAC;AACpF,CAAC;AASM,IAAM,sBAAsBA,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACvD;AAAA,EACA;AACF,MAAM;AACJ,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,QAAQ;AAAA,MACX,CAAC,KAAK,GAAG;AAAA,IACX;AAAA;AAAA,IAEA,gBAAgB;AAAA,EAClB,CAAC;AACH,CAAC;AAKM,IAAM,kBAAkBA,OAAK,MAAM,CAAC,KAAK,KAAK,aAAa;AAChE,QAAM,aAAa,IAAI,cAAc;AACrC,QAAM,SAAS,WAAW,KAAK,OAAK,EAAE,OAAO,QAAQ;AACrD,MAAI,CAAC,QAAQ;AACX,IAAAD,QAAM,KAAK,wBAAwB,QAAQ;AAC3C;AAAA,EACF;AACA,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,OAAO;AAAA,IACZ;AAAA,IACA,gBAAgB;AAAA,EAClB,CAAC;AACH,CAAC;AAKM,IAAM,mBAAmBC,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACpD;AAAA,EACA;AACF,MAAM;AACJ,QAAM,UAAU,IAAI,kBAAkB;AAGtC,QAAM,KAAK,UAAU,KAAK,IAAI,CAAC;AAC/B,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,MACR,GAAG,QAAQ;AAAA,IACb;AAAA,IACA,WAAW;AAAA,EACb;AACA,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,eAAe,CAAC,GAAG,QAAQ,eAAe,SAAS;AAAA,IACnD,gBAAgB;AAAA,EAClB,CAAC;AACD,SAAO;AACT,CAAC;AAKM,IAAM,mBAAmBA,OAAK,MAAM,CAAC,KAAK,KAAK,aAAa;AACjE,QAAM,UAAU,IAAI,kBAAkB;AAGtC,QAAM,cAAc,QAAQ,cAAc,UAAU,OAAK,EAAE,OAAO,QAAQ;AAC1E,MAAI,gBAAgB,IAAI;AACtB,IAAAD,QAAM,KAAK,oDAAoD,QAAQ;AACvE;AAAA,EACF;AACA,QAAM,iBAAiB,CAAC,GAAG,QAAQ,aAAa;AAChD,iBAAe,WAAW,IAAI;AAAA,IAC5B,GAAG,eAAe,WAAW;AAAA,IAC7B,UAAU;AAAA,MACR,GAAG,QAAQ;AAAA,IACb;AAAA,EACF;AACA,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB,CAAC;AACH,CAAC;AAKM,IAAM,mBAAmBC,OAAK,MAAM,CAAC,KAAK,KAAK,aAAa;AACjE,QAAM,UAAU,IAAI,kBAAkB;AAGtC,QAAM,mBAAmB,QAAQ,cAAc,OAAO,OAAK,EAAE,OAAO,QAAQ;AAC5E,MAAI,iBAAiB,WAAW,QAAQ,cAAc,QAAQ;AAC5D,IAAAD,QAAM,KAAK,oDAAoD,QAAQ;AACvE;AAAA,EACF;AAGA,QAAM,cAAc,QAAQ,mBAAmB,WAAW,YAAY,QAAQ;AAG9E,QAAM,cAAc,gBAAgB,YAAY,mBAAmB,QAAQ;AAC3E,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACZ,CAAC;AACH,CAAC;AAKM,IAAM,oBAAoBC,OAAK,MAAM,CAAC,KAAK,QAAQ;AACxD,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB,CAAC;AACH,CAAC;AAKM,IAAM,kBAAkBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AACtD,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,aAAa,CAAC,QAAQ;AAAA,EACxB,CAAC;AACH,CAAC;AAKM,IAAM,mBAAmBA,OAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AAC/D,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,aAAa;AAAA,EACf,CAAC;AACH,CAAC;AAKM,IAAM,+BAA+BA,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AAC5E,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,uBAAuB;AAAA,EACzB,CAAC;AACH,CAAC;AAKM,IAAM,2BAA2BA,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC/D,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,oBAAoB;AAAA,IACtB,GAAG;AAAA,IACH,uBAAuB,EAAE,QAAQ,yBAAyB;AAAA,EAC5D,CAAC;AACH,CAAC;;;AEtQD,OAAOC,YAAW;;;ACLlB,SAAS,QAAAC,cAAY;AAOrB,IAAMC,UAAQ,YAAY,WAAW;AAO9B,IAAM,eAAe;AAAA,EAC1B,GAAG;AAAA,EACH,GAAG;AACL;AAOO,IAAM,gBAAgBC,OAAK,IAAI;AAK/B,IAAM,0BAA0BA,OAAK,SAAO,IAAI,aAAa,MAAM,IAAI;AAKvE,IAAM,yBAAyBA,OAAK,SAAO;AAChD,QAAM,YAAY,IAAI,aAAa;AACnC,SAAO,WAAW,MAAM,UAAU;AACpC,CAAC;AAOD,SAASC,iBAAgB,OAAO;AAC9B,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,aAAW,QAAQ,OAAO;AACxB,WAAO,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC;AAClC,WAAO,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC;AAClC,WAAO,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK;AACrD,WAAO,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,MAAM;AAAA,EACxD;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,gBAAgB,OAAO;AAC9B,SAAO,SAAS,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAC/E;AAOO,IAAM,sBAAsBD,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AACnE,QAAM,cAAc,WAAW,MAAM,KAAK,IAAI,mBAAmB,CAAC;AAClE,MAAI,YAAY,WAAW,GAAG;AAC5B,IAAAD,QAAM,qCAAqC;AAC3C;AAAA,EACF;AACA,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,cAAc,IAAI,IAAI,WAAW;AACvC,QAAM,QAAQ,CAAC;AACf,QAAM,QAAQ,CAAC;AAGf,aAAW,UAAU,aAAa;AAChC,QAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,MAAAA,QAAM,wCAAwC,MAAM;AACpD;AAAA,IACF;AACA,UAAM,QAAQ,MAAM,kBAAkB,MAAM;AAC5C,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,QACL,GAAG;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,QACN,GAAG,MAAM;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,YAAY,CAAC,SAAS,OAAO,QAAQ,WAAW;AACpD,QAAI,YAAY,IAAI,MAAM,KAAK,YAAY,IAAI,MAAM,GAAG;AACtD,YAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,QACA,OAAO;AAAA,UACL,GAAG;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,UACN,GAAG,MAAM;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACD,QAAM,SAASE,iBAAgB,KAAK;AACpC,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,KAAK,IAAI;AAAA,EACtB;AACA,MAAI,eAAe,aAAa;AAChC,EAAAF,QAAM,6CAA6C,MAAM,QAAQ,MAAM,MAAM;AAC/E,CAAC;AAMM,IAAM,qBAAqBC,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AAClE,QAAM,cAAc,WAAW,MAAM,KAAK,IAAI,mBAAmB,CAAC;AAClE,MAAI,YAAY,WAAW,EAAG;AAG9B,MAAI,qBAAqB,WAAW;AAGpC,MAAI,iBAAiB,WAAW;AAGhC,aAAW,UAAU,aAAa;AAChC,QAAI,0BAA0B;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,kBAAkB;AACtB,EAAAD,QAAM,kEAA6D,YAAY,MAAM;AACvF,CAAC;AAKM,IAAM,yBAAyBC,OAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AACrE,QAAM,YAAY,IAAI,aAAa;AACnC,MAAI,CAAC,aAAa,UAAU,MAAM,WAAW,GAAG;AAC9C,IAAAD,QAAM,oCAAoC;AAC1C,WAAO,CAAC;AAAA,EACV;AACA,QAAM,cAAc,UAAU;AAC9B,QAAM,QAAQ,IAAI,SAAS;AAG3B,MAAI,iBAAiB,aAAa;AAGlC,QAAM,QAAQ,oBAAI,IAAI;AACtB,QAAM,aAAa,CAAC;AAGpB,WAAS,IAAI,GAAG,IAAI,UAAU,MAAM,QAAQ,KAAK;AAC/C,UAAM,WAAW,UAAU,MAAM,CAAC;AAClC,UAAM,QAAQ,gBAAgB,CAAC;AAC/B,UAAM,IAAI,SAAS,OAAO,IAAI,KAAK;AACnC,eAAW,KAAK,KAAK;AAGrB,UAAM,YAAY;AAAA,MAChB,GAAG,SAAS;AAAA,MACZ,IAAI;AAAA,MACJ,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,eAAe;AAAA,QACb,GAAI,SAAS,OAAO,iBAAiB,CAAC;AAAA,QACtC,GAAG,SAAS,MAAM,IAAI,YAAY;AAAA,QAClC,GAAG,SAAS,MAAM,IAAI,YAAY;AAAA,MACpC;AAAA,IACF;AACA,IAAAA,QAAM,qCAAqC,SAAS,OAAO,IAAI,OAAO,SAAS,MAAM,IAAI,YAAY,GAAG,SAAS,MAAM,IAAI,YAAY,CAAC;AACxI,QAAI,yBAAyB,SAAS;AAAA,EACxC;AAGA,aAAW,YAAY,UAAU,OAAO;AACtC,UAAM,cAAc,MAAM,IAAI,SAAS,MAAM;AAC7C,UAAM,cAAc,MAAM,IAAI,SAAS,MAAM;AAC7C,QAAI,CAAC,eAAe,CAAC,aAAa;AAChC,MAAAA,QAAM,2DAA2D,SAAS,OAAO,EAAE;AACnF;AAAA,IACF;AACA,UAAM,YAAY,gBAAgB,UAAU,MAAM,QAAQ,QAAQ,IAAI,UAAU,MAAM,MAAM;AAC5F,UAAM,YAAY;AAAA,MAChB,GAAG,SAAS;AAAA,MACZ,IAAI;AAAA,MACJ,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACrC;AACA,IAAAA,QAAM,yCAAyC,SAAS,OAAO,IAAI,WAAW,aAAa,WAAW;AACtG,QAAI,yBAAyB,SAAS;AAAA,EACxC;AAGA,MAAI,kBAAkB;AACtB,MAAI,yBAAyB,UAAU;AACvC,EAAAA,QAAM,gCAAgC,WAAW,QAAQ,UAAU,MAAM,MAAM;AAC/E,SAAO;AACT,CAAC;AAMM,IAAM,yBAAyBC,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC7D,MAAI,mBAAmB;AACvB,SAAO,IAAI,sBAAsB;AACnC,CAAC;AAKM,IAAM,qBAAqBA,OAAK,MAAM,CAAC,MAAM,QAAQ;AAC1D,MAAI,eAAe,IAAI;AACvB,EAAAD,QAAM,mBAAmB;AAC3B,CAAC;;;ACrPD,SAAS,QAAAG,cAAY;;;ACEd,IAAM,cAAN,MAAkB;AAAA,EAKvB,YAAY,WAAW,KAAK;AAH5B;AAAA,iCAAQ,oBAAI,IAAI;AAEhB;AAAA,mCAAU,oBAAI,IAAI;AAEhB,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGA,IAAI,OAAO;AACT,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EACA,QAAQ,IAAI,IAAI;AACd,WAAO,GAAG,EAAE,IAAI,EAAE;AAAA,EACpB;AAAA,EACA,aAAa,GAAG,GAAG,GAAG,GAAG;AACvB,UAAM,KAAK,KAAK;AAChB,WAAO;AAAA,MACL,OAAO,KAAK,MAAM,IAAI,EAAE;AAAA,MACxB,OAAO,KAAK,MAAM,IAAI,EAAE;AAAA,MACxB,OAAO,KAAK,OAAO,IAAI,KAAK,EAAE;AAAA,MAC9B,OAAO,KAAK,OAAO,IAAI,KAAK,EAAE;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,IAAI,GAAG,GAAG,OAAO,QAAQ;AAC9B,QAAI,KAAK,QAAQ,IAAI,EAAE,GAAG;AACxB,WAAK,OAAO,IAAI,GAAG,GAAG,OAAO,MAAM;AACnC;AAAA,IACF;AACA,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,SAAK,QAAQ,IAAI,IAAI,KAAK;AAC1B,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,KAAK,aAAa,GAAG,GAAG,OAAO,MAAM;AACzC,aAAS,KAAK,OAAO,MAAM,OAAO,MAAM;AACtC,eAAS,KAAK,OAAO,MAAM,OAAO,MAAM;AACtC,cAAM,MAAM,KAAK,QAAQ,IAAI,EAAE;AAC/B,YAAI,OAAO,KAAK,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,MAAM;AACT,iBAAO,oBAAI,IAAI;AACf,eAAK,MAAM,IAAI,KAAK,IAAI;AAAA,QAC1B;AACA,aAAK,IAAI,EAAE;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAI,GAAG,GAAG,OAAO,QAAQ;AAC9B,UAAM,OAAO,KAAK,QAAQ,IAAI,EAAE;AAChC,QAAI,CAAC,MAAM;AACT,WAAK,OAAO,IAAI,GAAG,GAAG,OAAO,MAAM;AACnC;AAAA,IACF;AAGA,UAAM,YAAY,KAAK,aAAa,KAAK,GAAG,KAAK,GAAG,KAAK,OAAO,KAAK,MAAM;AAC3E,UAAM,WAAW,KAAK,aAAa,GAAG,GAAG,OAAO,MAAM;AACtD,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,QAAI,UAAU,UAAU,SAAS,SAAS,UAAU,UAAU,SAAS,SAAS,UAAU,UAAU,SAAS,SAAS,UAAU,UAAU,SAAS,OAAO;AACxJ;AAAA,IACF;AAGA,aAAS,KAAK,UAAU,OAAO,MAAM,UAAU,OAAO,MAAM;AAC1D,eAAS,KAAK,UAAU,OAAO,MAAM,UAAU,OAAO,MAAM;AAC1D,cAAM,MAAM,KAAK,QAAQ,IAAI,EAAE;AAC/B,cAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,YAAI,MAAM;AACR,eAAK,OAAO,EAAE;AACd,cAAI,KAAK,SAAS,EAAG,MAAK,MAAM,OAAO,GAAG;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAGA,aAAS,KAAK,SAAS,OAAO,MAAM,SAAS,OAAO,MAAM;AACxD,eAAS,KAAK,SAAS,OAAO,MAAM,SAAS,OAAO,MAAM;AACxD,cAAM,MAAM,KAAK,QAAQ,IAAI,EAAE;AAC/B,YAAI,OAAO,KAAK,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,MAAM;AACT,iBAAO,oBAAI,IAAI;AACf,eAAK,MAAM,IAAI,KAAK,IAAI;AAAA,QAC1B;AACA,aAAK,IAAI,EAAE;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAI;AACT,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO;AACZ,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,KAAK,aAAa,MAAM,GAAG,MAAM,GAAG,MAAM,OAAO,MAAM,MAAM;AACjE,aAAS,KAAK,OAAO,MAAM,OAAO,MAAM;AACtC,eAAS,KAAK,OAAO,MAAM,OAAO,MAAM;AACtC,cAAM,MAAM,KAAK,QAAQ,IAAI,EAAE;AAC/B,cAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,YAAI,MAAM;AACR,eAAK,OAAO,EAAE;AACd,cAAI,KAAK,SAAS,EAAG,MAAK,MAAM,OAAO,GAAG;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AACA,SAAK,QAAQ,OAAO,EAAE;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ;AACZ,UAAM,SAAS,oBAAI,IAAI;AACvB,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,KAAK,aAAa,OAAO,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,MAAM,OAAO,OAAO,OAAO,IAAI;AACpG,aAAS,KAAK,OAAO,MAAM,OAAO,MAAM;AACtC,eAAS,KAAK,OAAO,MAAM,OAAO,MAAM;AACtC,cAAM,OAAO,KAAK,MAAM,IAAI,KAAK,QAAQ,IAAI,EAAE,CAAC;AAChD,YAAI,CAAC,KAAM;AACX,mBAAW,MAAM,MAAM;AACrB,cAAI,OAAO,IAAI,EAAE,EAAG;AAGpB,gBAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,gBAAM,aAAa,MAAM,IAAI,MAAM;AACnC,gBAAM,cAAc,MAAM,IAAI,MAAM;AACpC,cAAI,MAAM,KAAK,OAAO,QAAQ,cAAc,OAAO,QAAQ,MAAM,KAAK,OAAO,QAAQ,eAAe,OAAO,MAAM;AAC/G,mBAAO,IAAI,EAAE;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACN,SAAK,MAAM,MAAM;AACjB,SAAK,QAAQ,MAAM;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,IAAI;AACN,WAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,EAC5B;AACF;;;ADtKO,IAAM,wBAAwB;AAW9B,IAAM,mBAAmBC,OAAK,SAAO;AAC1C,MAAI,sBAAsB;AAC1B,MAAI,6BAA6B;AACjC,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,OAAO,IAAI,YAAY,GAAG;AAChC,QAAM,YAAY,CAAC,QAAQ,UAAU;AACnC,UAAM,IAAI;AACV,SAAK,OAAO,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,KAAK,EAAE,UAAU,GAAG;AAAA,EAC/D,CAAC;AACD,SAAO;AACT,CAAC;AAQM,IAAM,oBAAoBA,OAAK,SAAO;AAC3C,QAAM,WAAW,IAAI,gBAAgB;AACrC,QAAM,MAAM,IAAI,OAAO;AACvB,QAAM,OAAO,IAAI,QAAQ;AACzB,MAAI,CAAC,YAAY,SAAS,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AACf,SAAO;AAAA,IACL,OAAO,CAAC,SAAS,IAAI,KAAK;AAAA,IAC1B,OAAO,CAAC,SAAS,IAAI,KAAK;AAAA,IAC1B,OAAO,SAAS,QAAQ,SAAS,IAAI,KAAK;AAAA,IAC1C,OAAO,SAAS,SAAS,SAAS,IAAI,KAAK;AAAA,EAC7C;AACF,CAAC;AASM,IAAM,sBAAsBA,OAAK,SAAO;AAC7C,QAAM,MAAM,WAAW,qBAAqB;AAC5C,QAAM,UAAU,IAAI,yBAAyB;AAC7C,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,CAAC,SAAS;AACZ,QAAI;AACJ,WAAO;AAAA,EACT;AACA,QAAM,SAAS,IAAI,iBAAiB;AACpC,MAAI,CAAC,QAAQ;AACX,QAAI;AACJ,WAAO;AAAA,EACT;AACA,QAAM,OAAO,IAAI,gBAAgB;AACjC,QAAM,aAAa,KAAK,MAAM,MAAM;AAGpC,QAAM,SAAS,QAAQ,OAAO,OAAK,WAAW,IAAI,CAAC,CAAC;AACpD,MAAI;AACJ,SAAO;AACT,CAAC;AAYM,IAAM,sBAAsBA,OAAK,SAAO;AAC7C,QAAM,UAAU,IAAI,yBAAyB;AAC7C,QAAM,cAAc,IAAI,YAAY;AACpC,QAAM,eAAe,IAAI,gBAAgB;AACzC,QAAM,QAAQ,IAAI,sBAAsB;AAGxC,QAAM,cAAc,aAAa,aAAa,uBAAuB;AAGrE,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAG3B,QAAM,gBAAgB,YAAY,OAAO,aAAW;AAClD,UAAM,SAAS,MAAM,OAAO,OAAO;AACnC,UAAM,SAAS,MAAM,OAAO,OAAO;AACnC,UAAM,kBAAkB,MAAM,IAAI,MAAM,KAAK;AAC7C,UAAM,kBAAkB,MAAM,IAAI,MAAM,KAAK;AAG7C,QAAI,oBAAoB,gBAAiB,QAAO;AAChD,WAAO;AAAA,EACT,CAAC;AACD,MAAI,CAAC,SAAS;AACZ,WAAO,cAAc,CAAC,GAAG,eAAe,WAAW,IAAI;AAAA,EACzD;AAGA,QAAM,kBAAkB,IAAI,mBAAmB;AAC/C,QAAM,iBAAiB,IAAI,IAAI,eAAe;AAC9C,QAAM,eAAe,cAAc,OAAO,aAAW;AACnD,UAAM,SAAS,MAAM,OAAO,OAAO;AACnC,UAAM,SAAS,MAAM,OAAO,OAAO;AACnC,UAAM,kBAAkB,MAAM,IAAI,MAAM,KAAK;AAC7C,UAAM,kBAAkB,MAAM,IAAI,MAAM,KAAK;AAG7C,WAAO,eAAe,IAAI,eAAe,KAAK,eAAe,IAAI,eAAe;AAAA,EAClF,CAAC;AACD,SAAO,cAAc,CAAC,GAAG,cAAc,WAAW,IAAI;AACxD,CAAC;AAOM,IAAM,4BAA4BA,OAAK,SAAO;AACnD,QAAM,UAAU,IAAI,yBAAyB;AAC7C,QAAM,aAAa,IAAI,YAAY,EAAE;AACrC,QAAM,aAAa,IAAI,YAAY,EAAE;AACrC,QAAM,eAAe,IAAI,mBAAmB,EAAE;AAC9C,QAAM,eAAe,IAAI,mBAAmB,EAAE;AAC9C,QAAM,SAAS,IAAI,iBAAiB;AACpC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,aAAa;AAAA,IAC1B,aAAa,aAAa;AAAA,IAC1B;AAAA,EACF;AACF,CAAC;;;AEjKD,SAAS,QAAAC,cAAY;AAWd,IAAM,qBAAqBC,OAAK,oBAAI,IAAI,CAAC;AAOzC,IAAM,yBAAyBA,OAAK,OAAO;AAM3C,IAAM,wBAAwBA,OAAK,wBAAwB,CAAC;AAU5D,IAAM,qBAAqBA,OAAK,SAAO;AAC5C,QAAM,WAAW,IAAI,kBAAkB;AACvC,aAAW,CAAC,EAAE,OAAO,KAAK,UAAU;AAClC,QAAI,QAAQ,WAAW,SAAU,QAAO;AAAA,EAC1C;AACA,SAAO;AACT,CAAC;AAMM,IAAM,mBAAmBA,OAAK,SAAO;AAC1C,QAAM,WAAW,IAAI,kBAAkB;AACvC,MAAI,cAAc;AAClB,aAAW,CAAC,EAAE,OAAO,KAAK,UAAU;AAClC,QAAI,QAAQ,WAAW,SAAU;AAAA,EACnC;AACA,SAAO,cAAc;AACvB,CAAC;AAKM,IAAM,kBAAkBA,OAAK,SAAO;AACzC,QAAM,WAAW,IAAI,kBAAkB;AACvC,MAAI,QAAQ;AACZ,aAAW,CAAC,EAAE,OAAO,KAAK,UAAU;AAClC,QAAI,QAAQ,WAAW,SAAU;AAAA,EACnC;AACA,SAAO;AACT,CAAC;AAMM,IAAM,oBAAoBA,OAAK,SAAO;AAC3C,QAAM,OAAO,IAAI,qBAAqB;AACtC,SAAO,KAAK;AACd,CAAC;AAUM,IAAM,kBAAkBA,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AAC/D,QAAM,WAAW,IAAI,IAAI,IAAI,kBAAkB,CAAC;AAChD,WAAS,IAAI,QAAQ,WAAW,OAAO;AACvC,MAAI,oBAAoB,QAAQ;AAChC,MAAI,wBAAwB,QAAQ,MAAM;AAG1C,MAAI,QAAQ,WAAW,UAAU;AAC/B,UAAM,OAAO,IAAI,qBAAqB;AACtC,QAAI,CAAC,KAAK,WAAW;AACnB,UAAI,uBAAuB;AAAA,QACzB,GAAG;AAAA,QACH,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF;AACF,CAAC;AAKM,IAAM,gBAAgBA,OAAK,MAAM,CAAC,KAAK,KAAK,cAAc;AAC/D,QAAM,WAAW,IAAI,IAAI,IAAI,kBAAkB,CAAC;AAChD,WAAS,OAAO,SAAS;AACzB,MAAI,oBAAoB,QAAQ;AAClC,CAAC;AAMM,IAAM,oBAAoBA,OAAK,MAAM,CAAC,MAAM,QAAQ;AACzD,MAAI,oBAAoB,oBAAI,IAAI,CAAC;AACnC,CAAC;;;ACzHD,SAAS,QAAAC,cAAY;AASd,IAAM,oBAAoBC,OAAK,IAAI;AAGnC,IAAM,kBAAkBA,OAAK,SAAO,IAAI,iBAAiB,MAAM,IAAI;AAKnE,IAAM,qBAAqBA,OAAK,MAAM,CAAC,MAAM,KAAK;AAAA,EACvD;AAAA,EACA;AACF,MAAM;AACJ,MAAI,mBAAmB;AAAA,IACrB;AAAA,IACA,QAAQ,CAAC,KAAK;AAAA,EAChB,CAAC;AACH,CAAC;AAGM,IAAM,sBAAsBA,OAAK,MAAM,CAAC,KAAK,KAAK,UAAU;AACjE,QAAM,UAAU,IAAI,iBAAiB;AACrC,MAAI,CAAC,QAAS;AACd,MAAI,QAAQ,SAAS,QAAQ;AAE3B,QAAI,mBAAmB;AAAA,MACrB,GAAG;AAAA,MACH,QAAQ,CAAC,QAAQ,OAAO,CAAC,GAAG,KAAK;AAAA,IACnC,CAAC;AAAA,EACH,OAAO;AAEL,QAAI,mBAAmB;AAAA,MACrB,GAAG;AAAA,MACH,QAAQ,CAAC,GAAG,QAAQ,QAAQ,KAAK;AAAA,IACnC,CAAC;AAAA,EACH;AACF,CAAC;AAGM,IAAM,sBAAsBA,OAAK,MAAM,CAAC,MAAM,QAAQ;AAC3D,MAAI,mBAAmB,IAAI;AAC7B,CAAC;AAGM,IAAM,mBAAmBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AACvD,QAAM,OAAO,IAAI,iBAAiB;AAClC,MAAI,CAAC,QAAQ,KAAK,OAAO,SAAS,GAAG;AACnC,QAAI,mBAAmB,IAAI;AAC3B;AAAA,EACF;AACA,QAAM,QAAQ,IAAI,WAAW;AAC7B,QAAM,cAAc,CAAC;AACrB,MAAI,KAAK,SAAS,QAAQ;AACxB,UAAM,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,OAAO,CAAC,GAAG,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,CAAC;AACrE,UAAM,OAAO,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AAChC,UAAM,OAAO,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AAChC,UAAM,OAAO,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AAChC,UAAM,OAAO,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AAChC,eAAW,QAAQ,OAAO;AAExB,YAAM,YAAY,KAAK,SAAS,KAAK,KAAK,SAAS;AACnD,YAAM,aAAa,KAAK,SAAS,KAAK,KAAK,UAAU;AACrD,UAAI,KAAK,SAAS,IAAI,QAAQ,YAAY,QAAQ,KAAK,SAAS,IAAI,QAAQ,aAAa,MAAM;AAC7F,oBAAY,KAAK,KAAK,EAAE;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,OAAO;AAEL,UAAM,UAAU,KAAK;AACrB,eAAW,QAAQ,OAAO;AACxB,YAAM,KAAK,KAAK,SAAS,KAAK,KAAK,SAAS,OAAO;AACnD,YAAM,KAAK,KAAK,SAAS,KAAK,KAAK,UAAU,OAAO;AACpD,UAAI,eAAe,IAAI,IAAI,OAAO,GAAG;AACnC,oBAAY,KAAK,KAAK,EAAE;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAGA,MAAI,qBAAqB,IAAI,IAAI,WAAW,CAAC;AAC7C,MAAI,mBAAmB,IAAI;AAC7B,CAAC;AAKM,IAAM,oBAAoBA,OAAK,SAAO;AAC3C,QAAM,OAAO,IAAI,iBAAiB;AAClC,MAAI,CAAC,QAAQ,KAAK,SAAS,UAAU,KAAK,OAAO,SAAS,EAAG,QAAO;AACpE,QAAM,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,OAAO,CAAC,GAAG,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,CAAC;AACrE,SAAO;AAAA,IACL,GAAG,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AAAA,IACtB,GAAG,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AAAA,IACtB,OAAO,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC;AAAA,IAC3B,QAAQ,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC;AAAA,EAC9B;AACF,CAAC;AAQM,SAAS,eAAe,IAAI,IAAI,SAAS;AAC9C,MAAI,SAAS;AACb,QAAM,IAAI,QAAQ;AAClB,WAAS,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,KAAK;AACzC,UAAM,KAAK,QAAQ,CAAC,EAAE;AACtB,UAAM,KAAK,QAAQ,CAAC,EAAE;AACtB,UAAM,KAAK,QAAQ,CAAC,EAAE;AACtB,UAAM,KAAK,QAAQ,CAAC,EAAE;AACtB,QAAI,KAAK,OAAO,KAAK,MAAM,MAAM,KAAK,OAAO,KAAK,OAAO,KAAK,MAAM,IAAI;AACtE,eAAS,CAAC;AAAA,IACZ;AAAA,EACF;AACA,SAAO;AACT;;;AC7HA,SAAS,QAAAC,cAAY;AAcd,IAAM,kBAAkBC,OAAK,EAAE;AAK/B,IAAM,qBAAqBA,OAAK,MAAM,CAAC,MAAM,KAAK,UAAU;AACjE,MAAI,iBAAiB,KAAK;AAC1B,MAAI,4BAA4B,CAAC;AACnC,CAAC;AAKM,IAAM,kBAAkBA,OAAK,MAAM,CAAC,MAAM,QAAQ;AACvD,MAAI,iBAAiB,EAAE;AACvB,MAAI,4BAA4B,CAAC;AACnC,CAAC;AAcM,SAAS,WAAW,UAAU,WAAW;AAC9C,QAAM,SAAS,MAAM,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AAC9D,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,WAAW,UAAU,KAAK,GAAG,EAAE,YAAY;AACjD,SAAO,OAAO,MAAM,WAAS,SAAS,SAAS,KAAK,CAAC;AACvD;AAUO,IAAM,oBAAoBA,OAAK,SAAO;AAC3C,QAAM,QAAQ,IAAI,eAAe,EAAE,KAAK;AACxC,MAAI,CAAC,MAAO,QAAO,oBAAI,IAAI;AAC3B,QAAM,QAAQ,IAAI,WAAW;AAC7B,QAAM,UAAU,oBAAI,IAAI;AACxB,aAAW,QAAQ,OAAO;AACxB,QAAI,WAAW,OAAO,KAAK,SAAS,IAAI,KAAK,OAAO,aAAa,IAAI,KAAK,EAAE,GAAG;AAC7E,cAAQ,IAAI,KAAK,EAAE;AAAA,IACrB;AAAA,EACF;AACA,SAAO;AACT,CAAC;AAKM,IAAM,yBAAyBA,OAAK,SAAO;AAChD,SAAO,MAAM,KAAK,IAAI,iBAAiB,CAAC;AAC1C,CAAC;AAKM,IAAM,wBAAwBA,OAAK,SAAO;AAC/C,SAAO,IAAI,iBAAiB,EAAE;AAChC,CAAC;AAUM,IAAM,wBAAwBA,OAAK,SAAO;AAC/C,QAAM,QAAQ,IAAI,eAAe,EAAE,KAAK;AACxC,MAAI,CAAC,MAAO,QAAO,oBAAI,IAAI;AAG3B,MAAI,sBAAsB;AAC1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,UAAU,oBAAI,IAAI;AACxB,QAAM,YAAY,CAAC,SAAS,UAAU;AACpC,UAAM,QAAQ,MAAM,SAAS;AAC7B,UAAM,WAAW,MAAM,QAAQ,aAAa;AAC5C,QAAI,WAAW,OAAO,OAAO,UAAU,OAAO,GAAG;AAC/C,cAAQ,IAAI,OAAO;AAAA,IACrB;AAAA,EACF,CAAC;AACD,SAAO;AACT,CAAC;AAKM,IAAM,4BAA4BA,OAAK,SAAO;AACnD,SAAO,IAAI,qBAAqB,EAAE;AACpC,CAAC;AASM,IAAM,qBAAqBA,OAAK,SAAO;AAC5C,SAAO,IAAI,eAAe,EAAE,KAAK,EAAE,SAAS;AAC9C,CAAC;AAKM,IAAM,6BAA6BA,OAAK,SAAO;AACpD,SAAO,IAAI,qBAAqB,IAAI,IAAI,yBAAyB;AACnE,CAAC;AASM,IAAM,6BAA6BA,OAAK,CAAC;AAKzC,IAAM,uBAAuBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC3D,QAAM,UAAU,IAAI,sBAAsB;AAC1C,MAAI,QAAQ,WAAW,EAAG;AAC1B,QAAM,eAAe,IAAI,0BAA0B;AACnD,QAAM,aAAa,eAAe,KAAK,QAAQ;AAC/C,MAAI,4BAA4B,SAAS;AACzC,QAAM,SAAS,QAAQ,SAAS;AAChC,MAAI,kBAAkB,MAAM;AAC5B,MAAI,sBAAsB,MAAM;AAClC,CAAC;AAKM,IAAM,uBAAuBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC3D,QAAM,UAAU,IAAI,sBAAsB;AAC1C,MAAI,QAAQ,WAAW,EAAG;AAC1B,QAAM,eAAe,IAAI,0BAA0B;AACnD,QAAM,aAAa,eAAe,IAAI,QAAQ,UAAU,QAAQ;AAChE,MAAI,4BAA4B,SAAS;AACzC,QAAM,SAAS,QAAQ,SAAS;AAChC,MAAI,kBAAkB,MAAM;AAC5B,MAAI,sBAAsB,MAAM;AAClC,CAAC;AAKM,IAAM,8BAA8BA,OAAK,SAAO;AACrD,QAAM,UAAU,IAAI,sBAAsB;AAC1C,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAM,QAAQ,IAAI,0BAA0B;AAC5C,SAAO,QAAQ,KAAK,KAAK;AAC3B,CAAC;;;AChGM,SAAS,WAAW,UAAU,WAAW;AAC9C,QAAM,cAAc,IAAI,IAAI,UAAU,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACzD,QAAM,SAAS,CAAC;AAGhB,aAAW,QAAQ,UAAU;AAC3B,UAAM,WAAW,YAAY,IAAI,KAAK,EAAE;AACxC,QAAI,UAAU;AACZ,aAAO,KAAK,QAAQ;AACpB,kBAAY,OAAO,KAAK,EAAE;AAAA,IAC5B,OAAO;AACL,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,EACF;AAGA,aAAW,QAAQ,YAAY,OAAO,GAAG;AACvC,WAAO,KAAK,IAAI;AAAA,EAClB;AACA,SAAO;AACT;AASO,IAAM,wBAAwB;AAAA;AAAA,EAErC;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WAAW;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAA,EAAG;AAAA,IACD,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,IACX;AAAA,IACA,UAAU;AAAA,EACZ;AAAA;AAAA,EAEA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AAAC;;;ACpMM,SAAS,eAAe,OAAO;AACpC,QAAM,UAAU,oBAAI,IAAI;AACxB,QAAM,gBAAgB,CAAC;AACvB,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,KAAK,QAAQ;AACzB,QAAI,QAAQ,QAAW;AACrB,oBAAc,KAAK,IAAI;AAAA,IACzB,OAAO;AACL,YAAM,SAAS,QAAQ,IAAI,GAAG;AAC9B,UAAI,QAAQ;AACV,eAAO,KAAK,IAAI;AAAA,MAClB,OAAO;AACL,gBAAQ,IAAI,KAAK,CAAC,IAAI,CAAC;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,QAAQ,oBAAI,IAAI;AACtB,MAAI,cAAc,SAAS,GAAG;AAC5B,eAAW,CAAC,KAAK,MAAM,KAAK,SAAS;AACnC,YAAM,IAAI,KAAK,OAAO,OAAO,aAAa,CAAC;AAAA,IAC7C;AACA,UAAM,IAAI,gBAAgB,aAAa;AAAA,EACzC,OAAO;AACL,eAAW,CAAC,KAAK,MAAM,KAAK,SAAS;AACnC,YAAM,IAAI,KAAK,MAAM;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AACT;;;AChKA,SAAS,QAAAC,cAAY;AACrB,SAAS,mBAAAC,wBAAuB;AAOhC,IAAM,qBAAqB;AAAA,EACzB,aAAa,CAAC;AAAA,EACd,eAAe;AACjB;AAMO,IAAM,0BAA0BC,iBAAgB,wBAAwB,kBAAkB;AAU1F,IAAM,2BAA2BC,OAAK,CAAC,CAAC;AAMxC,IAAM,mBAAmBA,OAAK,SAAO;AAC1C,QAAM,WAAW,IAAI,uBAAuB;AAC5C,QAAM,gBAAgB,IAAI,wBAAwB;AAIlD,MAAI,QAAQ,WAAW,uBAAuB,SAAS,WAAW;AAElE,MAAI,cAAc,SAAS,GAAG;AAC5B,YAAQ,WAAW,OAAO,aAAa;AAAA,EACzC;AACA,SAAO;AACT,CAAC;AAMM,IAAM,uBAAuBA,OAAK,SAAO;AAC9C,SAAO,eAAe,IAAI,gBAAgB,CAAC;AAC7C,CAAC;AAKM,IAAM,2BAA2BA,OAAK,SAAO,IAAI,uBAAuB,EAAE,eAAe,CAAC,KAAK,KAAK,YAAY;AACrH,QAAM,UAAU,IAAI,uBAAuB;AAC3C,MAAI,yBAAyB;AAAA,IAC3B,GAAG;AAAA,IACH,eAAe;AAAA,EACjB,CAAC;AACH,CAAC;AAUM,IAAM,qBAAqBA,OAAK,MAAM,CAAC,KAAK,KAAK,SAAS;AAC/D,QAAM,UAAU,IAAI,uBAAuB;AAC3C,QAAM,WAAW,QAAQ,YAAY,UAAU,OAAK,EAAE,OAAO,KAAK,EAAE;AACpE,QAAM,WAAW,CAAC,GAAG,QAAQ,WAAW;AACxC,MAAI,YAAY,GAAG;AACjB,aAAS,QAAQ,IAAI;AAAA,EACvB,OAAO;AACL,aAAS,KAAK,IAAI;AAAA,EACpB;AACA,MAAI,yBAAyB;AAAA,IAC3B,GAAG;AAAA,IACH,aAAa;AAAA,EACf,CAAC;AACH,CAAC;AAKM,IAAM,wBAAwBA,OAAK,MAAM,CAAC,KAAK,KAAK,WAAW;AACpE,QAAM,UAAU,IAAI,uBAAuB;AAC3C,MAAI,yBAAyB;AAAA,IAC3B,GAAG;AAAA,IACH,aAAa,QAAQ,YAAY,OAAO,OAAK,EAAE,OAAO,MAAM;AAAA,EAC9D,CAAC;AACH,CAAC;AAKM,IAAM,wBAAwBA,OAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EACzD;AAAA,EACA;AACF,MAAM;AACJ,QAAM,UAAU,IAAI,uBAAuB;AAC3C,QAAM,QAAQ,QAAQ,YAAY,UAAU,OAAK,EAAE,OAAO,EAAE;AAC5D,MAAI,QAAQ,EAAG;AACf,QAAM,WAAW,CAAC,GAAG,QAAQ,WAAW;AACxC,WAAS,KAAK,IAAI;AAAA,IAChB,GAAG,SAAS,KAAK;AAAA,IACjB,GAAG;AAAA,EACL;AACA,MAAI,yBAAyB;AAAA,IAC3B,GAAG;AAAA,IACH,aAAa;AAAA,EACf,CAAC;AACH,CAAC;AAKM,IAAM,wBAAwBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC5D,QAAM,UAAU,IAAI,uBAAuB;AAC3C,MAAI,yBAAyB;AAAA,IAC3B,GAAG;AAAA,IACH,aAAa,CAAC;AAAA,EAChB,CAAC;AACH,CAAC;;;AC5HD,SAAS,QAAAC,cAAY;AAMd,IAAM,0BAA0BA,OAAK,KAAK;AAM1C,IAAM,4BAA4BA,OAAK,MAAM,CAAC,KAAK,QAAQ;AAChE,MAAI,OAAO,WAAW,YAAa;AACnC,QAAM,UAAU,OAAK;AAGnB,QAAI,EAAE,OAAO,EAAE,IAAI,WAAW,KAAK,CAAC,OAAO,UAAU,SAAS,WAAW,aAAa,aAAa,YAAY,EAAE,SAAS,EAAE,GAAG,GAAG;AAChI,UAAI,yBAAyB,IAAI;AACjC,aAAO,oBAAoB,WAAW,OAAO;AAAA,IAC/C;AAAA,EACF;AACA,SAAO,iBAAiB,WAAW,OAAO;AAC1C,SAAO,MAAM,OAAO,oBAAoB,WAAW,OAAO;AAC5D,CAAC;;;ACZD,IAAM,kBAAN,MAAsB;AAAA,EAAtB;AACE,oCAAW,oBAAI,IAAI;AACnB,mCAAU,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlB,SAAS,SAAS;AAChB,QAAI,KAAK,SAAS,IAAI,QAAQ,IAAI,GAAG;AACnC,YAAM,IAAI,MAAM,YAAY,QAAQ,IAAI,yBAAyB;AAAA,IACnE;AACA,SAAK,SAAS,IAAI,QAAQ,MAAM,OAAO;AAGvC,QAAI,QAAQ,SAAS;AACnB,iBAAW,SAAS,QAAQ,SAAS;AACnC,YAAI,KAAK,QAAQ,IAAI,KAAK,GAAG;AAC3B,gBAAM,IAAI,MAAM,UAAU,KAAK,wCAAwC,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG;AAAA,QACnG;AACA,YAAI,KAAK,SAAS,IAAI,KAAK,GAAG;AAC5B,gBAAM,IAAI,MAAM,UAAU,KAAK,wCAAwC;AAAA,QACzE;AACA,aAAK,QAAQ,IAAI,OAAO,QAAQ,IAAI;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,MAAM;AACf,UAAM,UAAU,KAAK,SAAS,IAAI,IAAI;AACtC,QAAI,SAAS;AAEX,UAAI,QAAQ,SAAS;AACnB,mBAAW,SAAS,QAAQ,SAAS;AACnC,eAAK,QAAQ,OAAO,KAAK;AAAA,QAC3B;AAAA,MACF;AACA,WAAK,SAAS,OAAO,IAAI;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,aAAa;AAEf,UAAM,SAAS,KAAK,SAAS,IAAI,WAAW;AAC5C,QAAI,OAAQ,QAAO;AAGnB,UAAM,cAAc,KAAK,QAAQ,IAAI,WAAW;AAChD,QAAI,aAAa;AACf,aAAO,KAAK,SAAS,IAAI,WAAW;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,aAAa;AACf,WAAO,KAAK,SAAS,IAAI,WAAW,KAAK,KAAK,QAAQ,IAAI,WAAW;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,OAAO;AACZ,QAAI,CAAC,MAAM,KAAK,GAAG;AACjB,aAAO,KAAK,IAAI;AAAA,IAClB;AACA,UAAM,aAAa,MAAM,YAAY,EAAE,KAAK;AAC5C,UAAM,UAAU,CAAC;AACjB,UAAM,WAAW,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC;AAClD,eAAW,WAAW,UAAU;AAC9B,UAAI,QAAQ;AAGZ,UAAI,QAAQ,KAAK,YAAY,MAAM,YAAY;AAC7C,gBAAQ;AAAA,MACV,WAES,QAAQ,KAAK,YAAY,EAAE,WAAW,UAAU,GAAG;AAC1D,gBAAQ;AAAA,MACV,WAES,QAAQ,KAAK,YAAY,EAAE,SAAS,UAAU,GAAG;AACxD,gBAAQ;AAAA,MACV,WAES,QAAQ,SAAS,KAAK,OAAK,EAAE,YAAY,MAAM,UAAU,GAAG;AACnE,gBAAQ;AAAA,MACV,WAES,QAAQ,SAAS,KAAK,OAAK,EAAE,YAAY,EAAE,WAAW,UAAU,CAAC,GAAG;AAC3E,gBAAQ;AAAA,MACV,WAES,QAAQ,SAAS,KAAK,OAAK,EAAE,YAAY,EAAE,SAAS,UAAU,CAAC,GAAG;AACzE,gBAAQ;AAAA,MACV,WAES,QAAQ,YAAY,YAAY,EAAE,SAAS,UAAU,GAAG;AAC/D,gBAAQ;AAAA,MACV;AACA,UAAI,QAAQ,GAAG;AACb,gBAAQ,KAAK;AAAA,UACX;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAGA,WAAO,QAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK,cAAc,EAAE,QAAQ,IAAI,CAAC,EAAE,IAAI,OAAK,EAAE,OAAO;AAAA,EACrH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM;AACJ,WAAO,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,UAAU;AACnB,WAAO,KAAK,IAAI,EAAE,OAAO,SAAO,IAAI,aAAa,QAAQ;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AACX,UAAM,aAAa,oBAAI,IAAI;AAC3B,UAAM,WAAW,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC;AAClD,eAAW,WAAW,UAAU;AAC9B,iBAAW,IAAI,QAAQ,QAAQ;AAAA,IACjC;AACA,WAAO,MAAM,KAAK,UAAU,EAAE,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAO;AACT,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ;AACN,SAAK,SAAS,MAAM;AACpB,SAAK,QAAQ,MAAM;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS;AACP,WAAO,KAAK,IAAI,EAAE,IAAI,UAAQ;AAAA,MAC5B,MAAM,IAAI;AAAA,MACV,SAAS,IAAI,WAAW,CAAC;AAAA,MACzB,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI;AAAA,MACd,QAAQ,IAAI,OAAO,IAAI,YAAU;AAAA,QAC/B,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,QACZ,QAAQ,MAAM;AAAA,QACd,UAAU,MAAM,aAAa;AAAA,MAC/B,EAAE;AAAA,IACJ,EAAE;AAAA,EACJ;AACF;AAGO,IAAM,kBAAkB,IAAI,gBAAgB;;;AC1MnD,IAAMC,UAAQ,YAAY,SAAS;;;ACVnC,SAAS,QAAAC,cAAY;;;ACArB,SAAS,QAAAC,cAAY;AACrB,SAAS,mBAAAC,wBAAuB;AASzB,IAAMC,iBAAgBF,OAAK;AAAA,EAChC,MAAM;AACR,CAAC;AAKM,IAAM,yBAAyBA,OAAK,KAAK;AAKzC,IAAM,uBAAuBA,OAAK;AAAA,EACvC,OAAO;AACT,CAAC;AAKM,IAAM,sBAAsBA,OAAK,IAAI;AAKrC,IAAM,qBAAqBC,iBAAgB,0BAA0B,CAAC,CAAC;AAKvE,IAAM,8BAA8BD,OAAK,CAAC;AAS1C,IAAMG,4BAA2BH,OAAK,IAAI;AAS1C,IAAM,sBAAsBA,OAAK,SAAO;AAC7C,QAAM,QAAQ,IAAI,oBAAoB;AACtC,SAAO,MAAM,UAAU,gBAAgB,MAAM,UAAU;AACzD,CAAC;AAKM,IAAM,mBAAmBA,OAAK,SAAO;AAC1C,QAAM,QAAQ,IAAI,oBAAoB;AACtC,MAAI,MAAM,UAAU,aAAc,QAAO;AACzC,SAAO,MAAM,QAAQ,OAAO,MAAM,UAAU;AAC9C,CAAC;AAKM,IAAM,sBAAsBA,OAAK,SAAO;AAC7C,QAAM,QAAQ,IAAI,oBAAoB;AACtC,MAAI,MAAM,UAAU,aAAc,QAAO;AACzC,SAAO;AAAA,IACL,SAAS,MAAM,aAAa;AAAA,IAC5B,OAAO,MAAM,QAAQ,OAAO;AAAA,EAC9B;AACF,CAAC;;;ADjEM,IAAM,sBAAsBI,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC1D,MAAI,wBAAwB,IAAI;AAChC,MAAI,sBAAsB;AAAA,IACxB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa,gBAAgB,IAAI;AAAA,EACnC,CAAC;AACD,MAAI,6BAA6B,CAAC;AACpC,CAAC;AAKM,IAAM,uBAAuBA,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC3D,MAAI,wBAAwB,KAAK;AACjC,MAAI,sBAAsB;AAAA,IACxB,OAAO;AAAA,EACT,CAAC;AACD,MAAIC,gBAAe;AAAA,IACjB,MAAM;AAAA,EACR,CAAC;AACD,MAAI,qBAAqB,IAAI;AAC7B,MAAIC,2BAA0B,IAAI;AACpC,CAAC;AAKM,IAAM,wBAAwBF,OAAK,MAAM,CAAC,KAAK,KAAK,UAAU;AACnE,QAAM,cAAc,gBAAgB,OAAO,KAAK;AAChD,MAAI,sBAAsB;AAAA,IACxB,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,6BAA6B,CAAC;AACpC,CAAC;AAKM,IAAM,oBAAoBA,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AAEjE,QAAM,UAAU,IAAI,kBAAkB;AACtC,QAAM,aAAa,CAAC,QAAQ,MAAM,GAAG,QAAQ,OAAO,OAAK,MAAM,QAAQ,IAAI,CAAC,EAAE,MAAM,GAAG,EAAE;AACzF,MAAI,oBAAoB,UAAU;AAGlC,MAAI,QAAQ,OAAO,WAAW,GAAG;AAC/B,QAAI,sBAAsB;AAAA,MACxB,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AACD;AAAA,EACF;AAGA,MAAI,sBAAsB;AAAA,IACxB,OAAO;AAAA,IACP;AAAA,IACA,YAAY;AAAA,IACZ,WAAW,CAAC;AAAA,EACd,CAAC;AAGD,QAAM,aAAa,QAAQ,OAAO,CAAC;AACnC,MAAIC,gBAAe,eAAe,UAAU,CAAC;AAC/C,CAAC;AAKM,IAAME,oBAAmBH,OAAK,MAAM,CAAC,KAAK,KAAK,UAAU;AAC9D,QAAM,QAAQ,IAAI,oBAAoB;AACtC,MAAI,MAAM,UAAU,aAAc;AAClC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,eAAe,QAAQ,OAAO,UAAU;AAG9C,MAAI,aAAa,UAAU;AACzB,UAAM,SAAS,aAAa,SAAS,OAAO,SAAS;AACrD,QAAI,WAAW,MAAM;AACnB,UAAI,sBAAsB;AAAA,QACxB,OAAO;AAAA,QACP,SAAS,OAAO,WAAW,WAAW,SAAS,qBAAqB,aAAa,IAAI;AAAA,MACvF,CAAC;AACD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,eAAe;AAAA,IACnB,GAAG;AAAA,IACH,CAAC,aAAa,IAAI,GAAG;AAAA,EACvB;AAGA,MAAI,aAAa,QAAQ,OAAO,SAAS,GAAG;AAC1C,UAAM,iBAAiB,aAAa;AACpC,UAAM,YAAY,QAAQ,OAAO,cAAc;AAC/C,QAAI,sBAAsB;AAAA,MACxB,OAAO;AAAA,MACP;AAAA,MACA,YAAY;AAAA,MACZ,WAAW;AAAA,IACb,CAAC;AAGD,QAAIC,gBAAe,eAAe,WAAW,YAAY,CAAC;AAG1D,QAAI,QAAQ,UAAU;AACpB,YAAM,WAAW,QAAQ,SAAS,cAAc,SAAS;AACzD,UAAI,UAAU;AAEZ,cAAM,gBAAgB;AAAA,UACpB,eAAe,SAAS;AAAA,UACxB,WAAW,SAAS;AAAA,UACpB,WAAW,SAAS;AAAA;AAAA,UAEpB,aAAa,SAAS,eAAe,QAAQ,SAAS,cAAc;AAAA,YAClE,MAAM,SAAS,YAAY;AAAA,YAC3B,IAAI,SAAS,YAAY;AAAA,UAC3B,IAAI;AAAA,QACN;AACA,YAAI,qBAAqB,aAAa;AAAA,MACxC,OAAO;AACL,YAAI,qBAAqB,IAAI;AAAA,MAC/B;AAAA,IACF;AAAA,EACF,OAAO;AAEL,QAAI,sBAAsB;AAAA,MACxB,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,WAAW;AAAA,IACb,CAAC;AAGD,QAAIA,gBAAe;AAAA,MACjB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF,CAAC;AAKM,IAAM,gBAAgBD,OAAK,MAAM,CAAC,KAAK,QAAQ;AACpD,QAAM,QAAQ,IAAI,oBAAoB;AACtC,MAAI,MAAM,UAAU,aAAc;AAClC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,eAAe,QAAQ,OAAO,UAAU;AAG9C,MAAI,aAAa,aAAa,OAAO;AACnC;AAAA,EACF;AAGA,QAAM,QAAQ,aAAa;AAC3B,MAAIG,mBAAkB,KAAK;AAC7B,CAAC;AAKM,IAAM,kBAAkBH,OAAK,MAAM,CAAC,KAAK,QAAQ;AACtD,QAAM,QAAQ,IAAI,oBAAoB;AACtC,MAAI,MAAM,UAAU,aAAc;AAClC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,MAAI,eAAe,GAAG;AAEpB,QAAI,sBAAsB;AAAA,MACxB,OAAO;AAAA,MACP,OAAO,QAAQ;AAAA,MACf,aAAa,CAAC,OAAO;AAAA,IACvB,CAAC;AACD,QAAIC,gBAAe;AAAA,MACjB,MAAM;AAAA,IACR,CAAC;AACD;AAAA,EACF;AAGA,QAAM,iBAAiB,aAAa;AACpC,QAAM,YAAY,QAAQ,OAAO,cAAc;AAG/C,QAAM,eAAe;AAAA,IACnB,GAAG;AAAA,EACL;AACA,SAAO,aAAa,UAAU,IAAI;AAClC,MAAI,sBAAsB;AAAA,IACxB,OAAO;AAAA,IACP;AAAA,IACA,YAAY;AAAA,IACZ,WAAW;AAAA,EACb,CAAC;AACD,MAAIA,gBAAe,eAAe,WAAW,YAAY,CAAC;AAC5D,CAAC;AAKM,IAAM,sBAAsBD,OAAK,MAAM,CAAC,KAAK,KAAK,YAAY;AACnE,MAAI,sBAAsB;AAAA,IACxB,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACD,MAAIC,gBAAe;AAAA,IACjB,MAAM;AAAA,EACR,CAAC;AACH,CAAC;AAKM,IAAM,wBAAwBD,OAAK,MAAM,CAAC,KAAK,QAAQ;AAC5D,MAAI,sBAAsB;AAAA,IACxB,OAAO;AAAA,EACT,CAAC;AACH,CAAC;AASD,SAAS,eAAe,OAAO,WAAW;AACxC,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,QACd,YAAY,MAAM;AAAA,MACpB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,QACd,QAAQ,MAAM,SAAS,UAAQ,MAAM,OAAO,MAAM,aAAa,CAAC,CAAC,IAAI;AAAA,MACvE;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,QACd,QAAQ,MAAM,SAAS,UAAQ,MAAM,OAAO,MAAM,aAAa,CAAC,CAAC,IAAI;AAAA,MACvE;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM,WAAW,CAAC;AAAA,MAC7B;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AACE,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,MAChB;AAAA,EACJ;AACF;;;AE7RO,SAAS,gBAAgB,OAAO;AACrC,SAAO,gBAAgB,KAAK,KAAK,MAAM;AACzC;AAKO,SAAS,mBAAmB,OAAO;AACxC,SAAO,MAAM,KAAK,MAAM,IAAI,mBAAmB,CAAC;AAClD;AAKO,SAAS,oBAAoB,OAAO;AACzC,QAAM,IAAI,kBAAkB;AAC5B,QAAM,IAAI,sBAAsB;AAClC;AAKO,SAAS,uBAAuB,OAAO;AAC5C,QAAM,gBAAgB,MAAM,IAAI,iBAAiB;AACjD,MAAI,cAAe,QAAO;AAC1B,QAAM,WAAW,mBAAmB,KAAK;AACzC,SAAO,SAAS,CAAC,KAAK;AACxB;AAKO,SAAS,kBAAkB,OAAO;AACvC,QAAM,iBAAiB,MAAM,IAAI,kBAAkB;AACnD,MAAI,eAAgB,QAAO;AAAA,IACzB,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AACA,QAAM,eAAe,MAAM,IAAI,gBAAgB;AAC/C,MAAI,aAAa,cAAc,aAAa,cAAc;AACxD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,aAAa;AAAA,IACvB;AAAA,EACF;AACA,QAAM,gBAAgB,uBAAuB,KAAK;AAClD,MAAI,cAAe,QAAO;AAAA,IACxB,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AACA,QAAM,iBAAiB,MAAM,IAAI,kBAAkB;AACnD,MAAI,eAAgB,QAAO;AAAA,IACzB,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AACA,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;AAKO,SAAS,iBAAiB,OAAO,OAAO;AAC7C,MAAI,MAAM,SAAS,SAAS,MAAM,YAAY,QAAW;AACvD,UAAM,UAAU,kBAAkB,KAAK;AAAA,EACzC;AACF;;;ACpEO,SAAS,gBAAgB,eAAe,OAAO,WAAW;AAC/D,QAAM,QAAQ,MAAM,IAAI,WAAW;AACnC,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,CAAC,eAAe;AAClB,UAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,IAAI,EAAE,SAAS,KAAK,EAAE,SAAS,IAAI,EAAE,SAAS,CAAC;AACnG,WAAO,OAAO,CAAC,GAAG,MAAM;AAAA,EAC1B;AACA,QAAM,cAAc,MAAM,KAAK,UAAQ,KAAK,OAAO,aAAa;AAChE,MAAI,CAAC,YAAa,QAAO,MAAM,CAAC,GAAG,MAAM;AACzC,QAAM,KAAK,YAAY,SAAS,KAAK,YAAY,SAAS,OAAO;AACjE,QAAM,KAAK,YAAY,SAAS,KAAK,YAAY,UAAU,OAAO;AAClE,MAAI,SAAS;AACb,MAAI,YAAY,OAAO;AACvB,aAAW,aAAa,OAAO;AAC7B,QAAI,UAAU,OAAO,YAAY,GAAI;AACrC,UAAM,KAAK,UAAU,SAAS,KAAK,UAAU,SAAS,OAAO;AAC7D,UAAM,KAAK,UAAU,SAAS,KAAK,UAAU,UAAU,OAAO;AAC9D,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,KAAK;AAChB,QAAI,UAAU;AACd,YAAQ,WAAW;AAAA,MACjB,KAAK;AACH,kBAAU,KAAK;AACf;AAAA,MACF,KAAK;AACH,kBAAU,KAAK;AACf;AAAA,MACF,KAAK;AACH,kBAAU,KAAK;AACf;AAAA,MACF,KAAK;AACH,kBAAU,KAAK;AACf;AAAA,IACJ;AACA,QAAI,CAAC,QAAS;AACd,UAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACxC,UAAM,eAAe,cAAc,UAAU,cAAc;AAC3D,UAAM,wBAAwB,eAAe,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE;AACvE,UAAM,QAAQ,OAAO,wBAAwB;AAC7C,QAAI,QAAQ,WAAW;AACrB,kBAAY;AACZ,eAAS,UAAU;AAAA,IACrB;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,WAAW,OAAO,WAAW;AAC3C,QAAM,QAAQ,MAAM,IAAI,WAAW;AACnC,MAAI,MAAM,WAAW,EAAG;AACxB,QAAM,gBAAgB,MAAM,IAAI,iBAAiB;AACjD,QAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC5D,QAAM,aAAa,gBAAgB,OAAO,UAAU,UAAQ,KAAK,OAAO,aAAa,IAAI;AACzF,QAAM,UAAU,cAAc,KAAK,cAAc,IAAI,OAAO,SAAS,IAAI,aAAa,KAAK,aAAa,KAAK,OAAO;AACpH,QAAM,IAAI,oBAAoB,OAAO,OAAO,EAAE,EAAE;AAClD;AAKO,SAAS,cAAc,OAAO,WAAW;AAC9C,QAAM,SAAS,gBAAgB,uBAAuB,KAAK,GAAG,OAAO,SAAS;AAC9E,MAAI,QAAQ;AACV,UAAM,IAAI,oBAAoB,MAAM;AAAA,EACtC;AACF;AAKO,SAAS,oBAAoB,OAAO,iBAAiB;AAC1D,QAAM,gBAAgB,uBAAuB,KAAK;AAClD,MAAI,CAAC,cAAe;AACpB,QAAM,IAAI,oBAAoB,aAAa;AAC3C,QAAM,IAAI,sBAAsB,aAAa;AAC7C,MAAI,iBAAiB;AACnB,UAAM,IAAI,gCAAgC,YAAY;AAAA,EACxD;AACF;;;AC3EO,IAAM,sBAAsB;AAAA,EACjC,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,uBAAuB;AACzB;AAMO,SAAS,eAAe,OAAO,IAAI,IAAI,OAAO;AACnD,QAAM,WAAW,mBAAmB,KAAK;AACzC,MAAI,SAAS,WAAW,GAAG;AACzB,UAAM,UAAU,MAAM,IAAI,iBAAiB;AAC3C,QAAI,SAAS;AACX,YAAM,IAAI,sBAAsB,OAAO;AAAA,IACzC;AAAA,EACF;AACA,QAAM,UAAU,mBAAmB,KAAK;AACxC,MAAI,QAAQ,WAAW,EAAG;AAC1B,QAAM,QAAQ,MAAM,IAAI,SAAS,EAAE,KAAK;AACxC,QAAM,IAAI,iBAAiB,KAAK;AAChC,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,MAAM,QAAQ,MAAM,EAAG;AAC5B,UAAM,IAAI,MAAM,iBAAiB,QAAQ,GAAG;AAC5C,UAAM,IAAI,MAAM,iBAAiB,QAAQ,GAAG;AAC5C,UAAM,iBAAiB,QAAQ,KAAK,IAAI,EAAE;AAC1C,UAAM,iBAAiB,QAAQ,KAAK,IAAI,EAAE;AAAA,EAC5C;AACA,QAAM,IAAI,WAAW,KAAK;AAC1B,QAAM,IAAI,+BAA+B,WAAS,QAAQ,CAAC;AAC7D;AACO,SAAS,gBAAgB,OAAO;AACrC,QAAM,iBAAiB,MAAM,IAAI,kBAAkB;AACnD,MAAI,gBAAgB;AAClB,UAAM,IAAI,0BAA0B;AAAA,MAClC,SAAS;AAAA,IACX,CAAC;AACD,UAAM,IAAI,sBAAsB;AAAA,EAClC;AACA,QAAM,kBAAkB,mBAAmB,KAAK;AAChD,MAAI,gBAAgB,WAAW,EAAG;AAClC,QAAM,IAAI,iBAAiB,gBAAgB,SAAS,IAAI,UAAU,gBAAgB,MAAM,WAAW,aAAa;AAChH,QAAM,gBAAgB,MAAM,IAAI,iBAAiB;AACjD,aAAW,UAAU,iBAAiB;AACpC,UAAM,IAAI,0BAA0B;AAAA,MAClC;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,iBAAiB,gBAAgB,SAAS,aAAa,GAAG;AAC5D,UAAM,IAAI,oBAAoB,IAAI;AAAA,EACpC;AACA,QAAM,IAAI,kBAAkB;AAC9B;AACO,SAAS,aAAa,OAAO;AAClC,QAAM,kBAAkB,mBAAmB,KAAK;AAChD,MAAI,gBAAgB,WAAW,EAAG;AAClC,QAAM,IAAI,qBAAqB,eAAe;AAC9C,kBAAgB,KAAK;AACvB;AAMO,SAAS,wBAAwB,OAAO;AAC7C,MAAI,YAAY;AAChB,MAAI,MAAM,IAAI,kBAAkB,MAAM,MAAM;AAC1C,UAAM,IAAI,eAAe;AACzB,gBAAY;AAAA,EACd;AACA,MAAI,MAAM,IAAI,gBAAgB,EAAE,YAAY;AAC1C,UAAM,IAAI,kBAAkB,mBAAmB;AAC/C,gBAAY;AAAA,EACd;AACA,MAAI,MAAM,IAAI,aAAa,EAAE,SAAS,eAAe,MAAM,IAAI,aAAa,EAAE,SAAS,cAAc,MAAM,IAAI,aAAa,EAAE,SAAS,aAAa;AAClJ,UAAM,IAAI,kBAAkB;AAC5B,gBAAY;AAAA,EACd;AACA,QAAM,gBAAgB,MAAM,IAAI,iBAAiB;AACjD,MAAI,kBAAkB,MAAM;AAC1B,UAAM,IAAI,mBAAmB;AAC7B,gBAAY;AAAA,EACd;AACA,SAAO;AACT;AACO,SAAS,YAAY,OAAO;AACjC,MAAI,wBAAwB,KAAK,EAAG;AACpC,MAAI,MAAM,IAAI,2BAA2B,MAAM,cAAc;AAC3D,UAAM,IAAI,gCAAgC;AAC1C;AAAA,EACF;AACA,MAAI,MAAM,IAAI,kBAAkB,GAAG;AACjC,UAAM,IAAI,eAAe;AACzB;AAAA,EACF;AACA,MAAI,MAAM,IAAI,sBAAsB,GAAG;AACrC,UAAM,IAAI,oBAAoB;AAC9B;AAAA,EACF;AACA,MAAI,MAAM,IAAI,mBAAmB,EAAE,OAAO,KAAK,MAAM,IAAI,kBAAkB,MAAM,MAAM;AACrF,wBAAoB,KAAK;AAAA,EAC3B;AACF;AAMO,SAAS,gBAAgB,OAAO,OAAO;AAC5C,mBAAiB,OAAO,KAAK;AAC7B,MAAI,MAAM,SAAS,SAAS,OAAQ;AACpC,MAAI,MAAM,IAAI,aAAa,EAAE,SAAS,aAAa;AACjD,UAAM,IAAI,2BAA2B,MAAM,QAAQ,MAAM;AACzD,UAAM,IAAI,oBAAoB,MAAM,QAAQ,MAAM;AAClD;AAAA,EACF;AACA,QAAM,IAAI,kBAAkB,MAAM,QAAQ,MAAM;AAChD,QAAM,IAAI,kBAAkB;AAC9B;AACO,SAAS,gBAAgB,OAAO;AACrC,QAAM,IAAI,kBAAkB,mBAAmB,KAAK,CAAC;AACrD,QAAM,IAAI,kBAAkB;AAC9B;AACO,SAAS,iBAAiB,OAAO,OAAO;AAC7C,MAAI,MAAM,SAAS,UAAW;AAC9B,QAAM,IAAI,kBAAkB,MAAM,aAAa;AAC/C,QAAM,IAAI,kBAAkB;AAC9B;AACO,SAAS,UAAU,OAAO;AAC/B,sBAAoB,KAAK;AACzB,QAAM,IAAI,yBAAyB,MAAM,IAAI,YAAY,CAAC;AAC5D;;;AC9IA,SAAS,UAAAI,SAAQ,aAAAC,YAAW,eAAe;AAC3C,SAAS,SAAS,YAAY,gBAAAC,qBAAoB;AAClD,SAAS,kBAAkB;;;ACb3B,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAStB,SAAS,gBAAgB,WAAW,cAAc;AACvD,QAAM,iBAAiB,aAAa,kBAAkB;AACtD,QAAM,cAAc,aAAa,eAAe;AAChD,QAAM,iBAAiB,aAAa,kBAAkB;AACtD,QAAM,gBAAgB,aAAa,iBAAiB;AACpD,QAAM,kBAAkB,aAAa,mBAAmB;AACxD,QAAM,YAAY,aAAa,aAAa;AAC5C,QAAM,0BAA0B,aAAa,2BAA2B;AACxE,QAAM,gBAAgB,aAAa,iBAAiB;AACpD,QAAM,eAAe,aAAa,gBAAgB;AAClD,QAAM,iBAAiB,aAAa,kBAAkB;AACtD,QAAM,qBAAqB,aAAa,sBAAsB;AAC9D,QAAM,WAAW,OAAO;AAAA,IACtB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IACA,yBAAyB;AAAA,IACzB,iBAAiB,oBAAI,IAAI;AAAA,IACzB,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,IACpB,UAAU;AAAA,IACV,QAAQ,CAAC;AAAA,EACX,CAAC;AACD,WAAS,UAAU;AAAA,IACjB;AAAA,IACA;AAAA,IACA,YAAY,mBAAmB;AAAA,IAC/B,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,MACN,aAAa,kBAAkB;AAAA,MAC/B,gBAAgB,aAAa;AAAA,IAC/B;AAAA,EACF;AACA,SAAO;AACT;;;AC1DA,SAAS,UAAAC,SAAQ,iBAAiB;AAM3B,IAAMC,uBAAsB;AAC5B,IAAM,oBAAoB;AACjC,IAAMC,yBAAwB;AAUvB,SAAS,SAAS,GAAG;AAC1B,SAAO,KAAK,IAAI,IAAI,CAAG,IAAID,uBAAsB,IAAM;AACzD;AAMO,SAAS,aAAa;AAC3B,QAAM,gBAAgBE,QAAO,IAAI;AACjC,QAAM,iBAAiBA,QAAO,IAAI;AAClC,QAAM,gBAAgBA,QAAO,IAAI,gBAAgBD,sBAAqB,CAAC;AACvE,QAAM,iBAAiBC,QAAO,IAAI,gBAAgBD,sBAAqB,CAAC;AACxE,QAAM,kBAAkBC,QAAO,IAAI;AACnC,QAAM,gBAAgBA,QAAO,IAAI;AACjC,QAAM,YAAY,MAAM;AACtB,QAAI,cAAc,SAAS;AACzB,2BAAqB,cAAc,QAAQ,IAAI;AAC/C,oBAAc,UAAU;AAAA,IAC1B;AAAA,EACF;AACA,QAAM,aAAa,MAAM;AACvB,QAAI,eAAe,SAAS;AAC1B,2BAAqB,eAAe,QAAQ,IAAI;AAChD,qBAAe,UAAU;AAAA,IAC3B;AAAA,EACF;AACA,QAAM,YAAY,MAAM;AACtB,cAAU;AACV,eAAW;AAAA,EACb;AACA,QAAM,kBAAkB,CAAC,UAAU,WAAW;AAC5C,cAAU;AACV,UAAM,SAAS,IAAI,WAAW,QAAQ;AACtC,UAAM,UAAU,MAAM;AACpB,YAAM,OAAO,OAAO,KAAK;AACzB,UAAI,CAAC,MAAM;AACT,sBAAc,UAAU;AACxB;AAAA,MACF;AACA,aAAO,WAAS;AAAA,QACd,GAAG,KAAK,IAAI,KAAK;AAAA,QACjB,GAAG,KAAK,IAAI,KAAK;AAAA,MACnB,EAAE;AACF,oBAAc,QAAQ,OAAO,sBAAsB,OAAO;AAAA,IAC5D;AACA,kBAAc,UAAU;AAAA,MACtB,MAAM,sBAAsB,OAAO;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACA,QAAM,mBAAmB,CAAC,YAAY,QAAQ,aAAa,SAAS,SAAS,SAAS,aAAa;AACjG,eAAW;AACX,UAAM,WAAW,IAAI,YAAY,YAAY,MAAM;AACnD,UAAM,YAAY,MAAM;AACtB,YAAM,SAAS,SAAS,KAAK,WAAW;AACxC,UAAI,CAAC,QAAQ;AACX,uBAAe,UAAU;AACzB;AAAA,MACF;AACA,cAAQ,cAAY;AAClB,cAAM,UAAU,KAAK,IAAI,SAAS,KAAK,IAAI,SAAS,WAAW,OAAO,KAAK,CAAC;AAC5E,iBAAS,aAAW;AAClB,gBAAM,UAAU,OAAO,OAAO,IAAI,QAAQ,KAAK;AAC/C,gBAAM,UAAU,OAAO,OAAO,IAAI,QAAQ,KAAK;AAC/C,iBAAO;AAAA,YACL,GAAG,OAAO,OAAO,IAAI,SAAS;AAAA,YAC9B,GAAG,OAAO,OAAO,IAAI,SAAS;AAAA,UAChC;AAAA,QACF,CAAC;AACD,eAAO,SAAS,OAAO;AAAA,MACzB,CAAC;AACD,qBAAe,QAAQ,OAAO,sBAAsB,SAAS;AAAA,IAC/D;AACA,mBAAe,UAAU;AAAA,MACvB,MAAM,sBAAsB,SAAS;AAAA,MACrC,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,YAAU,MAAM,WAAW,CAAC,CAAC;AAC7B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,cAAc;AAAA,IAC1B,aAAa,eAAe;AAAA,IAC5B;AAAA,IACA;AAAA,EACF;AACF;;;AC1FO,SAAS,mBAAmB,QAAQ;AACzC,SAAO,CAAC;AAAA,IACN;AAAA,IACA;AAAA,IACA,OAAO,CAAC,EAAE,EAAE;AAAA,IACZ;AAAA,EACF,MAAM;AACJ,QAAI,SAAS,QAAQ,YAAY,CAAC,OAAO,cAAc,CAAC,OAAO,IAAI,QAAS;AAG5E,UAAM,SAAS,MAAM;AACrB,UAAM,SAAS,OAAO,QAAQ,uBAAuB;AACrD,QAAI,QAAQ;AACV,YAAM,gBAAgB,OAAO,QAAQ,8BAA8B;AACnE,UAAI,eAAe;AACjB,cAAM,SAAS,cAAc,aAAa,cAAc;AACxD,YAAI,UAAU,OAAO,gBAAgB,IAAI,MAAM,GAAG;AAChD,cAAI,KAAK;AACT,iBAAO,MAAM,OAAO,SAAS,EAAE,GAAG;AAChC,gBAAI,GAAG,eAAe,GAAG,cAAc;AACrC,oBAAM,WAAW,GAAG,YAAY,GAAG,gBAAgB,GAAG,eAAe;AACrE,oBAAM,QAAQ,GAAG,aAAa;AAC9B,kBAAI,CAAC,YAAY,KAAK,KAAK,CAAC,SAAS,KAAK,KAAK,YAAY,KAAK,KAAK,SAAS,KAAK,GAAG;AACpF;AAAA,cACF;AAAA,YACF;AACA,iBAAK,GAAG;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,UAAM,eAAe;AACrB,UAAM,OAAO,OAAO,IAAI,QAAQ,sBAAsB;AACtD,UAAM,SAAS,MAAM,UAAU,KAAK;AACpC,UAAM,SAAS,MAAM,UAAU,KAAK;AACpC,UAAM,UAAU,SAAS,OAAO,IAAI,KAAK,OAAO;AAChD,UAAM,UAAU,SAAS,OAAO,IAAI,KAAK,OAAO;AAChD,UAAM,YAAY,CAAC,KAAK,OAAO,kBAAkB,OAAO;AACxD,UAAM,UAAU,SAAS,KAAK,IAAI,OAAO,SAAS,KAAK,IAAI,OAAO,SAAS,OAAO,OAAO,SAAS,CAAC,CAAC;AACpG,WAAO,QAAQ,OAAO;AACtB,WAAO,OAAO;AAAA,MACZ,GAAG,SAAS,SAAS;AAAA,MACrB,GAAG,SAAS,SAAS;AAAA,IACvB,CAAC;AAAA,EACH;AACF;;;AC7CO,SAAS,oBAAoB,QAAQ;AAC1C,QAAM,eAAe,CAAC;AAAA,IACpB,QAAQ,CAAC,IAAI,EAAE;AAAA,EACjB,MAAM;AACJ,QAAI,CAAC,OAAO,cAAc,CAAC,OAAO,IAAI,QAAS,QAAO;AACtD,WAAO,QAAQ,UAAU;AACzB,WAAO,QAAQ,gBAAgB,UAAU;AAAA,MACvC,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AACA,WAAO,QAAQ,YAAY,MAAM;AACjC,WAAO,QAAQ,cAAc,UAAU;AAAA,MACrC,MAAM,OAAO;AAAA,MACb,GAAG,YAAY,IAAI;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AACA,QAAM,UAAU,CAAC;AAAA,IACf,QAAQ,CAAC,CAAC;AAAA,IACV,QAAQ,CAAC,IAAI,EAAE;AAAA,IACf;AAAA,IACA;AAAA,EACF,MAAM;AACJ,QAAI,SAAS,QAAQ,CAAC,OAAO,cAAc,CAAC,OAAO,IAAI,QAAS;AAChE,UAAM,eAAe;AACrB,UAAM,OAAO,OAAO,IAAI,QAAQ,sBAAsB;AACtD,UAAM,SAAS,KAAK,KAAK;AACzB,UAAM,SAAS,KAAK,KAAK;AAGzB,QAAI,MAAM;AACV,QAAI,MAAM;AACV,QAAI,OAAO,QAAQ,gBAAgB,SAAS;AAC1C,YAAM,KAAK,OAAO,QAAQ,gBAAgB,QAAQ;AAClD,YAAM,KAAK,OAAO,QAAQ,gBAAgB,QAAQ;AAAA,IACpD;AACA,WAAO,QAAQ,gBAAgB,UAAU;AAAA,MACvC,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AACA,UAAM,UAAU,SAAS,OAAO,IAAI,KAAK,OAAO;AAChD,UAAM,UAAU,SAAS,OAAO,IAAI,KAAK,OAAO;AAChD,UAAM,UAAU,SAAS,KAAK,IAAI,OAAO,SAAS,KAAK,IAAI,OAAO,SAAS,CAAC,CAAC,CAAC;AAG9E,UAAM,MAAM,YAAY,IAAI;AAC5B,QAAI,OAAO,QAAQ,cAAc,SAAS;AACxC,YAAM,MAAM,MAAM,OAAO,QAAQ,cAAc,QAAQ,KAAK;AAC5D,UAAI,KAAK,GAAG;AACV,cAAM,KAAK,UAAU,OAAO,QAAQ,cAAc,QAAQ,QAAQ;AAClE,eAAO,QAAQ,YAAY,OAAO,GAAG,GAAG,GAAG;AAAA,MAC7C;AAAA,IACF;AACA,WAAO,QAAQ,cAAc,UAAU;AAAA,MACrC,MAAM;AAAA,MACN,GAAG;AAAA,IACL;AACA,WAAO,QAAQ,OAAO;AACtB,WAAO,OAAO;AAAA,MACZ,GAAG,SAAS,SAAS,UAAU;AAAA,MAC/B,GAAG,SAAS,SAAS,UAAU;AAAA,IACjC,CAAC;AAAA,EACH;AACA,QAAM,aAAa,MAAM;AACvB,UAAM,MAAM,OAAO,QAAQ,YAAY,QAAQ;AAC/C,UAAM,YAAY,IAAI,IAAI;AAC1B,QAAI,CAAC,OAAO,iBAAiB,KAAK,IAAI,SAAS,IAAI,QAAS,OAAO,IAAI,SAAS;AAC9E,YAAM,OAAO,OAAO,IAAI,QAAQ,sBAAsB;AACtD,YAAM,SAAS,OAAO,QAAQ,gBAAgB,WAAW;AAAA,QACvD,GAAG,KAAK,QAAQ;AAAA,QAChB,GAAG,KAAK,SAAS;AAAA,MACnB;AACA,aAAO,QAAQ,iBAAiB,WAAW;AAAA,QACzC,GAAG,OAAO,IAAI,KAAK;AAAA,QACnB,GAAG,OAAO,IAAI,KAAK;AAAA,MACrB,GAAG,OAAO,MAAM,OAAO,SAAS,OAAO,SAAS,OAAO,SAAS,OAAO,MAAM;AAAA,IAC/E;AACA,WAAO,QAAQ,gBAAgB,UAAU;AACzC,WAAO,QAAQ,YAAY,MAAM;AACjC,WAAO,QAAQ,cAAc,UAAU;AAAA,EACzC;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AJpEO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,cAAc;AAAA,EACd,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB;AAAA,EACA,WAAW;AACb,GAAG;AAED,QAAM,CAAC,SAAS,MAAM,IAAI,QAAQ,OAAO;AACzC,QAAM,CAAC,SAAS,OAAO,IAAI,QAAQ,QAAQ;AAC3C,QAAM,kBAAkB,WAAW,gBAAgB;AACnD,QAAM,kBAAkBC,cAAa,mBAAmB;AACxD,QAAM,iBAAiB,WAAW,kBAAkB;AACpD,QAAM,gBAAgBA,cAAa,iBAAiB;AAGpD,QAAM,iBAAiB,WAAW,eAAe;AACjD,QAAM,eAAe,WAAW,aAAa;AAC7C,QAAM,gBAAgB,WAAW,iBAAiB;AAClD,QAAM,qBAAqBA,cAAa,sBAAsB;AAC9D,QAAM,gBAAgBA,cAAa,wBAAwB;AAG3D,QAAM,iBAAiB,WAAW,kBAAkB;AACpD,QAAM,kBAAkB,WAAW,mBAAmB;AACtD,QAAM,eAAe,WAAW,gBAAgB;AAGhD,QAAM,WAAW,gBAAgB,QAAQ;AACzC,QAAM,UAAU,WAAW;AAG3B,QAAM,cAAcC,QAAO;AAAA,IACzB,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AACD,QAAM,qBAAqBA,QAAO,KAAK;AACvC,QAAM,gBAAgBA,QAAO,OAAO;AACpC,QAAM,YAAYA,QAAO,CAAC;AAC1B,QAAM,gBAAgBA,QAAO,MAAM;AAGnC,QAAM,cAAcA,QAAO,IAAI,iBAAiB,CAAC;AAGjD,QAAM,gBAAgB,QAAQ,MAAM;AAClC,UAAM,UAAU,CAAC;AACjB,QAAI,cAAe,SAAQ,KAAK,sBAAsB;AACtD,QAAI,cAAe,SAAQ,KAAK,GAAG,aAAa;AAChD,YAAQ,KAAK,eAAe;AAC5B,WAAO,kBAAkB,OAAO;AAAA,EAClC,GAAG,CAAC,eAAe,aAAa,CAAC;AACjC,QAAM,eAAe,iBAAiB;AAItC,QAAM,qBAAqB,YAAU;AACnC,QAAI,CAAC,IAAI,WAAW,CAAC,OAAQ,QAAO;AACpC,UAAM,QAAQ,IAAI,QAAQ;AAC1B,WAAO,WAAW,IAAI,WAAW,WAAW;AAAA,EAC9C;AACA,QAAM,mBAAmB,CAAC,MAAM,OAAO,SAAS,SAAS,SAAS,UAAU;AAC1E,UAAM,WAAW,cAAc,SAAS,OAAO;AAC/C,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,cAAc;AAAA,MACtB,QAAQ,UAAU;AAAA,MAClB,WAAW;AAAA,MACX;AAAA,MACA,gBAAgB;AAAA,QACd,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,MACA,eAAe;AAAA,MACf,GAAG;AAAA,IACL;AAAA,EACF;AACA,QAAM,qBAAqB,WAAS;AAClC,UAAM,aAAa,QAAQ,OAAO,cAAc,SAAS,OAAO;AAChE,QAAI,YAAY;AACd,eAAS,OAAO,UAAU;AAC1B,iBAAW,OAAO,UAAU;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAGA,EAAAC,WAAU,MAAM;AACd,UAAM,SAAS,YAAY;AAC3B,WAAO,SAAS,kBAAgB;AAAA,IAGhC;AACA,WAAO,MAAM;AACX,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,EAAAA,WAAU,MAAM;AACd,UAAM,KAAK,IAAI;AACf,QAAI,CAAC,IAAI;AACP,sBAAgB,IAAI;AACpB;AAAA,IACF;AACA,oBAAgB,GAAG,sBAAsB,CAAC;AAC1C,UAAM,WAAW,IAAI,eAAe,aAAW;AAC7C,iBAAW,SAAS,SAAS;AAC3B,wBAAgB,MAAM,WAAW;AAAA,MACnC;AAAA,IACF,CAAC;AACD,aAAS,QAAQ,EAAE;AACnB,WAAO,MAAM;AACX,eAAS,UAAU,EAAE;AACrB,eAAS,WAAW;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,eAAe,CAAC;AAGpB,EAAAA,WAAU,MAAM;AACd,WAAO,MAAM;AACX,cAAQ,UAAU;AAClB,kBAAY,QAAQ,QAAQ;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,EAAAA,WAAU,MAAM;AACd,UAAM,kBAAkB,MAAM;AAC5B,UAAI,SAAS,QAAQ;AACnB,gBAAQ,UAAU;AAClB,sBAAc;AACd,oBAAY,QAAQ,KAAK,QAAQ;AAAA,MACnC;AAAA,IACF;AACA,aAAS,iBAAiB,oBAAoB,eAAe;AAC7D,WAAO,MAAM,SAAS,oBAAoB,oBAAoB,eAAe;AAAA,EAC/E,GAAG,CAAC,aAAa,CAAC;AAMlB,aAAW;AAAA,IACT,eAAe,WAAS;AACtB,UAAI,CAAC,IAAI,SAAS;AAChB,2BAAmB,UAAU;AAC7B;AAAA,MACF;AACA,YAAM,KAAK,MAAM;AACjB,YAAM,aAAa,gBAAgB,EAAE;AACrC,qBAAe,UAAU;AACzB,oBAAc,UAAU,WAAW;AACnC,gBAAU,UAAU,GAAG,UAAU;AAGjC,cAAQ,UAAU;AAClB,UAAI,mBAAmB,MAAM,MAAM,MAAM,GAAG;AAC1C,2BAAmB,UAAU;AAG7B,oBAAY,QAAQ,KAAK,MAAM;AAG/B,cAAM,SAAS,GAAG;AAClB,cAAM,SAAS,GAAG;AAClB,oBAAY,QAAQ,SAAS,iBAAe;AAC1C,cAAI,gBAAgB,cAAc;AAChC,kBAAM,aAAa,cAAc,QAAQ,MAAM;AAC/C,kBAAM,UAAU,iBAAiB,cAAc,WAAW;AAAA,cACxD,MAAM;AAAA,YACR,GAAG,QAAQ,QAAQ;AAAA,cACjB,WAAW,iBAAiB,EAAE;AAAA,cAC9B,eAAe;AAAA,YACjB,CAAC;AACD,+BAAmB,OAAO;AAAA,UAC5B;AAAA,QACF;AAAA,MACF,OAAO;AACL,2BAAmB,UAAU;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,aAAa,aAAW;AACtB,YAAM,OAAO,QAAQ;AACrB,mBAAa,KAAK,SAAS;AAAA,IAC7B;AAAA,IACA,aAAa,CAAC;AAAA,MACZ,OAAO;AAAA,IACT,MAAM;AACJ,UAAI,CAAC,mBAAmB,QAAS;AACjC,YAAM,OAAO;AACb,YAAM,YAAY,OAAO,iBAAiB,IAAI,IAAI;AAGlD,YAAM,eAAe,iBAAiB,QAAQ,SAAS;AAAA,QACrD,MAAM;AAAA,MACR,GAAG,MAAM,WAAW,GAAG,MAAM,WAAW,GAAG;AAAA,QACzC;AAAA,MACF,CAAC;AACD,YAAM,eAAe,QAAQ,cAAc,cAAc,SAAS,OAAO;AACzE,oBAAc,UAAU,cAAc,YAAY;AAClD,UAAI,cAAc,YAAY,SAAS,WAAW;AAChD,oBAAY,UAAU;AAAA,UACpB,GAAG;AAAA,QACL;AACA,gBAAQ,WAAW,MAAM;AAAA,MAC3B,WAAW,cAAc,YAAY,kBAAkB,cAAc,YAAY,eAAe;AAC9F,cAAM,aAAa,cAAc,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC;AACvE,uBAAe;AAAA,UACb,MAAM,cAAc,YAAY,iBAAiB,UAAU;AAAA,UAC3D,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAGA,UAAI,cAAc;AAChB,iBAAS,cAAc,YAAY;AACnC,mBAAW,cAAc,YAAY;AAAA,MACvC;AAAA,IACF;AAAA,IACA,QAAQ,CAAC;AAAA,MACP,UAAU,CAAC,IAAI,EAAE;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,UAAU,CAAC,IAAI,EAAE;AAAA,MACjB,WAAW,CAAC,IAAI,EAAE;AAAA,IACpB,MAAM;AACJ,UAAI,OAAO,mBAAmB,SAAS;AAErC,cAAM,UAAU,YAAY,QAAQ,KAAK,IAAI;AAC7C,cAAM,OAAO;AACb,cAAM,cAAc,iBAAiB,IAAI;AACzC,cAAM,UAAU,WAAW;AAC3B,cAAM,iBAAiB,iBAAiB,SAAS,WAAW;AAAA,UAC1D,MAAM;AAAA,QACR,GAAG,KAAK,SAAS,KAAK,SAAS;AAAA,UAC7B,WAAW;AAAA,QACb,CAAC;AACD,cAAM,eAAe,QAAQ,gBAAgB,cAAc,SAAS,OAAO;AAC3E,YAAI,cAAc;AAChB,mBAAS,gBAAgB,YAAY;AACrC,qBAAW,gBAAgB,YAAY;AAAA,QACzC,OAAO;AACL,yBAAe;AAAA,QACjB;AACA;AAAA,MACF;AACA,UAAI,CAAC,OAAO,UAAU,CAAC,YAAY,mBAAmB,SAAS;AAE7D,oBAAY,QAAQ,KAAK,uBAAuB;AAChD,cAAM,SAAS,cAAc;AAC7B,YAAI,WAAW,SAAS,WAAW;AACjC,iBAAO;AAAA,YACL,GAAG,YAAY,QAAQ,IAAI;AAAA,YAC3B,GAAG,YAAY,QAAQ,IAAI;AAAA,UAC7B,CAAC;AACD,gBAAM,MAAM,YAAY,IAAI;AAC5B,kBAAQ,WAAW,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG;AAAA,QACjD,WAAW,WAAW,kBAAkB,WAAW,eAAe;AAChE,gBAAM,OAAO;AACb,gBAAM,aAAa,cAAc,KAAK,SAAS,KAAK,OAAO;AAC3D,0BAAgB,UAAU;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,QAAQ,KAAK,IAAI;AAC7B,YAAM,WAAW,cAAc;AAC/B,UAAI,aAAa,kBAAkB,aAAa,eAAe;AAC7D,qBAAa;AAAA,MACf;AAGA,UAAI,CAAC,iBAAiB,mBAAmB,WAAW,cAAc,YAAY,YAAY,aAAa,OAAO;AAC5G,cAAM,MAAM,QAAQ,WAAW,QAAQ;AACvC,cAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC;AAC/C,YAAI,QAAQ,mBAAmB;AAC7B,kBAAQ,gBAAgB,KAAK,MAAM;AAAA,QACrC;AAAA,MACF;AACA,yBAAmB,UAAU;AAC7B,oBAAc,UAAU;AACxB,cAAQ,WAAW,MAAM;AAAA,IAC3B;AAAA,IACA,SAAS,mBAAmB;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACD,GAAG,oBAAoB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,GAAG;AAAA,IACD,QAAQ;AAAA,IACR,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,IACA,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,eAAe,uBAAuB,WAAW,KAAK;AAAA,MACtD,SAAS;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,CAAC;AAAA,IACR,OAAO;AAAA,MACL,aAAa,OAAO;AAAA,QAClB,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAAA,MACA,MAAM,MAAM,CAAC,SAAS,CAAC;AAAA,IACzB;AAAA,EACF,CAAC;AACH;;;AKvXA,SAAS,UAAAC,SAAQ,aAAAC,kBAAiB;AAClC,SAAS,gBAAAC,qBAAoB;AAetB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AACb,GAAG;AACD,QAAM,gBAAgBC,cAAa,iBAAiB;AACpD,QAAM,iBAAiBA,cAAa,kBAAkB;AACtD,QAAM,cAAcA,cAAa,eAAe;AAChD,QAAM,YAAYA,cAAa,aAAa;AAC5C,QAAM,0BAA0BA,cAAa,2BAA2B;AACxE,QAAM,kBAAkBA,cAAa,mBAAmB;AACxD,QAAM,gBAAgBA,cAAa,iBAAiB;AACpD,QAAM,iBAAiBA,cAAa,kBAAkB;AACtD,QAAM,eAAeA,cAAa,gBAAgB;AAClD,QAAM,gBAAgBA,cAAa,iBAAiB;AACpD,QAAM,iBAAiBA,cAAa,kBAAkB;AACtD,QAAM,qBAAqBA,cAAa,sBAAsB;AAC9D,QAAM,SAASC,QAAO,IAAI,iBAAiB,CAAC;AAC5C,QAAM,YAAYA,QAAO,OAAO;AAChC,QAAM,YAAYA,QAAO,CAAC;AAC1B,QAAM,SAASA,QAAO;AAAA,IACpB,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AACD,QAAM,eAAeA,QAAO,YAAY;AAExC,QAAM,gBAAgBA,QAAO,KAAK;AAGlC,QAAM,WAAWA,QAAO;AAAA,IACtB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IACA,yBAAyB;AAAA,IACzB,iBAAiB,oBAAI,IAAI;AAAA,IACzB,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,IACpB,UAAU;AAAA,IACV,QAAQ,CAAC;AAAA,EACX,CAAC;AACD,WAAS,UAAU;AAAA,IACjB;AAAA,IACA;AAAA,IACA,YAAY,mBAAmB;AAAA,IAC/B,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,CAAC;AAAA,EACX;AACA,WAAS,QAAQ,SAAS;AAAA,IACxB,aAAa,kBAAkB;AAAA,IAC/B,gBAAgB,aAAa;AAAA,EAC/B;AAGA,EAAAC,WAAU,MAAM;AACd,WAAO,MAAM,OAAO,QAAQ,QAAQ;AAAA,EACtC,GAAG,CAAC,CAAC;AACL,QAAM,qBAAqB,WAAS;AAClC,UAAM,aAAa,QAAQ,OAAO,cAAc,SAAS,OAAO;AAChE,QAAI,YAAY;AACd,eAAS,OAAO,UAAU;AAC1B,iBAAW,OAAO,UAAU;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AACA,QAAM,YAAY,CAAC,MAAM,OAAO,SAAS,YAAY;AACnD,UAAM,WAAW,cAAc,SAAS,OAAO;AAC/C,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN;AAAA,MACF;AAAA,MACA,QAAQ,UAAU;AAAA,MAClB,QAAQ,UAAU;AAAA,MAClB,WAAW,aAAa;AAAA,MACxB;AAAA,MACA,gBAAgB;AAAA,QACd,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,MACA,eAAe;AAAA,IACjB;AAAA,EACF;AAGA,EAAAA,WAAU,MAAM;AACd,WAAO,QAAQ,SAAS,iBAAe;AACrC,UAAI,gBAAgB,cAAc;AAChC,cAAM,UAAU,UAAU,cAAc,WAAW,OAAO,QAAQ,GAAG,OAAO,QAAQ,CAAC;AACrF,2BAAmB,OAAO;AAAA,MAC5B;AAAA,IACF;AAAA,EACF,CAAC;AACD,QAAM,gBAAgB,OAAK;AACzB,UAAM,aAAa,gBAAgB,EAAE,WAAW;AAChD,cAAU,UAAU,WAAW;AAC/B,cAAU,UAAU,EAAE,UAAU;AAChC,WAAO,UAAU;AAAA,MACf,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,IACP;AACA,iBAAa,UAAU,iBAAiB,CAAC;AACzC,kBAAc,UAAU;AACxB,WAAO,QAAQ,KAAK,MAAM;AAAA,EAC5B;AACA,QAAM,cAAc,SAAO;AACzB,UAAM,UAAU,OAAO,QAAQ,KAAK,IAAI;AACxC,QAAI,SAAS;AAEX,YAAM,UAAU,UAAU,SAAS,WAAW,IAAI,SAAS,IAAI,OAAO;AACtE,yBAAmB,OAAO;AAAA,IAC5B;AAAA,EACF;AACA,QAAM,kBAAkB,QAAM;AAC5B,WAAO,QAAQ,KAAK,QAAQ;AAAA,EAC9B;AACA,QAAM,gBAAgB,SAAO;AAE3B,QAAI,eAAe;AACnB,QAAI,gBAAgB;AAGpB,QAAI,cAAc,SAAS;AACzB,oBAAc,UAAU;AACxB;AAAA,IACF;AAOA,UAAM,UAAU,UAAU,OAAO,WAAW,IAAI,SAAS,IAAI,OAAO;AACpE,YAAQ,SAAS;AACjB,YAAQ,YAAY,iBAAiB,GAAG;AACxC,uBAAmB,OAAO;AAAA,EAC5B;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AChMA,SAAS,KAAKC,WAAU;AAaxB,SAAS,gBAAgB;AAIlB,SAAS,eAAe,IAAI;AACjC,QAAM,IAAIC,IAAG,EAAE;AACf,QAAM,SAAS,OAAO,SAAY,CAAC,IAAI;AACvC,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,eAAe;AAAA,EACjB,IAAI;AACJ,QAAM,YAAY,OAAO,SAAY,OAAO;AAC5C,MAAI;AACJ,MAAI,EAAE,CAAC,MAAM,uBAAO,IAAI,2BAA2B,GAAG;AACpD,SAAK,CAAC;AACN,MAAE,CAAC,IAAI;AAAA,EACT,OAAO;AACL,SAAK,EAAE,CAAC;AAAA,EACV;AACA,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,EAAE;AACzD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,SAAS;AAC5D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,YAAY;AACrD,QAAM,MAAM,CAAC;AACb,MAAI,eAAe;AACjB,QAAI,KAAK,sBAAsB;AAAA,EACjC;AACA,MAAI,KAAK,4BAA4B,gBAAgB,6BAA6B,yBAAyB;AAC3G,MAAI,gBAAgB;AAClB,QAAI,KAAK,GAAG,cAAc;AAAA,EAC5B;AACA,MAAI,KAAK,GAAG,eAAe;AAC3B,MAAI,KAAK,eAAe;AACxB,QAAM,eAAe,kBAAkB,GAAG;AAC1C,MAAI;AACJ,MAAI,EAAE,CAAC,MAAM,oBAAoB;AAC/B,SAAK,SAAO;AACV,yBAAmB,UAAQ;AACzB,cAAM,WAAW,KAAK,OAAO,OAAK,EAAE,OAAO,IAAI,EAAE;AACjD,eAAO,CAAC,GAAG,UAAU,GAAG;AAAA,MAC1B,CAAC;AAAA,IACH;AACA,MAAE,CAAC,IAAI;AACP,MAAE,CAAC,IAAI;AAAA,EACT,OAAO;AACL,SAAK,EAAE,CAAC;AAAA,EACV;AACA,QAAM,cAAc;AACpB,MAAI;AACJ,MAAI,EAAE,CAAC,MAAM,oBAAoB;AAC/B,SAAK,QAAM;AACT,yBAAmB,YAAU,OAAO,OAAO,SAAO,IAAI,OAAO,EAAE,CAAC;AAAA,IAClE;AACA,MAAE,CAAC,IAAI;AACP,MAAE,CAAC,IAAI;AAAA,EACT,OAAO;AACL,SAAK,EAAE,CAAC;AAAA,EACV;AACA,QAAM,gBAAgB;AACtB,MAAI;AACJ,MAAI,EAAE,CAAC,MAAM,oBAAoB;AAC/B,SAAK,CAAC,MAAM,YAAY;AACtB,yBAAmB,YAAU,OAAO,IAAI,SAAO,IAAI,OAAO,OAAO;AAAA,QAC/D,GAAG;AAAA,QACH;AAAA,MACF,IAAI,GAAG,CAAC;AAAA,IACV;AACA,MAAE,CAAC,IAAI;AACP,MAAE,CAAC,IAAI;AAAA,EACT,OAAO;AACL,SAAK,EAAE,CAAC;AAAA,EACV;AACA,QAAM,oBAAoB;AAC1B,MAAI;AACJ,MAAI,EAAE,CAAC,MAAM,aAAa;AACxB,SAAK,MAAM;AACT,kBAAY,YAAY;AAAA,IAC1B;AACA,MAAE,CAAC,IAAI;AACP,MAAE,CAAC,IAAI;AAAA,EACT,OAAO;AACL,SAAK,EAAE,CAAC;AAAA,EACV;AACA,QAAM,gBAAgB;AACtB,MAAI;AACJ,MAAI,EAAE,CAAC,MAAM,iBAAiB,EAAE,EAAE,MAAM,YAAY,EAAE,EAAE,MAAM,gBAAgB,EAAE,EAAE,MAAM,iBAAiB,EAAE,EAAE,MAAM,eAAe,EAAE,EAAE,MAAM,iBAAiB,EAAE,EAAE,MAAM,qBAAqB,EAAE,EAAE,MAAM,eAAe,EAAE,EAAE,MAAM,kBAAkB;AAC/O,SAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,MAAE,CAAC,IAAI;AACP,MAAE,EAAE,IAAI;AACR,MAAE,EAAE,IAAI;AACR,MAAE,EAAE,IAAI;AACR,MAAE,EAAE,IAAI;AACR,MAAE,EAAE,IAAI;AACR,MAAE,EAAE,IAAI;AACR,MAAE,EAAE,IAAI;AACR,MAAE,EAAE,IAAI;AACR,MAAE,EAAE,IAAI;AAAA,EACV,OAAO;AACL,SAAK,EAAE,EAAE;AAAA,EACX;AACA,SAAO;AACT;AACO,IAAM,mBAAmB;;;AC5HhC,SAAS,KAAKC,WAAU;AAUxB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,gBAAAC,qBAAoB;AAStB,SAAS,2BAA2B,aAAa;AACtD,QAAM,IAAIC,IAAG,CAAC;AACd,QAAM,YAAYC,cAAa,aAAa;AAC5C,MAAI;AACJ,MAAI;AACJ,MAAI,EAAE,CAAC,MAAM,UAAU,QAAQ,EAAE,CAAC,MAAM,aAAa;AACnD,SAAK,MAAM;AACT,YAAM,WAAW,UAAU;AAC3B,YAAM,MAAM,oBAAoB,QAAQ,KAAK;AAC7C,UAAI,KAAK;AACP,oBAAY,YAAY,GAAG;AAAA,MAC7B,OAAO;AACL,mBAAW,OAAO,OAAO,KAAK,mBAAmB,GAAG;AAClD,gBAAM,WAAW,oBAAoB,GAAG;AACxC,cAAI,UAAU;AACZ,wBAAY,cAAc,SAAS,EAAE;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AACA,aAAO,MAAM;AACX,YAAI,KAAK;AACP,sBAAY,cAAc,IAAI,EAAE;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AACA,SAAK,CAAC,UAAU,MAAM,WAAW;AACjC,MAAE,CAAC,IAAI,UAAU;AACjB,MAAE,CAAC,IAAI;AACP,MAAE,CAAC,IAAI;AACP,MAAE,CAAC,IAAI;AAAA,EACT,OAAO;AACL,SAAK,EAAE,CAAC;AACR,SAAK,EAAE,CAAC;AAAA,EACV;AACA,EAAAC,WAAU,IAAI,EAAE;AAClB;;;ACvDA,SAAS,KAAKC,WAAU;AASxB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,gBAAgB;AAMzB,SAAS,SAAS,UAAU,SAAS;AACnC,iBAAe,UAAU,OAAO;AAChC,SAAO,MAAM,iBAAiB,QAAQ;AACxC;AACO,SAAS,0BAA0B;AACxC,QAAM,IAAIC,IAAG,CAAC;AACd,QAAM,QAAQ,SAAS;AACvB,MAAI;AACJ,MAAI;AACJ,MAAI,EAAE,CAAC,MAAM,OAAO;AAClB,SAAK,MAAM;AACT,YAAM,aAAa,CAAC,SAAS,eAAe,WAAS;AACnD,yBAAiB,OAAO,KAAK;AAC7B,YAAI,MAAM,SAAS,SAAS,QAAQ;AAClC;AAAA,QACF;AACA,cAAM,IAAI,oBAAoB,MAAM,QAAQ,MAAM;AAClD,YAAI,MAAM,SAAS,OAAO;AACxB,gBAAM,IAAI,sBAAsB,MAAM,QAAQ,MAAM;AAAA,QACtD;AAAA,MACF,CAAC,GAAG,SAAS,eAAe,aAAW;AACrC,yBAAiB,SAAS,KAAK;AAC/B,YAAI,QAAQ,SAAS,SAAS,QAAQ;AACpC;AAAA,QACF;AACA,cAAM,IAAI,gBAAgB,QAAQ,QAAQ,MAAM;AAAA,MAClD,CAAC,GAAG,SAAS,oBAAoB,aAAW;AAC1C,yBAAiB,SAAS,KAAK;AAC/B,YAAI,QAAQ,SAAS,SAAS,QAAQ;AACpC;AAAA,QACF;AACA,cAAM,IAAI,oBAAoB,QAAQ,QAAQ,MAAM;AACpD,YAAI,QAAQ,SAAS,OAAO;AAC1B,gBAAM,IAAI,2BAA2B,QAAQ,QAAQ,MAAM;AAAA,QAC7D;AAAA,MACF,CAAC,GAAG,SAAS,mBAAmB,MAAM;AACpC,4BAAoB,KAAK;AAAA,MAC3B,CAAC,GAAG,SAAS,cAAc,aAAW;AACpC,YAAI,gBAAgB,OAAO,GAAG;AAC5B;AAAA,QACF;AACA,kBAAU,KAAK;AAAA,MACjB,CAAC,GAAG,SAAS,eAAe,aAAW;AACrC,yBAAiB,SAAS,KAAK;AAC/B,YAAI,QAAQ,SAAS,SAAS,QAAQ;AACpC,gBAAM,IAAI,kBAAkB,QAAQ,QAAQ,MAAM;AAAA,QACpD;AAAA,MACF,CAAC,GAAG,SAAS,mBAAmB,MAAM;AACpC,cAAM,IAAI,iBAAiB;AAAA,UACzB,MAAM;AAAA,QACR,CAAC;AAAA,MACH,CAAC,GAAG,SAAS,eAAe,aAAW;AACrC,yBAAiB,SAAS,KAAK;AAC/B,YAAI,QAAQ,SAAS,SAAS,QAAQ;AACpC;AAAA,QACF;AACA,YAAI,MAAM,IAAI,gBAAgB,MAAM,QAAQ,QAAQ,QAAQ;AAC1D,gBAAM,IAAI,cAAc;AAAA,QAC1B,OAAO;AACL,gBAAM,IAAI,cAAc;AAAA,YACtB,QAAQ,QAAQ,QAAQ;AAAA,UAC1B,CAAC;AAAA,QACH;AAAA,MACF,CAAC,GAAG,SAAS,qBAAqB,aAAW;AAC3C,YAAI,gBAAgB,OAAO,GAAG;AAC5B;AAAA,QACF;AACA,cAAM,IAAI,mBAAmB;AAAA,MAC/B,CAAC,GAAG,SAAS,eAAe,aAAW;AACrC,YAAI,gBAAgB,OAAO,GAAG;AAC5B;AAAA,QACF;AACA,cAAM,IAAI,mBAAmB;AAAA,MAC/B,CAAC,GAAG,SAAS,sBAAsB,MAAM;AACvC,cAAM,IAAI,oBAAoB;AAAA,MAChC,CAAC,GAAG,SAAS,sBAAsB,MAAM;AACvC,cAAM,IAAI,oBAAoB;AAAA,MAChC,CAAC,GAAG,SAAS,kBAAkB,aAAW;AACxC,YAAI,gBAAgB,OAAO,GAAG;AAC5B;AAAA,QACF;AACA,cAAM,kBAAkB,mBAAmB,KAAK;AAChD,YAAI,gBAAgB,SAAS,GAAG;AAC9B,gBAAM,IAAI,qBAAqB,eAAe;AAAA,QAChD;AAAA,MACF,CAAC,GAAG,SAAS,iBAAiB,aAAW;AACvC,YAAI,gBAAgB,OAAO,GAAG;AAC5B;AAAA,QACF;AACA,qBAAa,KAAK;AAAA,MACpB,CAAC,GAAG,SAAS,mBAAmB,aAAW;AACzC,YAAI,gBAAgB,OAAO,GAAG;AAC5B;AAAA,QACF;AACA,cAAM,IAAI,sBAAsB;AAAA,MAClC,CAAC,GAAG,SAAS,uBAAuB,cAAY;AAC9C,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,cAAM,IAAI,sBAAsB;AAAA,MAClC,CAAC,GAAG,SAAS,mBAAmB,cAAY;AAC1C,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,cAAM,UAAU,mBAAmB,KAAK;AACxC,YAAI,QAAQ,UAAU,GAAG;AACvB,gBAAM,IAAI,gBAAgB;AAAA,YACxB;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,CAAC,GAAG,SAAS,oBAAoB,cAAY;AAC3C,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,wBAAgB,KAAK;AAAA,MACvB,CAAC,GAAG,SAAS,QAAQ,cAAY;AAC/B,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,cAAM,IAAI,QAAQ;AAAA,MACpB,CAAC,GAAG,SAAS,QAAQ,cAAY;AAC/B,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,cAAM,IAAI,QAAQ;AAAA,MACpB,CAAC,GAAG,SAAS,uBAAuB,MAAM;AACxC,gCAAwB,KAAK;AAAA,MAC/B,CAAC,GAAG,SAAS,gBAAgB,MAAM;AACjC,oBAAY,KAAK;AAAA,MACnB,CAAC,GAAG,SAAS,qBAAqB,MAAM;AACtC,sBAAc,OAAO,IAAI;AAAA,MAC3B,CAAC,GAAG,SAAS,uBAAuB,MAAM;AACxC,sBAAc,OAAO,MAAM;AAAA,MAC7B,CAAC,GAAG,SAAS,uBAAuB,MAAM;AACxC,sBAAc,OAAO,MAAM;AAAA,MAC7B,CAAC,GAAG,SAAS,wBAAwB,MAAM;AACzC,sBAAc,OAAO,OAAO;AAAA,MAC9B,CAAC,GAAG,SAAS,uBAAuB,cAAY;AAC9C,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,mBAAW,OAAO,CAAC;AAAA,MACrB,CAAC,GAAG,SAAS,wBAAwB,cAAY;AAC/C,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,mBAAW,OAAO,EAAE;AAAA,MACtB,CAAC,GAAG,SAAS,yBAAyB,cAAY;AAChD,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,4BAAoB,OAAO,KAAK;AAAA,MAClC,CAAC,GAAG,SAAS,kCAAkC,cAAY;AACzD,YAAI,gBAAgB,QAAQ,GAAG;AAC7B;AAAA,QACF;AACA,4BAAoB,OAAO,IAAI;AAAA,MACjC,CAAC,GAAG,SAAS,iCAAiC,MAAM;AAClD,cAAM,IAAI,gCAAgC;AAAA,MAC5C,CAAC,GAAG,SAAS,sBAAsB,MAAM;AACvC,uBAAe,OAAO,GAAG,KAAK,iBAAiB;AAAA,MACjD,CAAC,GAAG,SAAS,wBAAwB,MAAM;AACzC,uBAAe,OAAO,GAAG,IAAI,iBAAiB;AAAA,MAChD,CAAC,GAAG,SAAS,wBAAwB,MAAM;AACzC,uBAAe,OAAO,KAAK,GAAG,iBAAiB;AAAA,MACjD,CAAC,GAAG,SAAS,yBAAyB,MAAM;AAC1C,uBAAe,OAAO,IAAI,GAAG,iBAAiB;AAAA,MAChD,CAAC,GAAG,SAAS,4BAA4B,MAAM;AAC7C,uBAAe,OAAO,GAAG,KAAK,iBAAiB;AAAA,MACjD,CAAC,GAAG,SAAS,8BAA8B,MAAM;AAC/C,uBAAe,OAAO,GAAG,IAAI,iBAAiB;AAAA,MAChD,CAAC,GAAG,SAAS,8BAA8B,MAAM;AAC/C,uBAAe,OAAO,KAAK,GAAG,iBAAiB;AAAA,MACjD,CAAC,GAAG,SAAS,+BAA+B,MAAM;AAChD,uBAAe,OAAO,IAAI,GAAG,iBAAiB;AAAA,MAChD,CAAC,GAAG,SAAS,qBAAqB,cAAY;AAC5C,wBAAgB,UAAU,KAAK;AAAA,MACjC,CAAC,GAAG,SAAS,qBAAqB,MAAM;AACtC,wBAAgB,KAAK;AAAA,MACvB,CAAC,GAAG,SAAS,sBAAsB,cAAY;AAC7C,yBAAiB,UAAU,KAAK;AAAA,MAClC,CAAC,GAAG,SAAS,eAAe,MAAM;AAChC,cAAM,IAAI,kBAAkB;AAAA,MAC9B,CAAC,CAAC;AACF,aAAO,MAAM;AACX,mBAAW,WAAW,YAAY;AAChC,kBAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AACA,SAAK,CAAC,KAAK;AACX,MAAE,CAAC,IAAI;AACP,MAAE,CAAC,IAAI;AACP,MAAE,CAAC,IAAI;AAAA,EACT,OAAO;AACL,SAAK,EAAE,CAAC;AACR,SAAK,EAAE,CAAC;AAAA,EACV;AACA,EAAAC,WAAU,IAAI,EAAE;AAClB;;;AChNA,OAAOC,UAAS,eAAe,YAAY,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAC9E,SAAS,YAAAC,iBAAgB;;;ACclB,SAAS,iBAAiB,QAAQ;AACvC,MAAI,EAAE,kBAAkB,cAAc;AACpC,WAAO;AAAA,EACT;AACA,MAAI,OAAO,mBAAmB;AAC5B,WAAO;AAAA,EACT;AACA,QAAM,WAAW,OAAO,QAAQ,6EAA6E;AAC7G,SAAO,aAAa;AACtB;AAUO,SAAS,gBAAgB,SAAS,KAAK,QAAQ;AACpD,QAAM,WAAW,QAAQ,GAAG,KAAK;AACjC,MAAI,aAAa,QAAQ;AACvB,WAAO;AAAA,EACT;AACA,QAAM,OAAO;AAAA,IACX,GAAG;AAAA,EACL;AACA,MAAI,QAAQ;AACV,SAAK,GAAG,IAAI;AAAA,EACd,OAAO;AACL,WAAO,KAAK,GAAG;AAAA,EACjB;AACA,SAAO;AACT;AAMO,SAAS,kBAAkB,OAAO,SAAS;AAChD,QAAM,SAAS,MAAM,SAAS;AAC9B,QAAM,YAAY,gBAAgB,QAAQ,OAAO,MAAM,KAAK,MAAM;AAClE,QAAM,aAAa,gBAAgB,QAAQ,QAAQ,MAAM,MAAM,MAAM;AACrE,MAAI,cAAc,QAAQ,SAAS,eAAe,QAAQ,QAAQ;AAChE,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AACF;AASO,SAASC,mBAAkB,OAAO;AACvC,QAAM,iBAAiB,MAAM,IAAI,kBAAkB;AACnD,MAAI,gBAAgB;AAClB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF;AACA,QAAM,eAAe,MAAM,IAAI,gBAAgB;AAC/C,MAAI,aAAa,cAAc,aAAa,cAAc;AACxD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,aAAa;AAAA,IACvB;AAAA,EACF;AACA,QAAM,gBAAgB,MAAM,IAAI,iBAAiB;AACjD,MAAI,eAAe;AACjB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;AAKO,SAAS,mBAAmB,OAAO,MAAM,SAAS;AACvD,QAAM,gBAAgB,MAAM,IAAI,iBAAiB;AACjD,MAAI,QAAQ,SAAS,QAAQ;AAC3B,UAAM,OAAO,MAAM,IAAI,WAAW,EAAE,KAAK,WAAS,MAAM,OAAO,QAAQ,MAAM;AAC7E,QAAI,CAAC,MAAM;AACT,aAAO,CAAC;AAAA,IACV;AACA,UAAM,gBAAgB;AAAA,MACpB,GAAG,KAAK,SAAS,KAAK,KAAK,SAAS,OAAO;AAAA,MAC3C,GAAG,KAAK,SAAS,KAAK,KAAK,UAAU,OAAO;AAAA,IAC9C;AACA,WAAO;AAAA,MACL;AAAA,MACA,gBAAgB,cAAc,cAAc,GAAG,cAAc,CAAC;AAAA,IAChE;AAAA,EACF;AACA,MAAI,QAAQ,SAAS,gBAAgB,MAAM;AACzC,UAAM,OAAO,KAAK,sBAAsB;AACxC,UAAM,iBAAiB;AAAA,MACrB,GAAG,KAAK,OAAO,KAAK,QAAQ;AAAA,MAC5B,GAAG,KAAK,MAAM,KAAK,SAAS;AAAA,IAC9B;AACA,WAAO;AAAA,MACL;AAAA,MACA,eAAe,MAAM,IAAI,iBAAiB,EAAE,eAAe,GAAG,eAAe,CAAC;AAAA,IAChF;AAAA,EACF;AACA,SAAO,CAAC;AACV;AASO,SAAS,kBAAkB,OAAO,QAAQ;AAC/C,QAAM,WAAW,cAAc,SAAS,OAAO,WAAW;AAC1D,QAAM,eAAe,MAAM,IAAI,gBAAgB;AAC/C,SAAO;AAAA,IACL,gBAAgB,MAAM,IAAI,kBAAkB;AAAA,IAC5C,aAAa,MAAM,IAAI,eAAe;AAAA,IACtC,YAAY,MAAM,IAAI,kBAAkB,MAAM;AAAA,IAC9C,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,WAAW,MAAM,IAAI,aAAa;AAAA,IAClC,yBAAyB,MAAM,IAAI,2BAA2B;AAAA,IAC9D,iBAAiB,MAAM,IAAI,mBAAmB;AAAA,IAC9C,eAAe,MAAM,IAAI,iBAAiB;AAAA,IAC1C,gBAAgB,MAAM,IAAI,kBAAkB;AAAA,IAC5C,oBAAoB,MAAM,IAAI,sBAAsB;AAAA,IACpD;AAAA,IACA,QAAQ;AAAA,MACN,aAAa,MAAM,IAAI,iBAAiB,MAAM;AAAA,MAC9C,gBAAgB,aAAa;AAAA,IAC/B;AAAA,EACF;AACF;;;ADxJA,SAAS,OAAOC,aAAY;AAK5B,IAAI,cAAc;AAClB,IAAI,gBAAgB;AACpB,IAAM,eAA4B,8BAAc,IAAI;AAG7C,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AACF,GAAG;AACD,QAAM,QAAQC,UAAS;AACvB,QAAM,SAAS,eAAe;AAAA,IAC5B,UAAU,eAAe;AAAA,IACzB,eAAe,eAAe,iBAAiB;AAAA,EACjD,CAAC;AACD,6BAA2B,MAAM;AACjC,0BAAwB;AACxB,QAAM,CAAC,OAAO,IAAIC,UAAS,MAAM,aAAa;AAC9C,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,IAAI;AACjD,QAAM,UAAUC,QAAO,IAAI;AAC3B,QAAM,YAAYA,QAAO,MAAM;AAC/B,YAAU,UAAU;AACpB,QAAM,qBAAqB,UAAQ;AACjC,YAAQ,UAAU;AAClB,kBAAc,IAAI;AAAA,EACpB;AACA,EAAAC,WAAU,MAAM;AACd,UAAM,OAAO;AACb,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,UAAM,WAAW,WAAS;AACxB,sBAAgB;AAChB,UAAI,CAAC,iBAAiB,MAAM,MAAM,GAAG;AACnC,aAAK,MAAM;AAAA,UACT,eAAe;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AACA,SAAK,iBAAiB,eAAe,UAAU,IAAI;AACnD,SAAK,iBAAiB,WAAW,UAAU,IAAI;AAC/C,WAAO,MAAM;AACX,WAAK,oBAAoB,eAAe,UAAU,IAAI;AACtD,WAAK,oBAAoB,WAAW,UAAU,IAAI;AAClD,UAAI,kBAAkB,SAAS;AAC7B,wBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,YAAY,OAAO,CAAC;AACxB,EAAAA,WAAU,MAAM;AACd,UAAM,iBAAiB,iBAAe;AACpC,UAAI,kBAAkB,SAAS;AAC7B;AAAA,MACF;AACA,YAAM,SAAS,QAAQ;AACvB,UAAI,CAAC,UAAU,CAAC,OAAO,aAAa;AAClC;AAAA,MACF;AACA,YAAM,gBAAgB,UAAU;AAChC,YAAM,iBAAiB,iBAAiB,YAAY,MAAM;AAC1D,YAAM,qBAAqB,YAAY,SAAS,WAAW,CAAC,YAAY,eAAe,CAAC;AACxF,YAAM,eAAe,qBAAqB,kBAAkB,aAAa,cAAc,QAAQ,IAAI,cAAc;AACjH,UAAI,iBAAiB,cAAc,UAAU;AAC3C,sBAAc,YAAY,YAAY;AAAA,MACxC;AACA,UAAI,YAAY,eAAe,gBAAgB;AAC7C;AAAA,MACF;AACA,YAAM,UAAUC,mBAAkB,KAAK;AACvC,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF,IAAI,mBAAmB,OAAO,QAAQ,OAAO;AAC7C,YAAM,aAAa;AAAA,QACjB,MAAM;AAAA,QACN,OAAO,YAAY,SAAS,YAAY,SAAS;AAAA,QACjD,KAAK,YAAY;AAAA,QACjB,MAAM,YAAY;AAAA,QAClB,QAAQ,YAAY;AAAA,QACpB,WAAW;AAAA,UACT,OAAO,YAAY;AAAA,UACnB,MAAM,YAAY;AAAA,UAClB,KAAK,YAAY;AAAA,UACjB,MAAM,YAAY;AAAA,QACpB;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe;AAAA,MACjB;AACA,YAAM,aAAa,QAAQ,YAAY,cAAc,cAAc,kBAAkB,OAAO;AAAA,QAC1F,UAAU;AAAA,MACZ,CAAC,CAAC;AACF,UAAI,CAAC,YAAY;AACf;AAAA,MACF;AACA,kBAAY,eAAe;AAC3B,eAAS,YAAY,UAAU;AAC/B,iBAAW,YAAY,UAAU;AAAA,IACnC;AACA,UAAM,gBAAgB,MAAM;AAC1B,gBAAU,QAAQ,cAAc;AAAA,IAClC;AACA,WAAO,iBAAiB,WAAW,gBAAgB,IAAI;AACvD,WAAO,iBAAiB,SAAS,gBAAgB,IAAI;AACrD,WAAO,iBAAiB,QAAQ,aAAa;AAC7C,aAAS,iBAAiB,oBAAoB,aAAa;AAC3D,WAAO,MAAM;AACX,aAAO,oBAAoB,WAAW,gBAAgB,IAAI;AAC1D,aAAO,oBAAoB,SAAS,gBAAgB,IAAI;AACxD,aAAO,oBAAoB,QAAQ,aAAa;AAChD,eAAS,oBAAoB,oBAAoB,aAAa;AAAA,IAChE;AAAA,EACF,GAAG,CAAC,UAAU,SAAS,KAAK,CAAC;AAC7B,SAAoB,gBAAAL,MAAK,aAAa,UAAU;AAAA,IAC9C,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,EACF,CAAC;AACH;AACO,SAAS,kBAAkB;AAChC,QAAM,MAAM,WAAW,YAAY;AACnC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AACA,SAAO;AACT;AACO,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;","names":["atom","Graph","atom","debug","atom","Graph","atom","atomFamily","atom","atom","debug","atom","FitToBoundsMode","atom","atom","atom","atom","debug","atom","atom","atom","atom","atomFamily","graph","atom","Graph","atom","atom","debug","atom","atom","debug","atom","debug","atom","Graph","atom","debug","atom","atom","atom","atom","atom","atom","atom","CanvasEventType","ActionCategory","registerAction","registerAction","registerAction","registerAction","debug","atom","debug","atom","Graph","atom","debug","atom","calculateBounds","atom","atom","atom","atom","atom","atom","atom","atom","atom","atomWithStorage","atomWithStorage","atom","atom","debug","atom","atom","atomWithStorage","inputModeAtom","pendingInputResolverAtom","atom","inputModeAtom","pendingInputResolverAtom","provideInputAtom","useRef","useEffect","useAtomValue","useRef","ZOOM_SNAP_THRESHOLD","VELOCITY_SAMPLE_COUNT","useRef","useAtomValue","useRef","useEffect","useRef","useEffect","useAtomValue","useAtomValue","useRef","useEffect","_c","_c","_c","useEffect","useAtomValue","_c","useAtomValue","useEffect","_c","useEffect","_c","useEffect","React","useEffect","useRef","useState","useStore","getCurrentSubject","_jsx","useStore","useState","useRef","useEffect","getCurrentSubject"]}