{"version":3,"file":"useTimelineSelector.mjs","names":[],"sources":["../../../src/hooks/core/useTimelineSelector.ts"],"sourcesContent":["import { shallowEqual } from '#react/hooks/core/timelineSnapshotEqual';\nimport { useTimelineEngine } from '#react/hooks/core/useTimelineEngine';\nimport type {\n  EngineEventMap,\n  TimelineEngine,\n  TimelineStateSnapshot,\n} from '@techsquidtv/canvas-timeline-core';\nimport { useCallback, useMemo, useRef, useSyncExternalStore } from 'react';\ntype Store = ReturnType<typeof createStore>;\nconst stores = new WeakMap<TimelineEngine, Store>();\nconst events: readonly (keyof EngineEventMap)[] = [\n  'state:settled',\n  'history:change',\n  'state:inOut',\n  'playback:state',\n  'playback:rate',\n  'content:change',\n  'clip:select',\n  'keyframe:select',\n  'snap:change',\n  'track:select',\n];\nfunction createStore(engine: TimelineEngine) {\n  let snapshot = engine.getState();\n  const listeners = new Set<() => void>();\n  let unsubscribe: (() => void)[] = [];\n  const update = () => {\n    const next = engine.getState();\n    if (next === snapshot) {\n      return;\n    }\n    snapshot = next;\n    listeners.forEach((listener) => listener());\n  };\n  return {\n    getSnapshot: () => snapshot,\n    subscribe: (listener: () => void) => {\n      if (listeners.size === 0) {\n        unsubscribe = events.map((event) => engine.on(event, update));\n        update();\n      }\n      listeners.add(listener);\n      return () => {\n        listeners.delete(listener);\n        if (listeners.size === 0) {\n          unsubscribe.forEach((dispose) => dispose());\n        }\n      };\n    },\n  };\n}\n\n/**\n * Selects a value from the engine's immutable, settled state snapshot.\n *\n * @remarks\n * Primitive results use Object.is; arrays and plain objects compare their own\n * enumerable fields shallowly. Supply isEqual for another selection policy.\n * This hook excludes per-frame playback and edit-preview updates. Use\n * {@link useTimelinePlayheadTime} for a live playback readout.\n *\n * @param selector - Pure projection of the readonly timeline snapshot.\n * @param isEqual - Equality check used to preserve the last selected value.\n * @template Value - Selected value, including primitive values.\n * @returns The selected value, updated only when its equality check changes.\n * @example\n * ```tsx\n * import { useTimelineSelector } from '@techsquidtv/canvas-timeline-react';\n * export function TrackCount() {\n *   const count = useTimelineSelector(state => state.tracks.length);\n *   return <output>{count}</output>;\n * }\n * ```\n */\nexport function useTimelineSelector<Value>(\n  selector: (state: TimelineStateSnapshot) => Value,\n  isEqual: (previous: Value, next: Value) => boolean = shallowEqual\n): Value {\n  const engine = useTimelineEngine();\n  const store = useMemo(() => {\n    let result = stores.get(engine);\n    if (!result) {\n      result = createStore(engine);\n      stores.set(engine, result);\n    }\n    return result;\n  }, [engine]);\n  const previous = useRef<{ value: Value } | undefined>(undefined);\n  const getSnapshot = useCallback(() => {\n    const next = selector(store.getSnapshot());\n    if (previous.current && isEqual(previous.current.value, next)) {\n      return previous.current.value;\n    }\n    previous.current = { value: next };\n    return next;\n  }, [selector, store, isEqual]);\n  return useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n}\n"],"mappings":";;;;AASA,MAAM,yBAAS,IAAI,QAA+B;AAClD,MAAM,SAA4C;CAChD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AACA,SAAS,YAAY,QAAwB;CAC3C,IAAI,WAAW,OAAO,SAAS;CAC/B,MAAM,4BAAY,IAAI,IAAgB;CACtC,IAAI,cAA8B,CAAC;CACnC,MAAM,eAAe;EACnB,MAAM,OAAO,OAAO,SAAS;EAC7B,IAAI,SAAS,UACX;EAEF,WAAW;EACX,UAAU,SAAS,aAAa,SAAS,CAAC;CAC5C;CACA,OAAO;EACL,mBAAmB;EACnB,YAAY,aAAyB;GACnC,IAAI,UAAU,SAAS,GAAG;IACxB,cAAc,OAAO,KAAK,UAAU,OAAO,GAAG,OAAO,MAAM,CAAC;IAC5D,OAAO;GACT;GACA,UAAU,IAAI,QAAQ;GACtB,aAAa;IACX,UAAU,OAAO,QAAQ;IACzB,IAAI,UAAU,SAAS,GACrB,YAAY,SAAS,YAAY,QAAQ,CAAC;GAE9C;EACF;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,oBACd,UACA,UAAqD,cAC9C;CACP,MAAM,SAAS,kBAAkB;CACjC,MAAM,QAAQ,cAAc;EAC1B,IAAI,SAAS,OAAO,IAAI,MAAM;EAC9B,IAAI,CAAC,QAAQ;GACX,SAAS,YAAY,MAAM;GAC3B,OAAO,IAAI,QAAQ,MAAM;EAC3B;EACA,OAAO;CACT,GAAG,CAAC,MAAM,CAAC;CACX,MAAM,WAAW,OAAqC,KAAA,CAAS;CAC/D,MAAM,cAAc,kBAAkB;EACpC,MAAM,OAAO,SAAS,MAAM,YAAY,CAAC;EACzC,IAAI,SAAS,WAAW,QAAQ,SAAS,QAAQ,OAAO,IAAI,GAC1D,OAAO,SAAS,QAAQ;EAE1B,SAAS,UAAU,EAAE,OAAO,KAAK;EACjC,OAAO;CACT,GAAG;EAAC;EAAU;EAAO;CAAO,CAAC;CAC7B,OAAO,qBAAqB,MAAM,WAAW,aAAa,WAAW;AACvE"}