Recalculation on track edit end Changes rendering of ties to be evenly spaced Fixes ghost and held track rendering
95 lines
2.5 KiB
TypeScript
95 lines
2.5 KiB
TypeScript
type ContextStore = Record<string, any>;
|
|
|
|
const defaultContext: ContextStore = {};
|
|
const contextStack: ContextStore[] = [defaultContext];
|
|
|
|
const debug = JSON.parse(localStorage.getItem("debug") || "false");
|
|
|
|
export function setDefaultContext(context: ContextStore) {
|
|
Object.assign(defaultContext, context);
|
|
}
|
|
|
|
export function withContext<T>(context: ContextStore, fn: () => T): T {
|
|
contextStack.push(context);
|
|
try {
|
|
return fn();
|
|
} finally {
|
|
contextStack.pop();
|
|
}
|
|
}
|
|
|
|
export const ctx = new Proxy(
|
|
{},
|
|
{
|
|
get(_, prop: string) {
|
|
for (let i = contextStack.length - 1; i >= 0; i--) {
|
|
if (prop in contextStack[i]) return contextStack[i][prop];
|
|
}
|
|
if (prop in defaultContext) return defaultContext[prop];
|
|
throw new Error(`Context variable '${prop}' is not defined.`);
|
|
},
|
|
},
|
|
) as Record<string, unknown>;
|
|
|
|
export function getContext() {
|
|
return ctx;
|
|
}
|
|
export function getContextItem<T>(prop: string): T {
|
|
return ctx[prop] as T;
|
|
}
|
|
export function getContextItemOrDefault<T>(prop: string, defaultValue: T): T {
|
|
try {
|
|
return ctx[prop] as T;
|
|
} catch {
|
|
return defaultValue;
|
|
}
|
|
}
|
|
export function setContextItem<T>(prop: string, value: T) {
|
|
Object.assign(contextStack[contextStack.length - 1] ?? defaultContext, {
|
|
[prop]: value,
|
|
});
|
|
}
|
|
|
|
if (debug) {
|
|
setInterval(() => {
|
|
let ctxEl = document.getElementById("context");
|
|
if (!ctxEl) {
|
|
ctxEl = document.createElement("div");
|
|
ctxEl.id = "context";
|
|
document.body.append(ctxEl);
|
|
}
|
|
ctxEl.innerHTML = "";
|
|
const div = document.createElement("div");
|
|
const pre = document.createElement("pre");
|
|
const h3 = document.createElement("h3");
|
|
h3.textContent = "Default";
|
|
div.append(h3);
|
|
pre.textContent = safeStringify(defaultContext);
|
|
div.append(pre);
|
|
ctxEl.append(div);
|
|
for (const [idx, ctx] of contextStack.entries()) {
|
|
const div = document.createElement("div");
|
|
const pre = document.createElement("pre");
|
|
const h3 = document.createElement("h3");
|
|
h3.textContent = "CTX " + idx;
|
|
div.append(h3);
|
|
pre.textContent = safeStringify(ctx);
|
|
div.append(pre);
|
|
ctxEl.append(div);
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
function safeStringify(obj: any) {
|
|
const seen = new WeakSet();
|
|
return JSON.stringify(obj, (key, value) => {
|
|
if (typeof value === "object" && value !== null) {
|
|
if (seen.has(value)) {
|
|
return "[Circular]"; // Replace circular references
|
|
}
|
|
seen.add(value);
|
|
}
|
|
return value;
|
|
}, 2);
|
|
}
|