diff --git a/website/scripts/packages/lean-qr/README.md b/website/packages/lean-qr/README.md similarity index 100% rename from website/scripts/packages/lean-qr/README.md rename to website/packages/lean-qr/README.md diff --git a/website/scripts/packages/lean-qr/v2.3.4/script.js b/website/packages/lean-qr/v2.3.4/script.js similarity index 100% rename from website/scripts/packages/lean-qr/v2.3.4/script.js rename to website/packages/lean-qr/v2.3.4/script.js diff --git a/website/scripts/packages/lean-qr/v2.3.4/types.d.ts b/website/packages/lean-qr/v2.3.4/types.d.ts similarity index 100% rename from website/scripts/packages/lean-qr/v2.3.4/types.d.ts rename to website/packages/lean-qr/v2.3.4/types.d.ts diff --git a/website/scripts/packages/lightweight-charts/NOTICE.md b/website/packages/lightweight-charts/NOTICE.md similarity index 100% rename from website/scripts/packages/lightweight-charts/NOTICE.md rename to website/packages/lightweight-charts/NOTICE.md diff --git a/website/scripts/packages/lightweight-charts/README.md b/website/packages/lightweight-charts/README.md similarity index 100% rename from website/scripts/packages/lightweight-charts/README.md rename to website/packages/lightweight-charts/README.md diff --git a/website/scripts/packages/lightweight-charts/v4.2.0/script.js b/website/packages/lightweight-charts/v4.2.0/script.js similarity index 100% rename from website/scripts/packages/lightweight-charts/v4.2.0/script.js rename to website/packages/lightweight-charts/v4.2.0/script.js diff --git a/website/scripts/packages/lightweight-charts/v4.2.0/types.d.ts b/website/packages/lightweight-charts/v4.2.0/types.d.ts similarity index 100% rename from website/scripts/packages/lightweight-charts/v4.2.0/types.d.ts rename to website/packages/lightweight-charts/v4.2.0/types.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/script.js b/website/packages/solid-signals/2024-04-17/script.js similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/script.js rename to website/packages/solid-signals/2024-04-17/script.js diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/constants.d.ts b/website/packages/solid-signals/2024-04-17/types/constants.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/constants.d.ts rename to website/packages/solid-signals/2024-04-17/types/constants.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/core.d.ts b/website/packages/solid-signals/2024-04-17/types/core.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/core.d.ts rename to website/packages/solid-signals/2024-04-17/types/core.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/effect.d.ts b/website/packages/solid-signals/2024-04-17/types/effect.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/effect.d.ts rename to website/packages/solid-signals/2024-04-17/types/effect.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/error.d.ts b/website/packages/solid-signals/2024-04-17/types/error.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/error.d.ts rename to website/packages/solid-signals/2024-04-17/types/error.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/flags.d.ts b/website/packages/solid-signals/2024-04-17/types/flags.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/flags.d.ts rename to website/packages/solid-signals/2024-04-17/types/flags.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/index.d.ts b/website/packages/solid-signals/2024-04-17/types/index.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/index.d.ts rename to website/packages/solid-signals/2024-04-17/types/index.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/map.d.ts b/website/packages/solid-signals/2024-04-17/types/map.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/map.d.ts rename to website/packages/solid-signals/2024-04-17/types/map.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/owner.d.ts b/website/packages/solid-signals/2024-04-17/types/owner.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/owner.d.ts rename to website/packages/solid-signals/2024-04-17/types/owner.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/selector.d.ts b/website/packages/solid-signals/2024-04-17/types/selector.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/selector.d.ts rename to website/packages/solid-signals/2024-04-17/types/selector.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/signals.d.ts b/website/packages/solid-signals/2024-04-17/types/signals.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/signals.d.ts rename to website/packages/solid-signals/2024-04-17/types/signals.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/store.d.ts b/website/packages/solid-signals/2024-04-17/types/store.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/store.d.ts rename to website/packages/solid-signals/2024-04-17/types/store.d.ts diff --git a/website/scripts/packages/solid-signals/2024-04-17/types/utils.d.ts b/website/packages/solid-signals/2024-04-17/types/utils.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-04-17/types/utils.d.ts rename to website/packages/solid-signals/2024-04-17/types/utils.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/script.js b/website/packages/solid-signals/2024-10-28/script.js similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/script.js rename to website/packages/solid-signals/2024-10-28/script.js diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/constants.d.ts b/website/packages/solid-signals/2024-10-28/types/constants.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/constants.d.ts rename to website/packages/solid-signals/2024-10-28/types/constants.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/core.d.ts b/website/packages/solid-signals/2024-10-28/types/core.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/core.d.ts rename to website/packages/solid-signals/2024-10-28/types/core.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/effect.d.ts b/website/packages/solid-signals/2024-10-28/types/effect.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/effect.d.ts rename to website/packages/solid-signals/2024-10-28/types/effect.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/error.d.ts b/website/packages/solid-signals/2024-10-28/types/error.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/error.d.ts rename to website/packages/solid-signals/2024-10-28/types/error.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/flags.d.ts b/website/packages/solid-signals/2024-10-28/types/flags.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/flags.d.ts rename to website/packages/solid-signals/2024-10-28/types/flags.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/index.d.ts b/website/packages/solid-signals/2024-10-28/types/index.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/index.d.ts rename to website/packages/solid-signals/2024-10-28/types/index.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/map.d.ts b/website/packages/solid-signals/2024-10-28/types/map.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/map.d.ts rename to website/packages/solid-signals/2024-10-28/types/map.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/owner.d.ts b/website/packages/solid-signals/2024-10-28/types/owner.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/owner.d.ts rename to website/packages/solid-signals/2024-10-28/types/owner.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/scheduler.d.ts b/website/packages/solid-signals/2024-10-28/types/scheduler.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/scheduler.d.ts rename to website/packages/solid-signals/2024-10-28/types/scheduler.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/signals.d.ts b/website/packages/solid-signals/2024-10-28/types/signals.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/signals.d.ts rename to website/packages/solid-signals/2024-10-28/types/signals.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/store.d.ts b/website/packages/solid-signals/2024-10-28/types/store.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/store.d.ts rename to website/packages/solid-signals/2024-10-28/types/store.d.ts diff --git a/website/scripts/packages/solid-signals/2024-10-28/types/utils.d.ts b/website/packages/solid-signals/2024-10-28/types/utils.d.ts similarity index 100% rename from website/scripts/packages/solid-signals/2024-10-28/types/utils.d.ts rename to website/packages/solid-signals/2024-10-28/types/utils.d.ts diff --git a/website/packages/solid-signals/2024-11-01/script.js b/website/packages/solid-signals/2024-11-01/script.js new file mode 100644 index 000000000..a6a505059 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/script.js @@ -0,0 +1,908 @@ +// src/core/error.ts +var NotReadyError = class extends Error { +}; +var NoOwnerError = class extends Error { + constructor() { + super( + "" + ); + } +}; +var ContextNotFoundError = class extends Error { + constructor() { + super( + "" + ); + } +}; + +// src/utils.ts +function isUndefined(value) { + return typeof value === "undefined"; +} + +// src/core/constants.ts +var STATE_CLEAN = 0; +var STATE_CHECK = 1; +var STATE_DIRTY = 2; +var STATE_DISPOSED = 3; + +// src/core/owner.ts +var currentOwner = null; +var defaultContext = {}; +function getOwner() { + return currentOwner; +} +function setOwner(owner) { + const out = currentOwner; + currentOwner = owner; + return out; +} +var Owner = class { + // We flatten the owner tree into a linked list so that we don't need a pointer to .firstChild + // However, the children are actually added in reverse creation order + // See comment at the top of the file for an example of the _nextSibling traversal + p = null; + i = null; + m = null; + a = STATE_CLEAN; + f = null; + j = defaultContext; + g = null; + constructor(signal = false) { + if (currentOwner && !signal) + currentOwner.append(this); + } + append(child) { + child.p = this; + child.m = this; + if (this.i) + this.i.m = child; + child.i = this.i; + this.i = child; + if (child.j !== this.j) { + child.j = { ...this.j, ...child.j }; + } + if (this.g) { + child.g = !child.g ? this.g : [...child.g, ...this.g]; + } + } + dispose(self = true) { + if (this.a === STATE_DISPOSED) + return; + let head = self ? this.m || this.p : this, current = this.i, next = null; + while (current && current.p === this) { + current.dispose(true); + current.t(); + next = current.i; + current.i = null; + current = next; + } + if (self) + this.t(); + if (current) + current.m = !self ? this : this.m; + if (head) + head.i = current; + } + t() { + if (this.m) + this.m.i = null; + this.p = null; + this.m = null; + this.j = defaultContext; + this.g = null; + this.a = STATE_DISPOSED; + this.emptyDisposal(); + } + emptyDisposal() { + if (!this.f) + return; + if (Array.isArray(this.f)) { + for (let i = 0; i < this.f.length; i++) { + const callable = this.f[i]; + callable.call(callable); + } + } else { + this.f.call(this.f); + } + this.f = null; + } + handleError(error) { + if (!this.g) + throw error; + let i = 0, len = this.g.length; + for (i = 0; i < len; i++) { + try { + this.g[i](error); + break; + } catch (e) { + error = e; + } + } + if (i === len) + throw error; + } +}; +function createContext(defaultValue, description) { + return { id: Symbol(description), defaultValue }; +} +function getContext(context, owner = currentOwner) { + if (!owner) { + throw new NoOwnerError(); + } + const value = hasContext(context, owner) ? owner.j[context.id] : context.defaultValue; + if (isUndefined(value)) { + throw new ContextNotFoundError(); + } + return value; +} +function setContext(context, value, owner = currentOwner) { + if (!owner) { + throw new NoOwnerError(); + } + owner.j = { + ...owner.j, + [context.id]: isUndefined(value) ? context.defaultValue : value + }; +} +function hasContext(context, owner = currentOwner) { + return !isUndefined(owner?.j[context.id]); +} +function onCleanup(disposable) { + if (!currentOwner) + return; + const node = currentOwner; + if (!node.f) { + node.f = disposable; + } else if (Array.isArray(node.f)) { + node.f.push(disposable); + } else { + node.f = [node.f, disposable]; + } +} + +// src/core/flags.ts +var ERROR_OFFSET = 0; +var ERROR_BIT = 1 << ERROR_OFFSET; +var LOADING_OFFSET = 1; +var LOADING_BIT = 1 << LOADING_OFFSET; +var DEFAULT_FLAGS = ERROR_BIT; + +// src/core/scheduler.ts +var scheduled = false; +var runningScheduled = false; +var Computations = []; +var RenderEffects = []; +var Effects = []; +function flushSync() { + if (!runningScheduled) + runScheduled(); +} +function flushQueue() { + if (scheduled) + return; + scheduled = true; + queueMicrotask(runScheduled); +} +function runTop(node) { + const ancestors = []; + for (let current = node; current !== null; current = current.p) { + if (current.a !== STATE_CLEAN) { + ancestors.push(current); + } + } + for (let i = ancestors.length - 1; i >= 0; i--) { + if (ancestors[i].a !== STATE_DISPOSED) + ancestors[i].q(); + } +} +function runScheduled() { + if (!Effects.length && !RenderEffects.length && !Computations.length) { + scheduled = false; + return; + } + runningScheduled = true; + try { + runPureQueue(Computations); + runPureQueue(RenderEffects); + runPureQueue(Effects); + } finally { + const renderEffects = RenderEffects; + const effects = Effects; + Computations = []; + Effects = []; + RenderEffects = []; + scheduled = false; + runningScheduled = false; + incrementClock(); + runEffectQueue(renderEffects); + runEffectQueue(effects); + } +} +function runPureQueue(queue) { + for (let i = 0; i < queue.length; i++) { + if (queue[i].a !== STATE_CLEAN) + runTop(queue[i]); + } +} +function runEffectQueue(queue) { + for (let i = 0; i < queue.length; i++) { + if (queue[i].x && queue[i].a !== STATE_DISPOSED) { + queue[i].y(queue[i].d, queue[i].v); + queue[i].x = false; + queue[i].v = queue[i].d; + } + } +} + +// src/core/core.ts +var currentObserver = null; +var currentMask = DEFAULT_FLAGS; +var newSources = null; +var newSourcesIndex = 0; +var newFlags = 0; +var clock = 0; +var syncResolve = false; +var updateCheck = null; +function getObserver() { + return currentObserver; +} +function incrementClock() { + clock++; +} +var UNCHANGED = Symbol(0); +var Computation2 = class extends Owner { + b = null; + c = null; + d; + z; + // Used in __DEV__ mode, hopefully removed in production + L; + // Using false is an optimization as an alternative to _equals: () => false + // which could enable more efficient DIRTY notification + A = isEqual; + F; + /** Whether the computation is an error or has ancestors that are unresolved */ + k = 0; + /** Which flags raised by sources are handled, vs. being passed through. */ + w = DEFAULT_FLAGS; + B = null; + C = null; + D = -1; + constructor(initialValue, compute2, options) { + super(compute2 === null); + this.z = compute2; + this.a = compute2 ? STATE_DIRTY : STATE_CLEAN; + this.d = initialValue; + if (options?.equals !== void 0) + this.A = options.equals; + if (options?.unobserved) + this.F = options?.unobserved; + } + G() { + if (this.z) + this.q(); + if (!this.b || this.b.length) + track(this); + newFlags |= this.k & ~currentMask; + if (this.k & ERROR_BIT) { + throw this.d; + } else { + return this.d; + } + } + /** + * Return the current value of this computation + * Automatically re-executes the surrounding computation when the value changes + */ + read() { + return this.G(); + } + /** + * Return the current value of this computation + * Automatically re-executes the surrounding computation when the value changes + * + * If the computation has any unresolved ancestors, this function waits for the value to resolve + * before continuing + */ + wait() { + if (!syncResolve && this.loading()) { + throw new NotReadyError(); + } + return this.G(); + } + /** + * Return true if the computation is the value is dependent on an unresolved promise + * Triggers re-execution of the computation when the loading state changes + * + * This is useful especially when effects want to re-execute when a computation's + * loading state changes + */ + loading() { + if (this.C === null) { + this.C = loadingState(this); + } + return this.C.read(); + } + /** + * Return true if the computation is the computation threw an error + * Triggers re-execution of the computation when the error state changes + */ + error() { + if (this.B === null) { + this.B = errorState(this); + } + return this.B.read(); + } + /** Update the computation with a new value. */ + write(value, flags = 0, raw = false) { + const newValue = !raw && typeof value === "function" ? value(this.d) : value; + const valueChanged = newValue !== UNCHANGED && (!!(flags & ERROR_BIT) || this.A === false || !this.A(this.d, newValue)); + if (valueChanged) + this.d = newValue; + const changedFlagsMask = this.k ^ flags, changedFlags = changedFlagsMask & flags; + this.k = flags; + this.D = clock + 1; + if (this.c) { + for (let i = 0; i < this.c.length; i++) { + if (valueChanged) { + this.c[i].n(STATE_DIRTY); + } else if (changedFlagsMask) { + this.c[i].H(changedFlagsMask, changedFlags); + } + } + } + return this.d; + } + /** + * Set the current node's state, and recursively mark all of this node's observers as STATE_CHECK + */ + n(state) { + if (this.a >= state) + return; + this.a = state; + if (this.c) { + for (let i = 0; i < this.c.length; i++) { + this.c[i].n(STATE_CHECK); + } + } + } + /** + * Notify the computation that one of its sources has changed flags. + * + * @param mask A bitmask for which flag(s) were changed. + * @param newFlags The source's new flags, masked to just the changed ones. + */ + H(mask, newFlags2) { + if (this.a >= STATE_DIRTY) + return; + if (mask & this.w) { + this.n(STATE_DIRTY); + return; + } + if (this.a >= STATE_CHECK) + return; + const prevFlags = this.k & mask; + const deltaFlags = prevFlags ^ newFlags2; + if (newFlags2 === prevFlags) ; else if (deltaFlags & prevFlags & mask) { + this.n(STATE_CHECK); + } else { + this.k ^= deltaFlags; + if (this.c) { + for (let i = 0; i < this.c.length; i++) { + this.c[i].H(mask, newFlags2); + } + } + } + } + I(error) { + this.write(error, this.k | ERROR_BIT); + } + /** + * This is the core part of the reactivity system, which makes sure that the values are updated + * before they are read. We've also adapted it to return the loading state of the computation, + * so that we can propagate that to the computation's observers. + * + * This function will ensure that the value and states we read from the computation are up to date + */ + q() { + if (this.a === STATE_DISPOSED) { + throw new Error("Tried to read a disposed computation"); + } + if (this.a === STATE_CLEAN) { + return; + } + let observerFlags = 0; + if (this.a === STATE_CHECK) { + for (let i = 0; i < this.b.length; i++) { + this.b[i].q(); + observerFlags |= this.b[i].k; + if (this.a === STATE_DIRTY) { + break; + } + } + } + if (this.a === STATE_DIRTY) { + update(this); + } else { + this.write(UNCHANGED, observerFlags); + this.a = STATE_CLEAN; + } + } + /** + * Remove ourselves from the owner graph and the computation graph + */ + t() { + if (this.a === STATE_DISPOSED) + return; + if (this.b) + removeSourceObservers(this, 0); + super.t(); + } +}; +function loadingState(node) { + const prevOwner = setOwner(node.p); + const options = void 0; + const computation = new Computation2( + void 0, + () => { + track(node); + node.q(); + return !!(node.k & LOADING_BIT); + }, + options + ); + computation.w = ERROR_BIT | LOADING_BIT; + setOwner(prevOwner); + return computation; +} +function errorState(node) { + const prevOwner = setOwner(node.p); + const options = void 0; + const computation = new Computation2( + void 0, + () => { + track(node); + node.q(); + return !!(node.k & ERROR_BIT); + }, + options + ); + computation.w = ERROR_BIT; + setOwner(prevOwner); + return computation; +} +function track(computation) { + if (currentObserver) { + if (!newSources && currentObserver.b && currentObserver.b[newSourcesIndex] === computation) { + newSourcesIndex++; + } else if (!newSources) + newSources = [computation]; + else if (computation !== newSources[newSources.length - 1]) { + newSources.push(computation); + } + if (updateCheck) { + updateCheck.d = computation.D > currentObserver.D; + } + } +} +function update(node) { + const prevSources = newSources, prevSourcesIndex = newSourcesIndex, prevFlags = newFlags; + newSources = null; + newSourcesIndex = 0; + newFlags = 0; + try { + node.dispose(false); + node.emptyDisposal(); + const result = compute(node, node.z, node); + node.write(result, newFlags, true); + } catch (error) { + if (error instanceof NotReadyError) { + node.write(UNCHANGED, newFlags | LOADING_BIT); + } else { + node.I(error); + } + } finally { + if (newSources) { + if (node.b) + removeSourceObservers(node, newSourcesIndex); + if (node.b && newSourcesIndex > 0) { + node.b.length = newSourcesIndex + newSources.length; + for (let i = 0; i < newSources.length; i++) { + node.b[newSourcesIndex + i] = newSources[i]; + } + } else { + node.b = newSources; + } + let source; + for (let i = newSourcesIndex; i < node.b.length; i++) { + source = node.b[i]; + if (!source.c) + source.c = [node]; + else + source.c.push(node); + } + } else if (node.b && newSourcesIndex < node.b.length) { + removeSourceObservers(node, newSourcesIndex); + node.b.length = newSourcesIndex; + } + newSources = prevSources; + newSourcesIndex = prevSourcesIndex; + newFlags = prevFlags; + node.a = STATE_CLEAN; + } +} +function removeSourceObservers(node, index) { + let source; + let swap; + for (let i = index; i < node.b.length; i++) { + source = node.b[i]; + if (source.c) { + swap = source.c.indexOf(node); + source.c[swap] = source.c[source.c.length - 1]; + source.c.pop(); + if (!source.c.length) + source.F?.(); + } + } +} +function isEqual(a, b) { + return a === b; +} +function untrack(fn) { + if (currentObserver === null) + return fn(); + return compute(getOwner(), fn, null); +} +function hasUpdated(fn) { + const current = updateCheck; + updateCheck = { d: false }; + try { + fn(); + return updateCheck.d; + } finally { + updateCheck = current; + } +} +function isPending(fn) { + try { + fn(); + return false; + } catch (e) { + return e instanceof NotReadyError; + } +} +function latest(fn) { + const prevFlags = newFlags; + syncResolve = true; + try { + return fn(); + } catch { + } finally { + newFlags = prevFlags; + syncResolve = false; + } +} +function compute(owner, compute2, observer) { + const prevOwner = setOwner(owner), prevObserver = currentObserver, prevMask = currentMask; + currentObserver = observer; + currentMask = observer?.w ?? DEFAULT_FLAGS; + try { + return compute2(observer ? observer.d : void 0); + } finally { + setOwner(prevOwner); + currentObserver = prevObserver; + currentMask = prevMask; + } +} +var EagerComputation = class extends Computation2 { + constructor(initialValue, compute2, options) { + super(initialValue, compute2, options); + this.q(); + Computations.push(this); + } + n(state) { + if (this.a >= state) + return; + if (this.a === STATE_CLEAN) { + Computations.push(this); + flushQueue(); + } + super.n(state); + } +}; + +// src/core/effect.ts +var BaseEffect = class extends Computation2 { + y; + x = false; + v; + constructor(initialValue, compute2, effect, options) { + super(initialValue, compute2, options); + this.y = effect; + this.v = initialValue; + } + write(value) { + if (value === UNCHANGED) + return this.d; + this.d = value; + this.x = true; + return value; + } + I(error) { + this.handleError(error); + } + t() { + this.y = void 0; + this.v = void 0; + super.t(); + } +}; +var Effect = class extends BaseEffect { + constructor(initialValue, compute2, effect, options) { + super(initialValue, compute2, effect, options); + Effects.push(this); + flushQueue(); + } + n(state) { + if (this.a >= state) + return; + if (this.a === STATE_CLEAN) { + Effects.push(this); + flushQueue(); + } + this.a = state; + } +}; +var RenderEffect = class extends BaseEffect { + constructor(initialValue, compute2, effect, options) { + super(initialValue, compute2, effect, options); + this.q(); + RenderEffects.push(this); + } + n(state) { + if (this.a >= state) + return; + if (this.a === STATE_CLEAN) { + RenderEffects.push(this); + flushQueue(); + } + this.a = state; + } +}; + +// src/signals.ts +function createSignal(first, second, third) { + if (typeof first === "function") { + const memo = createMemo((p) => { + const node2 = new Computation2( + first(p ? untrack(p[0]) : second), + null, + third + ); + return [node2.read.bind(node2), node2.write.bind(node2)]; + }); + return [() => memo()[0](), (value) => memo()[1](value)]; + } + const node = new Computation2(first, null, second); + return [node.read.bind(node), node.write.bind(node)]; +} +function createAsync(fn, initial, options) { + const lhs = new EagerComputation( + { + d: initial + }, + (p) => { + const value = p?.d; + const source = fn(value); + const isPromise = source instanceof Promise; + const iterator = source[Symbol.asyncIterator]; + if (!isPromise && !iterator) { + return { + wait() { + return source; + }, + d: source + }; + } + const signal = new Computation2(value, null, options); + signal.write(UNCHANGED, LOADING_BIT); + if (isPromise) { + source.then( + (value2) => { + signal.write(value2, 0); + }, + (error) => { + signal.write(error, ERROR_BIT); + } + ); + } else { + let abort = false; + onCleanup(() => abort = true); + (async () => { + try { + for await (let value2 of source) { + if (abort) + return; + signal.write(value2, 0); + } + } catch (error) { + signal.write(error, ERROR_BIT); + } + })(); + } + return signal; + } + ); + return () => lhs.wait().wait(); +} +function createMemo(compute2, initialValue, options) { + let node = new Computation2(initialValue, compute2, options); + let value; + return () => { + if (node) { + value = node.wait(); + if (!node.b?.length) + node = void 0; + } + return value; + }; +} +function createEffect(compute2, effect, initialValue, options) { + void new Effect( + initialValue, + compute2, + effect, + void 0 + ); +} +function createRenderEffect(compute2, effect, initialValue, options) { + void new RenderEffect( + initialValue, + compute2, + effect, + void 0 + ); +} +function createRoot(init) { + const owner = new Owner(); + return compute(owner, !init.length ? init : () => init(() => owner.dispose()), null); +} +function runWithOwner(owner, run) { + try { + return compute(owner, run, null); + } catch (error) { + owner?.handleError(error); + return void 0; + } +} +function catchError(fn, handler) { + const owner = new Owner(); + owner.g = owner.g ? [handler, ...owner.g] : [handler]; + try { + compute(owner, fn, null); + } catch (error) { + owner.handleError(error); + } +} + +// src/map.ts +function mapArray(list, map, options) { + const keyFn = typeof options?.keyed === "function" ? options.keyed : void 0; + return Computation2.prototype.read.bind( + new Computation2( + [], + updateKeyedMap.bind({ + J: new Owner(), + r: 0, + K: list, + o: [], + E: map, + l: [], + s: [], + u: keyFn, + e: keyFn || options?.keyed === false ? [] : void 0, + h: map.length > 1 ? [] : void 0 + }), + options + ) + ); +} +function updateKeyedMap() { + const newItems = this.K() || []; + runWithOwner(this.J, () => { + let newLen = newItems.length, i, j, mapper = this.e ? () => { + this.e[j] = new Computation2(newItems[j], null); + this.h[j] = new Computation2(j, null); + return this.E( + Computation2.prototype.read.bind(this.e[j]), + Computation2.prototype.read.bind(this.h[j]) + ); + } : this.h ? () => { + const item = newItems[j]; + this.h[j] = new Computation2(j, null); + return this.E(() => item, Computation2.prototype.read.bind(this.h[j])); + } : () => { + const item = newItems[j]; + return this.E(() => item); + }; + if (newLen === 0) { + if (this.r !== 0) { + this.J.dispose(false); + this.s = []; + this.o = []; + this.l = []; + this.r = 0; + this.e && (this.e = []); + this.h && (this.h = []); + } + } else if (this.r === 0) { + this.l = new Array(newLen); + for (j = 0; j < newLen; j++) { + this.o[j] = newItems[j]; + this.l[j] = compute(this.s[j] = new Owner(), mapper, null); + } + this.r = newLen; + } else { + let start, end, newEnd, item, key, newIndices, newIndicesNext, temp = new Array(newLen), tempNodes = new Array(newLen), tempRows = this.e ? new Array(newLen) : void 0, tempIndexes = this.h ? new Array(newLen) : void 0; + for (start = 0, end = Math.min(this.r, newLen); start < end && (this.o[start] === newItems[start] || this.e && compare(this.u, this.o[start], newItems[start])); start++) { + if (this.e) + this.e[start].write(newItems[start]); + } + for (end = this.r - 1, newEnd = newLen - 1; end >= start && newEnd >= start && (this.o[end] === newItems[newEnd] || this.e && compare(this.u, this.o[end], newItems[newEnd])); end--, newEnd--) { + temp[newEnd] = this.l[end]; + tempNodes[newEnd] = this.s[end]; + tempRows && (tempRows[newEnd] = this.e[end]); + tempIndexes && (tempIndexes[newEnd] = this.h[end]); + } + newIndices = /* @__PURE__ */ new Map(); + newIndicesNext = new Array(newEnd + 1); + for (j = newEnd; j >= start; j--) { + item = newItems[j]; + key = this.u ? this.u(item) : item; + i = newIndices.get(key); + newIndicesNext[j] = i === void 0 ? -1 : i; + newIndices.set(key, j); + } + for (i = start; i <= end; i++) { + item = this.o[i]; + key = this.u ? this.u(item) : item; + j = newIndices.get(key); + if (j !== void 0 && j !== -1) { + temp[j] = this.l[i]; + tempNodes[j] = this.s[i]; + tempRows && (tempRows[j] = this.e[i]); + tempIndexes && (tempIndexes[j] = this.h[i]); + j = newIndicesNext[j]; + newIndices.set(key, j); + } else + this.s[i].dispose(); + } + for (j = start; j < newLen; j++) { + if (j in temp) { + this.l[j] = temp[j]; + this.s[j] = tempNodes[j]; + if (tempRows) { + this.e[j] = tempRows[j]; + this.e[j].write(newItems[j]); + } + if (tempIndexes) { + this.h[j] = tempIndexes[j]; + this.h[j].write(j); + } + } else { + this.l[j] = compute(this.s[j] = new Owner(), mapper, null); + } + } + this.l = this.l.slice(0, this.r = newLen); + this.o = newItems.slice(0); + } + }); + return this.l; +} +function compare(key, a, b) { + return key ? key(a) === key(b) : true; +} + +export { Computation2 as Computation, ContextNotFoundError, NoOwnerError, NotReadyError, Owner, catchError, createAsync, createContext, createEffect, createMemo, createRenderEffect, createRoot, createSignal, flushSync, getContext, getObserver, getOwner, hasContext, hasUpdated, isEqual, isPending, latest, mapArray, onCleanup, runWithOwner, setContext, untrack }; diff --git a/website/packages/solid-signals/2024-11-01/types/core/constants.d.ts b/website/packages/solid-signals/2024-11-01/types/core/constants.d.ts new file mode 100644 index 000000000..c27fe1bc4 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/core/constants.d.ts @@ -0,0 +1,10 @@ +/** + * See https://dev.to/modderme123/super-charging-fine-grained-reactive-performance-47ph + * State clean corresponds to a node where all the sources are fully up to date + * State check corresponds to a node where some sources (including grandparents) may have changed + * State dirty corresponds to a node where the direct parents of a node has changed + */ +export declare const STATE_CLEAN = 0; +export declare const STATE_CHECK = 1; +export declare const STATE_DIRTY = 2; +export declare const STATE_DISPOSED = 3; diff --git a/website/packages/solid-signals/2024-11-01/types/core/core.d.ts b/website/packages/solid-signals/2024-11-01/types/core/core.d.ts new file mode 100644 index 000000000..0c11181b6 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/core/core.d.ts @@ -0,0 +1,161 @@ +/** + * Nodes for constructing a graph of reactive values and reactive computations. + * + * - The graph is acyclic. + * - The user inputs new values into the graph by calling .write() on one more computation nodes. + * - The user retrieves computed results from the graph by calling .read() on one or more computation nodes. + * - The library is responsible for running any necessary computations so that .read() is up to date + * with all prior .write() calls anywhere in the graph. + * - We call the input nodes 'roots' and the output nodes 'leaves' of the graph here. + * - Changes flow from roots to leaves. It would be effective but inefficient to immediately + * propagate all changes from a root through the graph to descendant leaves. Instead, we defer + * change most change propagation computation until a leaf is accessed. This allows us to + * coalesce computations and skip altogether recalculating unused sections of the graph. + * - Each computation node tracks its sources and its observers (observers are other + * elements that have this node as a source). Source and observer links are updated automatically + * as observer computations re-evaluate and call get() on their sources. + * - Each node stores a cache state (clean/check/dirty) to support the change propagation algorithm: + * + * In general, execution proceeds in three passes: + * + * 1. write() propagates changes down the graph to the leaves + * direct children are marked as dirty and their deeper descendants marked as check + * (no computations are evaluated) + * 2. read() requests that parent nodes updateIfNecessary(), which proceeds recursively up the tree + * to decide whether the node is clean (parents unchanged) or dirty (parents changed) + * 3. updateIfNecessary() evaluates the computation if the node is dirty (the computations are + * executed in root to leaf order) + */ +import { type Flags } from "./flags.js"; +import { Owner } from "./owner.js"; +export interface SignalOptions { + name?: string; + equals?: ((prev: T, next: T) => boolean) | false; + unobserved?: () => void; +} +interface SourceType { + _observers: ObserverType[] | null; + _unobserved?: () => void; + _updateIfNecessary: () => void; + _stateFlags: Flags; + _time: number; +} +interface ObserverType { + _sources: SourceType[] | null; + _notify: (state: number) => void; + _handlerMask: Flags; + _notifyFlags: (mask: Flags, newFlags: Flags) => void; + _time: number; +} +/** + * Returns the current observer. + */ +export declare function getObserver(): ObserverType | null; +export declare function incrementClock(): void; +export declare const UNCHANGED: unique symbol; +export type UNCHANGED = typeof UNCHANGED; +export declare class Computation extends Owner implements SourceType, ObserverType { + _sources: SourceType[] | null; + _observers: ObserverType[] | null; + _value: T | undefined; + _compute: null | ((p?: T) => T); + _name: string | undefined; + _equals: false | ((a: T, b: T) => boolean); + _unobserved: (() => void) | undefined; + /** Whether the computation is an error or has ancestors that are unresolved */ + _stateFlags: number; + /** Which flags raised by sources are handled, vs. being passed through. */ + _handlerMask: number; + _error: Computation | null; + _loading: Computation | null; + _time: number; + constructor(initialValue: T | undefined, compute: null | ((p?: T) => T), options?: SignalOptions); + _read(): T; + /** + * Return the current value of this computation + * Automatically re-executes the surrounding computation when the value changes + */ + read(): T; + /** + * Return the current value of this computation + * Automatically re-executes the surrounding computation when the value changes + * + * If the computation has any unresolved ancestors, this function waits for the value to resolve + * before continuing + */ + wait(): T; + /** + * Return true if the computation is the value is dependent on an unresolved promise + * Triggers re-execution of the computation when the loading state changes + * + * This is useful especially when effects want to re-execute when a computation's + * loading state changes + */ + loading(): boolean; + /** + * Return true if the computation is the computation threw an error + * Triggers re-execution of the computation when the error state changes + */ + error(): boolean; + /** Update the computation with a new value. */ + write(value: T | ((currentValue: T) => T) | UNCHANGED, flags?: number, raw?: boolean): T; + /** + * Set the current node's state, and recursively mark all of this node's observers as STATE_CHECK + */ + _notify(state: number): void; + /** + * Notify the computation that one of its sources has changed flags. + * + * @param mask A bitmask for which flag(s) were changed. + * @param newFlags The source's new flags, masked to just the changed ones. + */ + _notifyFlags(mask: Flags, newFlags: Flags): void; + _setError(error: unknown): void; + /** + * This is the core part of the reactivity system, which makes sure that the values are updated + * before they are read. We've also adapted it to return the loading state of the computation, + * so that we can propagate that to the computation's observers. + * + * This function will ensure that the value and states we read from the computation are up to date + */ + _updateIfNecessary(): void; + /** + * Remove ourselves from the owner graph and the computation graph + */ + _disposeNode(): void; +} +/** + * Reruns a computation's _compute function, producing a new value and keeping track of dependencies. + * + * It handles the updating of sources and observers, disposal of previous executions, + * and error handling if the _compute function throws. It also sets the node as loading + * if it reads any parents that are currently loading. + */ +export declare function update(node: Computation): void; +export declare function isEqual(a: T, b: T): boolean; +/** + * Returns the current value stored inside the given compute function without triggering any + * dependencies. Use `untrack` if you want to also disable owner tracking. + */ +export declare function untrack(fn: () => T): T; +/** + * Returns true if the given functinon contains signals that have been updated since the last time + * the parent computation was run. + */ +export declare function hasUpdated(fn: () => any): boolean; +/** + * Returns true if the given function contains async signals that are not ready yet. + */ +export declare function isPending(fn: () => any): boolean; +export declare function latest(fn: () => T): T | undefined; +/** + * A convenient wrapper that calls `compute` with the `owner` and `observer` and is guaranteed + * to reset the global context after the computation is finished even if an error is thrown. + */ +export declare function compute(owner: Owner | null, compute: (val: T) => T, observer: Computation): T; +export declare function compute(owner: Owner | null, compute: (val: undefined) => T, observer: null): T; +export declare class EagerComputation extends Computation { + constructor(initialValue: T, compute: () => T, options?: SignalOptions); + _notify(state: number): void; +} +export {}; diff --git a/website/packages/solid-signals/2024-11-01/types/core/effect.d.ts b/website/packages/solid-signals/2024-11-01/types/core/effect.d.ts new file mode 100644 index 000000000..618740acf --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/core/effect.d.ts @@ -0,0 +1,23 @@ +import { Computation, type SignalOptions } from "./core.js"; +/** + * Effects are the leaf nodes of our reactive graph. When their sources change, they are + * automatically added to the queue of effects to re-execute, which will cause them to fetch their + * sources and recompute + */ +export declare class BaseEffect extends Computation { + _effect: (val: T, prev: T | undefined) => void; + _modified: boolean; + _prevValue: T | undefined; + constructor(initialValue: T, compute: () => T, effect: (val: T, prev: T | undefined) => void, options?: SignalOptions); + write(value: T): T; + _setError(error: unknown): void; + _disposeNode(): void; +} +export declare class Effect extends BaseEffect { + constructor(initialValue: T, compute: () => T, effect: (val: T, prev: T | undefined) => void, options?: SignalOptions); + _notify(state: number): void; +} +export declare class RenderEffect extends BaseEffect { + constructor(initialValue: T, compute: () => T, effect: (val: T, prev: T | undefined) => void, options?: SignalOptions); + _notify(state: number): void; +} diff --git a/website/packages/solid-signals/2024-11-01/types/core/error.d.ts b/website/packages/solid-signals/2024-11-01/types/core/error.d.ts new file mode 100644 index 000000000..b91a59791 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/core/error.d.ts @@ -0,0 +1,11 @@ +export declare class NotReadyError extends Error { +} +export declare class NoOwnerError extends Error { + constructor(); +} +export declare class ContextNotFoundError extends Error { + constructor(); +} +export interface ErrorHandler { + (error: unknown): void; +} diff --git a/website/packages/solid-signals/2024-11-01/types/core/flags.d.ts b/website/packages/solid-signals/2024-11-01/types/core/flags.d.ts new file mode 100644 index 000000000..b11fbb1d1 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/core/flags.d.ts @@ -0,0 +1,8 @@ +export type Flags = number; +export declare const ERROR_OFFSET = 0; +export declare const ERROR_BIT: number; +export declare const ERROR: unique symbol; +export declare const LOADING_OFFSET = 1; +export declare const LOADING_BIT: number; +export declare const LOADING: unique symbol; +export declare const DEFAULT_FLAGS: number; diff --git a/website/packages/solid-signals/2024-11-01/types/core/index.d.ts b/website/packages/solid-signals/2024-11-01/types/core/index.d.ts new file mode 100644 index 000000000..4a2fe21a3 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/core/index.d.ts @@ -0,0 +1,6 @@ +export { ContextNotFoundError, NoOwnerError, NotReadyError, type ErrorHandler } from "./error.js"; +export { Owner, createContext, getContext, setContext, hasContext, getOwner, onCleanup, type Context, type ContextRecord, type Disposable } from "./owner.js"; +export { Computation, EagerComputation, getObserver, isEqual, untrack, hasUpdated, isPending, latest, UNCHANGED, compute, type SignalOptions } from "./core.js"; +export { Effect, RenderEffect } from "./effect.js"; +export { flushSync } from "./scheduler.js"; +export * from "./flags.js"; diff --git a/website/packages/solid-signals/2024-11-01/types/core/owner.d.ts b/website/packages/solid-signals/2024-11-01/types/core/owner.d.ts new file mode 100644 index 000000000..0d5371f56 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/core/owner.d.ts @@ -0,0 +1,88 @@ +/** + * Owner tracking is used to enable nested tracking scopes with automatic cleanup. + * We also use owners to also keep track of which error handling context we are in. + * + * If you write the following + * + * const a = createOwner(() => { + * const b = createOwner(() => {}); + * + * const c = createOwner(() => { + * const d = createOwner(() => {}); + * }); + * + * const e = createOwner(() => {}); + * }); + * + * The owner tree will look like this: + * + * a + * /|\ + * b-c-e + * | + * d + * + * Following the _nextSibling pointers of each owner will first give you its children, and then its siblings (in reverse). + * a -> e -> c -> d -> b + * + * Note that the owner tree is largely orthogonal to the reactivity tree, and is much closer to the component tree. + */ +import { type ErrorHandler } from "./error.js"; +export type ContextRecord = Record; +export interface Disposable { + (): void; +} +/** + * Returns the currently executing parent owner. + */ +export declare function getOwner(): Owner | null; +export declare function setOwner(owner: Owner | null): Owner | null; +export declare class Owner { + _parent: Owner | null; + _nextSibling: Owner | null; + _prevSibling: Owner | null; + _state: number; + _disposal: Disposable | Disposable[] | null; + _context: ContextRecord; + _handlers: ErrorHandler[] | null; + constructor(signal?: boolean); + append(child: Owner): void; + dispose(this: Owner, self?: boolean): void; + _disposeNode(): void; + emptyDisposal(): void; + handleError(error: unknown): void; +} +export interface Context { + readonly id: symbol; + readonly defaultValue: T | undefined; +} +/** + * Context provides a form of dependency injection. It is used to save from needing to pass + * data as props through intermediate components. This function creates a new context object + * that can be used with `getContext` and `setContext`. + * + * A default value can be provided here which will be used when a specific value is not provided + * via a `setContext` call. + */ +export declare function createContext(defaultValue?: T, description?: string): Context; +/** + * Attempts to get a context value for the given key. + * + * @throws `NoOwnerError` if there's no owner at the time of call. + * @throws `ContextNotFoundError` if a context value has not been set yet. + */ +export declare function getContext(context: Context, owner?: Owner | null): T; +/** + * Attempts to set a context value on the parent scope with the given key. + * + * @throws `NoOwnerError` if there's no owner at the time of call. + */ +export declare function setContext(context: Context, value?: T, owner?: Owner | null): void; +/** + * Whether the given context is currently defined. + */ +export declare function hasContext(context: Context, owner?: Owner | null): boolean; +/** + * Runs the given function when the parent owner computation is being disposed. + */ +export declare function onCleanup(disposable: Disposable): void; diff --git a/website/packages/solid-signals/2024-11-01/types/core/scheduler.d.ts b/website/packages/solid-signals/2024-11-01/types/core/scheduler.d.ts new file mode 100644 index 000000000..2ba7596b1 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/core/scheduler.d.ts @@ -0,0 +1,9 @@ +import type { Effect, RenderEffect } from "./effect.js"; +import { Computation } from "./core.js"; +export declare let Computations: Computation[], RenderEffects: RenderEffect[], Effects: Effect[]; +/** + * By default, changes are batched on the microtask queue which is an async process. You can flush + * the queue synchronously to get the latest updates by calling `flushSync()`. + */ +export declare function flushSync(): void; +export declare function flushQueue(): void; diff --git a/website/packages/solid-signals/2024-11-01/types/index.d.ts b/website/packages/solid-signals/2024-11-01/types/index.d.ts new file mode 100644 index 000000000..2936d5b82 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/index.d.ts @@ -0,0 +1,5 @@ +export { Computation, ContextNotFoundError, NoOwnerError, NotReadyError, Owner, createContext, getContext, setContext, hasContext, getOwner, onCleanup, getObserver, isEqual, untrack, hasUpdated, isPending, latest } from "./core/index.js"; +export type { ErrorHandler, SignalOptions, Context, ContextRecord, Disposable } from "./core/index.js"; +export { flushSync } from "./core/scheduler.js"; +export { mapArray, type Maybe } from "./map.js"; +export * from "./signals.js"; diff --git a/website/packages/solid-signals/2024-11-01/types/map.d.ts b/website/packages/solid-signals/2024-11-01/types/map.d.ts new file mode 100644 index 000000000..d6a650658 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/map.d.ts @@ -0,0 +1,12 @@ +import type { Accessor } from "./signals.js"; +export type Maybe = T | void | null | undefined | false; +/** + * Reactive map helper that caches each list item by reference to reduce unnecessary mapping on + * updates. + * + * @see {@link https://github.com/solidjs/x-reactivity#maparray} + */ +export declare function mapArray(list: Accessor>, map: (value: Accessor, index: Accessor) => MappedItem, options?: { + keyed?: boolean | ((item: Item) => any); + name?: string; +}): Accessor; diff --git a/website/packages/solid-signals/2024-11-01/types/signals.d.ts b/website/packages/solid-signals/2024-11-01/types/signals.d.ts new file mode 100644 index 000000000..206e5879e --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/signals.d.ts @@ -0,0 +1,56 @@ +import type { SignalOptions } from "./core/index.js"; +import { Owner } from "./core/index.js"; +export interface Accessor { + (): T; +} +export interface Setter { + (value: T | SetValue): T; +} +export interface SetValue { + (currentValue: T): T; +} +export type Signal = [read: Accessor, write: Setter]; +/** + * Wraps the given value into a signal. The signal will return the current value when invoked + * `fn()`, and provide a simple write API via `write()`. The value can now be observed + * when used inside other computations created with `computed` and `effect`. + */ +export declare function createSignal(initialValue: Exclude, options?: SignalOptions): Signal; +export declare function createSignal(fn: (prev?: T) => T, initialValue?: T, options?: SignalOptions): Signal; +export declare function createAsync(fn: (prev?: T) => Promise | AsyncIterable | T, initial?: T, options?: SignalOptions): Accessor; +/** + * Creates a new computation whose value is computed and returned by the given function. The given + * compute function is _only_ re-run when one of it's dependencies are updated. Dependencies are + * are all signals that are read during execution. + */ +export declare function createMemo(compute: (prev?: T) => T, initialValue?: T, options?: SignalOptions): Accessor; +/** + * Invokes the given function each time any of the signals that are read inside are updated + * (i.e., their value changes). The effect is immediately invoked on initialization. + */ +export declare function createEffect(compute: () => T, effect: (v: T) => (() => void) | void, initialValue?: T, options?: { + name?: string; +}): void; +/** + * Invokes the given function each time any of the signals that are read inside are updated + * (i.e., their value changes). The effect is immediately invoked on initialization. + */ +export declare function createRenderEffect(compute: () => T, effect: (v: T) => (() => void) | void, initialValue?: T, options?: { + name?: string; +}): void; +/** + * Creates a computation root which is given a `dispose()` function to dispose of all inner + * computations. + */ +export declare function createRoot(init: ((dispose: () => void) => T) | (() => T)): T; +/** + * Runs the given function in the given owner so that error handling and cleanups continue to work. + * + * Warning: Usually there are simpler ways of modeling a problem that avoid using this function + */ +export declare function runWithOwner(owner: Owner | null, run: () => T): T | undefined; +/** + * Runs the given function when an error is thrown in a child owner. If the error is thrown again + * inside the error handler, it will trigger the next available parent owner handler. + */ +export declare function catchError(fn: () => T, handler: (error: unknown) => void): void; diff --git a/website/packages/solid-signals/2024-11-01/types/store/index.d.ts b/website/packages/solid-signals/2024-11-01/types/store/index.d.ts new file mode 100644 index 000000000..d5a0b1b9d --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/store/index.d.ts @@ -0,0 +1 @@ +export * from "./store.js"; diff --git a/website/packages/solid-signals/2024-11-01/types/store/store.d.ts b/website/packages/solid-signals/2024-11-01/types/store/store.d.ts new file mode 100644 index 000000000..4e05cd1d8 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/store/store.d.ts @@ -0,0 +1,31 @@ +export type Store = Readonly; +export type StoreSetter = (fn: (state: T) => void) => void; +declare const $TRACK: unique symbol, $PROXY: unique symbol; +export { $PROXY, $TRACK }; +export type StoreNode = Record; +export declare namespace SolidStore { + interface Unwrappable { + } +} +export type NotWrappable = string | number | bigint | symbol | boolean | Function | null | undefined | SolidStore.Unwrappable[keyof SolidStore.Unwrappable]; +export declare function isWrappable(obj: T | NotWrappable): obj is T; +/** + * Returns the underlying data in the store without a proxy. + * @param item store proxy object + * @example + * ```js + * const initial = {z...}; + * const [state, setState] = createStore(initial); + * initial === state; // => false + * initial === unwrap(state); // => true + * ``` + */ +export declare function unwrap(item: T, set?: Set): T; +export declare function createStore(store: T | Store): [get: Store, set: StoreSetter]; +export declare function createStore(fn: (store: T) => void, store: T | Store): [get: Store, set: StoreSetter]; +/** + * Creates a mutable derived value + * + * @see {@link https://github.com/solidjs/x-reactivity#createprojection} + */ +export declare function createProjection(fn: (draft: T) => void, initialValue: T): Readonly; diff --git a/website/packages/solid-signals/2024-11-01/types/utils.d.ts b/website/packages/solid-signals/2024-11-01/types/utils.d.ts new file mode 100644 index 000000000..6db6309f2 --- /dev/null +++ b/website/packages/solid-signals/2024-11-01/types/utils.d.ts @@ -0,0 +1 @@ +export declare function isUndefined(value: any): value is undefined; diff --git a/website/scripts/packages/solid-signals/README.md b/website/packages/solid-signals/README.md similarity index 100% rename from website/scripts/packages/solid-signals/README.md rename to website/packages/solid-signals/README.md diff --git a/website/scripts/packages/ufuzzy/README.md b/website/packages/ufuzzy/README.md similarity index 100% rename from website/scripts/packages/ufuzzy/README.md rename to website/packages/ufuzzy/README.md diff --git a/website/scripts/packages/ufuzzy/v1.0.14/script.js b/website/packages/ufuzzy/v1.0.14/script.js similarity index 100% rename from website/scripts/packages/ufuzzy/v1.0.14/script.js rename to website/packages/ufuzzy/v1.0.14/script.js diff --git a/website/scripts/packages/ufuzzy/v1.0.14/types.d.ts b/website/packages/ufuzzy/v1.0.14/types.d.ts similarity index 100% rename from website/scripts/packages/ufuzzy/v1.0.14/types.d.ts rename to website/packages/ufuzzy/v1.0.14/types.d.ts diff --git a/website/scripts/main.js b/website/scripts/main.js index f1231f60b..582dd48b7 100644 --- a/website/scripts/main.js +++ b/website/scripts/main.js @@ -2,18 +2,18 @@ /** * @import { Option, ResourceDataset, TimeScale, SerializedHistory, TimeRange, Unit, Marker, Weighted, DatasetPath, OHLC, FetchedJSON, DatasetValue, FetchedResult, AnyDatasetPath, SeriesBlueprint, BaselineSpecificSeriesBlueprint, CandlestickSpecificSeriesBlueprint, LineSpecificSeriesBlueprint, SpecificSeriesBlueprintWithChart, Signal, Color, SettingsTheme, DatasetCandlestickData, FoldersFilter, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, AnyPath, SimulationOption } from "./types/self" - * @import {createChart as CreateClassicChart, createChartEx as CreateCustomChart, LineStyleOptions} from "./packages/lightweight-charts/v4.2.0/types"; - * @import * as _ from "./packages/ufuzzy/v1.0.14/types" - * @import { DeepPartial, ChartOptions, IChartApi, IHorzScaleBehavior, WhitespaceData, SingleValueData, ISeriesApi, Time, LogicalRange, SeriesMarker, CandlestickData, SeriesType, BaselineStyleOptions, SeriesOptionsCommon } from "./packages/lightweight-charts/v4.2.0/types" + * @import {createChart as CreateClassicChart, createChartEx as CreateCustomChart, LineStyleOptions} from "../packages/lightweight-charts/v4.2.0/types"; + * @import * as _ from "../packages/ufuzzy/v1.0.14/types" + * @import { DeepPartial, ChartOptions, IChartApi, IHorzScaleBehavior, WhitespaceData, SingleValueData, ISeriesApi, Time, LogicalRange, SeriesMarker, CandlestickData, SeriesType, BaselineStyleOptions, SeriesOptionsCommon } from "../packages/lightweight-charts/v4.2.0/types" * @import { DatePath, HeightPath, LastPath } from "./types/paths"; - * @import { SignalOptions } from "./packages/solid-signals/2024-10-28/types/core" - * @import { getOwner as GetOwner, onCleanup as OnCleanup, Owner } from "./packages/solid-signals/2024-10-28/types/owner" - * @import { createSignal as CreateSignal, createEffect as CreateEffect, Accessor, Setter, createMemo as CreateMemo, createRoot as CreateRoot, runWithOwner as RunWithOwner } from "./packages/solid-signals/2024-10-28/types/signals"; + * @import { SignalOptions } from "../packages/solid-signals/2024-11-01/types/core/core" + * @import { getOwner as GetOwner, onCleanup as OnCleanup, Owner } from "../packages/solid-signals/2024-11-01/types/core/owner" + * @import { createSignal as CreateSignal, createEffect as CreateEffect, Accessor, Setter, createMemo as CreateMemo, createRoot as CreateRoot, runWithOwner as RunWithOwner } from "../packages/solid-signals/2024-11-01/types/signals"; */ function initPackages() { async function importSignals() { - return import("./packages/solid-signals/2024-10-28/script.js").then( + return import("../packages/solid-signals/2024-11-01/script.js").then( (_signals) => { const signals = { createSolidSignal: /** @type {CreateSignal} */ ( @@ -95,7 +95,7 @@ function initPackages() { signals: importSignals, async lightweightCharts() { return window.document.fonts.ready.then(() => - import("./packages/lightweight-charts/v4.2.0/script.js").then( + import("../packages/lightweight-charts/v4.2.0/script.js").then( ({ createChart: createClassicChart, createChartEx: createCustomChart, @@ -572,10 +572,10 @@ function initPackages() { ); }, async leanQr() { - return import("./packages/lean-qr/v2.3.4/script.js").then((d) => d); + return import("../packages/lean-qr/v2.3.4/script.js").then((d) => d); }, async ufuzzy() { - return import("./packages/ufuzzy/v1.0.14/script.js").then( + return import("../packages/ufuzzy/v1.0.14/script.js").then( ({ default: d }) => d, ); }, diff --git a/website/scripts/options.js b/website/scripts/options.js index 5c1f5b008..e73811a01 100644 --- a/website/scripts/options.js +++ b/website/scripts/options.js @@ -1,5 +1,5 @@ /** - * @import { AnySpecificSeriesBlueprint, CohortOption, CohortOptions, Color, DefaultCohortOption, DefaultCohortOptions, OptionPath, OptionsGroup, PartialChartOption, PartialOptionsGroup, PartialOptionsTree, Series, SeriesBlueprint, SeriesBlueprintParam, SeriesBluePrintType, TimeScale } from "./types/self" + * @import { AnySpecificSeriesBlueprint, CohortOption, CohortOptions, Color, DefaultCohortOption, DefaultCohortOptions, OptionPath, OptionsGroup, PartialChartOption, PartialOptionsGroup, PartialOptionsTree, RatioOption, RatioOptions, Series, SeriesBlueprint, SeriesBlueprintParam, SeriesBluePrintType, TimeScale } from "./types/self" */ const DATE_TO_PREFIX = "date-to-"; @@ -115,6 +115,12 @@ function initGroups() { ]); const fromXToY = /** @type {const} */ ([ + { + id: "up-to-1d", + key: "up_to_1d", + name: "24h", + legend: "24h", + }, { id: "from-1d-to-1w", key: "from_1d_to_1w", @@ -181,6 +187,12 @@ function initGroups() { name: "From 10 Years To 15 Years", legend: "10Y — 15Y", }, + { + id: "from-15y", + key: "from_15y", + name: "From 15 Years To End", + legend: "15Y — End", + }, ]); const fromX = /** @type {const} */ ([ @@ -854,21 +866,30 @@ function createPartialOptions(colors) { } /** - * @param {Object} args - * @param {TimeScale} args.scale - * @param {Color} args.color - * @param {AnyDatasetPath} args.valueDatasetPath - * @param {AnyDatasetPath} args.ratioDatasetPath - * @param {string} args.title + * @param {RatioOption | RatioOptions} arg * @returns {PartialOptionsGroup} */ - function createRatioOptions({ - scale, - color, - valueDatasetPath, - ratioDatasetPath, - title, - }) { + function createRatioOptions(arg) { + const { scale, title } = arg; + + const isSingle = !("list" in arg); + + /** + * @param {RatioOption | RatioOptions} arg + */ + function toList(arg) { + return "list" in arg ? arg.list : [arg]; + } + + /** + * @param {RatioOption | RatioOptions} arg + * @param {string} cohortName + * @param {string} legendName + */ + function toLegendName(arg, cohortName, legendName) { + return "list" in arg ? `${cohortName} ${legendName}` : legendName; + } + return { name: "Ratio", tree: [ @@ -879,73 +900,82 @@ function createPartialOptions(colors) { title: `Market Price To ${title} Ratio`, unit: "Ratio", description: "", - top: [ - { + top: toList(arg).map( + ({ title, color, valueDatasetPath: datasetPath }) => ({ title, color, - datasetPath: valueDatasetPath, - }, - ], + datasetPath, + }), + ), bottom: [ - { - title: `Ratio`, - type: "Baseline", - datasetPath: ratioDatasetPath, - options: { - baseValue: { - price: 1, + ...toList(arg).map( + ({ title, color, ratioDatasetPath: datasetPath }) => ({ + title: toLegendName(arg, title, "Ratio"), + color: isSingle ? undefined : color, + type: /** @type {const} */ ("Baseline"), + datasetPath, + options: { + baseValue: { + price: 1, + }, }, - }, - }, + }), + ), bases[1](scale), ], }, - { - scale, - name: "Averages", - description: "", - icon: "〰️", - unit: "Ratio", - title: `Market Price To ${title} Ratio Averages`, - top: [ - { - title, - color, - datasetPath: valueDatasetPath, - }, - ], - bottom: [ - { - title: `1Y SMA`, - color: colors.red, - datasetPath: /** @type {any} */ (`${ratioDatasetPath}-1y-sma`), - }, - { - title: `1M SMA`, - color: colors.orange, - datasetPath: `${ratioDatasetPath}-1m-sma`, - }, - { - title: `1W SMA`, - color: colors.yellow, - datasetPath: `${ratioDatasetPath}-1w-sma`, - }, - { - title: `Raw`, - color: colors.default, - datasetPath: ratioDatasetPath, - }, - { - title: `Even`, - color: colors.off, - datasetPath: `${scale}-to-1`, - options: { - lineStyle: 3, - lastValueVisible: false, + ...(isSingle + ? /** @satisfies {PartialChartOption[]} */ ([ + { + scale, + name: "Averages", + description: "", + icon: "〰️", + unit: "Ratio", + title: `Market Price To ${title} Ratio Averages`, + top: [ + { + title, + color: arg.color, + datasetPath: arg.valueDatasetPath, + }, + ], + bottom: [ + { + title: `1Y SMA`, + color: colors.red, + datasetPath: /** @type {any} */ ( + `${arg.ratioDatasetPath}-1y-sma` + ), + }, + { + title: `1M SMA`, + color: colors.orange, + datasetPath: `${arg.ratioDatasetPath}-1m-sma`, + }, + { + title: `1W SMA`, + color: colors.yellow, + datasetPath: `${arg.ratioDatasetPath}-1w-sma`, + }, + { + title: `Raw`, + color: colors.default, + datasetPath: arg.ratioDatasetPath, + }, + { + title: `Even`, + color: colors.off, + datasetPath: `${scale}-to-1`, + options: { + lineStyle: 3, + lastValueVisible: false, + }, + }, + ], }, - }, - ], - }, + ]) + : []), { scale, name: "Momentum Oscillator", @@ -953,145 +983,282 @@ function createPartialOptions(colors) { description: "", unit: "Ratio", icon: "🔀", - top: [ - { - title: `SMA`, + top: toList(arg).map( + ({ title, color, valueDatasetPath: datasetPath }) => ({ + title: toLegendName(arg, title, ""), color, - datasetPath: valueDatasetPath, - }, - ], + datasetPath, + }), + ), bottom: [ - { - title: `Momentum`, - type: "Baseline", - datasetPath: /** @type {any} */ ( - `${ratioDatasetPath}-1y-sma-momentum-oscillator` - ), - }, + ...toList(arg).map( + ({ title, color, ratioDatasetPath: datasetPath }) => ({ + title: toLegendName(arg, title, "Momentum"), + color: isSingle ? undefined : color, + type: /** @type {const} */ ("Baseline"), + datasetPath: /** @type {any} */ ( + `${datasetPath}-1y-sma-momentum-oscillator` + ), + }), + ), bases[0](scale), ], }, { - scale, - name: "Top Percentiles", - icon: "✈️", - title: `Market Price To ${title} Ratio Top Percentiles`, - description: "", - unit: "Ratio", - top: [ + name: "Top", + tree: [ + ...(isSingle + ? /** @satisfies {PartialChartOption[]} */ ([ + { + scale, + name: "Percentiles", + icon: "✈️", + title: `Market Price To ${title} Ratio Top Percentiles`, + description: "", + unit: "Ratio", + top: [ + { + title, + color: arg.color, + datasetPath: arg.valueDatasetPath, + }, + ], + bottom: [ + { + title: `99.9%`, + color: colors.probability0_1p, + datasetPath: /** @type {any} */ ( + `${arg.ratioDatasetPath}-99-9p` + ), + }, + { + title: `99.5%`, + color: colors.probability0_5p, + datasetPath: `${arg.ratioDatasetPath}-99-5p`, + }, + { + title: `99%`, + color: colors.probability1p, + datasetPath: `${arg.ratioDatasetPath}-99p`, + }, + { + title: `Raw`, + color: colors.default, + datasetPath: arg.ratioDatasetPath, + }, + ], + }, + ]) + : []), { - title, - color, - datasetPath: valueDatasetPath, - }, - ], - bottom: [ - { - title: `99.9%`, - color: colors.probability0_1p, - datasetPath: /** @type {any} */ (`${ratioDatasetPath}-99-9p`), - }, - { - title: `99.5%`, - color: colors.probability0_5p, - datasetPath: `${ratioDatasetPath}-99-5p`, - }, - { - title: `99%`, - color: colors.probability1p, - datasetPath: `${ratioDatasetPath}-99p`, - }, - { - title: `Raw`, - color: colors.default, - datasetPath: ratioDatasetPath, + name: "Prices", + tree: [ + ...(isSingle + ? /** @satisfies {PartialChartOption[]} */ ([ + { + scale, + name: "All", + icon: "🚀", + title: `${title} Top Prices`, + description: "", + unit: "US Dollars", + top: [ + { + title: `99.9%`, + color: colors.probability0_1p, + datasetPath: /** @type {any} */ ( + `${arg.valueDatasetPath}-99-9p` + ), + }, + { + title: `99.5%`, + color: colors.probability0_5p, + datasetPath: `${arg.valueDatasetPath}-99-5p`, + }, + { + title: `99%`, + color: colors.probability1p, + datasetPath: `${arg.valueDatasetPath}-99p`, + }, + ], + }, + ]) + : []), + { + scale, + name: "99%", + icon: "🚀", + title: `${title} Top 99% Price`, + description: "", + unit: "US Dollars", + top: toList(arg).map((cohort) => ({ + title: toLegendName(arg, cohort.title, `99%`), + color: isSingle ? colors.probability1p : cohort.color, + datasetPath: /** @type {any} */ ( + `${cohort.valueDatasetPath}-99p` + ), + })), + }, + { + scale, + name: "99.5%", + icon: "🚀", + title: `${title} Top 99.5% Price`, + description: "", + unit: "US Dollars", + top: toList(arg).map((cohort) => ({ + title: toLegendName(arg, cohort.title, `99.5%`), + color: isSingle ? colors.probability0_5p : cohort.color, + datasetPath: /** @type {any} */ ( + `${cohort.valueDatasetPath}-99-5p` + ), + })), + }, + { + scale, + name: "99.9%", + icon: "🚀", + title: `${title} Top 99.9% Price`, + description: "", + unit: "US Dollars", + top: toList(arg).map((cohort) => ({ + title: toLegendName(arg, cohort.title, `99.9%`), + color: isSingle ? colors.probability0_1p : cohort.color, + datasetPath: /** @type {any} */ ( + `${cohort.valueDatasetPath}-99-9p` + ), + })), + }, + ], }, ], }, { - scale, - name: "Bottom Percentiles", - icon: "🤿", - title: `Market Price To ${title} Ratio Bottom Percentiles`, - description: "", - unit: "Ratio", - top: [ + name: "Bottom", + tree: [ + ...(isSingle + ? /** @satisfies {PartialChartOption[]} */ ([ + { + scale, + name: "Percentiles", + icon: "🤿", + title: `Market Price To ${title} Ratio Bottom Percentiles`, + description: "", + unit: "Ratio", + top: [ + { + title, + color: arg.color, + datasetPath: arg.valueDatasetPath, + }, + ], + bottom: [ + { + title: `0.1%`, + color: colors.probability0_1p, + datasetPath: `${arg.ratioDatasetPath}-0-1p`, + }, + { + title: `0.5%`, + color: colors.probability0_5p, + datasetPath: `${arg.ratioDatasetPath}-0-5p`, + }, + { + title: `1%`, + color: colors.probability1p, + datasetPath: /** @type {any} */ ( + `${arg.ratioDatasetPath}-1p` + ), + }, + { + title: `Raw`, + color: colors.default, + datasetPath: arg.ratioDatasetPath, + }, + ], + }, + ]) + : []), { - title: `SMA`, - color, - datasetPath: valueDatasetPath, - }, - ], - bottom: [ - { - title: `0.1%`, - color: colors.probability0_1p, - datasetPath: `${ratioDatasetPath}-0-1p`, - }, - { - title: `0.5%`, - color: colors.probability0_5p, - datasetPath: `${ratioDatasetPath}-0-5p`, - }, - { - title: `1%`, - color: colors.probability1p, - datasetPath: /** @type {any} */ (`${ratioDatasetPath}-1p`), - }, - { - title: `Raw`, - color: colors.default, - datasetPath: ratioDatasetPath, - }, - ], - }, - { - scale, - name: "Top Probabilities", - icon: "🚀", - title: `${title} Top Probabilities`, - description: "", - unit: "US Dollars", - top: [ - { - title: `99.9%`, - color: colors.probability0_1p, - datasetPath: /** @type {any} */ (`${valueDatasetPath}-99-9p`), - }, - { - title: `99.5%`, - color: colors.probability0_5p, - datasetPath: `${valueDatasetPath}-99-5p`, - }, - { - title: `99%`, - color: colors.probability1p, - datasetPath: `${valueDatasetPath}-99p`, - }, - ], - }, - { - scale, - name: "Bottom Probabilities", - icon: "🚇", - title: `${title} Bottom Probabilities`, - description: "", - unit: "US Dollars", - top: [ - { - title: `99.9%`, - color: colors.probability0_1p, - datasetPath: `${valueDatasetPath}-0-1p`, - }, - { - title: `99.5%`, - color: colors.probability0_5p, - datasetPath: `${valueDatasetPath}-0-5p`, - }, - { - title: `99%`, - color: colors.probability1p, - datasetPath: `${valueDatasetPath}-1p`, + name: "Prices", + tree: [ + ...(isSingle + ? /** @satisfies {PartialChartOption[]} */ ([ + { + scale, + name: "All", + icon: "🚇", + title: `${title} Bottom Prices`, + description: "", + unit: "US Dollars", + top: [ + { + title: `0.1%`, + color: colors.probability0_1p, + datasetPath: /** @type {any} */ ( + `${arg.valueDatasetPath}-0-1p` + ), + }, + { + title: `0.5%`, + color: colors.probability0_5p, + datasetPath: `${arg.valueDatasetPath}-0-5p`, + }, + { + title: `1%`, + color: colors.probability1p, + datasetPath: `${arg.valueDatasetPath}-1p`, + }, + ], + }, + ]) + : []), + { + scale, + name: "1%", + icon: "🚇", + title: `${title} Bottom 1% Price`, + description: "", + unit: "US Dollars", + top: toList(arg).map((cohort) => ({ + title: toLegendName(arg, cohort.title, `1%`), + color: isSingle ? colors.probability1p : cohort.color, + datasetPath: /** @type {any} */ ( + `${cohort.valueDatasetPath}-1p` + ), + })), + }, + { + scale, + name: "0.5%", + icon: "🚇", + title: `${title} Bottom 0.5% Price`, + description: "", + unit: "US Dollars", + top: toList(arg).map((cohort) => ({ + title: toLegendName(arg, cohort.title, `0.5%`), + color: isSingle ? colors.probability0_5p : cohort.color, + datasetPath: /** @type {any} */ ( + `${cohort.valueDatasetPath}-0-5p` + ), + })), + }, + { + scale, + name: "0.1%", + icon: "🚇", + title: `${title} Bottom 0.1% Price`, + description: "", + unit: "US Dollars", + top: toList(arg).map((cohort) => ({ + title: toLegendName(arg, cohort.title, `0.1%`), + color: isSingle ? colors.probability0_1p : cohort.color, + datasetPath: /** @type {any} */ ( + `${cohort.valueDatasetPath}-0-1p` + ), + })), + }, + ], }, ], }, @@ -2733,6 +2900,20 @@ function createPartialOptions(colors) { function createCohortRealizedOptions(arg) { const { scale, title } = arg; + /** + * @param {DefaultCohortOption} arg + * @returns {RatioOption} + */ + function argToRatioArg(arg) { + return { + scale, + color: arg.color, + ratioDatasetPath: `${scale}-to-market-price-to-${datasetIdToPrefix(arg.datasetId)}realized-price-ratio`, + valueDatasetPath: `${scale}-to-${datasetIdToPrefix(arg.datasetId)}realized-price`, + title: `${arg.title} Realized Price`, + }; + } + return { name: "Realized", tree: [ @@ -2746,20 +2927,19 @@ function createPartialOptions(colors) { top: cohortOptionOrOptions.toSeriesBlueprints(arg, { title: "Realized Price", genPath: (id, scale) => - `${scale}-to-${datasetIdToPrefix(id)}realized-price`, + /** @type {const} */ ( + `${scale}-to-${datasetIdToPrefix(id)}realized-price` + ), }), }, - ...(!("list" in arg) - ? [ - createRatioOptions({ - scale, - color: arg.color, - ratioDatasetPath: `${scale}-to-market-price-to-${datasetIdToPrefix(arg.datasetId)}realized-price-ratio`, - valueDatasetPath: `${scale}-to-${datasetIdToPrefix(arg.datasetId)}realized-price`, - title: `${title} Realized Price`, - }), - ] - : []), + createRatioOptions( + "list" in arg + ? { + ...arg, + list: arg.list.map(argToRatioArg), + } + : argToRatioArg(arg), + ), { scale, name: `Capitalization`, @@ -2774,7 +2954,9 @@ function createPartialOptions(colors) { { title: "Realized Cap.", genPath: (id, scale) => - `${scale}-to-${datasetIdToPrefix(id)}realized-cap`, + /** @type {const} */ ( + `${scale}-to-${datasetIdToPrefix(id)}realized-cap` + ), }, ), ...(cohortOptionOrOptions.shouldShowAll(arg) diff --git a/website/scripts/service-worker.js b/website/scripts/service-worker.js index 348171cb2..1f86d6079 100644 --- a/website/scripts/service-worker.js +++ b/website/scripts/service-worker.js @@ -17,10 +17,10 @@ self.addEventListener("install", (_event) => { "/scripts/options.js", "/scripts/chart.js", "/styles/chart.css", - "/scripts/packages/lean-qr/v2.3.4/script.js", - "/scripts/packages/lightweight-charts/v4.2.0/script.js", - "/scripts/packages/solid-signals/2024-10-28/script.js", - "/scripts/packages/ufuzzy/v1.0.14/script.js", + "/packages/lean-qr/v2.3.4/script.js", + "/packages/lightweight-charts/v4.2.0/script.js", + "/packages/solid-signals/2024-11-01/script.js", + "/packages/ufuzzy/v1.0.14/script.js", ]); }), ); diff --git a/website/scripts/types/self.d.ts b/website/scripts/types/self.d.ts index 95ec806df..84f954efa 100644 --- a/website/scripts/types/self.d.ts +++ b/website/scripts/types/self.d.ts @@ -1,7 +1,7 @@ import { Accessor, Setter, -} from "../packages/solid-signals/2024-10-28/types/signals"; +} from "../../packages/solid-signals/2024-11-01/types/signals"; import { DeepPartial, BaselineStyleOptions, @@ -15,9 +15,9 @@ import { SeriesType, IChartApi, ISeriesApi, -} from "../packages/lightweight-charts/v4.2.0/types"; +} from "../../packages/lightweight-charts/v4.2.0/types"; import { DatePath, HeightPath, LastPath } from "./paths"; -import { Owner } from "../packages/solid-signals/2024-10-28/types/owner"; +import { Owner } from "../../packages/solid-signals/2024-11-01/types/core/owner"; import { AnyPossibleCohortId } from "../options"; type GrowToSize = A["length"] extends N @@ -327,3 +327,17 @@ interface SeriesBlueprintParam { singleColor?: Color; genPath: (id: T, scale: TimeScale) => AnyDatasetPath; } + +interface RatioOption { + scale: TimeScale; + color: Color; + valueDatasetPath: AnyDatasetPath; + ratioDatasetPath: AnyDatasetPath; + title: string; +} + +interface RatioOptions { + scale: TimeScale; + title: string; + list: RatioOption[]; +} diff --git a/website/tsconfig.json b/website/tsconfig.json index d28110d3f..6dec788c9 100644 --- a/website/tsconfig.json +++ b/website/tsconfig.json @@ -6,6 +6,5 @@ "module": "ESNext", "outDir": "/tmp/kibo" }, - // "include": ["scripts"], "exclude": ["assets", "packages", "ignore"] }