@mindees/core 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation/animation.d.ts +69 -0
- package/dist/animation/animation.d.ts.map +1 -0
- package/dist/animation/animation.js +294 -0
- package/dist/animation/animation.js.map +1 -0
- package/dist/animation/easing.d.ts +25 -0
- package/dist/animation/easing.d.ts.map +1 -0
- package/dist/animation/easing.js +61 -0
- package/dist/animation/easing.js.map +1 -0
- package/dist/component/component.d.ts +26 -2
- package/dist/component/component.d.ts.map +1 -1
- package/dist/component/component.js +19 -1
- package/dist/component/component.js.map +1 -1
- package/dist/gesture/animated.d.ts +23 -0
- package/dist/gesture/animated.d.ts.map +1 -0
- package/dist/gesture/animated.js +53 -0
- package/dist/gesture/animated.js.map +1 -0
- package/dist/gesture/recognizers.d.ts +133 -0
- package/dist/gesture/recognizers.d.ts.map +1 -0
- package/dist/gesture/recognizers.js +507 -0
- package/dist/gesture/recognizers.js.map +1 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/reactive/reactive.d.ts +38 -21
- package/dist/reactive/reactive.d.ts.map +1 -1
- package/dist/reactive/reactive.js +88 -25
- package/dist/reactive/reactive.js.map +1 -1
- package/dist/scheduler/scheduler.d.ts.map +1 -1
- package/dist/scheduler/scheduler.js +13 -0
- package/dist/scheduler/scheduler.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","names":[],"sources":["../../src/component/component.ts"],"sourcesContent":["/**\n * MindeesNative component model — a minimal, renderer-agnostic element tree plus\n * **selector-based, re-render-isolated context**.\n *\n * The element tree (`createElement` / `Fragment`) is a plain data structure: a\n * component is a function of `props` returning elements. It carries no rendering\n * logic itself — the Helix renderer (Phase 3) turns this tree into host nodes.\n *\n * The context system is the important primitive: a `createContext` value is read\n * through a **selector**, and a consumer only re-runs when its *selected slice*\n * actually changes — not on every context update. This is the re-render\n * isolation the Quantum Router (Phase 6) builds on. It is implemented on the\n * Phase 1 signals, so selection participates in normal reactivity.\n *\n * @module\n */\n\nimport { computed, createRoot, getOwner, signal } from '../reactive'\n\n// ---------------------------------------------------------------------------\n// Element tree\n// ---------------------------------------------------------------------------\n\n/** A component: a function from props to a renderable node. */\nexport type Component<P = Record<string, unknown>> = (props: P) => MindeesNode\n\n/**\n * Anything that can appear in the tree.\n *\n * Includes an **accessor** form `() => MindeesNode`: a function child (or\n * function prop value) is a *reactive region* — the renderer subscribes to it\n * and patches exactly that region when its signals change (the fine-grained\n * update model, à la SolidJS). Static trees never need it; reactive UIs do.\n */\nexport type MindeesNode =\n | MindeesElement\n // A node may hold a keyed region of ANY item type. KeyedRegion is invariant in T (its\n // mapFn/key take T), so `KeyedRegion<unknown>` would reject `KeyedRegion<Row>`; `any` is\n // the correct \"some item type\" here.\n // biome-ignore lint/suspicious/noExplicitAny: see above — invariant T at a node boundary.\n | KeyedRegion<any>\n | string\n | number\n | boolean\n | null\n | undefined\n | (() => MindeesNode)\n | MindeesNode[]\n\n/** The tag of an element: a host string (e.g. `\"view\"`) or a component function. */\nexport type ElementType = string | Component<never>\n\n/** A virtual element: a tag, its props, and its children. */\nexport interface MindeesElement {\n readonly $$typeof: typeof ELEMENT_TYPE\n readonly type: ElementType\n readonly props: Readonly<Record<string, unknown>>\n readonly children: readonly MindeesNode[]\n readonly key: string | number | null\n}\n\n/** Brand so a renderer can reliably distinguish elements from plain objects. */\nexport const ELEMENT_TYPE: unique symbol = Symbol.for('mindees.element')\n\n/** Marker tag for a fragment (children with no wrapper host node). */\nexport const Fragment: unique symbol = Symbol.for('mindees.fragment')\n\n/** Brand identifying a keyed list region (reconciled by key, not full-rebuilt). */\nexport const KEYED_REGION: unique symbol = Symbol.for('mindees.keyed-region')\n\n/**\n * A keyed list region: a reactive item list + a per-item render function, reconciled by key\n * so rows keep their identity (host node, focus, caret, scroll) across reorders instead of\n * being torn down and rebuilt. This is a serializable *description* (no rendering logic); the\n * renderer materializes it (`bindKeyedChild`). Build one with {@link keyedRegion}.\n */\nexport interface KeyedRegion<T = unknown> {\n readonly $$keyed: typeof KEYED_REGION\n /** The items, as a reactive accessor. */\n readonly each: () => readonly T[]\n /** Render one row from reactive `item`/`index` accessors (consume them lazily to patch in place). */\n readonly mapFn: (item: () => T, index: () => number) => MindeesNode\n /** Stable key per item (when omitted, the row is keyed by item identity). */\n readonly key: ((item: T, index: number) => unknown) | undefined\n /** Rendered when the list is empty. */\n readonly fallback: (() => MindeesNode) | undefined\n}\n\n/** Options for {@link keyedRegion}. */\nexport interface KeyedRegionOptions<T> {\n /** The items, static or reactive. */\n readonly each: readonly T[] | (() => readonly T[])\n /** Render one row from reactive `item`/`index` accessors. */\n readonly children: (item: () => T, index: () => number) => MindeesNode\n /** Stable key per item (defaults to item identity). */\n readonly key?: (item: T, index: number) => unknown\n /** Rendered when the list is empty. */\n readonly fallback?: () => MindeesNode\n}\n\n/** Build a {@link KeyedRegion} — a keyed, identity-preserving list node. */\nexport function keyedRegion<T>(options: KeyedRegionOptions<T>): KeyedRegion<T> {\n const each: () => readonly T[] =\n typeof options.each === 'function' ? options.each : () => options.each as readonly T[]\n return {\n $$keyed: KEYED_REGION,\n each,\n mapFn: options.children,\n key: options.key,\n fallback: options.fallback,\n }\n}\n\n/** Type guard: is `value` a {@link KeyedRegion}? */\nexport function isKeyedRegion(value: unknown): value is KeyedRegion {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { $$keyed?: unknown }).$$keyed === KEYED_REGION\n )\n}\n\ninterface PropsWithKey {\n key?: string | number | null\n children?: MindeesNode\n}\n\n/**\n * Create a virtual element. `type` is a host-component string or a component\n * function; `Fragment` groups children without a wrapper.\n *\n * @example\n * createElement('view', { id: 'root' }, createElement('text', null, 'hi'))\n */\nexport function createElement(\n type: ElementType | typeof Fragment,\n props?: (Record<string, unknown> & PropsWithKey) | null,\n ...children: MindeesNode[]\n): MindeesElement {\n const { key = null, children: propsChildren, ...rest } = props ?? {}\n // Children passed as args win over a `children` prop; otherwise fall back to it.\n const resolved: MindeesNode[] =\n children.length > 0 ? children : propsChildren !== undefined ? [propsChildren] : []\n return {\n $$typeof: ELEMENT_TYPE,\n type: type as ElementType,\n props: Object.freeze({ ...rest }),\n children: Object.freeze(resolved),\n key,\n }\n}\n\n/** Type guard: is `value` a MindeesElement? */\nexport function isElement(value: unknown): value is MindeesElement {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { $$typeof?: unknown }).$$typeof === ELEMENT_TYPE\n )\n}\n\n// ---------------------------------------------------------------------------\n// Selector-based, re-render-isolated context\n// ---------------------------------------------------------------------------\n\n/** Equality used by context selectors. Defaults to `Object.is`. */\nexport type SelectorEquals<S> = (a: S, b: S) => boolean\n\n/** A context handle created by {@link createContext}. */\nexport interface Context<T> {\n /** Provide a value to a subtree (conceptually); returns a scoped reader set. */\n readonly id: symbol\n /** The default value used when no provider is present. */\n readonly defaultValue: T\n}\n\n/**\n * A live provider instance: holds the current value and lets consumers subscribe\n * to a derived slice with re-render isolation.\n */\nexport interface ContextProvider<T> {\n /** Replace the provided value (notifies only consumers whose slice changed). */\n set(value: T): void\n /** Read the current value without subscribing. */\n peek(): T\n /**\n * Subscribe to a selected slice. The returned accessor is a memo that only\n * changes — and thus only re-runs its observers — when `selector(value)`\n * changes under `equals` (default `Object.is`).\n */\n select<S>(selector: (value: T) => S, equals?: SelectorEquals<S>): () => S\n}\n\n/** Create a context with a default value. */\nexport function createContext<T>(defaultValue: T): Context<T> {\n return { id: Symbol('mindees.context'), defaultValue }\n}\n\n/**\n * Create a provider instance for `context`. Built on a signal, so selected\n * slices are memos: a consumer that selects `c => c.user.name` does not re-run\n * when an unrelated field changes.\n *\n * @example\n * const Theme = createContext({ mode: 'light', accent: 'blue' })\n * const p = createProvider(Theme, { mode: 'light', accent: 'blue' })\n * const mode = p.select((t) => t.mode) // only re-runs when `mode` changes\n */\nexport function createProvider<T>(context: Context<T>, initial?: T): ContextProvider<T> {\n // equals:false at the root — every set() re-evaluates selectors, but each\n // selector memo applies its own equality to isolate re-renders.\n const source = signal<T>(initial ?? context.defaultValue, { equals: false })\n return {\n set: (value: T) => {\n source.set(value)\n },\n peek: () => source.peek(),\n select<S>(selector: (value: T) => S, equals: SelectorEquals<S> = Object.is): () => S {\n return computed(() => selector(source()), { equals })\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rendering a component subtree under an owner (so it can be disposed)\n// ---------------------------------------------------------------------------\n\n/**\n * Invoke a component within a reactive ownership scope, so every effect, memo,\n * and `onCleanup` it registers is torn down together when `dispose` is called.\n * Returns the produced node and that disposer.\n *\n * Built on the Phase 1 {@link createRoot}, so disposal reuses the same\n * leak-free teardown the reactivity tests cover. This is a renderer building\n * block; it does not touch any host.\n */\nexport function renderComponent<P>(\n component: Component<P>,\n props: P,\n): { node: MindeesNode; dispose: () => void } {\n let node!: MindeesNode\n // Capture the disposer eagerly: createRoot hands it to the callback synchronously\n // *before* the component runs, so if the component throws mid-render we can still\n // tear down anything it registered before the throw (effects, subscriptions,\n // timers). Without this, createRoot re-throws without disposing and the caller\n // never receives a disposer — the partial scope would leak forever.\n let dispose!: () => void\n try {\n createRoot((d) => {\n dispose = d\n node = component(props)\n })\n } catch (error) {\n dispose?.()\n throw error\n }\n return { node, dispose }\n}\n\n/** Whether code is currently running inside a reactive ownership scope. */\nexport function hasOwner(): boolean {\n return getOwner() !== null\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA8DA,MAAa,eAA8B,OAAO,IAAI,iBAAiB;;AAGvE,MAAa,WAA0B,OAAO,IAAI,kBAAkB;;AAGpE,MAAa,eAA8B,OAAO,IAAI,sBAAsB;;AAiC5E,SAAgB,YAAe,SAAgD;CAG7E,OAAO;EACL,SAAS;EACT,MAHA,OAAO,QAAQ,SAAS,aAAa,QAAQ,aAAa,QAAQ;EAIlE,OAAO,QAAQ;EACf,KAAK,QAAQ;EACb,UAAU,QAAQ;CACpB;AACF;;AAGA,SAAgB,cAAc,OAAsC;CAClE,OACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAgC,YAAY;AAEjD;;;;;;;;AAcA,SAAgB,cACd,MACA,OACA,GAAG,UACa;CAChB,MAAM,EAAE,MAAM,MAAM,UAAU,eAAe,GAAG,SAAS,SAAS,CAAC;CAEnE,MAAM,WACJ,SAAS,SAAS,IAAI,WAAW,kBAAkB,KAAA,IAAY,CAAC,aAAa,IAAI,CAAC;CACpF,OAAO;EACL,UAAU;EACJ;EACN,OAAO,OAAO,OAAO,EAAE,GAAG,KAAK,CAAC;EAChC,UAAU,OAAO,OAAO,QAAQ;EAChC;CACF;AACF;;AAGA,SAAgB,UAAU,OAAyC;CACjE,OACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAiC,aAAa;AAEnD;;AAmCA,SAAgB,cAAiB,cAA6B;CAC5D,OAAO;EAAE,IAAI,OAAO,iBAAiB;EAAG;CAAa;AACvD;;;;;;;;;;;AAYA,SAAgB,eAAkB,SAAqB,SAAiC;CAGtF,MAAM,SAAS,OAAU,WAAW,QAAQ,cAAc,EAAE,QAAQ,MAAM,CAAC;CAC3E,OAAO;EACL,MAAM,UAAa;GACjB,OAAO,IAAI,KAAK;EAClB;EACA,YAAY,OAAO,KAAK;EACxB,OAAU,UAA2B,SAA4B,OAAO,IAAa;GACnF,OAAO,eAAe,SAAS,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC;EACtD;CACF;AACF;;;;;;;;;;AAeA,SAAgB,gBACd,WACA,OAC4C;CAC5C,IAAI;CAMJ,IAAI;CACJ,IAAI;EACF,YAAY,MAAM;GAChB,UAAU;GACV,OAAO,UAAU,KAAK;EACxB,CAAC;CACH,SAAS,OAAO;EACd,UAAU;EACV,MAAM;CACR;CACA,OAAO;EAAE;EAAM;CAAQ;AACzB;;AAGA,SAAgB,WAAoB;CAClC,OAAO,SAAS,MAAM;AACxB"}
|
|
1
|
+
{"version":3,"file":"component.js","names":[],"sources":["../../src/component/component.ts"],"sourcesContent":["/**\n * MindeesNative component model — a minimal, renderer-agnostic element tree plus\n * **selector-based, re-render-isolated context**.\n *\n * The element tree (`createElement` / `Fragment`) is a plain data structure: a\n * component is a function of `props` returning elements. It carries no rendering\n * logic itself — the Helix renderer (Phase 3) turns this tree into host nodes.\n *\n * The context system is the important primitive: a `createContext` value is read\n * through a **selector**, and a consumer only re-runs when its *selected slice*\n * actually changes — not on every context update. This is the re-render\n * isolation the Quantum Router (Phase 6) builds on. It is implemented on the\n * Phase 1 signals, so selection participates in normal reactivity.\n *\n * @module\n */\n\nimport { computed, createRoot, getOwner, signal } from '../reactive'\n\n// ---------------------------------------------------------------------------\n// Element tree\n// ---------------------------------------------------------------------------\n\n/** A component: a function from props to a renderable node. */\nexport type Component<P = Record<string, unknown>> = (props: P) => MindeesNode\n\n/**\n * Anything that can appear in the tree.\n *\n * Includes an **accessor** form `() => MindeesNode`: a function child (or\n * function prop value) is a *reactive region* — the renderer subscribes to it\n * and patches exactly that region when its signals change (the fine-grained\n * update model, à la SolidJS). Static trees never need it; reactive UIs do.\n */\nexport type MindeesNode =\n | MindeesElement\n // A node may hold a keyed region of ANY item type. KeyedRegion is invariant in T (its\n // mapFn/key take T), so `KeyedRegion<unknown>` would reject `KeyedRegion<Row>`; `any` is\n // the correct \"some item type\" here.\n // biome-ignore lint/suspicious/noExplicitAny: see above — invariant T at a node boundary.\n | KeyedRegion<any>\n | PortalRegion\n | string\n | number\n | boolean\n | null\n | undefined\n | (() => MindeesNode)\n | MindeesNode[]\n\n/** The tag of an element: a host string (e.g. `\"view\"`) or a component function. */\nexport type ElementType = string | Component<never>\n\n/** A virtual element: a tag, its props, and its children. */\nexport interface MindeesElement {\n readonly $$typeof: typeof ELEMENT_TYPE\n readonly type: ElementType\n readonly props: Readonly<Record<string, unknown>>\n readonly children: readonly MindeesNode[]\n readonly key: string | number | null\n}\n\n/** Brand so a renderer can reliably distinguish elements from plain objects. */\nexport const ELEMENT_TYPE: unique symbol = Symbol.for('mindees.element')\n\n/** Marker tag for a fragment (children with no wrapper host node). */\nexport const Fragment: unique symbol = Symbol.for('mindees.fragment')\n\n/** Brand identifying a keyed list region (reconciled by key, not full-rebuilt). */\nexport const KEYED_REGION: unique symbol = Symbol.for('mindees.keyed-region')\n\n/**\n * A keyed list region: a reactive item list + a per-item render function, reconciled by key\n * so rows keep their identity (host node, focus, caret, scroll) across reorders instead of\n * being torn down and rebuilt. This is a serializable *description* (no rendering logic); the\n * renderer materializes it (`bindKeyedChild`). Build one with {@link keyedRegion}.\n */\nexport interface KeyedRegion<T = unknown> {\n readonly $$keyed: typeof KEYED_REGION\n /** The items, as a reactive accessor. */\n readonly each: () => readonly T[]\n /** Render one row from reactive `item`/`index` accessors (consume them lazily to patch in place). */\n readonly mapFn: (item: () => T, index: () => number) => MindeesNode\n /** Stable key per item (when omitted, the row is keyed by item identity). */\n readonly key: ((item: T, index: number) => unknown) | undefined\n /** Rendered when the list is empty. */\n readonly fallback: (() => MindeesNode) | undefined\n}\n\n/** Options for {@link keyedRegion}. */\nexport interface KeyedRegionOptions<T> {\n /** The items, static or reactive. */\n readonly each: readonly T[] | (() => readonly T[])\n /** Render one row from reactive `item`/`index` accessors. */\n readonly children: (item: () => T, index: () => number) => MindeesNode\n /** Stable key per item (defaults to item identity). */\n readonly key?: (item: T, index: number) => unknown\n /** Rendered when the list is empty. */\n readonly fallback?: () => MindeesNode\n}\n\n/** Build a {@link KeyedRegion} — a keyed, identity-preserving list node. */\nexport function keyedRegion<T>(options: KeyedRegionOptions<T>): KeyedRegion<T> {\n const each: () => readonly T[] =\n typeof options.each === 'function' ? options.each : () => options.each as readonly T[]\n return {\n $$keyed: KEYED_REGION,\n each,\n mapFn: options.children,\n key: options.key,\n fallback: options.fallback,\n }\n}\n\n/** Type guard: is `value` a {@link KeyedRegion}? */\nexport function isKeyedRegion(value: unknown): value is KeyedRegion {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { $$keyed?: unknown }).$$keyed === KEYED_REGION\n )\n}\n\n/** Brand identifying a portal region (children relocated to an overlay target above the tree). */\nexport const PORTAL: unique symbol = Symbol.for('mindees.portal')\n\n/**\n * A portal: its children render into a different host parent (an overlay/root layer) than their\n * position in the tree, while staying owned by the logical owner so reactive disposal + unmount\n * still work. The renderer materializes it (`bindPortalChild`); build one with {@link portal}.\n */\nexport interface PortalRegion {\n readonly $$portal: typeof PORTAL\n /** Children to relocate, normalized to a (reactive) accessor. */\n readonly children: () => MindeesNode\n /** Optional explicit host target (an `N`); else the backend's overlay root; else the local parent. Opaque to core. */\n readonly mount: unknown\n}\n\n/**\n * Build a {@link PortalRegion} — relocate `children` to an overlay target. Pass `opts.mount` to\n * override the target host node; otherwise the renderer uses the backend's overlay root (or, with\n * no overlay, mounts in place — the SSR-correct default).\n */\nexport function portal(\n children: MindeesNode | (() => MindeesNode),\n opts?: { readonly mount?: unknown },\n): PortalRegion {\n return {\n $$portal: PORTAL,\n children: typeof children === 'function' ? (children as () => MindeesNode) : () => children,\n mount: opts?.mount,\n }\n}\n\n/** Type guard: is `value` a {@link PortalRegion}? */\nexport function isPortal(value: unknown): value is PortalRegion {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { $$portal?: unknown }).$$portal === PORTAL\n )\n}\n\ninterface PropsWithKey {\n key?: string | number | null\n children?: MindeesNode\n}\n\n/**\n * Create a virtual element. `type` is a host-component string or a component\n * function; `Fragment` groups children without a wrapper.\n *\n * @example\n * createElement('view', { id: 'root' }, createElement('text', null, 'hi'))\n */\nexport function createElement(\n type: ElementType | typeof Fragment,\n props?: (Record<string, unknown> & PropsWithKey) | null,\n ...children: MindeesNode[]\n): MindeesElement {\n const { key = null, children: propsChildren, ...rest } = props ?? {}\n // Children passed as args win over a `children` prop; otherwise fall back to it.\n const resolved: MindeesNode[] =\n children.length > 0 ? children : propsChildren !== undefined ? [propsChildren] : []\n return {\n $$typeof: ELEMENT_TYPE,\n type: type as ElementType,\n props: Object.freeze({ ...rest }),\n children: Object.freeze(resolved),\n key,\n }\n}\n\n/** Type guard: is `value` a MindeesElement? */\nexport function isElement(value: unknown): value is MindeesElement {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { $$typeof?: unknown }).$$typeof === ELEMENT_TYPE\n )\n}\n\n// ---------------------------------------------------------------------------\n// Selector-based, re-render-isolated context\n// ---------------------------------------------------------------------------\n\n/** Equality used by context selectors. Defaults to `Object.is`. */\nexport type SelectorEquals<S> = (a: S, b: S) => boolean\n\n/** A context handle created by {@link createContext}. */\nexport interface Context<T> {\n /** Provide a value to a subtree (conceptually); returns a scoped reader set. */\n readonly id: symbol\n /** The default value used when no provider is present. */\n readonly defaultValue: T\n}\n\n/**\n * A live provider instance: holds the current value and lets consumers subscribe\n * to a derived slice with re-render isolation.\n */\nexport interface ContextProvider<T> {\n /** Replace the provided value (notifies only consumers whose slice changed). */\n set(value: T): void\n /** Read the current value without subscribing. */\n peek(): T\n /**\n * Subscribe to a selected slice. The returned accessor is a memo that only\n * changes — and thus only re-runs its observers — when `selector(value)`\n * changes under `equals` (default `Object.is`).\n */\n select<S>(selector: (value: T) => S, equals?: SelectorEquals<S>): () => S\n}\n\n/** Create a context with a default value. */\nexport function createContext<T>(defaultValue: T): Context<T> {\n return { id: Symbol('mindees.context'), defaultValue }\n}\n\n/**\n * Create a provider instance for `context`. Built on a signal, so selected\n * slices are memos: a consumer that selects `c => c.user.name` does not re-run\n * when an unrelated field changes.\n *\n * @example\n * const Theme = createContext({ mode: 'light', accent: 'blue' })\n * const p = createProvider(Theme, { mode: 'light', accent: 'blue' })\n * const mode = p.select((t) => t.mode) // only re-runs when `mode` changes\n */\nexport function createProvider<T>(context: Context<T>, initial?: T): ContextProvider<T> {\n // equals:false at the root — every set() re-evaluates selectors, but each\n // selector memo applies its own equality to isolate re-renders.\n const source = signal<T>(initial ?? context.defaultValue, { equals: false })\n return {\n set: (value: T) => {\n source.set(value)\n },\n peek: () => source.peek(),\n select<S>(selector: (value: T) => S, equals: SelectorEquals<S> = Object.is): () => S {\n return computed(() => selector(source()), { equals })\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rendering a component subtree under an owner (so it can be disposed)\n// ---------------------------------------------------------------------------\n\n/**\n * Invoke a component within a reactive ownership scope, so every effect, memo,\n * and `onCleanup` it registers is torn down together when `dispose` is called.\n * Returns the produced node and that disposer.\n *\n * Built on the Phase 1 {@link createRoot}, so disposal reuses the same\n * leak-free teardown the reactivity tests cover. This is a renderer building\n * block; it does not touch any host.\n */\nexport function renderComponent<P>(\n component: Component<P>,\n props: P,\n): { node: MindeesNode; dispose: () => void } {\n let node!: MindeesNode\n // Capture the disposer eagerly: createRoot hands it to the callback synchronously\n // *before* the component runs, so if the component throws mid-render we can still\n // tear down anything it registered before the throw (effects, subscriptions,\n // timers). Without this, createRoot re-throws without disposing and the caller\n // never receives a disposer — the partial scope would leak forever.\n let dispose!: () => void\n try {\n createRoot((d) => {\n dispose = d\n node = component(props)\n })\n } catch (error) {\n dispose?.()\n throw error\n }\n return { node, dispose }\n}\n\n/** Whether code is currently running inside a reactive ownership scope. */\nexport function hasOwner(): boolean {\n return getOwner() !== null\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA+DA,MAAa,eAA8B,OAAO,IAAI,iBAAiB;;AAGvE,MAAa,WAA0B,OAAO,IAAI,kBAAkB;;AAGpE,MAAa,eAA8B,OAAO,IAAI,sBAAsB;;AAiC5E,SAAgB,YAAe,SAAgD;CAG7E,OAAO;EACL,SAAS;EACT,MAHA,OAAO,QAAQ,SAAS,aAAa,QAAQ,aAAa,QAAQ;EAIlE,OAAO,QAAQ;EACf,KAAK,QAAQ;EACb,UAAU,QAAQ;CACpB;AACF;;AAGA,SAAgB,cAAc,OAAsC;CAClE,OACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAgC,YAAY;AAEjD;;AAGA,MAAa,SAAwB,OAAO,IAAI,gBAAgB;;;;;;AAoBhE,SAAgB,OACd,UACA,MACc;CACd,OAAO;EACL,UAAU;EACV,UAAU,OAAO,aAAa,aAAc,iBAAuC;EACnF,OAAO,MAAM;CACf;AACF;;AAGA,SAAgB,SAAS,OAAuC;CAC9D,OACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAiC,aAAa;AAEnD;;;;;;;;AAcA,SAAgB,cACd,MACA,OACA,GAAG,UACa;CAChB,MAAM,EAAE,MAAM,MAAM,UAAU,eAAe,GAAG,SAAS,SAAS,CAAC;CAEnE,MAAM,WACJ,SAAS,SAAS,IAAI,WAAW,kBAAkB,KAAA,IAAY,CAAC,aAAa,IAAI,CAAC;CACpF,OAAO;EACL,UAAU;EACJ;EACN,OAAO,OAAO,OAAO,EAAE,GAAG,KAAK,CAAC;EAChC,UAAU,OAAO,OAAO,QAAQ;EAChC;CACF;AACF;;AAGA,SAAgB,UAAU,OAAyC;CACjE,OACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAiC,aAAa;AAEnD;;AAmCA,SAAgB,cAAiB,cAA6B;CAC5D,OAAO;EAAE,IAAI,OAAO,iBAAiB;EAAG;CAAa;AACvD;;;;;;;;;;;AAYA,SAAgB,eAAkB,SAAqB,SAAiC;CAGtF,MAAM,SAAS,OAAU,WAAW,QAAQ,cAAc,EAAE,QAAQ,MAAM,CAAC;CAC3E,OAAO;EACL,MAAM,UAAa;GACjB,OAAO,IAAI,KAAK;EAClB;EACA,YAAY,OAAO,KAAK;EACxB,OAAU,UAA2B,SAA4B,OAAO,IAAa;GACnF,OAAO,eAAe,SAAS,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC;EACtD;CACF;AACF;;;;;;;;;;AAeA,SAAgB,gBACd,WACA,OAC4C;CAC5C,IAAI;CAMJ,IAAI;CACJ,IAAI;EACF,YAAY,MAAM;GAChB,UAAU;GACV,OAAO,UAAU,KAAK;EACxB,CAAC;CACH,SAAS,OAAO;EACd,UAAU;EACV,MAAM;CACR;CACA,OAAO;EAAE;EAAM;CAAQ;AACzB;;AAGA,SAAgB,WAAoB;CAClC,OAAO,SAAS,MAAM;AACxB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AnimatedValue } from "../animation/animation.js";
|
|
2
|
+
import { PanState, Recognizer } from "./recognizers.js";
|
|
3
|
+
|
|
4
|
+
//#region src/gesture/animated.d.ts
|
|
5
|
+
/** Drag `x`/`y` with a pan; on release, spring each axis to `release()`'s target (default: stay put), seeded with the gesture velocity. */
|
|
6
|
+
declare function panAnimated(x: AnimatedValue, y: AnimatedValue, opts?: {
|
|
7
|
+
/** Choose the per-axis settle target on release (e.g. snap-back to 0). Returns `void` to stay put. */readonly release?: (e: {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
velocityX: number;
|
|
11
|
+
velocityY: number;
|
|
12
|
+
}) => {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
} | void;
|
|
16
|
+
readonly spring?: {
|
|
17
|
+
stiffness?: number;
|
|
18
|
+
damping?: number;
|
|
19
|
+
};
|
|
20
|
+
}): Recognizer<PanState>;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { panAnimated };
|
|
23
|
+
//# sourceMappingURL=animated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animated.d.ts","names":[],"sources":["../../src/gesture/animated.ts"],"mappings":";;;;;iBAcgB,WAAA,CACd,CAAA,EAAG,aAAA,EACH,CAAA,EAAG,aAAA,EACH,IAAA;EAUW,+GARA,OAAA,IAAW,CAAA;IAClB,CAAA;IACA,CAAA;IACA,SAAA;IACA,SAAA;EAAA;IACM,CAAA;IAAW,CAAA;EAAA;EAAA,SACV,MAAA;IAAW,SAAA;IAAoB,OAAA;EAAA;AAAA,IAEzC,UAAA,CAAW,QAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { untrack } from "../reactive/reactive.js";
|
|
2
|
+
import { spring } from "../animation/animation.js";
|
|
3
|
+
import { pan } from "./recognizers.js";
|
|
4
|
+
//#region src/gesture/animated.ts
|
|
5
|
+
/**
|
|
6
|
+
* Bridge a {@link pan} gesture to {@link AnimatedValue}s — the headline interaction: drag follows
|
|
7
|
+
* the finger 1:1, and on release each axis springs to a target **seeded with the gesture's own
|
|
8
|
+
* velocity** (so a flick keeps flowing). This explicit velocity handoff is required because
|
|
9
|
+
* `AnimatedValue.set` doesn't populate the value's velocity cell.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
/** Drag `x`/`y` with a pan; on release, spring each axis to `release()`'s target (default: stay put), seeded with the gesture velocity. */
|
|
14
|
+
function panAnimated(x, y, opts) {
|
|
15
|
+
let baseX = 0;
|
|
16
|
+
let baseY = 0;
|
|
17
|
+
return pan({
|
|
18
|
+
onBegin: () => {
|
|
19
|
+
baseX = untrack(x);
|
|
20
|
+
baseY = untrack(y);
|
|
21
|
+
x.set(baseX);
|
|
22
|
+
y.set(baseY);
|
|
23
|
+
},
|
|
24
|
+
onUpdate: (e) => {
|
|
25
|
+
x.set(baseX + e.translationX);
|
|
26
|
+
y.set(baseY + e.translationY);
|
|
27
|
+
},
|
|
28
|
+
onEnd: (e) => {
|
|
29
|
+
const target = opts?.release?.({
|
|
30
|
+
x: untrack(x),
|
|
31
|
+
y: untrack(y),
|
|
32
|
+
velocityX: e.velocityX,
|
|
33
|
+
velocityY: e.velocityY
|
|
34
|
+
});
|
|
35
|
+
if (!target) return;
|
|
36
|
+
const sp = opts?.spring ?? {};
|
|
37
|
+
spring(x, {
|
|
38
|
+
to: target.x,
|
|
39
|
+
velocity: e.velocityX * 1e3,
|
|
40
|
+
...sp
|
|
41
|
+
});
|
|
42
|
+
spring(y, {
|
|
43
|
+
to: target.y,
|
|
44
|
+
velocity: e.velocityY * 1e3,
|
|
45
|
+
...sp
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { panAnimated };
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=animated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animated.js","names":[],"sources":["../../src/gesture/animated.ts"],"sourcesContent":["/**\n * Bridge a {@link pan} gesture to {@link AnimatedValue}s — the headline interaction: drag follows\n * the finger 1:1, and on release each axis springs to a target **seeded with the gesture's own\n * velocity** (so a flick keeps flowing). This explicit velocity handoff is required because\n * `AnimatedValue.set` doesn't populate the value's velocity cell.\n *\n * @module\n */\n\nimport { type AnimatedValue, spring } from '../animation'\nimport { untrack } from '../reactive'\nimport { type PanState, pan, type Recognizer } from './recognizers'\n\n/** Drag `x`/`y` with a pan; on release, spring each axis to `release()`'s target (default: stay put), seeded with the gesture velocity. */\nexport function panAnimated(\n x: AnimatedValue,\n y: AnimatedValue,\n opts?: {\n /** Choose the per-axis settle target on release (e.g. snap-back to 0). Returns `void` to stay put. */\n readonly release?: (e: {\n x: number\n y: number\n velocityX: number\n velocityY: number\n }) => { x: number; y: number } | void\n readonly spring?: { stiffness?: number; damping?: number }\n },\n): Recognizer<PanState> {\n let baseX = 0\n let baseY = 0\n return pan({\n onBegin: () => {\n baseX = untrack(x)\n baseY = untrack(y)\n // Grab mid-fling: writing the values stops any in-flight release spring immediately, so the\n // drag takes over instead of fighting the animation (AnimatedValue.set cancels its driver).\n x.set(baseX)\n y.set(baseY)\n },\n onUpdate: (e) => {\n x.set(baseX + e.translationX)\n y.set(baseY + e.translationY)\n },\n onEnd: (e) => {\n const target = opts?.release?.({\n x: untrack(x),\n y: untrack(y),\n velocityX: e.velocityX,\n velocityY: e.velocityY,\n })\n if (!target) return // stay where released\n const sp = opts?.spring ?? {}\n // px/ms → px/s for the spring integrator; seed each axis with the finger's velocity.\n spring(x, { to: target.x, velocity: e.velocityX * 1000, ...sp })\n spring(y, { to: target.y, velocity: e.velocityY * 1000, ...sp })\n },\n })\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,YACd,GACA,GACA,MAUsB;CACtB,IAAI,QAAQ;CACZ,IAAI,QAAQ;CACZ,OAAO,IAAI;EACT,eAAe;GACb,QAAQ,QAAQ,CAAC;GACjB,QAAQ,QAAQ,CAAC;GAGjB,EAAE,IAAI,KAAK;GACX,EAAE,IAAI,KAAK;EACb;EACA,WAAW,MAAM;GACf,EAAE,IAAI,QAAQ,EAAE,YAAY;GAC5B,EAAE,IAAI,QAAQ,EAAE,YAAY;EAC9B;EACA,QAAQ,MAAM;GACZ,MAAM,SAAS,MAAM,UAAU;IAC7B,GAAG,QAAQ,CAAC;IACZ,GAAG,QAAQ,CAAC;IACZ,WAAW,EAAE;IACb,WAAW,EAAE;GACf,CAAC;GACD,IAAI,CAAC,QAAQ;GACb,MAAM,KAAK,MAAM,UAAU,CAAC;GAE5B,OAAO,GAAG;IAAE,IAAI,OAAO;IAAG,UAAU,EAAE,YAAY;IAAM,GAAG;GAAG,CAAC;GAC/D,OAAO,GAAG;IAAE,IAAI,OAAO;IAAG,UAAU,EAAE,YAAY;IAAM,GAAG;GAAG,CAAC;EACjE;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
//#region src/gesture/recognizers.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Gesture recognizers — RN Gesture Handler / Flutter GestureDetector parity, built on the reactive
|
|
4
|
+
* core. Each factory returns a {@link Recognizer}: a bag of pointer-event handlers to spread onto a
|
|
5
|
+
* host element, plus REACTIVE state (signals) you read in a `style` accessor or feed to the
|
|
6
|
+
* animation engine. The only platform-aware code is {@link normalizePointer}; everything else is
|
|
7
|
+
* pure payload → signal, so it runs on web (Pointer Events), native (the command-backend payload),
|
|
8
|
+
* and tests (synthetic events), and SSRs safely (no `document` access).
|
|
9
|
+
*
|
|
10
|
+
* Attach two recognizers to ONE element via {@link composeGestures} — the renderer binds a single
|
|
11
|
+
* listener per event name, so spreading two `onPointerMove`s would drop one; compose merges them.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
/** A normalized pointer sample (platform differences absorbed by {@link normalizePointer}). */
|
|
16
|
+
interface PointerSample {
|
|
17
|
+
readonly pointerId: number;
|
|
18
|
+
readonly x: number;
|
|
19
|
+
readonly y: number;
|
|
20
|
+
/** Timestamp in ms. */
|
|
21
|
+
readonly t: number;
|
|
22
|
+
readonly pointerType?: string;
|
|
23
|
+
}
|
|
24
|
+
/** @internal Test-only: inject a deterministic clock + timer. */
|
|
25
|
+
declare function _setGestureClock(opts: {
|
|
26
|
+
now?: () => number;
|
|
27
|
+
schedule?: (fn: () => void, ms: number) => () => void;
|
|
28
|
+
}): void;
|
|
29
|
+
/** Normalize a host pointer event to a {@link PointerSample}. Web `PointerEvent` or a native payload. */
|
|
30
|
+
declare function normalizePointer(e: unknown): PointerSample;
|
|
31
|
+
/** Handlers to spread onto a host element. */
|
|
32
|
+
interface GestureHandlers {
|
|
33
|
+
onPointerDown(e: unknown): void;
|
|
34
|
+
onPointerMove(e: unknown): void;
|
|
35
|
+
onPointerUp(e: unknown): void;
|
|
36
|
+
onPointerCancel(e: unknown): void;
|
|
37
|
+
}
|
|
38
|
+
/** A recognizer: handlers to attach, reactive `state`, and a `reset()` for cleanup. */
|
|
39
|
+
interface Recognizer<S = Record<string, () => number | boolean>> {
|
|
40
|
+
readonly handlers: GestureHandlers;
|
|
41
|
+
readonly state: S;
|
|
42
|
+
/** Clear pointers, timers, and reset state to rest (call from `onCleanup`). */
|
|
43
|
+
reset(): void;
|
|
44
|
+
}
|
|
45
|
+
/** A continuous pan/drag update (translations relative to gesture start; velocity in px/ms). */
|
|
46
|
+
interface PanEvent {
|
|
47
|
+
readonly translationX: number;
|
|
48
|
+
readonly translationY: number;
|
|
49
|
+
readonly velocityX: number;
|
|
50
|
+
readonly velocityY: number;
|
|
51
|
+
readonly x: number;
|
|
52
|
+
readonly y: number;
|
|
53
|
+
}
|
|
54
|
+
interface PanState {
|
|
55
|
+
readonly active: () => boolean;
|
|
56
|
+
readonly translationX: () => number;
|
|
57
|
+
readonly translationY: () => number;
|
|
58
|
+
readonly velocityX: () => number;
|
|
59
|
+
readonly velocityY: () => number;
|
|
60
|
+
readonly x: () => number;
|
|
61
|
+
readonly y: () => number;
|
|
62
|
+
}
|
|
63
|
+
/** Recognize a drag. Becomes active once the pointer moves past `minDistance` (slop). */
|
|
64
|
+
declare function pan(config: {
|
|
65
|
+
onBegin?: (e: PanEvent) => void;
|
|
66
|
+
onUpdate?: (e: PanEvent) => void;
|
|
67
|
+
onEnd?: (e: PanEvent & {
|
|
68
|
+
completed: boolean;
|
|
69
|
+
}) => void;
|
|
70
|
+
minDistance?: number;
|
|
71
|
+
axis?: 'both' | 'x' | 'y';
|
|
72
|
+
}): Recognizer<PanState>;
|
|
73
|
+
interface TapState {
|
|
74
|
+
readonly active: () => boolean;
|
|
75
|
+
}
|
|
76
|
+
/** Recognize a tap: down + up within `maxDistance` and `maxDurationMs`, no extra pointer. */
|
|
77
|
+
declare function tap(config: {
|
|
78
|
+
onTap?: () => void;
|
|
79
|
+
maxDistance?: number;
|
|
80
|
+
maxDurationMs?: number;
|
|
81
|
+
}): Recognizer<TapState>;
|
|
82
|
+
/** Recognize a long press: pointer held past `minDurationMs` without moving past `maxDistance`. */
|
|
83
|
+
declare function longPress(config: {
|
|
84
|
+
onBegin?: () => void;
|
|
85
|
+
onLongPress?: () => void;
|
|
86
|
+
onEnd?: () => void;
|
|
87
|
+
minDurationMs?: number;
|
|
88
|
+
maxDistance?: number;
|
|
89
|
+
}): Recognizer<TapState>;
|
|
90
|
+
interface PinchEvent {
|
|
91
|
+
readonly scale: number;
|
|
92
|
+
readonly velocity: number;
|
|
93
|
+
readonly focalX: number;
|
|
94
|
+
readonly focalY: number;
|
|
95
|
+
}
|
|
96
|
+
interface PinchState {
|
|
97
|
+
readonly active: () => boolean;
|
|
98
|
+
readonly scale: () => number;
|
|
99
|
+
readonly focalX: () => number;
|
|
100
|
+
readonly focalY: () => number;
|
|
101
|
+
}
|
|
102
|
+
/** Recognize a two-finger pinch. `scale` is current distance / start distance between the pinned pair. */
|
|
103
|
+
declare function pinch(config: {
|
|
104
|
+
onBegin?: (e: PinchEvent) => void;
|
|
105
|
+
onUpdate?: (e: PinchEvent) => void;
|
|
106
|
+
onEnd?: (e: PinchEvent) => void;
|
|
107
|
+
}): Recognizer<PinchState>;
|
|
108
|
+
type SwipeDirection = 'left' | 'right' | 'up' | 'down';
|
|
109
|
+
interface SwipeEvent {
|
|
110
|
+
readonly direction: SwipeDirection;
|
|
111
|
+
readonly velocityX: number;
|
|
112
|
+
readonly velocityY: number;
|
|
113
|
+
readonly x: number;
|
|
114
|
+
readonly y: number;
|
|
115
|
+
}
|
|
116
|
+
/** Recognize a fast flick on pointer-up (velocity ≥ `minVelocity` px/ms over `minDistance`). */
|
|
117
|
+
declare function swipe(config: {
|
|
118
|
+
onSwipe?: (e: SwipeEvent) => void;
|
|
119
|
+
direction?: 'any' | SwipeDirection;
|
|
120
|
+
minVelocity?: number;
|
|
121
|
+
minDistance?: number;
|
|
122
|
+
}): Recognizer<TapState>;
|
|
123
|
+
/**
|
|
124
|
+
* Merge several recognizers into ONE so they can attach to a single element — required because the
|
|
125
|
+
* renderer binds a single listener per event name (spreading two `onPointerMove`s would drop one).
|
|
126
|
+
* `simultaneous` (the default): every recognizer sees every event independently (e.g. pan + pinch
|
|
127
|
+
* together). Per-recognizer slop already disambiguates tap-vs-pan; an explicit exclusive arena is a
|
|
128
|
+
* follow-up.
|
|
129
|
+
*/
|
|
130
|
+
declare function composeGestures(recognizers: readonly Recognizer<never>[]): Recognizer<never>;
|
|
131
|
+
//#endregion
|
|
132
|
+
export { GestureHandlers, PanEvent, PanState, PinchEvent, PinchState, PointerSample, Recognizer, SwipeDirection, SwipeEvent, TapState, _setGestureClock, composeGestures, longPress, normalizePointer, pan, pinch, swipe, tap };
|
|
133
|
+
//# sourceMappingURL=recognizers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recognizers.d.ts","names":[],"sources":["../../src/gesture/recognizers.ts"],"mappings":";;AAiBA;;;;;;;;;;AAMsB;AAWtB;;UAjBiB,aAAA;EAAA,SACN,SAAA;EAAA,SACA,CAAA;EAAA,SACA,CAAA;EAgBG;EAAA,SAdH,CAAA;EAAA,SACA,WAAA;AAAA;AAcV;AAAA,iBAHe,gBAAA,CAAiB,IAAA;EAC/B,GAAA;EACA,QAAA,IAAY,EAAA,cAAgB,EAAA;AAAA;AAO6B;AAAA,iBAA3C,gBAAA,CAAiB,CAAA,YAAa,aAAa;;UAgB1C,eAAA;EACf,aAAA,CAAc,CAAA;EACd,aAAA,CAAc,CAAA;EACd,WAAA,CAAY,CAAA;EACZ,eAAA,CAAgB,CAAA;AAAA;;UAID,UAAA,KAAe,MAAA;EAAA,SACrB,QAAA,EAAU,eAAA;EAAA,SACV,KAAA,EAAO,CAAA;EANU;EAQ1B,KAAA;AAAA;;UAoDe,QAAA;EAAA,SACN,YAAA;EAAA,SACA,YAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;EAAA,SACA,CAAA;EAAA,SACA,CAAA;AAAA;AAAA,UAGM,QAAA;EAAA,SACN,MAAA;EAAA,SACA,YAAA;EAAA,SACA,YAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;EAAA,SACA,CAAA;EAAA,SACA,CAAA;AAAA;;iBAIK,GAAA,CAAI,MAAA;EAClB,OAAA,IAAW,CAAA,EAAG,QAAA;EACd,QAAA,IAAY,CAAA,EAAG,QAAA;EACf,KAAA,IAAS,CAAA,EAAG,QAAA;IAAa,SAAA;EAAA;EACzB,WAAA;EACA,IAAA;AAAA,IACE,UAAA,CAAW,QAAA;AAAA,UAqHE,QAAA;EAAA,SACN,MAAM;AAAA;;iBAID,GAAA,CAAI,MAAA;EAClB,KAAA;EACA,WAAA;EACA,aAAA;AAAA,IACE,UAAU,CAAC,QAAA;;iBAoDC,SAAA,CAAU,MAAA;EACxB,OAAA;EACA,WAAA;EACA,KAAA;EACA,aAAA;EACA,WAAA;AAAA,IACE,UAAU,CAAC,QAAA;AAAA,UA0DE,UAAA;EAAA,SACN,KAAA;EAAA,SACA,QAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;AAAA;AAAA,UAEM,UAAA;EAAA,SACN,MAAA;EAAA,SACA,KAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;AAAA;;iBAIK,KAAA,CAAM,MAAA;EACpB,OAAA,IAAW,CAAA,EAAG,UAAA;EACd,QAAA,IAAY,CAAA,EAAG,UAAA;EACf,KAAA,IAAS,CAAA,EAAG,UAAA;AAAA,IACV,UAAA,CAAW,UAAA;AAAA,KAuHH,cAAA;AAAA,UACK,UAAA;EAAA,SACN,SAAA,EAAW,cAAc;EAAA,SACzB,SAAA;EAAA,SACA,SAAA;EAAA,SACA,CAAA;EAAA,SACA,CAAA;AAAA;;iBAIK,KAAA,CAAM,MAAA;EACpB,OAAA,IAAW,CAAA,EAAG,UAAA;EACd,SAAA,WAAoB,cAAA;EACpB,WAAA;EACA,WAAA;AAAA,IACE,UAAA,CAAW,QAAA;;;;;;;AA5QQ;iBA2UP,eAAA,CAAgB,WAAA,WAAsB,UAAA,YAAsB,UAAU"}
|