@ixfx/ui 0.40.3 → 0.42.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["interval","object","#handlers","#counter","#id","toStringDefault","toStringDefault","#store","#disposed","#listeners","manual","iterator","isEmpty","value","debounce","debounceReactive","init","elem: Readonly<Element>","interval?: Interval","opts: MutationObserverInit","initialValue?: HslScalar","v: HslScalar","hsl: HslScalar","__export","fromHexString","fromLibrary","fromCss","rgbToLibraryHsl","toScalar","toCssString","abs","scalar","absolute","guard","opacity","vf","guard","opacity","fromLibrary","scalar","fromHexString","fromCss","rgbTo8bit","lch","Colorizr","toCssString","chroma","colour","fromCss","scalar","hslToLibraryRgb","guard","opacity","colour","targetOrQuery: HTMLInputElement | string","options: Partial<DomNumberInputValueOptions>","value: number","options: Partial<DomValueOptions>","target: HTMLInputElement | null","value: string | null | undefined","value: string","v: any","formElOrQuery: HTMLFormElement | string","options: Partial<DomFormOptions<T>>","entries: [ string, unknown ][]","name: string","value: any","value: T","query: string","elements","source: Rx.Reactive<TSource>","elOrQuery: string | HTMLElement | null","bindOpts: Partial<DomBindSourceValue<TSource, string>>","elOrQuery: string | HTMLInputElement | null","bindOpts: DomBindSourceValue<TSource, string>","b: DomBindValueTarget[]","bind","bind: DomBindValueTarget","element: HTMLElement","value: any","v: any","_: any","_element: HTMLElement","bind: DomBindSourceValue<TSource, TDestination>","value: TSource","binds: DomBindResolvedSource<TSource, TDestination>[]","removeElements: boolean","source: Rx.Reactive<V>","elOrQuery: string | HTMLElement","updater: (v: V, el: HTMLElement) => void","value: V","updater","removeElement: boolean","source: Rx.ReactiveDiff<V>","updater: (diffs: Pathed.PathDataChange<any>[], el: HTMLElement) => void","opts: Partial<BindUpdateOpts<V>>","value: Pathed.PathDataChange<any>[]","init","source: Rx.ReactiveDiff<T> | (Rx.ReactiveDiff<T> & Rx.ReactiveInitial<T>)","options: Partial<ElementsOptions>","path: string","mapFindBySomeKey","el: HTMLElement","changes: (Pathed.PathDataChange<any> | Pathed.PathData<any>)[]","changes","args: Event | undefined"],"sources":["../../guards/dist/src/result.js","../../guards/dist/src/numbers.js","../../guards/dist/src/object.js","../../core/dist/src/continuously.js","../../core/dist/src/elapsed.js","../../core/dist/src/text.js","../../core/dist/src/is-equal.js","../../core/dist/src/is-integer.js","../../core/dist/src/is-primitive.js","../../core/dist/src/iterable-compare-values-shallow.js","../../core/dist/src/interval-type.js","../../debug/dist/src/error-message.js","../../core/dist/src/sleep.js","../../core/dist/src/records/compare.js","../../core/dist/src/pathed.js","../../flow/dist/src/timeout.js","../../flow/dist/src/dispatch-list.js","../../arrays/dist/src/util/to-string.js","../../arrays/dist/src/unique.js","../../events/dist/src/map-of.js","../../events/dist/src/simple-event-emitter.js","../../iterables/dist/src/guard.js","../../collections/dist/src/queue/queue-fns.js","../../collections/dist/src/queue/queue-mutable.js","../../iterables/dist/src/async.js","../../core/dist/src/maps.js","../../flow/dist/src/state-machine/state-machine.js","../../rx/dist/src/from/function.js","../../rx/dist/src/from/iterator.js","../../rx/dist/src/util.js","../../rx/dist/src/resolve-source.js","../../rx/dist/src/init-stream.js","../../rx/dist/src/from/object.js","../../rx/dist/src/to-readable.js","../../rx/dist/src/from/event.js","../../dom/dist/src/resolve-el.js","../../rx/dist/src/ops/transform.js","../../rx/dist/src/reactives/debounce.js","../../rx/dist/src/ops/debounce.js","../../rx/dist/src/index.js","../../rx/dist/src/from/observable.js","../src/rx/browser-resize.ts","../src/rx/browser-theme-change.ts","../src/rx/colour.ts","../../../node_modules/.pnpm/colorizr@3.0.7/node_modules/colorizr/dist/index.mjs","../../visual/dist/src/colour/guards.js","../../visual/dist/src/colour/hsl.js","../../visual/dist/src/colour/oklch.js","../../visual/dist/src/colour/css-colours.js","../../visual/dist/src/colour/srgb.js","../../visual/dist/src/colour/conversion.js","../src/rx/dom-source.ts","../src/rx/dom.ts","../src/rx/index.ts"],"sourcesContent":["export const getErrorMessage = (ex) => {\n if (typeof ex === `string`)\n return ex;\n if (ex instanceof Error) {\n return ex.message;\n }\n return ex;\n};\n/**\n * Throws an error if any result is a failure.\n * Error message will be the combined from all errors.\n * @param results\n * @returns\n */\nexport const throwIfFailed = (...results) => {\n const failed = results.filter(r => resultIsError(r)); // as ResultError<any>[];\n if (failed.length === 0)\n return;\n const messages = failed.map(f => resultErrorToString(f));\n throw new Error(messages.join(`, `));\n};\n/**\n * If any of `results` is an error, throws it, otherwise ignored.\n * @param results\n * @returns _true_ or throws\n */\nexport function resultThrow(...results) {\n for (const r of results) {\n const rr = typeof r === `object` ? r : r();\n if (rr === undefined)\n continue;\n if (rr.success)\n continue;\n throw resultToError(rr);\n }\n return true;\n}\nexport function resultThrowSingle(result) {\n if (result.success)\n return true;\n throw resultToError(result);\n}\n/**\n * Returns the first failed result, or _undefined_ if there are no fails\n * @param results\n * @returns\n */\nexport const resultFirstFail_ = (...results) => {\n for (const r of results) {\n const rr = typeof r === `object` ? r : r();\n if (rr === undefined)\n continue;\n if (!rr.success)\n return rr;\n }\n};\n/**\n * Returns _true_ if `result` is an error\n * @param result\n * @returns\n */\nexport function resultIsError(result) {\n if (typeof result !== `object`)\n return false;\n return !result.success;\n}\n/**\n * Returns _true_ if `result` is OK and has a value\n * @param result\n * @returns\n */\nexport function resultIsOk(result) {\n if (typeof result !== `object`)\n return false;\n return result.success;\n}\n/**\n * Gets the result as an Error\n * @param result\n * @returns\n */\nexport function resultToError(result) {\n if (typeof result.error === `string`) {\n throw new Error(result.error, { cause: result.info });\n }\n if (result.error instanceof Error)\n throw result.error;\n return new Error(JSON.stringify(result.error), { cause: result.info });\n}\n/**\n * Unwraps the result, returning its value if OK.\n * If not, an exception is thrown.\n * @param result\n * @returns\n */\nexport function resultToValue(result) {\n if (resultIsOk(result)) {\n return result.value;\n }\n throw resultToError(result);\n}\n/**\n * Returns the error as a string.\n * @param result\n * @returns\n */\nexport function resultErrorToString(result) {\n if (result.error instanceof Error)\n return getErrorMessage(result.error);\n if (typeof result.error === `string`)\n return result.error;\n return JSON.stringify(result.error);\n}\n/**\n * Returns first failed result or final value.\n * @param results\n * @returns\n */\nexport const resultsCollate = (...results) => {\n let rr;\n for (const r of results) {\n rr = typeof r === `object` ? r : r();\n if (rr === undefined)\n continue;\n if (!rr.success)\n return rr;\n }\n if (!rr)\n throw new Error(`No results`);\n return rr;\n};\n/**\n * If `result` is an error, calls `callback`, passing the error.\n * Otherwise does nothing\n * @param result\n * @param callback\n */\nexport const resultWithFail = (result, callback) => {\n if (resultIsError(result)) {\n callback(result);\n }\n};\n","import { resultsCollate } from \"./result.js\";\n/**\n * Returns true if `x` is a power of two\n * @param x\n * @returns True if `x` is a power of two\n */\nexport const isPowerOfTwo = (x) => Math.log2(x) % 1 === 0;\n/**\n * Returns `fallback` if `v` is NaN, otherwise returns `v`.\n *\n * Throws if `v` is not a number type, null or undefined\n * @param v\n * @param fallback\n * @returns\n */\nexport const ifNaN = (v, fallback) => {\n if (typeof v !== `number`) {\n throw new TypeError(`v is not a number. Got: ${typeof v}`);\n }\n if (Number.isNaN(v))\n return fallback;\n return v;\n};\n/**\n * Parses `value` as an integer, returning it if it meets the `range` criteria.\n * If not, `defaultValue` is returned.\n *\n * ```js\n * const i = integerParse('10', 'positive'); // 10\n * const i = integerParse('10.5', 'positive'); // 10\n * const i = integerParse('0', 'nonZero', 100); // 100\n * ```\n *\n * NaN is returned if criteria does not match and no default is given\n * ```js\n * const i = integerParse('10', 'negative'); // NaN\n * ```\n *\n * @param value\n * @param range\n * @param defaultValue\n * @returns\n */\nexport const integerParse = (value, range = ``, defaultValue = Number.NaN) => {\n if (typeof value === `undefined`)\n return defaultValue;\n if (value === null)\n return defaultValue;\n try {\n const parsed = Number.parseInt(typeof value === `number` ? value.toString() : value);\n const r = integerTest(parsed, range, `parsed`);\n return r.success ? parsed : defaultValue;\n }\n catch {\n return defaultValue;\n }\n};\n/**\n * Checks if `t` is not a number or within specified range.\n * Returns `[false, reason:string]` if invalid or `[true]` if valid.\n *\n * Alternatives: {@link integerTest} for additional integer check, {@link percentTest} for percentage-range.\n *\n * * (empty, default): must be a number type and not NaN.\n * * finite: must be a number, not NaN and not infinite\n * * positive: must be at least zero\n * * negative: must be zero or lower\n * * aboveZero: must be above zero\n * * belowZero: must be below zero\n * * percentage: must be within 0-1, inclusive\n * * nonZero: can be anything except zero\n * * bipolar: can be -1 to 1, inclusive\n * @param value Value to check\n * @param parameterName Name of parameter (for more helpful exception messages)\n * @param range Range to enforce\n * @returns\n */\nexport const numberTest = (value, range = ``, parameterName = `?`, info) => {\n if (value === null)\n return { success: false, error: `Parameter '${parameterName}' is null`, info };\n if (typeof value === `undefined`) {\n return { success: false, error: `Parameter '${parameterName}' is undefined`, info };\n }\n if (Number.isNaN(value)) {\n return { success: false, error: `Parameter '${parameterName}' is NaN`, info };\n }\n if (typeof value !== `number`) {\n return { success: false, error: `Parameter '${parameterName}' is not a number (${JSON.stringify(value)})`, info };\n }\n switch (range) {\n case `finite`: {\n if (!Number.isFinite(value)) {\n return { success: false, error: `Parameter '${parameterName} must be finite (Got: ${value})`, info };\n }\n break;\n }\n case `positive`: {\n if (value < 0) {\n return { success: false, error: `Parameter '${parameterName}' must be at least zero (${value})`, info };\n }\n break;\n }\n case `negative`: {\n if (value > 0) {\n return { success: false, error: `Parameter '${parameterName}' must be zero or lower (${value})`, info };\n }\n break;\n }\n case `aboveZero`: {\n if (value <= 0) {\n return {\n success: false, error: `Parameter '${parameterName}' must be above zero (${value})`, info\n };\n }\n break;\n }\n case `belowZero`: {\n if (value >= 0) {\n return { success: false, error: `Parameter '${parameterName}' must be below zero (${value})`, info };\n }\n break;\n }\n case `percentage`: {\n if (value > 1 || value < 0) {\n return {\n success: false, error: `Parameter '${parameterName}' must be in percentage range (0 to 1). (${value})`, info\n };\n }\n break;\n }\n case `nonZero`: {\n if (value === 0) {\n return { success: false, error: `Parameter '${parameterName}' must non-zero. (${value})`, info };\n }\n break;\n }\n case `bipolar`: {\n if (value > 1 || value < -1) {\n return { success: false, error: `Parameter '${parameterName}' must be in bipolar percentage range (-1 to 1). (${value})`, info };\n }\n break;\n }\n }\n return { success: true, value, info };\n};\n/**\n * Checks if `t` is not a number or within specified range.\n * Throws if invalid. Use {@link numberTest} to test without throwing.\n *\n* * (empty, default): must be a number type and not NaN.\n* * positive: must be at least zero\n* * negative: must be zero or lower\n* * aboveZero: must be above zero\n* * belowZero: must be below zero\n* * percentage: must be within 0-1, inclusive\n* * nonZero: can be anything except zero\n* * bipolar: can be -1 to 1, inclusive\n*\n * Alternatives: {@link integerTest} for additional integer check, {@link percentTest} for percentage-range.\n * @param value Value to test\n * @param range Range\n * @param parameterName Name of parameter\n */\n// export const throwNumberTest = (value?: unknown,\n// range: NumberGuardRange = ``,\n// parameterName = `?`) => {\n// throwFromResult(numberTest(value, range, parameterName));\n// }\n/**\n * Compares two numbers with a given number of decimal places\n * ```js\n * a: 10.123 b: 10.1 decimals: 1 = true\n * a: 10.123 b: 10.2 decimals: 0 = true\n * a: 10.123 b: 10.14 decimals: 1 = true\n * a: 10.123 b: 10.14 decimals: 2 = false\n * ``\n * @param a\n * @param b\n * @param decimals How many decimals to include\n * @returns\n */\nexport const numberDecimalTest = (a, b, decimals = 3) => {\n if (decimals === 0) {\n a = Math.floor(a);\n b = Math.floor(b);\n if (a === b)\n return { success: true, value: a };\n return { success: false, error: `A is not identical to B` };\n }\n const mult = Math.pow(10, decimals);\n const aa = Math.floor(a * mult);\n const bb = Math.floor(b * mult);\n if (aa !== bb)\n return { success: false, error: `A is not close enough to B. A: ${a} B: ${b} Decimals: ${decimals}` };\n return { success: true, value: a };\n};\n/**\n * Returns test of `value` being in the range of 0-1.\n * Equiv to `number(value, `percentage`);`\n *\n * This is the same as calling ```number(t, `percentage`)```\n * @param value Value to check\n * @param parameterName Param name for customising exception message\n * @returns\n */\nexport const percentTest = (value, parameterName = `?`, info) => numberTest(value, `percentage`, parameterName, info);\n// export const throwPercentTest = (value: number, parameterName = `?`) => {\n// throwFromResult(percentTest(value, parameterName));\n//}\n/**\n * Checks if `value` an integer and meets additional criteria.\n * See {@link numberTest} for guard details, or use that if integer checking is not required.\n *\n * Note:\n * * `bipolar` will mean -1, 0 or 1.\n * * positive: must be at least zero\n * * negative: must be zero or lower\n * * aboveZero: must be above zero\n * * belowZero: must be below zero\n * * percentage: must be within 0-1, inclusive\n * * nonZero: can be anything except zero\n * @param value Value to check\n * @param parameterName Param name for customising exception message\n * @param range Guard specifier.\n */\nexport const integerTest = (value, range = ``, parameterName = `?`) => {\n return resultsCollate(numberTest(value, range, parameterName), () => {\n if (!Number.isInteger(value)) {\n return { success: false, error: `Param '${parameterName}' is not an integer` };\n }\n return { success: true, value: value };\n });\n};\nexport const integerArrayTest = (numbers) => {\n for (const v of numbers) {\n if (Math.abs(v) % 1 !== 0)\n return { success: false, error: `Value is not an integer: ${v}` };\n }\n return { success: true, value: numbers };\n};\n/**\n * Returns _true_ if `value` is an integer in number or string form\n * @param value\n * @returns\n */\nexport const isInteger = (value) => {\n if (typeof value === `string`)\n value = Number.parseFloat(value);\n const r = integerTest(value);\n return r.success;\n};\n// export const throwIntegerTest = (value: number | undefined,\n// range: NumberGuardRange = ``,\n// parameterName = `?`) => {\n// throwFromResult(integerTest(value, range, parameterName));\n// }\nexport const numberInclusiveRangeTest = (value, min, max, parameterName = `?`) => {\n if (typeof value !== `number`) {\n return { success: false, error: `Param '${parameterName}' is not a number type. Got type: '${typeof value}' value: '${JSON.stringify(value)}'` };\n }\n if (Number.isNaN(value)) {\n return { success: false, error: `Param '${parameterName}' is not within range ${min}-${max}. Got: NaN` };\n }\n if (Number.isFinite(value)) {\n if (value < min) {\n return { success: false, error: `Param '${parameterName}' is below range ${min}-${max}. Got: ${value}` };\n }\n else if (value > max) {\n return { success: false, error: `Param '${parameterName}' is above range ${min}-${max}. Got: ${value}` };\n }\n return { success: true, value };\n }\n else {\n return { success: false, error: `Param '${parameterName}' is not within range ${min}-${max}. Got: infinite` };\n }\n};\n// export const throwNumberInclusiveRangeTest = (value: number | undefined, min: number, max: number, parameterName = `?`) => {\n// const r = numberInclusiveRangeTest(value, min, max, parameterName);\n// if (r[ 0 ]) return;\n// throw new Error(r[ 1 ]);\n// }\n","/**\n * Tests_if `value` is a plain object\n *\n * ```js\n * isPlainObject(`text`); // false\n * isPlainObject(document); // false\n * isPlainObject({ hello: `there` }); // true\n * ```\n * @param value\n * @returns\n */\nexport const testPlainObject = (value) => {\n if (typeof value !== `object` || value === null)\n return { success: false, error: `Value is null or not object type` };\n const prototype = Object.getPrototypeOf(value);\n const t = (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);\n if (t)\n return { success: true, value };\n return { success: false, error: `Fancy object` };\n};\n/**\n * Tests if `value` is primitive value (bigint,number,string or boolean) or plain object\n * @param value\n * @returns\n */\nexport const testPlainObjectOrPrimitive = (value) => {\n const t = typeof value;\n if (t === `symbol`)\n return { success: false, error: `Symbol type` };\n if (t === `function`)\n return { success: false, error: `Function type` };\n if (t === `bigint`)\n return { success: true, value: value };\n if (t === `number`)\n return { success: true, value: value };\n if (t === `string`)\n return { success: true, value: value };\n if (t === `boolean`)\n return { success: true, value: value };\n return testPlainObject(value);\n};\n","import { integerTest, resultThrow } from '@ixfx/guards';\nimport { intervalToMs } from '@ixfx/core';\n/**\n * Returns a {@link Continuously} that continually executes `callback` at `interval` rate.\n *\n * By default, first the sleep period happens and then the callback happens.\n *\n * Call `start` to begin/reset loop. The looping stops when `cancel` is called, or when `callback` returns _false_.\n *\n * @example\n * Animation loop\n * ```js\n * const draw = () => {\n * // Draw on canvas\n * }\n *\n * // Run draw() synchronised with monitor refresh rate via `window.requestAnimationFrame`\n * continuously(draw).start();\n * ```\n *\n * @example\n * With delay\n * ```js\n * const fn = () => {\n * // Runs after one minute\n * }\n * const c = continuously(fn, { mins: 1 } );\n * c.start(); // Runs `fn` every minute\n * ```\n *\n * @example\n * Control a 'continuously'\n * ```js\n * c.cancel(); // Stop the loop, cancelling any up-coming calls to `fn`\n * c.elapsedMs; // How many milliseconds have elapsed since start\n * c.ticks; // How many iterations of loop since start\n * c.interval; // Get/set speed of loop. Change kicks-in at next loop.\n * // Use .start() to reset to new interval immediately\n * ```\n *\n * Asynchronous callback functions are supported too:\n * ```js\n * continuously(async () => { ..});\n * ```\n *\n * The `callback` function can receive a few arguments:\n *\n * ```js\n * continuously( (ticks, elapsedMs) => {\n * // ticks: how many times loop has run\n * // elapsedMs: how long since last loop\n * }).start();\n * ```\n *\n * If the callback explicitly returns _false_, the loop will be cancelled.\n *\n * ```js\n * continuously(ticks => {\n * // Stop after 100 iterations\n * if (ticks > 100) return false;\n * }).start();\n * ```\n *\n * You can intercept the logic for calls to `start()` with `onStartCalled`. It can determine\n * whether the `start()` proceeds, if the loop is cancelled, or the whole thing disposed,\n * so it can't run any longer.\n *\n * ```js\n * continuously(callback, intervalMs, {\n * onStartCalled:(ticks, elapsedMs) => {\n * // Cancel the loop after 1000ms has elapsed\n * if (elapsedMs > 1000) return `cancel`;\n * }\n * }).start();\n * ```\n *\n * To run `callback` *before* the sleep happens, set `fireBeforeWait`:\n * ```js\n * continuously(callback, intervalMs, { fireBeforeWait: true });\n * ```\n * @param callback - Function to run. If it returns _false_, loop exits.\n * @param options - {@link ContinuouslyOpts ContinuouslyOpts}\n * @param interval - Speed of loop (default: 0)\n * @returns Instance to control looping.\n * @see Flow.timeout if you want to trigger something once.\n */\nexport const continuously = (callback, interval, options = {}) => {\n let intervalMs = intervalToMs(interval, 0);\n resultThrow(integerTest(intervalMs, `positive`, `interval`));\n const fireBeforeWait = options.fireBeforeWait ?? false;\n const onStartCalled = options.onStartCalled;\n const signal = options.signal;\n let disposed = false;\n let runState = `idle`;\n let startCount = 0;\n let startCountTotal = 0;\n let startedAt = performance.now();\n let intervalUsed = interval ?? 0;\n let cancelled = false;\n let currentTimer;\n const deschedule = () => {\n if (currentTimer === undefined)\n return;\n globalThis.clearTimeout(currentTimer);\n currentTimer = undefined;\n startCount = 0;\n startedAt = Number.NaN;\n };\n const schedule = (scheduledCallback) => {\n if (intervalMs === 0) {\n if (typeof requestAnimationFrame === `undefined`) {\n currentTimer = globalThis.setTimeout(scheduledCallback, 0);\n }\n else {\n currentTimer = undefined;\n requestAnimationFrame(scheduledCallback);\n }\n }\n else {\n currentTimer = globalThis.setTimeout(scheduledCallback, intervalMs);\n }\n };\n const cancel = () => {\n if (cancelled)\n return;\n cancelled = true;\n if (runState === `idle`)\n return; // No need to cancel\n runState = `idle`;\n deschedule();\n };\n const loop = async () => {\n if (signal?.aborted) {\n runState = `idle`;\n }\n if (runState === `idle`)\n return;\n runState = `running`;\n startCount++;\n startCountTotal++;\n const valueOrPromise = callback(startCount, performance.now() - startedAt);\n const value = typeof valueOrPromise === `object` ? (await valueOrPromise) : valueOrPromise;\n if (cancelled) {\n return;\n }\n runState = `scheduled`;\n // Didn't get a value, exit out\n if (value !== undefined && !value) {\n cancel();\n return;\n }\n if (cancelled)\n return; // has been cancelled\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n schedule(loop);\n };\n const start = () => {\n if (disposed)\n throw new Error(`Disposed`);\n cancelled = false;\n if (onStartCalled !== undefined) {\n // A function governs whether to allow .start() to go ahead\n const doWhat = onStartCalled(startCount, performance.now() - startedAt);\n switch (doWhat) {\n case `cancel`: {\n cancel();\n return;\n }\n case `reset`: {\n reset();\n return;\n }\n case `dispose`: {\n disposed = true;\n cancel();\n return;\n }\n // No default\n }\n }\n if (runState === `idle`) {\n // Start running\n startCount = 0;\n startedAt = performance.now();\n runState = `scheduled`;\n if (fireBeforeWait) {\n void loop(); // Exec first, then wait\n }\n else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n schedule(loop); // Wait first, then exec\n }\n } // else: already running, ignore\n };\n const reset = () => {\n if (disposed)\n throw new Error(`Disposed`);\n cancelled = false;\n startCount = 0;\n startedAt = Number.NaN;\n // Cancel scheduled iteration\n if (runState !== `idle`) {\n cancel();\n }\n start();\n };\n return {\n start,\n reset,\n cancel,\n get interval() {\n return intervalUsed;\n },\n get runState() {\n return runState;\n },\n get startCountTotal() {\n return startCountTotal;\n },\n get startCount() {\n return startCount;\n },\n set interval(interval) {\n const ms = intervalToMs(interval, 0);\n resultThrow(integerTest(ms, `positive`, `interval`));\n intervalMs = ms;\n intervalUsed = interval;\n },\n get isDisposed() {\n return disposed;\n },\n get elapsedMs() {\n return performance.now() - startedAt;\n },\n };\n};\n","//import { intervalToMs, type Interval } from './IntervalType.js';\n//import { elapsedMillisecondsAbsolute, relative } from './Timer.js';\n/**\n * Returns elapsed time since the initial call.\n *\n * ```js\n * // Record start\n * const elapsed = elapsedSince();\n *\n * // Get elapsed time in millis\n * // since Elapsed.since()\n * elapsed(); // Yields number\n * ```\n *\n * If you want to initialise a stopwatch, but not yet start it, consider:\n * ```js\n * // Init\n * let state = {\n * clicked: Stopwatch.infinity()\n * };\n *\n * state.click(); // Returns a giant value\n *\n * // Later, when click happens:\n * state = { click: elapsedSince() }\n * ```\n *\n * See also:\n * * {@link elapsedOnce} if you want to measure a single period, and stop it.\n * * {@link elapsedInterval} time _between_ calls\n * @returns\n */\nexport const elapsedSince = () => {\n const start = performance.now();\n return () => {\n return performance.now() - start;\n };\n};\n/**\n * Returns the interval between the start and each subsequent call.\n *\n * ```js\n * const interval = elapsedInterval();\n * interval(); // Time from elapsedInterval()\n * interval(); // Time since last interval() call\n * ```\n *\n * See also:\n * * {@link elapsedSince}: time since first call\n * * {@link elapsedOnce}: time between two events\n * @returns\n */\nexport const elapsedInterval = () => {\n let start = performance.now();\n return () => {\n const now = performance.now();\n const x = now - start;\n start = now;\n return x;\n };\n};\n/**\n * Returns elapsed time since initial call, however\n * unlike {@link elapsedSince}, timer stops when first invoked.\n *\n * ```js\n * const elapsed = elapsedOnce();\n * // ...do stuff\n * elapsed(); // Yields time since elapsedOnce() was called\n * // ...do more stuff\n * elapsed(); // Is still the same number as above\n * ```\n *\n * See also:\n * * {@link elapsedSince}: elapsed time\n * * {@link elapsedInterval}: time _between_ calls\n * @returns\n */\nexport const elapsedOnce = () => {\n const start = Date.now();\n let stoppedAt = 0;\n return () => {\n if (stoppedAt === 0) {\n stoppedAt = Date.now() - start;\n }\n return stoppedAt;\n };\n};\n/**\n * Returns a function that reports an 'infinite' elapsed time.\n * this can be useful as an initialiser for `elapsedSince` et al.\n *\n * ```js\n * // Init clicked to be an infinite time\n * let clicked = elapsedInfinity();\n *\n * document.addEventListener('click', () => {\n * // Now that click has happened, we can assign it properly\n * clicked = Stopwatch.since();\n * });\n * ```\n * @returns\n */\nexport const elapsedInfinity = () => {\n return () => {\n return Number.POSITIVE_INFINITY;\n };\n};\n","import { integerTest, resultThrow } from '@ixfx/guards';\n//export { string as random } from './random/String.js';\n//import { afterMatch, beforeAfterMatch, beforeMatch } from '../Text.js';\n/**\n * Returns chunks of `source`, broken up by `delimiter` (default '.').\n *\n * Whittles down from whole string to last token.\n *\n * If `delimiter` is not found, no results are yielded.\n *\n * ```js\n * stringSegmentsWholeToEnd(`a.b.c.d`);\n * // Yields:\n * // `a.b.c.d`\n * // `b.c.d`\n * // `c.d`\n * // `d`\n * ```\n * @param source\n * @param delimiter\n */\nexport function* stringSegmentsWholeToEnd(source, delimiter = `.`) {\n while (source.length > 0) {\n yield source;\n const trimmed = afterMatch(source, delimiter);\n if (trimmed === source) {\n // Delimiter not found\n break;\n }\n source = trimmed;\n }\n}\n/**\n * Returns chunks of `source`, broken up by `delimiter` (default '.').\n *\n * Starts with last token, builds to whole.\n *\n * If `delimiter` is not found, no results are yielded.\n *\n * ````js\n * stringSegmentsLastToWhole(`a.b.c.d`);\n * // Yields:\n * // `d`\n * // `c.d`\n * // `b.c.d`\n * // `a.b.c.d`\n * ```\n * @param source\n * @param delimiter\n */\nexport function* stringSegmentsLastToWhole(source, delimiter = `.`) {\n let accumulator = ``;\n const orig = source;\n while (source.length > 0) {\n const ba = beforeAfterMatch(source, delimiter, { fromEnd: true, ifNoMatch: `original` });\n if (ba[0] === ba[1] && ba[1] === source) {\n // Delimiter not found\n break;\n }\n const v = ba[1] + accumulator;\n yield v;\n accumulator = delimiter + v;\n source = ba[0];\n }\n yield orig;\n}\n/**\n * Returns chunks of `source`, broken up by `delimiter` (default '.').\n *\n * We start with the first token and build up until end.\n *\n * If `delimiter` is not found, no results are yielded.\n *\n * ```js\n * stringSegmentsFirstToWhole(`a.b.c.d`);\n * // Yields:\n * // `a`\n * // `a.b`\n * // `a.b.c`\n * // `a.b.c.d`\n * ```\n * @param source\n * @param delimiter\n */\nexport function* stringSegmentsFirstToWhole(source, delimiter = `.`) {\n let accumulator = ``;\n const orig = source;\n while (source.length > 0) {\n const ba = beforeAfterMatch(source, delimiter, { ifNoMatch: `original` });\n if (ba[0] === source && ba[1] === source)\n break;\n accumulator += ba[0];\n yield accumulator;\n accumulator += delimiter;\n source = ba[1];\n }\n yield orig;\n}\n/**\n * Returns chunks of `source`, broken up by `delimiter` (default '.').\n *\n * We start with whole string and whittle down to starting token.\n *\n * If `delimiter` is not found, no results are yielded.\n *\n * ```js\n * stringSegmentsWholeToFirst(`a.b.c.d`);\n * // Yields:\n * // `a.b.c.d`\n * // `a.b.c`,\n * // `a.b`,\n * // `a`,\n * ```\n * @param source\n * @param delimiter\n */\nexport function* stringSegmentsWholeToFirst(source, delimiter = `.`) {\n while (source.length > 0) {\n yield source;\n const b = beforeMatch(source, delimiter, { ifNoMatch: `original`, fromEnd: true });\n if (b === source)\n break;\n source = b;\n }\n}\n/**\n * Given a long string, abbreviates it with ...\n * ```js\n * abbreviate(`This is something`, 7); // `This is...`\n * ```\n *\n * If `source` is under `maxLength` the original is returned.\n * @param source\n * @param maxLength Maximum length. Defaults to 20\n * @returns\n */\nexport const abbreviate = (source, maxLength = 15) => {\n resultThrow(integerTest(maxLength, `aboveZero`, `maxLength`));\n if (typeof source !== `string`)\n throw new Error(`Parameter 'source' is not a string`);\n if (source.length > maxLength && source.length > 3) {\n if (maxLength > 15) {\n const chunk = Math.round((maxLength - 2) / 2);\n return source.slice(0, chunk) + `...` + source.slice(-chunk);\n }\n return source.slice(0, maxLength) + `...`;\n }\n return source;\n};\n/**\n * Uses JSON.toString() on `source`, but abbreviates result.\n * @param source Object to stringify\n * @param maxLength Default 20\n * @returns\n */\nexport const toStringAbbreviate = (source, maxLength = 20) => {\n if (source === undefined)\n return `(undefined)`;\n if (source === null)\n return `(null)`;\n return abbreviate(JSON.stringify(source), maxLength);\n};\n/**\n * Returns source text that is between `start` and `end` match strings. Returns _undefined_ if start/end is not found.\n *\n * ```js\n * // Yields ` orange `;\n * between(`apple orange melon`, `apple`, `melon`);\n * ```\n * @param source Source text\n * @param start Start match\n * @param end If undefined, the `start` string will be looked for\n * @param lastEndMatch If true, looks for the last match of `end` (default). If false, looks for the first match.\n * @returns\n */\nexport const between = (source, start, end, lastEndMatch = true) => {\n // ✔ Unit tested\n const startPos = source.indexOf(start);\n if (startPos < 0)\n return;\n if (typeof end === `undefined`)\n end = start;\n const endPos = lastEndMatch\n ? source.lastIndexOf(end)\n : source.indexOf(end, startPos + 1);\n if (endPos < 0)\n return;\n return source.slice(startPos + 1, endPos);\n};\n/**\n * Like {@link between}, but also returns the source string without the start/end match and what's between.\n * ```js\n * const [src,between] = betweenChomp('hello [there] friend', '[', ']');\n * // src: 'hello friend'\n * // between: 'there'\n * ```\n * @param source\n * @param start\n * @param end\n * @param lastEndMatch\n * @returns\n */\nexport const betweenChomp = (source, start, end, lastEndMatch = true) => {\n // ✔ Unit tested\n if (typeof source !== `string`)\n throw new Error(`Parameter 'source' is not a string`);\n if (typeof start !== `string`)\n throw new Error(`Parameter 'start' is not a string`);\n if (end !== undefined && typeof end !== `string`)\n throw new Error(`Parameter 'end' is not a string`);\n const startPos = source.indexOf(start);\n if (startPos < 0)\n return [source, undefined];\n if (typeof end === `undefined`)\n end = start;\n const endPos = lastEndMatch\n ? source.lastIndexOf(end)\n : source.indexOf(end, startPos + 1);\n if (endPos < 0)\n return [source, undefined];\n const between = source.slice(startPos + 1, endPos);\n const sourceResult = source.slice(0, startPos) + source.slice(endPos + 1);\n return [sourceResult, between];\n};\n/**\n * Returns first position of the given character code, or -1 if not found.\n * @param source Source string\n * @param code Code to seek\n * @param start Start index, 0 by default\n * @param end End index (inclusive), source.length-1 by default\n * @returns Found position, or -1 if not found\n */\nexport const indexOfCharCode = (source, code, start = 0, end = source.length - 1) => {\n for (let index = start; index <= end; index++) {\n if (source.codePointAt(index) === code)\n return index;\n }\n return -1;\n};\n/**\n * Returns `source` with a given number of characters removed from start position.\n *\n * ```js\n * // Remove three characters starting at position 1\n * omitChars(`hello there`, 1, 3); // ie. removes 'ell'\n * // Yields: `ho there`\n * ```\n * @param source\n * @param removeStart Start point to remove\n * @param removeLength Number of characters to remove\n * @returns\n */\nexport const omitChars = (source, removeStart, removeLength) => source.slice(0, removeStart) +\n source.slice(removeStart + removeLength);\n/**\n * Splits a string into `length`-size chunks.\n *\n * If `length` is greater than the length of `source`, a single element array is returned with source.\n * The final array element may be smaller if we ran out of characters.\n *\n * ```js\n * splitByLength(`hello there`, 2);\n * // Yields:\n * // [`he`, `ll`, `o `, `th`, `er`, `e`]\n * ```\n * @param source Source string\n * @param length Length of each chunk\n * @returns\n */\nexport const splitByLength = (source, length) => {\n resultThrow(integerTest(length, `aboveZero`, `length`));\n if (source === null)\n throw new Error(`source parameter null`);\n if (typeof source !== `string`) {\n throw new TypeError(`source parameter not a string`);\n }\n // ✔ Unit tested\n const chunks = Math.ceil(source.length / length);\n const returnValue = [];\n let start = 0;\n for (let c = 0; c < chunks; c++) {\n returnValue.push(source.slice(start, start + length));\n start += length;\n }\n return returnValue;\n};\n// export const afterMatch = (\n// source: string,\n// match: string,\n// options: MatchOptions = {}\n// ): string => {\n// if (source === undefined) throw new Error(`Param 'source' is undefined`);\n// // ✔️ Unit tested\n// const startPos = options.startPos ?? undefined;\n// const fromEnd = options.fromEnd ?? false;\n// const m = fromEnd\n// ? source.lastIndexOf(match, startPos)\n// : source.indexOf(match, startPos);\n// if (m < 0) return source;\n// return source.slice(Math.max(0, m + match.length));\n// };\n/**\n * Returns all the text in `source` that precedes (and does not include) `match`. If not found, `source` is returned.\n *\n * See also: {@link beforeMatch}, {@link beforeAfterMatch}.\n *\n * ```js\n * afterMatch(`Hello. There`, `.`); // ' There'\n * afterMatch(`Hello, there', `,`); // 'Hello, there'\n * ```\n *\n * If `source` is _undefined_, an error is thrown.\n * @param source\n * @param match\n * @param options\n * @returns\n */\nexport const beforeMatch = (source, match, options = {}) => {\n const ba = beforeAfterMatch(source, match, options);\n return ba[0];\n};\n/**\n * Returns all the text in `source` that follows `match`. If not found, `source` is returned.\n *\n * See also: {@link beforeMatch}, {@link beforeAfterMatch}.\n *\n * ```js\n * afterMatch(`Hello. There`, `.`); // ' There'\n * afterMatch(`Hello, there', `,`); // 'Hello, there'\n * ```\n *\n * If `source` is _undefined_, an error is thrown.\n * @param source\n * @param match\n * @param options\n * @returns\n */\nexport const afterMatch = (source, match, options = {}) => {\n const ba = beforeAfterMatch(source, match, options);\n return ba[1];\n};\n/**\n * Returns the text that is before and after `match`.\n *\n * See also: {@link beforeMatch}, {@link afterMatch}.\n *\n * If `match` is at the end of start of `source`, after or before might be an empty string.\n * @param source\n * @param match\n * @param options\n * @returns\n */\nexport const beforeAfterMatch = (source, match, options = {}) => {\n if (source === undefined)\n throw new Error(`Param 'source' is undefined`);\n let fallback = options.fallback;\n const ifNoMatch = options.ifNoMatch ?? (fallback ? `fallback` : `original`);\n if (ifNoMatch === `original`)\n fallback = source;\n if (ifNoMatch === `fallback` && fallback === undefined)\n throw new Error(`Fallback must be provided`);\n const startPos = options.startPos ?? undefined;\n const fromEnd = options.fromEnd ?? false;\n const m = fromEnd\n ? source.lastIndexOf(match, startPos)\n : source.indexOf(match, startPos);\n if (m < 0 && ifNoMatch === `throw`)\n throw new Error(`Match '${match}' not found in source.`);\n if (m < 0 && ifNoMatch === `original`)\n return [source, source];\n if (m < 0 && ifNoMatch === `fallback`) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return [fallback, fallback];\n }\n return [\n source.slice(0, m),\n source.slice(Math.max(0, m + match.length))\n ];\n};\n/**\n * 'Unwraps' a string, removing one or more 'wrapper' strings that it starts and ends with.\n * Only removes when a matching end is found.\n * ```js\n * unwrap(\"'hello'\", \"'\"); // hello\n * // No mataching end 'a', so nothing happens\n * unwrap(\"apple\", \"a\"); // apple\n * unwrap(\"wow\", \"w\"); // o\n * unwrap(`\"'blah'\"`, '\"', \"'\"); // blah\n * ```\n * @param source\n * @param wrappers\n * @returns\n */\nexport const unwrap = (source, ...wrappers) => {\n let matched = false;\n do {\n matched = false;\n for (const w of wrappers) {\n if (source.startsWith(w) && source.endsWith(w)) {\n source = source.slice(w.length, source.length - w.length * 2 + 1);\n matched = true;\n }\n }\n } while (matched);\n return source;\n};\n/**\n * Calculates the span, defined in {@link Range} indexes, that includes `start` through to `end` character positions.\n *\n * After using {@link splitRanges} to split text, `lineSpan` is used to associate some text coordinates with ranges.\n *\n * @param ranges Ranges\n * @param start Start character position, in source text reference\n * @param end End character position, in source text reference\n * @returns Span\n */\nexport const lineSpan = (ranges, start, end) => {\n let s = -1;\n let endPos = -1;\n for (const [index, r] of ranges.entries()) {\n s = index;\n if (r.text.length === 0)\n continue;\n if (start < r.end) {\n break;\n }\n }\n for (let index = s; index < ranges.length; index++) {\n const r = ranges[index];\n endPos = index;\n if (end === r.end) {\n endPos = index + 1;\n break;\n }\n if (end < r.end) {\n break;\n }\n }\n return { length: endPos - s, start: s, end: endPos };\n};\n/**\n * Splits a source string into ranges:\n * ```js\n * const ranges = splitRanges(\"hello;there;fella\", \";\");\n * ```\n *\n * Each range consists of:\n * ```js\n * {\n * text: string - the text of range\n * start: number - start pos of range, wrt to source\n * end: number - end pos of range, wrt to source\n * index: number - index of range (starting at 0)\n * }\n * ```\n * @param source\n * @param split\n * @returns\n */\nexport const splitRanges = (source, split) => {\n let start = 0;\n let text = ``;\n const ranges = [];\n let index = 0;\n for (let index_ = 0; index_ < source.length; index_++) {\n if (source.indexOf(split, index_) === index_) {\n const end = index_;\n ranges.push({\n text,\n start,\n end,\n index,\n });\n start = end + 1;\n text = ``;\n index++;\n }\n else {\n text += source.charAt(index_);\n }\n }\n if (start < source.length) {\n ranges.push({ text, start, index, end: source.length });\n }\n return ranges;\n};\n/**\n * Counts the number of times one of `chars` appears at the front of\n * a string, contiguously.\n *\n * ```js\n * countCharsFromStart(` hi`, ` `); // 2\n * countCharsFromStart(`hi `, ` `); // 0\n * countCharsFromStart(` hi `, ` `); // 2\n * ```\n * @param source\n * @param chars\n * @returns\n */\nexport const countCharsFromStart = (source, ...chars) => {\n let counted = 0;\n for (let index = 0; index < source.length; index++) {\n if (chars.includes(source.charAt(index))) {\n counted++;\n }\n else {\n break;\n }\n }\n return counted;\n};\n/**\n * Returns _true_ if `source` starts and ends with `start` and `end`. Case-sensitive.\n * If _end_ is omitted, the the `start` value will be used.\n *\n * ```js\n * startsEnds(`This is a string`, `This`, `string`); // True\n * startsEnds(`This is a string`, `is`, `a`); // False\n * starsEnds(`test`, `t`); // True, starts and ends with 't'\n * ```\n * @param source String to search within\n * @param start Start\n * @param end End (if omitted, start will be looked for at end as well)\n * @returns True if source starts and ends with provided values.\n */\nexport const startsEnds = (source, start, end = start) => source.startsWith(start) && source.endsWith(end);\nexport const htmlEntities = (source) => source.replaceAll(/[&<>\\u00A0-\\u9999]/g, (index) => `&#${index.codePointAt(0)};`);\n/**\n * Simple wilcard matching. Use '*' in `pattern` to denote any number of characters.\n * ```js\n * // Must start with 'cat'\n * wildcard(`cat*`,`caterpillar`); // true\n * // Must end with 'cat'\n * wildcat(`*cat`, `bobcat`); // true\n * // 'cat' anywhere in string\n * wildcard(`*cat*`, `see cat run`); // true\n * ```\n * @param pattern\n * @returns\n */\nexport const wildcard = (pattern) => {\n // Based on source: https://stackoverflow.com/questions/26246601/wildcard-string-comparison-in-javascript\n // for this solution to work on any string, no matter what characters it has\n const escapeRegex = (value) => value.replaceAll(/([!$()*+./:=?[\\\\\\]^{|}])/g, `\\\\$1`);\n // \".\" => Find a single character, except newline or line terminator\n // \".*\" => Matches any string that contains zero or more characters\n pattern = pattern.split(`*`).map(m => escapeRegex(m)).join(`.*`);\n // \"^\" => Matches any string with the following at the beginning of it\n // \"$\" => Matches any string with that in front at the end of it\n pattern = `^` + pattern + `$`;\n // Create a regular expression object for matching string\n const regex = new RegExp(pattern);\n return (value) => {\n // Returns true if it finds a match, otherwse it returns false\n return regex.test(value);\n };\n};\n","import { toStringDefault } from \"./to-string.js\";\n/**\n * If input is a string, it is returned.\n * Otherwise, it returns the result of JSON.stringify() with fields ordered.\n *\n * This allows for more consistent comparisons when object field orders are different but values the same.\n * @param itemToMakeStringFor\n * @returns\n */\nexport const toStringOrdered = (itemToMakeStringFor) => {\n if (typeof itemToMakeStringFor === `string`)\n return itemToMakeStringFor;\n const allKeys = new Set();\n JSON.stringify(itemToMakeStringFor, (key, value) => (allKeys.add(key), value));\n return JSON.stringify(itemToMakeStringFor, [...allKeys].sort());\n};\n/**\n * Default comparer function is equiv to checking `a === b`.\n * Use {@link isEqualValueDefault} to compare by value, via comparing JSON string representation.\n */\nexport const isEqualDefault = (a, b) => a === b;\n/**\n * Comparer returns true if string representation of `a` and `b` are equal.\n * Use {@link isEqualDefault} to compare using === semantics\n * Uses `toStringDefault` to generate a string representation (via `JSON.stringify`).\n *\n * Returns _false_ if the ordering of fields is different, even though values are identical:\n * ```js\n * isEqualValueDefault({ a: 10, b: 20}, { b: 20, a: 10 }); // false\n * ```\n *\n * Use {@link isEqualValueIgnoreOrder} to ignore order (with an overhead of additional processing).\n * ```js\n * isEqualValueIgnoreOrder({ a: 10, b: 20}, { b: 20, a: 10 }); // true\n * ```\n *\n * Use {@link isEqualValuePartial} to partially match `b` against `a`.\n * @returns True if the contents of `a` and `b` are equal\n */\nexport const isEqualValueDefault = (a, b) => {\n // ✔ UNIT TESTED\n if (a === b)\n return true; // Object references are the same, or string values are the same\n return toStringDefault(a) === toStringDefault(b); // String representations are the same\n};\n/**\n * Returns _true_ if `a` contains the values of `b`. `a` may contain other values, but we\n * only check against what is in `b`. `a` and `b` must both be simple objects.\n *\n * ```js\n * const obj = {\n * name: `Elle`,\n * size: 100,\n * colour: {\n * red: 0.5,\n * green: 0.1,\n * blue: 0.2\n * }\n * }\n *\n * isEqualValuePartial(obj, { name: `Elle` }); // true\n * isEqualValuePartial(obj, { name: { colour: red: { 0.5, green: 0.1 }} }); // true\n *\n * isEqualValuePartial(obj, { name: `Ellen` }); // false\n * isEqualValuePartial(obj, { lastname: `Elle` }); // false\n * ```\n * @param a\n * @param b\n * @param fieldComparer\n * @returns\n */\nexport const isEqualValuePartial = (a, b, fieldComparer) => {\n if (typeof a !== `object`)\n throw new Error(`Param 'a' expected to be object`);\n if (typeof b !== `object`)\n throw new Error(`Param 'b' expected to be object`);\n if (Object.is(a, b))\n return true;\n const comparer = fieldComparer ?? isEqualValuePartial;\n for (const entryB of Object.entries(b)) {\n const valueOnAKeyFromB = a[entryB[0]];\n const valueB = entryB[1];\n if (typeof valueOnAKeyFromB === `object` && typeof valueB === `object`) {\n if (!comparer(valueOnAKeyFromB, valueB)) {\n return false;\n }\n }\n else {\n if (valueOnAKeyFromB !== valueB) {\n return false;\n }\n }\n }\n return true;\n};\n/**\n * Comparer returns true if string representation of `a` and `b` are equal, regardless of field ordering.\n * Uses `toStringOrdered` to generate a string representation (via JSON.stringify`).\n *\n * ```js\n * isEqualValueIgnoreOrder({ a: 10, b: 20}, { b: 20, a: 10 }); // true\n * isEqualValue({ a: 10, b: 20}, { b: 20, a: 10 }); // false, fields are different order\n * ```\n *\n * There is an overhead to ordering fields. Use {@link isEqualValueDefault} if it's not possible that field ordering will change.\n * @returns True if the contents of `a` and `b` are equal\n * @typeParam T - Type of objects being compared\n */\nexport const isEqualValueIgnoreOrder = (a, b) => {\n // ✔ UNIT TESTED\n if (a === b)\n return true; // Object references are the same, or string values are the same\n return toStringOrdered(a) === toStringOrdered(b); // String representations are the same\n};\n/**\n * Returns _true_ if Object.entries() is empty for `value`\n * @param value\n * @returns\n */\nexport const isEmptyEntries = (value) => [...Object.entries(value)].length === 0;\n/**\n * Returns _true_ if `a` and `b` are equal based on their JSON representations.\n * `path` is ignored.\n * @param a\n * @param b\n * @param path\n * @returns\n */\nexport const isEqualContextString = (a, b, _path) => {\n return JSON.stringify(a) === JSON.stringify(b);\n};\n","/**\n * Returns _true_ if `value` is an integer. Parses string input, but\n * all other data types return _false_.\n *\n * ```js\n * isInteger(1); // true\n * isInteger(1.1); // false\n * isInteger(`1`); // true\n * isInteger(`1.1`); // false\n * isInteger(true); // false\n * isInteger(false); // false\n * ```\n *\n * Returns _false_ for _undefined_, NaN, booleans and infinite numbers.\n * @param value\n * @returns\n */\nexport const isInteger = (value) => {\n if (value === undefined)\n return false;\n if (typeof value === `string`) {\n const v = Number.parseInt(value);\n if (Number.isNaN(v))\n return false;\n if (v.toString() === value.toString())\n return true;\n return false;\n }\n if (typeof value === `number`) {\n if (Number.isNaN(value))\n return false;\n if (!Number.isFinite(value))\n return false;\n if (Math.round(value) === value)\n return true;\n return false;\n }\n return false;\n};\n","/**\n * Returns _true_ if `value` is number, string, bigint or boolean.\n * Returns _false_ if `value` is an object, null, undefined\n *\n * Use {@link isPrimitiveOrObject} to also return true if `value` is an object.\n * @param value Value to check\n * @returns _True_ if value is number, string, bigint or boolean.\n */\nexport function isPrimitive(value) {\n if (typeof value === `number`)\n return true;\n if (typeof value === `string`)\n return true;\n if (typeof value === `bigint`)\n return true;\n if (typeof value === `boolean`)\n return true;\n return false;\n}\n/**\n * Returns _true_ if `value` is number, string, bigint, boolean or an object\n *\n * Use {@link isPrimitive} to not include objects.\n * @param value\n * @returns\n */\nexport function isPrimitiveOrObject(value) {\n if (isPrimitive(value))\n return true;\n if (typeof value === `object`)\n return true;\n return false;\n}\n","import { isEqualDefault } from \"./is-equal.js\";\n/**\n * Compares the values of two iterables, returning a list\n * of items they have in common and those unique in `a` or `b`.\n * Ignores ordering of values, and is NOT recursive.\n *\n * ```js\n * const a = ['apples', 'oranges', 'pears' ]\n * const b = ['pears', 'kiwis', 'bananas' ];\n *\n * const r = compareValuesShallow(a, b);\n * r.shared; // [ 'pears' ]\n * r.a; // [ 'apples', 'oranges' ]\n * r.b; // [ 'kiwis', 'bananas' ]\n * ```\n *\n * By default uses === semantics for comparison.\n * @param a\n * @param b\n * @param eq\n * @returns\n */\nexport const compareIterableValuesShallow = (a, b, eq = (isEqualDefault)) => {\n const shared = [];\n const aUnique = [];\n const bUnique = [];\n for (const elementOfA of a) {\n let seenInB = false;\n // Does B contain this thing from A?\n for (const elementOfB of b) {\n if (eq(elementOfA, elementOfB)) {\n seenInB = true;\n break;\n }\n }\n if (seenInB) {\n // Common in A & B\n shared.push(elementOfA);\n }\n else {\n // No, it's only found in A\n aUnique.push(elementOfA);\n }\n }\n for (const elementOfB of b) {\n let seenInA = false;\n // Does A contain this thing from B?\n for (const elementOfA of a) {\n if (eq(elementOfB, elementOfA)) {\n seenInA = true;\n }\n }\n if (!seenInA) {\n // No, something unique to B\n bUnique.push(elementOfB);\n }\n }\n // Are the two iterables the same?\n const isSame = aUnique.length === 0 && bUnique.length === 0;\n return {\n shared,\n isSame,\n a: aUnique,\n b: bUnique\n };\n};\n","import { numberTest } from '@ixfx/guards';\nimport { round } from './util/round.js';\n// export function intervalToMs(interval: Interval | undefined): number | undefined;\n// export function intervalToMs(\n// interval: Interval | undefined,\n// defaultNumber: number\n// ): number;\n/**\n * Return the millisecond value of an Interval.\n *\n * ```js\n * intervalToMs(100); // 100\n * intervalToMs({ millis: 100 }); // 100\n * ```\n *\n * Use `defaultNumber` to return a default in the case of\n * _undefined_ or invalid input.\n *\n * ```js\n * intervalToMs(undefined); // throws error\n * intervalToMs(undefined, 100); // 100\n * ```\n *\n * If no default is provided, an exception is thrown.\n * @param interval Interval\n * @param defaultNumber Default value if `interval` is _undefined_ or invalid\n * @returns Milliseconds\n */\nexport function intervalToMs(interval, defaultNumber) {\n if (isInterval(interval)) {\n // Number given, must be millis?\n if (typeof interval === `number`)\n return interval;\n let ms = interval.millis ?? 0;\n ms += (interval.hours ?? 0) * 60 * 60 * 1000;\n ms += (interval.mins ?? 0) * 60 * 1000;\n ms += (interval.secs ?? 0) * 1000;\n return ms;\n }\n else {\n if (typeof defaultNumber !== `undefined`)\n return defaultNumber;\n throw new Error(`Not a valid interval: ${JSON.stringify(interval)}`);\n }\n}\n/**\n * Returns _true_ if `interval` matches the {@link Interval} type.\n * @param interval\n * @returns _True_ if `interval` is an {@link Interval}.\n */\nexport function isInterval(interval) {\n if (typeof interval === `undefined`)\n return false;\n if (interval === null)\n return false;\n if (typeof interval === `number`) {\n if (Number.isNaN(interval))\n return false;\n if (!Number.isFinite(interval))\n return false;\n return true;\n }\n if (typeof interval !== `object`)\n return false;\n const hasMillis = `millis` in interval;\n const hasSecs = `secs` in interval;\n const hasMins = `mins` in interval;\n const hasHours = `hours` in interval;\n if (hasMillis && !numberTest(interval.millis).success)\n return false;\n if (hasSecs && !numberTest(interval.secs).success)\n return false;\n if (hasMins && !numberTest(interval.mins).success)\n return false;\n if (hasHours && !numberTest(interval.hours).success)\n return false;\n if (hasMillis || hasSecs || hasHours || hasMins)\n return true;\n return false;\n}\n/**\n * Returns a human-readable representation\n * of some elapsed milliseconds\n *\n * @example\n * ```js\n * elapsedToHumanString(10); // `10ms`\n * elapsedToHumanString(2000); // `2s`\n * elapsedToHumanString(65*1000); // `1mins`\n * ```\n * @param millisOrFunction Milliseconds as a number, {@link Interval} or function that resolve to a number\n * @param rounding Rounding (default: 2)\n * @returns\n */\nexport const elapsedToHumanString = (millisOrFunction, rounding = 2) => {\n let interval = 0;\n if (typeof millisOrFunction === `function`) {\n const intervalResult = millisOrFunction();\n return elapsedToHumanString(intervalResult);\n }\n else if (typeof millisOrFunction === `number`) {\n interval = millisOrFunction;\n }\n else if (typeof millisOrFunction === `object`) {\n interval = intervalToMs(interval);\n }\n let ms = intervalToMs(interval);\n if (typeof ms === `undefined`)\n return `(undefined)`;\n if (ms < 1000)\n return `${round(rounding, ms)}ms`;\n ms /= 1000;\n if (ms < 120)\n return `${ms.toFixed(1)}secs`;\n ms /= 60;\n if (ms < 60)\n return `${ms.toFixed(2)}mins`;\n ms /= 60;\n return `${ms.toFixed(2)}hrs`;\n};\n","/**\n * Returns a string representation of an error\n * @param ex\n * @returns\n */\nexport const getErrorMessage = (ex) => {\n if (typeof ex === `string`)\n return ex;\n if (ex instanceof Error) {\n return ex.message;\n }\n return ex;\n};\n","import { numberTest, resultThrow } from '@ixfx/guards';\nimport { intervalToMs } from './interval-type.js';\nif (typeof window === `undefined` || !(`requestAnimationFrame` in window)) {\n if (typeof window === `undefined`) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n globalThis.requestAnimationFrame = (callback) => {\n setTimeout(callback, 1);\n };\n }\n}\n/**\n * Returns after timeout period.\n *\n * @example In an async function\n * ```js\n * console.log(`Hello`);\n * await sleep(1000);\n * console.log(`There`); // Prints one second after\n * ```\n *\n * @example As a promise\n * ```js\n * console.log(`Hello`);\n * sleep({ millis: 1000 })\n * .then(() => console.log(`There`)); // Prints one second after\n * ```\n *\n * If a timeout of 0 is given, `requestAnimationFrame` is used instead of `setTimeout`.\n *\n * `Flow.delay()` and {@link sleep} are similar. `Flow.delay()` takes a parameter of what code to execute after the timeout, while `sleep()` just resolves after the timeout.\n *\n * A value can be provided, which is returned on awaking:\n * ```js\n * const v = await sleep({ seconds: 1, value: `hello`);\n * // v = `hello`\n * ```\n *\n * Provide an AbortSignal to cancel the sleep and throwing an exception\n * so code after the sleep doesn't happen.\n *\n * ```js\n * const ac = new AbortController();\n * setTimeout(() => { ac.abort(); }, 1000); // Abort after 1s\n *\n * // Sleep for 1min\n * await sleep({ minutes: 1, signal: ac.signal });\n * console.log(`Awake`); // This line doesn't get called because an exception is thrown when aborting\n * ```\n * @param optsOrMillis Milliseconds to sleep, or options\n * @return\n */\nexport const sleep = (optsOrMillis) => {\n const timeoutMs = intervalToMs(optsOrMillis, 1);\n const signal = optsOrMillis.signal;\n const value = optsOrMillis.value;\n resultThrow(numberTest(timeoutMs, `positive`, `timeoutMs`));\n if (timeoutMs === 0) {\n return new Promise((resolve) => requestAnimationFrame((_) => {\n resolve(value);\n }));\n }\n else {\n return new Promise((resolve, reject) => {\n const onAbortSignal = () => {\n clearTimeout(t);\n if (signal) {\n signal.removeEventListener(`abort`, onAbortSignal);\n reject(new Error(signal.reason));\n }\n else {\n reject(new Error(`Cancelled`));\n }\n };\n if (signal) {\n signal.addEventListener(`abort`, onAbortSignal);\n }\n const t = setTimeout(() => {\n signal?.removeEventListener(`abort`, onAbortSignal);\n if (signal?.aborted) {\n reject(new Error(signal.reason));\n return;\n }\n resolve(value);\n }, timeoutMs);\n });\n }\n};\n/**\n * Delays until `predicate` returns true.\n * Can be useful for synchronising with other async activities.\n * ```js\n * // Delay until 'count' reaches 5\n * await sleepWhile(() => count >= 5, 100);\n * ```\n * @param predicate\n * @param checkInterval\n */\nexport const sleepWhile = async (predicate, checkInterval = 100) => {\n while (predicate()) {\n await sleep(checkInterval);\n }\n};\n","import { compareIterableValuesShallow, isEqualDefault } from '@ixfx/core';\nimport { mapObjectKeys } from './map-object-keys.js';\n/**\n * Compares the keys of two objects, returning a set of those in\n * common, and those in either A or B exclusively.\n * ```js\n * const a = { colour: `red`, intensity: 5 };\n * const b = { colour: `pink`, size: 10 };\n * const c = compareObjectKeys(a, b);\n * // c.shared = [ `colour` ]\n * // c.a = [ `intensity` ]\n * // c.b = [ `size` ]\n * ```\n * @param a\n * @param b\n * @returns\n */\nexport const compareObjectKeys = (a, b) => {\n const c = compareIterableValuesShallow(Object.keys(a), Object.keys(b));\n return c;\n};\n/**\n * Returns the changed fields from A -> B. It's assumed that A and B have the same shape.\n * ie. returns an object that only consists of fields which have changed in B compared to A.\n *\n * ```js\n * const a = { msg: `hi`, v: 10 };\n *\n * changedDataFields(a, { msg: `hi`, v: 10 }); // {}\n * changedDataFields(a, { msg: `hi!!`, v: 10 }); // { msg: `hi!!` }\n * changedDataFields(a, { msg: `hi!!` }); // { msg: `hi!!`, v: undefined }\n * ```\n *\n * Under the hood, we use {@link compareResultToObject}(a, b, true). If B has additional or removed fields,\n * this is considered an error.\n *\n * If a field is an array, the whole array is returned, rather than a diff.\n * @param a\n * @param b\n */\nexport const changedObjectDataFields = (a, b) => {\n const r = compareObjectData(a, b, true);\n if (Object.entries(r.added).length > 0)\n throw new Error(`Shape of data has changed`);\n if (Object.entries(r.removed).length > 0)\n throw new Error(`Shape of data has changed`);\n const output = compareResultToObject(r, b);\n return output;\n};\nconst compareResultToObject = (r, b) => {\n const output = {};\n if (r.isArray) {\n return b;\n }\n for (const entry of Object.entries(r.changed)) {\n output[entry[0]] = entry[1];\n }\n for (const entry of Object.entries(r.added)) {\n output[entry[0]] = entry[1];\n }\n for (const childEntry of Object.entries(r.children)) {\n const childResult = childEntry[1];\n if (childResult.hasChanged) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n output[childEntry[0]] = compareResultToObject(childResult, b[childEntry[0]]);\n }\n }\n return output;\n};\n/**\n * Produces a {@link CompareChangeSet} between two arrays.\n *\n * @param a Earlier array to compare\n * @param b Later array to compare\n * @param eq Equality comparison for values\n * @returns Change set.\n */\nexport const compareArrays = (a, b, eq = (isEqualDefault)) => {\n if (!Array.isArray(a))\n throw new Error(`Param 'a' is not an array`);\n if (!Array.isArray(b))\n throw new Error(`Param 'b' is not an array`);\n const c = compareObjectData(a, b, false, eq);\n if (!c.isArray)\n throw new Error(`Change set does not have arrays as parameters`);\n const convert = (key) => {\n if (key.startsWith(`_`)) {\n return Number.parseInt(key.slice(1));\n }\n else\n throw new Error(`Unexpected key '${key}'`);\n };\n const cc = {\n ...c,\n added: mapObjectKeys(c.added, convert),\n changed: mapObjectKeys(c.changed, convert),\n removed: c.removed.map(v => convert(v)),\n summary: c.summary.map(value => {\n return [value[0], convert(value[1]), value[2]];\n })\n };\n return cc;\n};\n/**\n * Compares A to B. Assumes they are simple objects, essentially key-value pairs, where the\n * values are primitive values or other simple objects. It also works with arrays.\n *\n * Uses === equality semantics by default.\n * @param a\n * @param b\n */\nexport const compareObjectData = (a, b, assumeSameShape = false, eq = isEqualDefault) => {\n a ??= {};\n b ??= {};\n const entriesA = Object.entries(a);\n const entriesB = Object.entries(b);\n const scannedKeys = new Set();\n const changed = {};\n const added = {};\n const children = {};\n const removed = [];\n const isArray = Array.isArray(a);\n const summary = new Array();\n let hasChanged = false;\n // Look for existing entries of A that are modified\n for (const entry of entriesA) {\n const outputKey = isArray ? `_${entry[0]}` : entry[0];\n const aValue = entry[1];\n const bValue = b[entry[0]];\n scannedKeys.add(entry[0]);\n if (bValue === undefined) {\n // B does not have a key from A\n hasChanged = true;\n if (assumeSameShape && !isArray) {\n // If we're assuming it's the same shape, then _undefined_ is actually the value\n changed[outputKey] = bValue;\n summary.push([`mutate`, outputKey, bValue]);\n }\n else {\n // Key removed\n removed.push(outputKey);\n summary.push([`del`, outputKey, aValue]);\n }\n continue;\n }\n if (typeof aValue === `object`) {\n const r = compareObjectData(aValue, bValue, assumeSameShape, eq);\n if (r.hasChanged)\n hasChanged = true;\n children[outputKey] = r;\n const childSummary = r.summary.map(sum => { return [sum[0], outputKey + `.` + sum[1], sum[2]]; });\n summary.push(...childSummary);\n }\n else {\n if (!eq(aValue, bValue)) {\n changed[outputKey] = bValue;\n hasChanged = true;\n summary.push([`mutate`, outputKey, bValue]);\n }\n }\n }\n // Look for entries in B that weren't in A\n if (!assumeSameShape || isArray) {\n for (const entry of entriesB) {\n const key = isArray ? `_${entry[0]}` : entry[0];\n if (scannedKeys.has(entry[0]))\n continue;\n added[key] = entry[1];\n hasChanged = true;\n summary.push([`add`, key, entry[1]]);\n }\n }\n return {\n changed, added, removed, children, hasChanged, isArray, summary\n };\n};\n","import { recordEntriesDepthFirst } from \"@ixfx/core/records\";\nimport { isPrimitive, isInteger, isEqualContextString } from '@ixfx/core';\nimport { testPlainObjectOrPrimitive } from '@ixfx/guards';\nimport { compareObjectKeys } from './records/compare.js';\n/**\n * Get the entries for `target`.\n *\n * 'deep probe' uses alternative means to get entries of object, since `Object.entries`\n * can fail for some objects.\n * @param target Object to get entries from\n * @param deepProbe If true\n * @returns\n */\nconst getEntries = (target, deepProbe) => {\n if (target === undefined)\n throw new Error(`Param 'target' is undefined`);\n if (target === null)\n throw new Error(`Param 'target' is null`);\n if (typeof target !== `object`)\n throw new Error(`Param 'target' is not an object (got: ${typeof target})`);\n if (deepProbe) {\n const entries = [];\n for (const field in target) {\n const value = target[field];\n if (testPlainObjectOrPrimitive(value)) {\n entries.push([field, value]);\n }\n }\n return entries;\n }\n else {\n return Object.entries(target);\n }\n};\n/**\n * Scans object, producing a list of changed fields where B's value (newer) differs from A (older).\n *\n * Options:\n * - `deepEntries` (_false_): If _false_ Object.entries are used to scan the object. However this won't work for some objects, eg event args, thus _true_ is needed.\n * - `eq` (JSON.stringify): By-value comparison function\n * - `includeMissingFromA` (_false): If _true_ includes fields present on B but missing on A.\n * - `asPartial` (_false): If _true_, treats B as a partial update to B. This means that things missing from B are not considered removals.\n * @param a 'Old' value\n * @param b 'New' value\n * @param options Options for comparison\n * @returns\n */\nexport function* compareData(a, b, options = {}) {\n if (typeof a === `undefined`) {\n yield {\n path: options.pathPrefix ?? ``,\n value: b,\n state: `added`\n };\n return;\n }\n if (typeof b === `undefined`) {\n yield { path: options.pathPrefix ?? ``, previous: a, value: undefined, state: `removed` };\n return;\n }\n const asPartial = options.asPartial ?? false;\n const undefinedValueMeansRemoved = options.undefinedValueMeansRemoved ?? false;\n const pathPrefix = options.pathPrefix ?? ``;\n const deepEntries = options.deepEntries ?? false;\n const eq = options.eq ?? isEqualContextString;\n const includeMissingFromA = options.includeMissingFromA ?? false;\n const includeParents = options.includeParents ?? false;\n //console.log(`Pathed.compareData: a: ${ JSON.stringify(a) } b: ${ JSON.stringify(b) } prefix: ${ pathPrefix }`);\n if (isPrimitive(a) && isPrimitive(b)) {\n if (a !== b)\n yield { path: pathPrefix, value: b, previous: a, state: `change` };\n return;\n }\n if (isPrimitive(b)) {\n yield { path: pathPrefix, value: b, previous: a, state: `change` };\n return;\n }\n const entriesA = getEntries(a, deepEntries);\n const entriesAKeys = new Set();\n for (const [key, valueA] of entriesA) {\n entriesAKeys.add(key);\n const keyOfAInB = key in b;\n const valueOfKeyInB = b[key];\n //console.log(`Pathed.compareData Pathed.compareDataA key: ${ key } valueA: ${ JSON.stringify(valueA) }`);\n if (typeof valueA === `object` && valueA !== null) {\n if (keyOfAInB) {\n //console.log(`Pathed.compareData key ${ key } exists in B. value:`, valueB);\n if (valueOfKeyInB === undefined) {\n throw new Error(`Pathed.compareData Value for key ${key} is undefined`);\n }\n else {\n const sub = [...compareData(valueA, valueOfKeyInB, {\n ...options,\n pathPrefix: pathPrefix + key + `.`\n })];\n if (sub.length > 0) {\n for (const s of sub)\n yield s;\n if (includeParents) {\n yield { path: pathPrefix + key, value: b[key], previous: valueA, state: `change` };\n }\n }\n }\n }\n else {\n if (asPartial)\n continue;\n //throw new Error(`Key does not exist in B. Key: '${ key }'. B: ${ JSON.stringify(b) } A: ${ JSON.stringify(a) }`);\n yield { path: pathPrefix + key, value: undefined, previous: valueA, state: `removed` };\n }\n }\n else {\n const subPath = pathPrefix + key;\n if (keyOfAInB) {\n // B contains key from A\n if (valueOfKeyInB === undefined && undefinedValueMeansRemoved) {\n //console.error(`Pathed.compareData (2) value for B is undefined. key: ${ key }. B: ${ JSON.stringify(b) } A: ${ JSON.stringify(a) }`);\n yield { path: subPath, previous: valueA, value: undefined, state: `removed` };\n }\n else {\n if (!eq(valueA, valueOfKeyInB, subPath)) {\n //console.log(`Pathed.compareData value changed. A: ${ valueA } B: ${ valueB } subPath: ${ subPath }`)\n yield { path: subPath, previous: valueA, value: valueOfKeyInB, state: `change` };\n }\n }\n }\n else {\n // B does not contain key from A\n if (asPartial)\n continue; // Ignore\n yield { path: subPath, previous: valueA, value: undefined, state: `removed` };\n }\n }\n }\n if (includeMissingFromA) {\n const entriesB = getEntries(b, deepEntries);\n for (const [key, valueB] of entriesB) {\n if (entriesAKeys.has(key))\n continue;\n // Key in B that's not in A\n //console.log(`Pathed.compareDataB key: ${ key } value: ${ valueB }`);\n yield { path: pathPrefix + key, previous: undefined, value: valueB, state: `added` };\n }\n }\n}\n/**\n * Returns a copy of `source` with `changes` applied.\n * @param source\n * @param changes\n */\nexport const applyChanges = (source, changes) => {\n for (const change of changes) {\n source = updateByPath(source, change.path, change.value);\n }\n return source;\n};\n/**\n * Returns a copy of `target` object with a specified path changed to `value`.\n *\n * ```js\n * const a = {\n * message: `Hello`,\n * position: { x: 10, y: 20 }\n * }\n *\n * const a1 = updateByPath(a, `message`, `new message`);\n * // a1 = { message: `new message`, position: { x: 10, y: 20 }}\n * const a2 = updateByPath(a, `position.x`, 20);\n * // a2 = { message: `hello`, position: { x: 20, y: 20 }}\n * ```\n *\n * Paths can also be array indexes:\n * ```js\n * updateByPath([`a`,`b`,`c`], 2, `d`);\n * // Yields: [ `a`, `b`, `d` ]\n * ```\n *\n * By default, only existing array indexes can be updated. Use the `allowShapeChange` parameter\n * to allow setting arbitrary indexes.\n * ```js\n * // Throws because array index 3 is undefined\n * updateByPath([ `a`, `b`, `c` ], `3`, `d`);\n *\n * // With allowShapeChange flag\n * updateByPath([ `a`, `b`, `c` ], `3`, `d`, true);\n * // Returns: [ `a`, `b`, `c`, `d` ]\n * ```\n *\n * Throws an error if:\n * * `path` cannot be resolved (eg. `position.z` in the above example)\n * * `value` applied to `target` results in the object having a different shape (eg missing a field, field\n * changing type, or array index out of bounds). Use `allowShapeChange` to suppress this error.\n * * Path is undefined or not a string\n * * Target is undefined/null\n * @param target Object to update\n * @param path Path to set value\n * @param value Value to set\n * @param allowShapeChange By default _false_, throwing an error if an update change the shape of the original object.\n * @returns\n */\nexport const updateByPath = (target, path, value, allowShapeChange = false) => {\n if (path === undefined)\n throw new Error(`Parameter 'path' is undefined`);\n if (typeof path !== `string`)\n throw new Error(`Parameter 'path' should be a string. Got: ${typeof path}`);\n if (target === undefined)\n throw new Error(`Parameter 'target' is undefined`);\n if (target === null)\n throw new Error(`Parameter 'target' is null`);\n const split = path.split(`.`);\n const r = updateByPathImpl(target, split, value, allowShapeChange);\n return r;\n};\nconst updateByPathImpl = (o, split, value, allowShapeChange) => {\n if (split.length === 0) {\n //console.log(`Pathed.updateByPathImpl o: ${ JSON.stringify(o) } value: ${ JSON.stringify(value) }`);\n if (allowShapeChange)\n return value; // yolo\n if (Array.isArray(o) && !Array.isArray(value))\n throw new Error(`Expected array value, got: '${JSON.stringify(value)}'. Set allowShapeChange=true to ignore.`);\n if (!Array.isArray(o) && Array.isArray(value))\n throw new Error(`Unexpected array value, got: '${JSON.stringify(value)}'. Set allowShapeChange=true to ignore.`);\n if (typeof o !== typeof value)\n throw new Error(`Cannot reassign object type. (${typeof o} -> ${typeof value}). Set allowShapeChange=true to ignore.`);\n // Make sure new value has the same set of keys\n if (typeof o === `object` && !Array.isArray(o)) {\n const c = compareObjectKeys(o, value);\n if (c.a.length > 0) {\n throw new Error(`New value is missing key(s): ${c.a.join(`,`)}`);\n }\n if (c.b.length > 0) {\n throw new Error(`New value cannot add new key(s): ${c.b.join(`,`)}`);\n }\n }\n return value;\n }\n const start = split.shift();\n if (!start)\n return value;\n const isInt = isInteger(start);\n if (isInt && Array.isArray(o)) {\n const index = Number.parseInt(start);\n if (index >= o.length && !allowShapeChange)\n throw new Error(`Array index ${index.toString()} is outside of the existing length of ${o.length.toString()}. Use allowShapeChange=true to permit this.`);\n const copy = [...o];\n copy[index] = updateByPathImpl(copy[index], split, value, allowShapeChange);\n return copy;\n }\n else if (start in o) {\n const copy = { ...o };\n copy[start] = updateByPathImpl(copy[start], split, value, allowShapeChange);\n return copy;\n }\n else {\n throw new Error(`Path ${start} not found in data`);\n }\n};\n/**\n * Gets the data at `path` in `object`. Assumes '.' separates each segment of path.\n *\n * ```js\n * getField({ name: { first: `Thom`, last: `Yorke` }}, `name.first`); // { value: `Thom` success: true }\n * getField({ colours: [`red`, `green`, `blue` ]}, `colours.1`); // { value: `green` success: true }\n * ```\n *\n * Returns an error result with more details, eg `{ success: false, error: 'Path could not be found' }`\n *\n * Throws if:\n * * `path` is not a string or empty\n * * `object` is _undefined_ or null\n * @param object Object to query\n * @param path Path\n * @param separator Separator of chunks of path. Defaults to '.'\n * @returns\n */\nexport const getField = (object, path, separator = `.`) => {\n if (typeof path !== `string`)\n throw new Error(`Param 'path' ought to be a string. Got: '${typeof path}'`);\n if (path.length === 0)\n throw new Error(`Param string 'path' is empty`);\n if (object === undefined)\n throw new Error(`Param 'object' is undefined`);\n if (object === null)\n throw new Error(`Param 'object' is null`);\n const split = path.split(separator);\n const v = getFieldImpl(object, split, path);\n return v;\n};\nconst getFieldImpl = (object, split, position) => {\n if (object === undefined)\n return { success: false, error: `Param 'object' is undefined. Position: ${position}` };\n if (split.length === 0)\n return { success: false, error: `Path has been exhausted. position: ${position}` };\n const start = split.shift();\n if (!start)\n return { success: false, error: `Unexpected empty split path. Position: ${position}` };\n const isInt = isInteger(start);\n if (isInt && Array.isArray(object)) { //(arrayStart === 0 && arrayEnd === start.length - 1 && Array.isArray(o)) {\n const index = Number.parseInt(start); //start.slice(1, -1));\n //console.log(`getFieldImpl index: ${ index } value: ${ object[ index ] }`);\n if (typeof object[index] === `undefined`) {\n return { success: false, error: `Index '${index}' does not exist. Length: ${object.length}. Position: ${position}` };\n }\n if (split.length === 0) {\n return { value: object[index], success: true };\n }\n else {\n return getFieldImpl(object[index], split, split.join(`.`));\n }\n }\n else if (typeof object === `object` && start in object) {\n //console.log(`start in object. Start: ${ start } Len: ${ split.length } Object`, object);\n if (split.length === 0) {\n return { value: object[start], success: true };\n }\n else {\n return getFieldImpl(object[start], split, split.join(`.`));\n }\n }\n else {\n return { success: false, error: `Path '${start}' not found. Position: ${position}` };\n }\n};\n/**\n * Iterates 'paths' for all the fields on `o`\n * ```\n * const d = {\n * accel: { x: 1, y: 2, z: 3 },\n * gyro: { x: 4, y: 5, z: 6 }\n * };\n * const paths = [...getFieldPaths(d)];\n * // Yields [ `accel`, `gyro`, `accel.x`, `accel.y`,`accel.z`,`gyro.x`,`gyro.y`,`gyro.z` ]\n * ```\n *\n * Use {@link getField} to fetch data based on a path\n *\n * If object is _null_ or _undefined_, no results are returned.\n *\n * If `onlyLeaves` is _true_ (default: _false_), only 'leaf' nodes are included.\n * Leaf nodes are those that contain a primitive value.\n * ```js\n * const paths = getFieldPaths(d, true);\n * // Yields [ `accel.x`, `accel.y`,`accel.z`,`gyro.x`,`gyro.y`,`gyro.z` ]\n * ```\n *\n * @param object Object to get paths for.\n * @param onlyLeaves If true, only paths with a primitive value are returned.\n * @returns\n */\nexport function* getPaths(object, onlyLeaves = false) {\n if (object === undefined || object === null)\n return;\n const iter = recordEntriesDepthFirst(object);\n for (const c of iter) {\n if (c.nodeValue === undefined && onlyLeaves)\n continue;\n let path = c.name;\n if (c.ancestors.length > 0)\n path = c.ancestors.join(`.`) + `.` + path;\n yield path;\n }\n}\n;\n/**\n * Returns a representation of the object as a set of paths and data.\n * ```js\n * const o = { name: `hello`, size: 20, colour: { r:200, g:100, b:40 } }\n * const pd = [...getPathsAndData(o)];\n * // Yields:\n * // [\n * // { path: `name`, value: `hello` },\n * // { path: `size`, value: `20` },\n * // { path: `colour.r`, value: `200` },\n * // { path: `colour.g`, value: `100` },\n * // { path: `colour.b`, value: `40` }\n * //]\n * ```\n * @param o Object to get paths and data for\n * @param maxDepth Set maximum recursion depth. By default unlimited.\n * @param prefix Manually set a path prefix if it's necessary\n * @returns\n */\nexport function* getPathsAndData(o, onlyLeaves = false, maxDepth = Number.MAX_SAFE_INTEGER, prefix = ``) {\n if (o === null)\n return;\n if (o === undefined)\n return;\n yield* getPathsAndDataImpl(o, prefix, onlyLeaves, maxDepth);\n}\nfunction* getPathsAndDataImpl(o, prefix, onlyLeaves = false, maxDepth) {\n if (maxDepth <= 0)\n return;\n if (typeof o !== `object`)\n return;\n for (const entries of Object.entries(o)) {\n const sub = (prefix.length > 0 ? prefix + `.` : ``) + entries[0];\n const value = entries[1];\n const leaf = (typeof value !== `object`);\n if (onlyLeaves && leaf || !onlyLeaves) {\n yield { path: sub, value };\n }\n yield* getPathsAndDataImpl(value, sub, onlyLeaves, maxDepth - 1);\n }\n}\n","import { integerTest, resultToError, resultIsError, resultThrow } from '@ixfx/guards';\nimport {} from '@ixfx/core';\nimport { intervalToMs } from '@ixfx/core';\n/**\n * Returns a {@link Timeout} that can be triggered, cancelled and reset. Use {@link continuously} for interval-\n * based loops.\n *\n * Once `start()` is called, `callback` will be scheduled to execute after `interval`.\n * If `start()` is called again, the waiting period will be reset to `interval`.\n *\n * @example Essential functionality\n * ```js\n * const fn = () => {\n * console.log(`Executed`);\n * };\n * const t = timeout(fn, 60*1000);\n * t.start(); // After 1 minute `fn` will run, printing to the console\n * ```\n *\n * @example Control execution functionality\n * ```\n * t.cancel(); // Cancel it from running\n * t.start(); // Schedule again after 1 minute\n * t.start(30*1000); // Cancel that, and now scheduled after 30s\n *\n * // Get the current state of timeout\n * t.runState; // \"idle\", \"scheduled\" or \"running\"\n * ```\n *\n * Callback function receives any additional parameters passed in from start. This can be useful for passing through event data:\n *\n * @example\n * ```js\n * const t = timeout( (elapsedMs, ...args) => {\n * // args contains event data\n * }, 1000);\n * el.addEventListener(`click`, t.start);\n * ```\n *\n * Asynchronous callbacks can be used as well:\n * ```js\n * timeout(async () => {...}, 100);\n * ```\n *\n * If you don't expect to need to control the timeout, consider using {@link delay},\n * which can run a given function after a specified delay.\n * @param callback\n * @param interval\n * @returns {@link Timeout}\n */\nexport const timeout = (callback, interval) => {\n if (callback === undefined) {\n throw new Error(`callback parameter is undefined`);\n }\n const intervalMs = intervalToMs(interval);\n resultThrow(integerTest(intervalMs, `aboveZero`, `interval`));\n let timer;\n let startedAt = 0;\n let startCount = 0;\n let startCountTotal = 0;\n let state = `idle`;\n const clear = () => {\n startedAt = 0;\n globalThis.clearTimeout(timer);\n state = `idle`;\n };\n const start = async (altInterval = interval, args) => {\n const p = new Promise((resolve, reject) => {\n startedAt = performance.now();\n const altTimeoutMs = intervalToMs(altInterval);\n const it = integerTest(altTimeoutMs, `aboveZero`, `altTimeoutMs`);\n if (resultIsError(it)) {\n reject(resultToError(it));\n return;\n }\n switch (state) {\n case `scheduled`: {\n // Cancel other scheduled execution\n cancel();\n break;\n }\n case `running`: {\n //console.warn(`Timeout being rescheduled while task is already running`);\n break;\n }\n }\n state = `scheduled`;\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n timer = globalThis.setTimeout(async () => {\n if (state !== `scheduled`) {\n console.warn(`Timeout skipping execution since state is not 'scheduled'`);\n clear();\n return;\n }\n const args_ = args ?? [];\n startCount++;\n startCountTotal++;\n state = `running`;\n await callback(performance.now() - startedAt, ...args_);\n state = `idle`;\n clear();\n resolve();\n }, altTimeoutMs);\n });\n return p;\n };\n const cancel = () => {\n if (state === `idle`)\n return;\n clear();\n };\n return {\n start,\n cancel,\n get runState() {\n return state;\n },\n get startCount() {\n return startCount;\n },\n get startCountTotal() {\n return startCountTotal;\n }\n };\n};\n// const average = movingAverageLight();\n// const rm = rateMinimum({\n// interval: { secs: 1 },\n// whatToCall: (distance: number) => {\n// average(distance);\n// },\n// fallback() {\n// return 0;\n// }\n// })\n// document.addEventListener(`pointermove`, event => {\n// rm(event.movementX + event.movementY);\n// });\n","/**\n * Maintains a list of listeners to receive data\n *\n * ```js\n * const d = new DispatchList();\n *\n * // Eg: add a listener\n * d.add(v => {\n * // Handle a value\n * });\n *\n * // Eg. send a value to all listeners\n * d.notify(`some value`);\n * ```\n */\nexport class DispatchList {\n #handlers;\n #counter = 0;\n #id = Math.floor(Math.random() * 100);\n constructor() {\n this.#handlers = [];\n }\n /**\n * Returns _true_ if list is empty\n * @returns\n */\n isEmpty() {\n return this.#handlers.length === 0;\n }\n /**\n * Adds a handler. You get back an id which can be used\n * to remove the handler later.\n *\n * Handlers can be added with 'once' flag set to _true_. This will\n * automatically remove them after the first value is sent to them.\n * @param handler\n * @param options\n * @returns\n */\n add(handler, options = {}) {\n this.#counter++;\n const once = options.once ?? false;\n const wrap = {\n id: `${this.#id} - ${this.#counter}`,\n handler,\n once\n };\n this.#handlers.push(wrap);\n return wrap.id;\n }\n /**\n * Remove a handler by its id.\n * @param id\n * @returns _True_ if handler was removed, _false_ if not found.\n */\n remove(id) {\n const length = this.#handlers.length;\n this.#handlers = this.#handlers.filter(handler => handler.id !== id);\n return this.#handlers.length !== length;\n }\n /**\n * Emit a value to all handlers\n * @param value\n */\n notify(value) {\n for (const handler of this.#handlers) {\n handler.handler(value);\n if (handler.once) {\n this.remove(handler.id);\n }\n }\n }\n /**\n * Remove all handlers\n */\n clear() {\n this.#handlers = [];\n }\n}\n","/**\n * A default converter to string that uses JSON.stringify if its an object, or the thing itself if it's a string\n */\nexport const toStringDefault = (itemToMakeStringFor) => typeof itemToMakeStringFor === `string`\n ? itemToMakeStringFor\n : JSON.stringify(itemToMakeStringFor);\n","import { isEqualDefault } from \"./util/is-equal.js\";\nimport { toStringDefault } from \"./util/to-string.js\";\n//import { additionalValues } from \"../iterables/sync/AdditionalValues.js\";\n/**\n * Combines the values of one or more arrays, removing duplicates.\n * ```js\n * const v = Arrays.uniqueDeep([ [1, 2, 3, 4], [ 3, 4, 5, 6] ]);\n * // [ 1, 2, 3, 4, 5, 6]\n * ```\n *\n * A single array can be provided as well:\n * ```js\n * const v = Arrays.uniqueDeep([ 1, 2, 3, 1, 2, 3 ]);\n * // [ 1, 2, 3 ]\n * ```\n *\n * By default uses Javascript's default equality checking\n *\n * See also:\n * * {@link intersection}: Overlap between two arrays\n * * Iterables.additionalValues: Yield values from an iterable not present in the other\n * * {@link containsDuplicateValues}: Returns true if array contains duplicates\n * @param arrays\n * @param comparer\n * @returns\n */\nexport const uniqueDeep = (arrays, comparer = (isEqualDefault)) => {\n const t = [];\n const contains = (v) => {\n for (const tValue of t) {\n if (comparer(tValue, v))\n return true;\n }\n return false;\n };\n const flattened = arrays.flat(10);\n for (const v of flattened) {\n if (!contains(v))\n t.push(v);\n }\n return t;\n};\n/**\n * Combines the values of one or more arrays, removing duplicates.\n * Compares based on a string representation of object. Uses a Set\n * to avoid unnecessary comparisons, perhaps faster than `uniqueDeep`.\n *\n * ```js\n * const v = Arrays.unique([ [1, 2, 3, 4], [ 3, 4, 5, 6] ]);\n * // [ 1, 2, 3, 4, 5, 6]\n * ```\n *\n * A single array can be provided as well:\n * ```js\n * const v = Arrays.unique([ 1, 2, 3, 1, 2, 3 ]);\n * // [ 1, 2, 3 ]\n * ```\n *\n * By default uses JSON.toString() to compare values.\n *\n * See also:\n * * {@link intersection}: Overlap between two arrays\n * * Iterables.additionalValues: Yield values from an iterable not present in the other\n * * {@link containsDuplicateValues}: Returns true if array contains duplicates\n * @param arrays Array (or array of arrays) to examine\n * @param toString Function to convert values to a string for comparison purposes. By default uses JSON formatting.\n * @returns\n */\nexport const unique = (arrays, toString = toStringDefault) => {\n const matching = new Set();\n const t = [];\n const flattened = arrays.flat(10);\n for (const a of flattened) {\n const stringRepresentation = toString(a);\n if (matching.has(stringRepresentation))\n continue;\n matching.add(stringRepresentation);\n t.push(a);\n }\n return t;\n};\n","export class MapOfSimple {\n #store = new Map();\n /**\n * Gets a copy of the underlying array storing values at `key`, or an empty array if\n * key does not exist\n * @param key\n * @returns\n */\n get(key) {\n const arr = this.#store.get(key);\n if (!arr)\n return [];\n return [...arr];\n }\n /**\n * Returns the number of values stored under `key`\n * @param key\n * @returns\n */\n size(key) {\n const arr = this.#store.get(key);\n if (!arr)\n return 0;\n return arr.length;\n }\n /**\n * Iterate over all values contained under `key`\n * @param key\n * @returns\n */\n *iterateKey(key) {\n const arr = this.#store.get(key);\n if (!arr)\n return;\n yield* arr.values();\n }\n /**\n * Iterate all values, regardless of key\n */\n *iterateValues() {\n for (const key of this.#store.keys()) {\n yield* this.iterateKey(key);\n }\n }\n /**\n * Iterate all keys\n */\n *iterateKeys() {\n yield* this.#store.keys();\n }\n addKeyedValues(key, ...values) {\n let arr = this.#store.get(key);\n if (!arr) {\n arr = [];\n this.#store.set(key, arr);\n }\n arr.push(...values);\n }\n deleteKeyValue(key, value) {\n const arr = this.#store.get(key);\n if (!arr)\n return false;\n const arrCopy = arr.filter(v => v !== value);\n if (arrCopy.length === arr.length)\n return false;\n this.#store.set(key, arrCopy);\n return true;\n }\n clear() {\n this.#store.clear();\n }\n}\n","import { MapOfSimple } from \"./map-of.js\";\nexport class SimpleEventEmitter {\n #listeners = new MapOfSimple();\n #disposed = false;\n dispose() {\n if (this.#disposed)\n return;\n this.clearEventListeners();\n }\n get isDisposed() {\n return this.#disposed;\n }\n /**\n * Fire event\n * @param type Type of event\n * @param args Arguments for event\n * @returns\n */\n fireEvent(type, args) {\n if (this.#disposed)\n throw new Error(`Disposed`);\n //console.log(`Firing ${ type as string }. Listeners: ${ this.#listeners.size(type as string) }`);\n for (const l of this.#listeners.iterateKey(type)) {\n l(args, this);\n }\n }\n /**\n * Adds event listener.\n *\n * @throws Error if emitter is disposed\n * @typeParam K - Events\n * @param name Event name\n * @param listener Event handler\n */\n addEventListener(name, listener) {\n if (this.#disposed)\n throw new Error(`Disposed`);\n this.#listeners.addKeyedValues(name, listener);\n }\n /**\n * Remove event listener\n *\n * @param listener\n */\n removeEventListener(type, listener) {\n if (this.#disposed)\n return;\n // listener: Listener<Events>): void {\n this.#listeners.deleteKeyValue(type, listener);\n }\n /**\n * Clear all event listeners\n * @private\n */\n clearEventListeners() {\n if (this.#disposed)\n return;\n this.#listeners.clear();\n }\n}\n","export const isAsyncIterable = (v) => {\n if (typeof v !== `object`)\n return false;\n if (v === null)\n return false;\n return Symbol.asyncIterator in v;\n};\nexport const isIterable = (v) => {\n if (typeof v !== `object`)\n return false;\n if (v === null)\n return false;\n return Symbol.iterator in v;\n};\n","export const debug = (opts, message) => {\n opts.debug ? console.log(`queue:${message}`) : undefined;\n};\nexport const trimQueue = (opts, queue, toAdd) => {\n const potentialLength = queue.length + toAdd.length;\n const capacity = opts.capacity ?? potentialLength;\n const toRemove = potentialLength - capacity;\n const policy = opts.discardPolicy ?? `additions`;\n // debug(\n // opts,\n // `queueLen: ${queue.length} potentialLen: ${potentialLength} toRemove: ${toRemove} policy: ${policy} toAdd.length: ${toAdd.length} capacity: ${capacity}`\n // );\n // debug(opts, `to add: ${JSON.stringify(toAdd)}`);\n switch (policy) {\n // Only add what we can from toAdd\n case `additions`: {\n // debug(\n // opts,\n // `trimQueue:DiscardAdditions: queueLen: ${queue.length} slice: ${\n // potentialLength - capacity\n // } toAddLen: ${toAdd.length} nowFull: ${queue.length === opts.capacity}`\n // );\n if (queue.length === 0)\n return toAdd.slice(0, toAdd.length - toRemove);\n // eslint-disable-next-line unicorn/prefer-ternary\n if (queue.length === opts.capacity) {\n return queue; // Completely full\n }\n else {\n // Only add some from the new array (from the front)\n return [...queue, ...toAdd.slice(0, toRemove - 1)];\n }\n }\n // Remove from rear of queue (last index) before adding new things\n case `newer`: {\n if (toRemove >= queue.length) {\n // New items will completely flush out old\n //debug(opts, `slice start: ${toAdd.length - capacity}`);\n if (queue.length === 0) {\n // Special case when queue starts off empty\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return [...toAdd.slice(0, capacity - 1), toAdd.at(-1)];\n }\n return toAdd.slice(Math.max(0, toAdd.length - capacity), Math.min(toAdd.length, capacity) + 1);\n //debug(opts, `Final value: ${JSON.stringify(tmp)}`);\n //return tmp;\n }\n else {\n // Keep some of the old\n // const toAddFinal = toAdd.slice(\n // 0,\n // Math.min(toAdd.length, capacity - toRemove + 1)\n // );\n // Cap 5, queue 5, toAdd: 10.\n const countToAdd = Math.max(1, toAdd.length - queue.length);\n const toAddFinal = toAdd.slice(toAdd.length - countToAdd, toAdd.length);\n const toKeep = queue.slice(0, Math.min(queue.length, capacity - 1)); //toRemove);\n // debug(\n // opts,\n // `trimQueue: countToAdd: ${countToAdd} qLen: ${\n // queue.length\n // } capacity: ${capacity} toRemove: ${toRemove} keeping: ${JSON.stringify(\n // toKeep\n // )} from orig: ${JSON.stringify(queue)} toAddFinal: ${JSON.stringify(\n // toAddFinal\n // )}`\n // );\n const t = [...toKeep, ...toAddFinal];\n //debug(opts, `final: ${JSON.stringify(t)}`);\n return t;\n }\n }\n // Remove from the front of the queue (0 index). ie. older items are discarded\n case `older`: {\n // If queue is A, B and toAdd is C, D this yields A, B, C, D\n return [...queue, ...toAdd].slice(toRemove);\n }\n default: {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new Error(`Unknown overflow policy ${policy}`);\n }\n }\n};\n/**\n * Adds to the back of the queue (last array index)\n * Last item of `toAdd` will potentially be the new end of the queue (depending on capacity limit and overflow policy)\n * @typeParam V - Type of values\n * @param {QueueOpts} opts\n * @param {V[]} queue\n * @param {...V[]} toAdd\n * @returns {V[]}\n */\nexport const enqueue = (opts, queue, ...toAdd) => {\n if (opts === undefined)\n throw new Error(`opts parameter undefined`);\n const potentialLength = queue.length + toAdd.length;\n const overSize = opts.capacity && potentialLength > opts.capacity;\n const toReturn = overSize\n ? trimQueue(opts, queue, toAdd)\n : [...queue, ...toAdd];\n if (opts.capacity && toReturn.length !== opts.capacity && overSize) {\n throw new Error(`Bug! Expected return to be at capacity. Return len: ${toReturn.length} capacity: ${opts.capacity} opts: ${JSON.stringify(opts)}`);\n }\n if (!opts.capacity && toReturn.length !== potentialLength) {\n throw new Error(`Bug! Return length not expected. Return len: ${toReturn.length} expected: ${potentialLength} opts: ${JSON.stringify(opts)}`);\n }\n return toReturn;\n};\n// Remove from front of queue (0 index)\nexport const dequeue = (opts, queue) => {\n if (queue.length === 0)\n throw new Error(`Queue is empty`);\n return queue.slice(1);\n};\n/**\n * Returns front of queue (oldest item), or undefined if queue is empty\n *\n * @typeParam V - Type of values stored\n * @param {QueueOpts} opts\n * @param {V[]} queue\n * @returns {(V | undefined)}\n */\nexport const peek = (opts, queue) => queue[0];\nexport const isEmpty = (opts, queue) => queue.length === 0;\nexport const isFull = (opts, queue) => {\n if (opts.capacity) {\n return queue.length >= opts.capacity;\n }\n return false;\n};\n","import {} from './iqueue-mutable.js';\nimport { enqueue, peek, dequeue, isEmpty, isFull } from './queue-fns.js';\nimport {} from './queue-types.js';\nimport { isEqualDefault } from '@ixfx/core';\nimport { SimpleEventEmitter } from '@ixfx/events'; //'../../Events.js';\n/**\n * Mutable queue that fires events when manipulated.\n *\n * Queues are useful if you want to treat 'older' or 'newer'\n * items differently. _Enqueing_ adds items at the back of the queue, while\n * _dequeing_ removes items from the front (ie. the oldest).\n *\n * ```js\n * const q = Queues.mutable(); // Create\n * q.enqueue(`a`, `b`); // Add two strings\n * const front = q.dequeue(); // `a` is at the front of queue (oldest)\n * ```\n *\n * @example Cap size to 5 items, throwing away newest items already in queue.\n * ```js\n * const q = Queues.mutable({capacity: 5, discardPolicy: `newer`});\n * ```\n *\n * Events can be used to monitor data flows.\n * * 'enqueue': fires when item(s) are added\n * * 'dequeue': fires when an item is dequeued from front\n * * 'removed': fires when an item is dequeued, queue is cleared or .removeWhere is used to trim queue\n *\n * Each of the event handlers return the state of the queue as the 'finalData'\n * field.\n *\n * ```js\n * q.addEventListener(`enqueue`, e => {\n * // e.added, e.finalData\n * });\n * q.addEventListener(`removed`, e => {\n * // e.removed, e.finalData\n * });\n * q.addEventListener(`dequeue`, e=> {\n * // e.removed, e.finalData\n * })\n * ```\n * @typeParam V - Data type of items\n */\nexport class QueueMutable extends SimpleEventEmitter {\n options;\n data;\n eq;\n constructor(opts = {}, data = []) {\n super();\n if (opts === undefined)\n throw new Error(`opts parameter undefined`);\n this.options = opts;\n this.data = data;\n this.eq = opts.eq ?? isEqualDefault;\n }\n clear() {\n const copy = [...this.data];\n this.data = [];\n this.fireEvent(`removed`, { finalData: this.data, removed: copy });\n this.onClear();\n }\n /**\n * Called when all data is cleared\n */\n onClear() {\n }\n at(index) {\n if (index >= this.data.length)\n throw new Error(`Index outside bounds of queue`);\n const v = this.data.at(index);\n if (v === undefined)\n throw new Error(`Index appears to be outside range of queue`);\n return v;\n }\n enqueue(...toAdd) {\n this.data = enqueue(this.options, this.data, ...toAdd);\n const length = this.data.length;\n this.onEnqueue(this.data, toAdd);\n return length;\n }\n onEnqueue(result, attemptedToAdd) {\n this.fireEvent(`enqueue`, { added: attemptedToAdd, finalData: result });\n }\n dequeue() {\n const v = peek(this.options, this.data);\n if (v === undefined)\n return;\n /* eslint-disable-next-line functional/immutable-data */\n this.data = dequeue(this.options, this.data);\n this.fireEvent(`dequeue`, { removed: v, finalData: this.data });\n this.onRemoved([v], this.data);\n return v;\n }\n onRemoved(removed, finalData) {\n this.fireEvent(`removed`, { removed, finalData });\n }\n /**\n * Removes values that match `predicate`.\n * @param predicate\n * @returns Returns number of items removed.\n */\n removeWhere(predicate) {\n const countPre = this.data.length;\n const toRemove = this.data.filter(v => predicate(v));\n if (toRemove.length === 0)\n return 0;\n this.data = this.data.filter((element) => !predicate(element));\n this.onRemoved(toRemove, this.data);\n return countPre - this.data.length;\n }\n /**\n * Return a copy of the array\n * @returns\n */\n toArray() {\n return [...this.data];\n }\n get isEmpty() {\n return isEmpty(this.options, this.data);\n }\n get isFull() {\n return isFull(this.options, this.data);\n }\n get length() {\n return this.data.length;\n }\n get peek() {\n return peek(this.options, this.data);\n }\n}\n/**\n * Creates a new QueueMutable\n * @param options\n * @param startingItems\n * @returns\n */\nexport function mutable(options = {}, ...startingItems) {\n return new QueueMutable({ ...options }, [...startingItems]);\n}\n","import { intervalToMs, toStringDefault } from '@ixfx/core';\nimport { sleep } from '@ixfx/core';\nimport { isAsyncIterable, isIterable } from './guard.js';\n/**\n * Yield values from `array`, one at a time.\n * Use `interval` to add time between each item.\n * The first item is yielded without delay.\n *\n * @param array Array of values\n * @param interval Interval (defaults: 1ms)\n */\nexport async function* fromArray(array, interval = 1) {\n for (const v of array) {\n yield v;\n await sleep(interval);\n }\n}\n/**\n * Yield values from `iterable`, one at a time.\n * Use `interval` to add time between each item.\n * The first item is yielded without delay.\n * @param iterable Iterable or AsyncIterable\n * @param [interval=1] Interval to wait between yield\n */\nexport async function* fromIterable(iterable, interval = 1) {\n for await (const v of iterable) {\n yield v;\n await sleep(interval);\n }\n}\nexport async function* chunks(it, size) {\n // Source: https://surma.github.io/underdash/\n let buffer = [];\n for await (const v of it) {\n buffer.push(v);\n if (buffer.length === size) {\n yield buffer;\n buffer = [];\n }\n }\n if (buffer.length > 0)\n yield buffer;\n}\nexport async function* concat(...its) {\n // Source: https://surma.github.io/underdash/\n for await (const it of its)\n yield* it;\n}\nexport async function* dropWhile(it, f) {\n for await (const v of it) {\n if (!f(v)) {\n yield v;\n }\n }\n}\n/**\n * Loops over a generator until it finishes, calling `callback`.\n * Useful if you don't care about the value generator produces, just the number of loops.\n *\n * In this version, we do a `for await of` over `gen`, and also `await callback()`.\n\n * ```js\n * await until(count(5), () => {\n * // do something 5 times\n * });\n * ```\n *\n * If you want the value from the generator, use a `for of` loop as usual.\n *\n * If `callback` explicitly returns _false_, the generator is aborted.\n * @param it Generator to run\n * @param callback Code to call for each iteration\n */\n// eslint-disable-next-line @typescript-eslint/no-invalid-void-type\nexport const until = async (it, callback) => {\n for await (const _ of it) {\n const value = await callback();\n if (typeof value === `boolean` && !value)\n break;\n }\n};\n/**\n * This generator will repeat another generator up until some condition. This is the version\n * that can handle async generators.\n *\n * For example, {@link @ixfx/numbers.count} will count from 0..number and then finish:\n * ```js\n * import { count } from '@ixfx/numbers'\n * for (const v of count(5)) {\n * // v: 0, 1, 2, 3, 4\n * }\n * ```\n *\n * But what if we want to repeat the count? We have to provide a function to create the generator,\n * rather than using the generator directly, since it's \"one time use\"\n * ```js\n * for await (const v of repeat(() => count(5))) {\n * // v: 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, ...\n * // warning: never ends\n * }\n * ```\n *\n * Limiting the number of repeats can be done by passing in extra parameters\n * ```js\n * repeat(generator, { count: 5} ); // Iterate over `generator` five times\n * ```\n *\n * ```js\n * const ac = new AbortController();\n * repeat(generator, { signal: ac.signal }); // Pass in signal\n * ...\n * ac.abort(); // Trigger signal at some point\n * ```\n * @param genCreator\n * @param repeatsOrSignal\n */\nexport const repeat = async function* (genCreator, repeatsOrSignal) {\n const repeats = typeof repeatsOrSignal === `number` ? repeatsOrSignal : Number.POSITIVE_INFINITY;\n const signal = typeof repeatsOrSignal === `number` ? undefined : repeatsOrSignal;\n let count = repeats;\n while (true) {\n for await (const v of genCreator()) {\n yield v;\n if (signal?.aborted)\n break;\n }\n if (Number.isFinite(repeats)) {\n count--;\n if (count === 0)\n break;\n }\n if (signal?.aborted)\n break;\n }\n};\n/**\n * Returns true if items in two iterables are equal, as\n * determined by the `equality` function.\n * Order matters. It compares items at the same 'step' of each iterable.\n * @param it1\n * @param it2\n * @param equality\n * @returns\n */\nexport async function equals(it1, it2, equality) {\n // https://surma.github.io/underdash/\n const iit1 = it1[Symbol.asyncIterator](); // it1[ Symbol.iterator ]();\n const iit2 = it2[Symbol.asyncIterator]();\n while (true) {\n const index1 = await iit1.next();\n const index2 = await iit2.next();\n if (equality !== undefined) {\n if (!equality(index1.value, index2.value))\n return false;\n }\n else if (index1.value !== index2.value)\n return false;\n if (index1.done ?? index2.done)\n return index1.done && index2.done;\n }\n}\nexport async function every(it, f) {\n for await (const v of it) {\n const result = await f(v);\n if (!result)\n return false;\n }\n return true;\n}\nexport async function* fill(it, v) {\n // https://surma.github.io/underdash/\n for await (const _ of it)\n yield v;\n}\n/**\n * Filters an iterable, only yielding items which match `f`.\n *\n * ```js\n * filter([1, 2, 3, 4], e => e % 2 == 0);\n * returns [2, 4]\n * ```\n * @param it\n * @param f\n */\nexport async function* filter(it, f) {\n // https://surma.github.io/underdash/\n for await (const v of it) {\n if (!await f(v))\n continue;\n yield v;\n }\n}\nexport async function find(it, f) {\n // https://surma.github.io/underdash/\n for await (const v of it) {\n if (await f(v))\n return v;\n }\n}\nexport async function* flatten(it) {\n // https://surma.github.io/underdash/\n for await (const v of it) {\n if (typeof v === `object`) {\n if (Array.isArray(v)) {\n for (const vv of v)\n yield vv;\n }\n else if (isAsyncIterable(v)) {\n for await (const vv of v) {\n yield vv;\n }\n }\n else if (isIterable(v)) {\n for (const vv of v) {\n yield vv;\n }\n }\n }\n else {\n yield v;\n }\n }\n}\n/**\n * Iterates over an async iterable or array, calling `fn` for each value, with optional\n * interval between each loop. If the async `fn` returns _false_, iterator cancels.\n *\n * ```\n * import { forEach } from \"@ixfx/flow.js\"\n * // Prints items from array every second\n * await forEach([0,1,2,3], i => console.log(i), 1000);\n * ```\n *\n * ```\n * // Retry up to five times, with 5 seconds between each attempt\n * await forEach(count(5), i=> {\n * try {\n * await doSomething();\n * return false; // Succeeded, exit early\n * } catch (ex) {\n * console.log(ex);\n * return true; // Keep trying\n * }\n * }, 5000);\n * ```\n * @param iterator Iterable thing to loop over\n * @param fn Function to invoke on each item. If it returns _false_ loop ends.\n * @param options Options\n * @typeParam V Type of iterable\n */\nexport const forEach = async function (iterator, fn, options = {}) {\n const interval = options.interval;\n if (Array.isArray(iterator)) {\n // Handle array\n for (const x of iterator) {\n const r = await fn(x);\n if (typeof r === `boolean` && !r)\n break;\n if (interval)\n await sleep(interval);\n }\n }\n else {\n // Handle an async iterator\n for await (const x of iterator) {\n const r = await fn(x);\n if (typeof r === `boolean` && !r)\n break;\n if (interval)\n await sleep(interval);\n }\n }\n};\n// export async function forEach<V>(it: AsyncIterable<V>, f: (v: V) => void | boolean | Promise<boolean | void>) {\n// // https://surma.github.io/underdash/\n// for await (const v of it) {\n// const result = await f(v);\n// if (typeof result === `boolean` && !result) break;\n// }\n// }\n/**\n * Returns last value from an iterable, or _undefined_\n * if no values are generated\n * @param it\n */\nexport async function last(it, opts = {}) {\n const abort = opts.abort;\n let returnValue;\n for await (const value of it) {\n if (abort?.aborted)\n return undefined;\n returnValue = value;\n }\n return returnValue;\n}\n/**\n * Maps an iterable through function `f`\n * ```js\n * // For every input value, multiply it by itself\n * map([1, 2, 3], e => e*e)\n * // Yields: 1, 4, 9\n * ```\n *\n * It can also be used to transform types:\n * ```js\n * map([1, 2, 3], e => { value: e });\n * // Yields: { value: 1 }, { value: 2 }, { value: 3 }\n * ```\n * @param it\n * @param f\n */\nexport async function* map(it, f) {\n // https://surma.github.io/underdash/\n for await (const v of it) {\n yield f(v);\n }\n}\nexport async function* max(it, gt = ((a, b) => a > b)) {\n let max;\n for await (const v of it) {\n if (max === undefined) {\n max = v;\n yield (max);\n continue;\n }\n // If V is bigger than max, we have a new max\n if (gt(v, max)) {\n max = v;\n yield v;\n }\n }\n}\n/**\n * Returns the minimum seen of an iterable as it changes.\n * Streaming result: works with endless iterables.\n *\n * Note that `gt` function returns true if A is _greater_ than B, even\n * though we're looking for the minimum.\n *\n * ```js\n * // Rank objects based on 'v' value\n * const rank = (a,b) => a.v > b.v;\n * min([\n * {i:0,v:1},\n * {i:1,v:9},\n * {i:2,v:-2}\n * ], rank);\n * // Yields: {i:2, v:1}, {i:2,v:-2}\n * ```\n * @param it Iterable\n * @param gt Should return _true_ if `a` is greater than `b`.\n * @returns\n */\nexport async function* min(it, gt = (a, b) => a > b) {\n let min;\n for await (const v of it) {\n if (min === undefined) {\n min = v;\n yield min;\n continue;\n }\n // If min is bigger than V, V is the new min\n if (gt(min, v)) {\n min = v;\n yield v;\n }\n }\n return min;\n}\nexport async function reduce(it, f, start) {\n // https://surma.github.io/underdash/\n for await (const v of it)\n start = f(start, v);\n return start;\n}\n/**\n * Calls `callback` whenever the async generator produces a value.\n *\n * When using `asCallback`, call it with `await` to let generator\n * run its course before continuing:\n * ```js\n * await asCallback(tick({ interval:1000, loops:5 }), x => {\n * // Gets called 5 times, with 1000ms interval\n * });\n * console.log(`Hi`); // Prints after 5 seconds\n * ```\n *\n * Or if you skip the `await`, code continues and callback will still run:\n * ```js\n * asCallback(tick({ interval: 1000, loops: 5}), x => {\n * // Gets called 5 times, with 1000ms interval\n * });\n * console.log(`Hi`); // Prints immediately\n * ```\n * @param input\n * @param callback\n */\nexport async function asCallback(input, callback, onDone) {\n for await (const value of input) {\n callback(value);\n }\n if (onDone)\n onDone();\n}\nexport async function* slice(it, start = 0, end = Number.POSITIVE_INFINITY) {\n console.log(`Async slice start: ${start}`);\n // https://surma.github.io/underdash/\n const iit = it[Symbol.asyncIterator]();\n if (end < start)\n throw new Error(`Param 'end' should be more than 'start'`);\n for (; start > 0; start--, end--)\n await iit.next();\n for await (const v of it) {\n if (end-- > 0) {\n yield v;\n }\n else {\n break;\n }\n }\n}\n/**\n * Enumerates over an input iterable, with a delay between items.\n * @param it\n * @param delay\n */\nexport async function* withDelay(it, delay) {\n for (const v of it) {\n await sleep(delay);\n yield v;\n }\n}\n/***\n * Returns the next IteratorResult,\n * throwing an error if it does not happen\n * within `interval` (default: 1s)\n */\nexport async function nextWithTimeout(it, options) {\n const ms = intervalToMs(options, 1000);\n const value = await Promise.race([\n (async () => {\n await sleep({ millis: ms, signal: options.signal });\n return undefined;\n })(),\n (async () => {\n return await it.next();\n })()\n ]);\n if (value === undefined)\n throw new Error(`Timeout`);\n return value;\n}\nexport async function some(it, f) {\n // https://surma.github.io/underdash/\n for await (const v of it) {\n if (await f(v))\n return true;\n }\n return false;\n}\n// export async function* takeWhile<V>(\n// it: AsyncIterable<V>,\n// f: (v: V) => boolean\n// ) {\n// // https://surma.github.io/underdash/\n// for await (const v of it) {\n// if (!f(v)) return;\n// yield v;\n// }\n// }\n/**\n * Returns an array of values from an iterator.\n *\n * ```js\n * const data = await toArray(adsrIterable(opts, 10));\n * ```\n *\n * Note: If the iterator is infinite, be sure to provide limits via the options.\n * ```js\n * // Return maximum five items\n * const data = await toArray(iterable, { limit: 5 });\n * // Return results for a maximum of 5 seconds\n * const data = await toArray(iterable, { elapsed: 5000 });\n * ```\n * Note that limits are ORed, `toArray` will finish if either of them is true.\n *\n * @param it Asynchronous iterable\n * @param options Options when converting to array\n * @returns\n */\nexport async function toArray(it, options = {}) {\n // https://2ality.com/2016/10/asynchronous-iteration.html\n const result = [];\n const iterator = it[Symbol.asyncIterator]();\n const started = Date.now();\n const maxItems = options.limit ?? Number.POSITIVE_INFINITY;\n const whileFunction = options.while;\n const maxElapsed = intervalToMs(options.elapsed, Number.POSITIVE_INFINITY);\n while (result.length < maxItems && (Date.now() - started < maxElapsed)) {\n if (whileFunction) {\n if (!whileFunction(result.length))\n break;\n }\n const r = await iterator.next();\n if (r.done)\n break;\n //eslint-disable-next-line functional/immutable-data\n result.push(r.value);\n }\n return result;\n}\nexport async function* unique(iterable) {\n const buffer = [];\n const itera = Array.isArray(iterable) ? iterable : [iterable];\n for await (const it of itera) {\n for await (const v of it) {\n if (buffer.includes(v))\n continue;\n buffer.push(v);\n yield v;\n }\n }\n}\nexport async function* uniqueByValue(input, toString = toStringDefault, seen = new Set()) {\n for await (const v of input) {\n const key = toString(v);\n if (seen.has(key))\n continue;\n seen.add(key);\n yield v;\n }\n}\n/**\n * Returns unique items from iterables, given a particular key function\n * ```js\n * unique([{i:0,v:2},{i:1,v:3},{i:2,v:2}], e => e.v);\n * Yields: [{i:0,v:2},{i:1,v:3}]\n * @param it\n * @param f\n */\n// export async function* unique<V>(\n// it: AsyncIterable<V>,\n// f: (id: V) => V = (id) => id\n// ) {\n// // https://surma.github.io/underdash/\n// const buffer: Array<V> = [];\n// for await (const v of it) {\n// const fv = f(v);\n// if (buffer.includes(fv)) continue;\n// buffer.push(fv);\n// yield v;\n// }\n// }\n/**\n * Combine same-positioned items from several iterables\n * ```js\n * zip( [1, 2, 3], [4, 5, 6], [7, 8, 9] );\n * Yields: [ [1, 4, 7], [2, 5, 8], [3, 6, 9] ]\n * ```\n * @param its\n * @returns\n */\nexport async function* zip(...its) {\n // https://surma.github.io/underdash/\n const iits = its.map((it) => it[Symbol.asyncIterator]());\n while (true) {\n const vs = await Promise.all(iits.map((it) => it.next()));\n if (vs.some((v) => v.done))\n return;\n yield vs.map((v) => v.value);\n }\n}\n","import { defaultComparer } from './comparers.js';\nimport { isEqualDefault } from './is-equal.js';\nimport { toStringDefault, } from './to-string.js';\n/**\n * Gets the closest integer key to `target` in `data`.\n * * Requires map to have numbers as keys, not strings\n * * Math.round is used for rounding `target`.\n *\n * Examples:\n * ```js\n * // Assuming numeric keys 1, 2, 3, 4 exist:\n * getClosestIntegerKey(map, 3); // 3\n * getClosestIntegerKey(map, 3.1); // 3\n * getClosestIntegerKey(map, 3.5); // 4\n * getClosestIntegerKey(map, 3.6); // 4\n * getClosestIntegerKey(map, 100); // 4\n * getClosestIntegerKey(map, -100); // 1\n * ```\n * @param data Map\n * @param target Target value\n * @returns\n */\nexport const getClosestIntegerKey = (data, target) => {\n target = Math.round(target);\n if (data.has(target)) {\n return target;\n }\n else {\n let offset = 1;\n while (offset < 1000) {\n if (data.has(target - offset))\n return target - offset;\n else if (data.has(target + offset))\n return target + offset;\n offset++;\n }\n throw new Error(`Could not find target ${target.toString()}`);\n }\n};\n/**\n * Returns the first value in `data` that matches a key from `keys`.\n * ```js\n * // Iterate, yielding: `a.b.c.d`, `b.c.d`, `c.d`, `d`\n * const keys = Text.segmentsFromEnd(`a.b.c.d`);\n * // Gets first value that matches a key (starting from most precise)\n * const value = findBySomeKey(data, keys);\n * ```\n * @param data\n * @param keys\n * @returns\n */\nexport const findBySomeKey = (data, keys) => {\n for (const key of keys) {\n if (data.has(key))\n return data.get(key);\n }\n};\n/**\n * Returns true if map contains `value` under `key`, using `comparer` function. Use {@link hasAnyValue} if you don't care\n * what key value might be under.\n *\n * Having a comparer function is useful to check by value rather than object reference.\n *\n * @example Find key value based on string equality\n * ```js\n * hasKeyValue(map,`hello`, `samantha`, (a, b) => a === b);\n * ```\n * @param map Map to search\n * @param key Key to search\n * @param value Value to search\n * @param comparer Function to determine match. By default uses === comparison.\n * @returns True if key is found\n */\nexport const hasKeyValue = (map, key, value, comparer = isEqualDefault) => {\n if (!map.has(key))\n return false;\n const values = [...map.values()];\n return values.some((v) => comparer(v, value));\n};\n/**\n * Deletes all key/values from map where value matches `value`,\n * with optional comparer. Mutates map.\n *\n * ```js\n * // Compare fruits based on their colour property\n * const colourComparer = (a, b) => a.colour === b.colour;\n *\n * // Deletes all values where .colour = `red`\n * deleteByValueCompareMutate(map, { colour: `red` }, colourComparer);\n * ```\n * @param map\n * @param value\n * @param comparer Uses === equality by default. Use isEqualValueDefault to compare by value\n */\nexport const deleteByValueCompareMutate = (map, value, comparer = isEqualDefault) => {\n for (const entry of map.entries()) {\n if (comparer(entry[1], value)) {\n map.delete(entry[0]);\n }\n }\n};\n/**\n * Finds first entry by iterable value. Expects a map with an iterable as values.\n *\n * ```js\n * const map = new Map();\n * map.set('hello', 'a');\n * map.set('there', 'b');\n *\n * const entry = findEntryByPredicate(map, (value, key) => {\n * return (value === 'b');\n * });\n * // Entry is: ['there', 'b']\n * ```\n *\n * An alternative is {@link findEntryByValue} to search by value.\n * @param map Map to search\n * @param predicate Filter function returns true when there is a match of value\n * @returns Entry, or _undefined_ if `filter` function never returns _true_\n */\nexport const findEntryByPredicate = (map, predicate) => {\n for (const entry of map.entries()) {\n if (predicate(entry[1], entry[0]))\n return entry;\n }\n};\n/**\n * Finds first entry by value.\n *\n * ```js\n * const map = new Map();\n * map.set('hello', 'a');\n * map.set('there', 'b');\n *\n * const entry = findEntryByValue(map, 'b');\n * // Entry is: ['there', 'b']\n * ```\n *\n * Uses JS's === comparison by default. Consider using {@link isEqualValueDefault} to match by value.\n * An alternative is {@link findEntryByValue} to search by predicate function.\n * @param map Map to search\n * @param value Value to seek\n * @param isEqual Filter function which checks equality. Uses JS comparer by default.\n * @returns Entry, or _undefined_ if `value` not found.\n */\nexport const findEntryByValue = (map, value, isEqual = isEqualDefault) => {\n for (const entry of map.entries()) {\n if (isEqual(entry[1], value))\n return entry;\n }\n};\n/**\n * Adds items to a map only if their key doesn't already exist\n *\n * Uses provided {@link ToString} function to create keys for items. Item is only added if it doesn't already exist.\n * Thus the older item wins out, versus normal `Map.set` where the newest wins.\n *\n * Returns a copy of the input map.\n * @example\n * ```js\n * const map = new Map();\n * const peopleArray = [ _some people objects..._];\n * addKeepingExisting(map, p => p.name, ...peopleArray);\n * ```\n * @param set\n * @param hasher\n * @param values\n * @returns\n */\n// export const addKeepingExisting = <V>(\n// set: ReadonlyMap<string, V> | undefined,\n// hasher: ToString<V>,\n// ...values: readonly V[]\n// ) => {\n// const s = set === undefined ? new Map() : new Map(set);\n// for (const v of values) {\n// const hashResult = hasher(v);\n// if (s.has(hashResult)) continue;\n// s.set(hashResult, v);\n// }\n// return s;\n// };\n/**\n * Mutates `map`, adding each value to it using a\n * function to produce a key. Use {@link addValue} for an immutable version.\n * ```\n * const map = new Map();\n * addValueMutate(map, v=>v.name, { name:`Jane`, size:10 }, { name:`Bob`, size: 9 });\n * // Map consists of entries:\n * // [ `Jane`, { name:`Jane`, size:10 } ],\n * // [ `Bob` { name:`Bob`, size: 9 } ]\n * ```\n *\n * Uses {@link addValueMutator} under the hood.\n * @param map Map to modify. If _undefined_, a new map is created\n * @param hasher Function to generate a string key for a given object value\n * @param values Values to add\n * @param collisionPolicy What to do if the key already exists\n * @returns Map instance\n */\nexport const addValueMutate = (map, hasher, collisionPolicy, ...values) => {\n const m = map ?? new Map();\n const f = addValueMutator(m, hasher, collisionPolicy);\n f(...values);\n return m;\n};\n/**\n * Adds values to a map, returning a new, modified copy and leaving the original\n * intact.\n *\n * Use {@link addValueMutate} for a mutable\n * @param map Map to start with, or _undefined_ to automatically create a map\n * @param hasher Function to create keys for values\n * @param collisionPolicy What to do if a key already exists\n * @param values Values to add\n * @returns A new map containing values\n */\nexport const addValue = (map, hasher, collisionPolicy, ...values) => {\n const m = map === undefined ? new Map() : new Map(map);\n for (const v of values) {\n const hashResult = hasher(v);\n if (collisionPolicy !== `overwrite`) {\n if (m.has(hashResult)) {\n if (collisionPolicy === `throw`)\n throw new Error(`Key '${hashResult}' already in map`);\n if (collisionPolicy === `skip`)\n continue;\n }\n }\n m.set(hashResult, v);\n }\n return m;\n};\n/**\n * Returns a function that adds values to a map, using a hashing function to produce a key.\n * Use {@link addValueMutate} if you don't need a reusable function.\n *\n * ```js\n * const map = new Map(); // Create map\n * const mutate = addValueMutator(map, v=>v.name); // Create a mutator using default 'overwrite' policy\n * mutate( { name:`Bob`, size:10 }, { name: `Alice`, size: 2 }); // Add values to map\n * mutate( {name: `Bob`, size: 11 }); // Change the value stored under key `Bob`.\n * map.get(`Bob`); // { name: `Bob`, size: 11 }\n * ```\n *\n * The 'collision policy' determines what to do if the key already exists. The default behaviour\n * is to overwrite the key, just as Map.set would.\n * ```js\n * const map = new Map();\n * const mutate = addValueMutator(map, v=>v.name, `skip`);\n * mutate( { name:`Bob`,size:10 }, { name: `Alice`, size: 2 }); // Add values to map\n * mutate( { name:`Bob`, size: 20 }); // This value would be skipped because map already contains 'Bob'\n * map.get(`Bob`); // { name: `Bob`, size: 10 }\n * ```\n *\n * @param map Map to modify\n * @param hasher Hashing function to make a key for a value\n * @param collisionPolicy What to do if a value is already stored under a key\n * @returns Function\n */\nexport const addValueMutator = (map, hasher, collisionPolicy = `overwrite`) => {\n return (...values) => {\n for (const v of values) {\n const hashResult = hasher(v);\n if (collisionPolicy !== `overwrite`) {\n if (map.has(hashResult)) {\n if (collisionPolicy === `throw`)\n throw new Error(`Key '${hashResult}' already in map`);\n if (collisionPolicy === `skip`)\n continue;\n }\n }\n map.set(hashResult, v);\n }\n return map;\n };\n};\n/**\n * Returns a array of entries from a map, sorted by value.\n *\n * ```js\n * const m = new Map();\n * m.set(`4491`, { name: `Bob` });\n * m.set(`2319`, { name: `Alice` });\n *\n * // Compare by name\n * const comparer = (a, b) => defaultComparer(a.name, b.name);\n *\n * // Get sorted values\n * const sorted = Maps.sortByValue(m, comparer);\n * ```\n *\n * `sortByValue` takes a comparison function that should return -1, 0 or 1 to indicate order of `a` to `b`. If not provided, {@link Util.defaultComparer} is used.\n * @param map\n * @param comparer\n * @returns\n */\nexport const sortByValue = (map, comparer) => {\n const f = comparer ?? defaultComparer;\n return [...map.entries()].sort((a, b) => f(a[1], b[1]));\n};\n/**\n * Returns an array of entries from a map, sorted by a property of the value\n *\n * ```js\n * const m = new Map();\n * m.set(`4491`, { name: `Bob` });\n * m.set(`2319`, { name: `Alice` });\n * const sorted = sortByValueProperty(m, `name`);\n * ```\n * @param map Map to sort\n * @param property Property of value\n * @param compareFunction Comparer. If unspecified, uses a default.\n */\nexport const sortByValueProperty = (map, property, compareFunction) => {\n const cfn = typeof compareFunction === `undefined` ? defaultComparer : compareFunction;\n return [...map.entries()].sort((aE, bE) => {\n const a = aE[1];\n const b = bE[1];\n return cfn(a[property], b[property]);\n });\n};\n/**\n * Returns _true_ if any key contains `value`, based on the provided `comparer` function. Use {@link hasKeyValue}\n * if you only want to find a value under a certain key.\n *\n * Having a comparer function is useful to check by value rather than object reference.\n * @example Finds value where name is 'samantha', regardless of other properties\n * ```js\n * hasAnyValue(map, {name:`samantha`}, (a, b) => a.name === b.name);\n * ```\n *\n * Works by comparing `value` against all values contained in `map` for equality using the provided `comparer`.\n *\n * @param map Map to search\n * @param value Value to find\n * @param comparer Function that determines matching. Should return true if `a` and `b` are considered equal.\n * @returns True if value is found\n */\nexport const hasAnyValue = (map, value, comparer) => {\n const entries = [...map.entries()];\n return entries.some((kv) => comparer(kv[1], value));\n};\n/**\n * Returns values where `predicate` returns true.\n *\n * If you just want the first match, use `find`\n *\n * @example All people over thirty\n * ```js\n * // for-of loop\n * for (const v of filterValues(people, person => person.age > 30)) {\n *\n * }\n * // If you want an array\n * const overThirty = Array.from(filterValues(people, person => person.age > 30));\n * ```\n * @param map Map\n * @param predicate Filtering predicate\n * @returns Values that match predicate\n */\nexport function* filterValues(map, predicate) {\n for (const v of map.values()) {\n if (predicate(v))\n yield v;\n }\n}\n//export const filter = <V>(map:ReadonlyMap<string, V>, predicate:(v:V) => boolean):ReadonlyArray<V> => Array.from(map.values()).filter(predicate);\n/**\n * Copies data to an array\n * @param map\n * @returns\n */\nexport const toArray = (map) => [...map.values()];\n/**\n * Returns a Map from an iterable. By default throws an exception\n * if iterable contains duplicate values.\n *\n * ```js\n * const data = [\n * { fruit: `granny-smith`, family: `apple`, colour: `green` },\n * { fruit: `mango`, family: `stone-fruit`, colour: `orange` }\n * ];\n * const map = fromIterable(data, v => v.fruit);\n * map.get(`granny-smith`); // { fruit: `granny-smith`, family: `apple`, colour: `green` }\n * ```\n * @param data Input data\n * @param keyFunction Function which returns a string id. By default uses the JSON value of the object.\n * @param collisionPolicy By default, values with same key overwrite previous (`overwrite`)\n * @returns\n */\nexport const fromIterable = (data, keyFunction = (toStringDefault), collisionPolicy = `overwrite`) => {\n const m = new Map();\n for (const d of data) {\n const key = keyFunction(d);\n if (m.has(key)) {\n if (collisionPolicy === `throw`)\n throw new Error(`Key '${key}' is already used and new data will overwrite it. `);\n if (collisionPolicy === `skip`)\n continue;\n }\n m.set(key, d);\n }\n return m;\n};\n/**\n * Returns a Map from an object, or array of objects.\n * Assumes the top-level properties of the object is the key.\n *\n * ```js\n * const data = {\n * Sally: { name: `Sally`, colour: `red` },\n * Bob: { name: `Bob`, colour: `pink` }\n * };\n * const map = fromObject(data);\n * map.get(`Sally`); // { name: `Sally`, colour: `red` }\n * ```\n *\n * To add an object to an existing map, use {@link addObjectEntriesMutate}.\n * @param data\n * @returns\n */\nexport const fromObject = (data) => {\n const map = new Map();\n if (Array.isArray(data)) {\n for (const d of data)\n addObjectEntriesMutate(map, d);\n }\n else {\n addObjectEntriesMutate(map, data);\n }\n return map;\n};\n/**\n * Adds an object to an existing map, mutating it.\n * It assumes a structure where each top-level property is a key:\n *\n * ```js\n * const data = {\n * Sally: { colour: `red` },\n * Bob: { colour: `pink` }\n * };\n * const map = new Map();\n * addObjectEntriesMutate(map, data);\n *\n * map.get(`Sally`); // { name: `Sally`, colour: `red` }\n * ```\n *\n * To create a new map from an object, use {@link fromObject} instead.\n * @param map\n * @param data\n */\nexport const addObjectEntriesMutate = (map, data) => {\n const entries = Object.entries(data);\n for (const [key, value] of entries) {\n map.set(key, value);\n }\n};\n/**\n * Returns the first found value that matches `predicate` or _undefined_.\n * To get an entry see {@link findEntryByPredicate}\n *\n * Use {@link some} if you don't care about the value, just whether it appears.\n * Use {@link filter} to get all value(s) that match `predicate`.\n *\n * @example First person over thirty\n * ```js\n * const overThirty = findValue(people, person => person.age > 30);\n * ```\n * @param map Map to search\n * @param predicate Function that returns true for a matching value\n * @returns Found value or _undefined_\n */\nexport const findValue = (map, predicate) => [...map.values()].find(v => predicate(v));\n/**\n * Returns _true_ if `predicate` yields _true_ for any value in `map`.\n * Use {@link find} if you want the matched value.\n * ```js\n * const map = new Map();\n * map.set(`fruit`, `apple`);\n * map.set(`colour`, `red`);\n * Maps.some(map, v => v === `red`); // true\n * Maps.some(map, v => v === `orange`); // false\n * ```\n * @param map\n * @param predicate\n * @returns\n */\nexport const some = (map, predicate) => [...map.values()].some(v => predicate(v));\n/**\n * Converts a map to a simple object, transforming from type `T` to `K` as it does so. If no transforms are needed, use {@link toObject}.\n *\n * ```js\n * const map = new Map();\n * map.set(`name`, `Alice`);\n * map.set(`pet`, `dog`);\n *\n * const o = mapToObjectTransform(map, v => {\n * ...v,\n * registered: true\n * });\n *\n * // Yields: { name: `Alice`, pet: `dog`, registered: true }\n * ```\n *\n * If the goal is to create a new map with transformed values, use {@link transformMap}.\n * @param m\n * @param valueTransform\n * @typeParam T Value type of input map\n * @typeParam K Value type of destination map\n * @returns\n */\nexport const mapToObjectTransform = (m, valueTransform) => [...m].reduce((object, [key, value]) => {\n const t = valueTransform(value);\n object[key] = t;\n return object;\n}, {});\n/**\n * Zips together an array of keys and values into an object. Requires that\n * `keys` and `values` are the same length.\n *\n * @example\n * ```js\n * const o = zipKeyValue([`a`, `b`, `c`], [0, 1, 2])\n * Yields: { a: 0, b: 1, c: 2}\n *```\n * @param keys String keys\n * @param values Values\n * @typeParam V Type of values\n * @return Object with keys and values\n */\nexport const zipKeyValue = (keys, values) => {\n if (keys.length !== values.length) {\n throw new Error(`Keys and values arrays should be same length`);\n }\n return Object.fromEntries(keys.map((k, index) => [k, values[index]]));\n};\n//#region Functions by Kees C. Bakker\n// Functions by Kees C. Bakker\n// https://keestalkstech.com/2021/10/having-fun-grouping-arrays-into-maps-with-typescript/\n/**\n * Like `Array.map`, but for a Map. Transforms from Map<K,V> to Map<K,R>, returning as a new Map.\n *\n * @example\n * ```js\n * const mapOfStrings = new Map();\n * mapOfStrings.set(`a`, `10`);\n * mapOfStrings.get(`a`); // Yields `10` (a string)\n *\n * // Convert a map of string->string to string->number\n * const mapOfInts = transformMap(mapOfStrings, (value, key) => parseInt(value));\n *\n * mapOfInts.get(`a`); // Yields 10 (a proper number)\n * ```\n *\n * If you want to combine values into a single object, consider instead {@link mapToObjectTransform}.\n * @param source\n * @param transformer\n * @typeParam K Type of keys (generally a string)\n * @typeParam V Type of input map values\n * @typeParam R Type of output map values\n * @returns\n */\nexport const transformMap = (source, transformer) => new Map(Array.from(source, (v) => [v[0], transformer(v[1], v[0])]));\n/**\n * Converts a `Map` to a plain object, useful for serializing to JSON.\n * To convert back to a map use {@link fromObject}.\n *\n * @example\n * ```js\n * const map = new Map();\n * map.set(`Sally`, { name: `Sally`, colour: `red` });\n * map.set(`Bob`, { name: `Bob`, colour: `pink });\n *\n * const objects = Maps.toObject(map);\n * // Yields: {\n * // Sally: { name: `Sally`, colour: `red` },\n * // Bob: { name: `Bob`, colour: `pink` }\n * // }\n * ```\n * @param m\n * @returns\n */\nexport const toObject = (m) => [...m].reduce((object, [key, value]) => {\n object[key] = value;\n return object;\n}, {});\n/**\n * Converts Map to Array with a provided `transformer` function. Useful for plucking out certain properties\n * from contained values and for creating a new map based on transformed values from an input map.\n *\n * @example Get an array of ages from a map of Person objects\n * ```js\n * const person = { age: 29, name: `John`};\n * map.set(person.name, person);\n *\n * const ages = mapToArray(map, (key, person) => person.age);\n * // [29, ...]\n * ```\n *\n * In the above example, the `transformer` function returns a number, but it could\n * just as well return a transformed version of the input:\n *\n * ```js\n * // Return with random heights and uppercased name\n * mapToArray(map, (key, person) => ({\n * ...person,\n * height: Math.random(),\n * name: person.name.toUpperCase();\n * }))\n * // Yields:\n * // [{height: 0.12, age: 29, name: \"JOHN\"}, ...]\n * ```\n * @param m\n * @param transformer A function that takes a key and item, returning a new item.\n * @returns\n */\nexport const mapToArray = (m, transformer) => [...m.entries()].map((x) => transformer(x[0], x[1]));\n/**\n * Merges maps left to right, using the provided\n * `reconcile` function to choose a winner when keys overlap.\n *\n * There's also {@link Data.Arrays.mergeByKey Arrays.mergeByKey} if you don't already have a map.\n *\n * For example, if we have the map A:\n * 1 => `A-1`, 2 => `A-2`, 3 => `A-3`\n *\n * And map B:\n * 1 => `B-1`, 2 => `B-2`, 4 => `B-4`\n *\n * If they are merged with the reconile function:\n * ```js\n * const reconcile = (a, b) => b.replace(`-`, `!`);\n * const output = mergeByKey(reconcile, mapA, mapB);\n * ```\n *\n * The final result will be:\n *\n * 1 => `B!1`, 2 => `B!2`, 3 => `A-3`, 4 => `B-4`\n *\n * In this toy example, it's obvious how the reconciler transforms\n * data where the keys overlap. For the keys that do not overlap -\n * 3 and 4 in this example - they are copied unaltered.\n *\n * A practical use for `mergeByKey` has been in smoothing keypoints\n * from a TensorFlow pose. In this case, we want to smooth new keypoints\n * with older keypoints. But if a keypoint is not present, for it to be\n * passed through.\n *\n * @param reconcile\n * @param maps\n */\nexport const mergeByKey = (reconcile, ...maps) => {\n const result = new Map();\n for (const m of maps) {\n for (const [mk, mv] of m) {\n let v = result.get(mk);\n v = v ? reconcile(v, mv) : mv;\n result.set(mk, v);\n }\n }\n return result;\n};\n/**\n * @inheritDoc getOrGenerate\n * @param map\n * @param fn\n * @returns\n */\nexport const getOrGenerateSync = (map, fn) => (key, args) => {\n let value = map.get(key);\n if (value !== undefined)\n return value;\n value = fn(key, args);\n map.set(key, value);\n return value;\n};\n/**\n * Returns a function that fetches a value from a map, or generates and sets it if not present.\n * Undefined is never returned, because if `fn` yields that, an error is thrown.\n *\n * See {@link getOrGenerateSync} for a synchronous version.\n *\n * ```\n * const m = getOrGenerate(new Map(), (key) => {\n * return key.toUppercase();\n * });\n *\n * // Not contained in map, so it will run the uppercase function,\n * // setting the value to the key 'hello'.\n * const v = await m(`hello`); // Yields 'HELLO'\n * const v1 = await m(`hello`); // Value exists, so it is returned ('HELLO')\n * ```\n *\n */\nexport const getOrGenerate = (map, fn) => async (key, args) => {\n let value = map.get(key);\n if (value !== undefined)\n return value; //Promise.resolve(value);\n value = await fn(key, args);\n if (value === undefined)\n throw new Error(`fn returned undefined`);\n map.set(key, value);\n return value;\n};\n","import { unique } from '@ixfx/arrays';\n/**\n * Clones machine state\n * @param toClone\n * @returns Cloned of `toClone`\n */\nexport const cloneState = (toClone) => {\n return Object.freeze({\n value: toClone.value,\n visited: [...toClone.visited],\n machine: toClone.machine,\n });\n};\n/**\n * Initialises a state machine\n * ```js\n * const desc = {\n * pants: ['shoes','socks'],\n * socks: ['shoes', 'pants'],\n * shoes: 'shirt',\n * shirt: null\n * }\n * // Defaults to first key, 'pants'\n * let sm = StateMachine.init(descr);\n * // Move to 'shoes' state\n * sm = StateMachine.to(sm, 'shoes');\n * sm.state; // 'shoes'\n * sm.visited; // [ 'pants' ]\n * StateMachineLight.isDdone(sm); // false\n * StateMachineLight.possible(sm); // [ 'shirt' ]\n * ```\n * @param stateMachine Settings for state machine\n * @param initialState Initial state name\n * @returns\n */\nexport const init = (stateMachine, initialState) => {\n const [machine, machineValidationError] = validateMachine(stateMachine);\n if (!machine)\n throw new Error(machineValidationError);\n const state = \n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n (initialState) ?? Object.keys(machine.states)[0];\n if (typeof machine.states[state] === `undefined`) {\n throw new TypeError(`Initial state ('${state}') not found`);\n }\n // Normalise states\n const transitions = validateAndNormaliseTransitions(machine.states);\n if (transitions === undefined) {\n throw new Error(`Could not normalise transitions`);\n }\n return Object.freeze({\n value: state,\n visited: [],\n machine: Object.freeze(Object.fromEntries(transitions)),\n });\n};\nexport const reset = (sm) => {\n return init(sm.machine);\n};\nexport const validateMachine = (smOrTransitions) => {\n if (typeof smOrTransitions === `undefined`) {\n return [undefined, `Parameter undefined`];\n }\n if (smOrTransitions === null) {\n return [undefined, `Parameter null`];\n }\n if (`states` in smOrTransitions) {\n // Assume Machine type\n return [smOrTransitions, ``];\n }\n if (typeof smOrTransitions === `object`) {\n return [\n {\n states: smOrTransitions,\n },\n ``,\n ];\n }\n return [\n undefined,\n `Unexpected type: ${typeof smOrTransitions}. Expected object`,\n ];\n};\n// export const validateMachine = <V extends Transitions>(\n// sm: Machine<V>\n// ): [machine: Machine<V> | undefined, msg: string] => {\n// if (typeof sm === 'undefined') {\n// return [undefined, `Parameter 'sm' is undefined`];\n// }\n// if (sm === null) return [undefined, `Parameter 'sm' is null`];\n// if (`states` in sm) {\n// const [transitions, validationError] = validateAndNormaliseTransitions(\n// sm.states\n// );\n// if (transitions) {\n// const machine: Machine<V> = {\n// // @ts-ignore\n// states: Object.fromEntries(transitions),\n// };\n// return [machine, ''];\n// } else {\n// return [undefined, validationError];\n// }\n// } else {\n// return [undefined, `Parameter 'sm.states' is undefined`];\n// }\n// };\n/**\n * Returns _true_ if MachineState `sm` is in its final state.\n * @param sm\n * @returns\n */\nexport const isDone = (sm) => {\n return possible(sm).length === 0;\n};\n/**\n * Returns a list of possible state targets for `sm`, or\n * an empty list if no transitions are possible.\n * @param sm\n * @returns\n */\nexport const possibleTargets = (sm) => {\n // Validate current state\n validateMachineState(sm);\n // get list of possible targets\n const fromS = sm.machine[sm.value];\n if (fromS.length === 1 && fromS[0].state === null)\n return [];\n return fromS;\n};\n/**\n * Returns a list of possible state names for `sm`, or\n * an empty list if no transitions are possible.\n *\n * @param sm\n * @returns\n */\nexport const possible = (sm) => {\n const targets = possibleTargets(sm);\n return targets.map((v) => v.state);\n};\nexport const normaliseTargets = (targets) => {\n const normaliseSingleTarget = (target) => {\n // Terminal target\n if (target === null)\n return { state: null };\n // String is the target state\n if (typeof target === `string`) {\n return {\n state: target,\n };\n }\n else if (typeof target === `object` && `state` in target) {\n const targetState = target.state;\n if (typeof targetState !== `string`) {\n throw new TypeError(`Target 'state' field is not a string. Got: ${typeof targetState}`);\n }\n if (`preconditions` in target) {\n return {\n state: targetState,\n preconditions: target.preconditions,\n };\n }\n return { state: targetState };\n }\n else {\n throw new Error(`Unexpected type: ${typeof target}. Expected string or object with 'state' field.`);\n }\n };\n // Array of targets (either strings or objects)\n if (Array.isArray(targets)) {\n let containsNull = false;\n const mapResults = targets.map((t) => {\n const r = normaliseSingleTarget(t);\n if (!r)\n throw new Error(`Invalid target`);\n containsNull = containsNull || r.state === null;\n return r;\n });\n if (containsNull && mapResults.length > 1) {\n throw new Error(`Cannot have null as an possible state`);\n }\n return mapResults;\n }\n else {\n const target = normaliseSingleTarget(targets);\n if (!target)\n return;\n return [target];\n }\n};\nconst validateAndNormaliseTransitions = (d) => {\n const returnMap = new Map();\n // 1. Index top-level states\n for (const [topLevelState, topLevelTargets] of Object.entries(d)) {\n if (typeof topLevelState === `undefined`) {\n throw new TypeError(`Top-level undefined state`);\n }\n if (typeof topLevelTargets === `undefined`) {\n throw new TypeError(`Undefined target state for ${topLevelState}`);\n }\n if (returnMap.has(topLevelState)) {\n throw new Error(`State defined twice: ${topLevelState}`);\n }\n if (topLevelState.includes(` `)) {\n throw new Error(`State names cannot contain spaces`);\n }\n returnMap.set(topLevelState, []);\n }\n // 2. Normalise target\n for (const [topLevelState, topLevelTargets] of Object.entries(d)) {\n const targets = normaliseTargets(topLevelTargets);\n if (targets === undefined)\n throw new Error(`Could not normalise target`);\n if (targets !== null) {\n // Check that they all exist as top-level states\n const seenStates = new Set();\n for (const target of targets) {\n if (seenStates.has(target.state)) {\n throw new Error(`Target state '${target.state}' already exists for '${topLevelState}'`);\n }\n seenStates.add(target.state);\n if (target.state === null)\n continue;\n if (!returnMap.has(target.state)) {\n throw new Error(`Target state '${target.state}' is not defined as a top-level state. Defined under: '${topLevelState}'`);\n }\n }\n returnMap.set(topLevelState, targets);\n }\n }\n return returnMap;\n};\n/**\n * Validates machine state, throwing an exception if not valid\n * and returning `StateTargetStrict`\n * @param state\n * @returns\n */\nconst validateMachineState = (state) => {\n if (typeof state === `undefined`) {\n throw new TypeError(`Param 'state' is undefined`);\n }\n if (typeof state.value !== `string`) {\n throw new TypeError(`Existing state is not a string`);\n }\n};\n/**\n * Attempts to transition to a new state. Either a new\n * `MachineState` is returned reflecting the change, or\n * an exception is thrown.\n * @param sm\n * @param toState\n * @returns\n */\nexport const to = (sm, toState) => {\n validateMachineState(sm); // throws if not OK\n validateTransition(sm, toState); // throws if not OK\n return Object.freeze({\n value: toState,\n machine: sm.machine,\n visited: unique([sm.visited, [sm.value]]),\n });\n};\nexport const next = (sm) => {\n //validateMachineState(sm);\n const first = possibleTargets(sm).at(0);\n // eslint-disable-next-line @typescript-eslint/prefer-optional-chain\n if (!first || first.state === null) {\n throw new Error(`Not possible to move to a next state from '${sm.value}`);\n }\n return to(sm, first.state);\n};\n/**\n * Returns _true_ if `toState` is a valid transition from current state of `sm`\n * @param sm\n * @param toState\n * @returns\n */\nexport const isValidTransition = (sm, toState) => {\n try {\n validateTransition(sm, toState);\n return true;\n }\n catch {\n return false;\n }\n};\nexport const validateTransition = (sm, toState) => {\n if (toState === null)\n throw new Error(`Cannot transition to null state`);\n if (typeof toState === `undefined`) {\n throw new Error(`Cannot transition to undefined state`);\n }\n if (typeof toState !== `string`) {\n throw new TypeError(`Parameter 'toState' should be a string. Got: ${typeof toState}`);\n }\n //const toS = sm.machine[toState];\n //if (typeof toS === 'undefined') throw new Error(`Target state '${toState}' not defined`);\n const p = possible(sm);\n if (p.length === 0)\n throw new Error(`Machine is in terminal state`);\n if (!p.includes(toState)) {\n throw new Error(`Target state '${toState}' not available at current state '${sm.value}'. Possible states: ${p.join(`, `)}`);\n }\n};\n/**\n * Returns state transitions based on a list of strings.\n * The last string is the terminal state.\n * A -> B -> C -> D\n *\n * See also: {@link fromListBidirectional}\n *\n * ```js\n * const transitions = fromList([`a`, `b`, `c`, `d`]);\n * // Object state machine with events\n * const sm = new StateMachine.WithEvents(transitions);\n * // OR, immutable state machine\n * const sm = StateMachine.init(transitions);\n * ```\n * @param states List of states\n * @return MachineDescription\n */\nexport const fromList = (...states) => {\n const t = {};\n if (!Array.isArray(states))\n throw new Error(`Expected array of strings`);\n if (states.length <= 2)\n throw new Error(`Expects at least two states`);\n for (let index = 0; index < states.length; index++) {\n const s = states[index];\n if (typeof s !== `string`) {\n throw new TypeError(`Expected array of strings. Got type '${typeof s}' at index ${index.toString()}`);\n }\n t[s] = (index === states.length - 1) ? null : states[index + 1];\n }\n return t;\n};\n/**\n * Returns a machine description based on a list of strings. Machine\n * can go back and forth between states:\n * A <-> B <-> C <-> D\n *\n * See also {@link fromList}.\n *\n * ```js\n * const transitions = fromListBidirectional([`a`, `b`, `c`, `d`]);\n * // Object state machine with events\n * const sm = new StateMachine.WithEvents(transitions);\n * // OR, immutable state machine\n * const sm = StateMachine.init(transitions);\n * ```\n * @param states\n * @returns\n */\nexport const fromListBidirectional = (...states) => {\n const t = {};\n if (!Array.isArray(states))\n throw new Error(`Expected array of strings`);\n if (states.length < 2)\n throw new Error(`Expects at least two states`);\n for (const [index, s] of states.entries()) {\n if (typeof s !== `string`) {\n throw new TypeError(`Expected array of strings. Got type '${typeof s}' at index ${index.toString()}`);\n }\n t[s] = [];\n }\n for (let index = 0; index < states.length; index++) {\n const v = t[states[index]];\n if (index === states.length - 1) {\n if (states.length > 1) {\n v.push(states[index - 1]);\n }\n else {\n t[states[index]] = null;\n }\n }\n else {\n v.push(states[index + 1]);\n if (index > 0)\n v.push(states[index - 1]);\n }\n }\n return t;\n};\n","import { continuously, intervalToMs } from \"@ixfx/core\";\nimport { getErrorMessage } from \"@ixfx/debug\";\nimport { sleep } from \"@ixfx/core\";\nimport { initLazyStream } from \"../init-stream.js\";\n/**\n * Produces a reactive from the basis of a function. `callback` is executed, with its result emitted via the returned reactive.\n *\n * ```js\n * // Produce a random number every second\n * const r = Rx.From.func(Math.random, { interval: 1000 });\n * ```\n *\n * `callback` can be called repeatedly by providing the `interval` option to set the rate of repeat.\n * Looping can be limited with `options.maximumRepeats`, or passing a signal `options.signal`\n * and then activating it.\n * ```js\n * // Reactive that emits a random number every second, five times\n * const r1 = Rx.From.func(Math.random, { interval: 1000, maximumRepeats: 5 }\n * ```\n *\n * ```js\n * // Generate a random number every second until ac.abort() is called\n * const ac = new AbortController();\n * const r2 = Rx.From.func(Math.random, { interval: 1000, signal: ac.signal });\n * ```\n *\n * The third option is for `callback` to fire the provided abort function.\n * ```js\n * Rx.From.func((abort) => {\n * if (Math.random() > 0.5) abort('Random exit');\n * return 1;\n * });\n * ```\n *\n * By default has a laziness of 'very' meaning that `callback` is run only when there's a subscriber\n * By default stream closes if `callback` throws an error. Use `options.closeOnError:'ignore'` to change.\n * @param callback\n * @param options\n * @returns\n */\nexport function func(callback, options = {}) {\n const maximumRepeats = options.maximumRepeats ?? Number.MAX_SAFE_INTEGER;\n const closeOnError = options.closeOnError ?? true;\n const intervalMs = options.interval ? intervalToMs(options.interval) : -1;\n let manual = options.manual ?? false;\n // If niether interval or manual is set, assume manual\n if (options.interval === undefined && options.manual === undefined)\n manual = true;\n if (manual && options.interval)\n throw new Error(`If option 'manual' is set, option 'interval' cannot be used`);\n const predelay = intervalToMs(options.predelay, 0);\n const lazy = options.lazy ?? `very`;\n const signal = options.signal;\n const internalAbort = new AbortController();\n const internalAbortCallback = (reason) => { internalAbort.abort(reason); };\n let sentResults = 0;\n let enabled = false;\n const done = (reason) => {\n events.dispose(reason);\n enabled = false;\n if (run)\n run.cancel();\n };\n const ping = async () => {\n if (!enabled)\n return false;\n if (predelay)\n await sleep(predelay);\n if (sentResults >= maximumRepeats) {\n done(`Maximum repeats reached ${maximumRepeats.toString()}`);\n return false;\n }\n //console.log(`sent: ${ sentResults } max: ${ maximumRepeats }`);\n try {\n if (signal?.aborted) {\n done(`Signal (${signal.aborted})`);\n return false;\n }\n const value = await callback(internalAbortCallback);\n sentResults++;\n events.set(value);\n return true;\n }\n catch (error) {\n if (closeOnError) {\n done(`Function error: ${getErrorMessage(error)}`);\n return false;\n }\n else {\n events.signal(`warn`, getErrorMessage(error));\n return true;\n }\n }\n };\n const run = manual ? undefined : continuously(async () => {\n const pingResult = await ping();\n if (!pingResult)\n return false;\n // if (!loop) {\n // done(`fromFunction done`);\n // return false; // Stop loop\n // }\n if (internalAbort.signal.aborted) {\n done(`callback function aborted (${internalAbort.signal.reason})`);\n return false;\n }\n }, intervalMs);\n const events = initLazyStream({\n lazy,\n onStart() {\n enabled = true;\n if (run)\n run.start();\n },\n onStop() {\n enabled = false;\n if (run)\n run.cancel();\n },\n });\n if (lazy === `never` && run)\n run.start();\n return { ...events, ping };\n}\n","import { nextWithTimeout } from \"@ixfx/iterables/async\";\nimport { intervalToMs } from \"@ixfx/core\";\nimport { initLazyStream } from \"../init-stream.js\";\nimport { isAsyncIterable } from \"@ixfx/iterables\";\nimport * as StateMachine from \"@ixfx/flow/state-machine\";\n/**\n * Creates a Reactive from an AsyncGenerator or Generator\n * @param gen\n * @returns\n */\n// export function readFromGenerator<V>(gen: AsyncGenerator<V> | Generator<V>) {\n// const rx = initStream<V>();\n// // eslint-disable-next-line @typescript-eslint/no-misused-promises\n// setTimeout(async () => {\n// try {\n// for await (const value of gen) {\n// rx.set(value);\n// }\n// rx.dispose(`Source generator complete`);\n// } catch (error) {\n// console.error(error);\n// rx.dispose(`Error while iterating`);\n// }\n// }, 1);\n// return rx;\n// }\n/**\n * Creates a readable reactive based on a (async)generator or iterator\n * ```js\n * // Generator a random value every 5 seconds\n * const valuesOverTime = Flow.interval(() => Math.random(), 5000);\n * // Wrap the generator\n * const r = Rx.From.iterator(time);\n * // Get notified when there is a new value\n * r.onValue(v => {\n * console.log(v);\n * });\n * ```\n *\n * Awaiting values could potentially hang code. Thus there is a `readTimeout`, the maximum time to wait for a value from the generator. Default: 5 minutes.\n * If `signal` is given, this will also cancel waiting for the value.\n * @param source\n */\nexport function iterator(source, options = {}) {\n const lazy = options.lazy ?? `very`;\n const log = options.traceLifecycle ? (message) => { console.log(`Rx.From.iterator ${message}`); } : (_) => { };\n const readIntervalMs = intervalToMs(options.readInterval, 5);\n const readTimeoutMs = intervalToMs(options.readTimeout, 5 * 60 * 1000);\n const whenStopped = options.whenStopped ?? `continue`;\n let iterator;\n //let reading = false;\n let ourAc;\n let sm = StateMachine.init({\n idle: [`wait_for_next`],\n wait_for_next: [`processing_result`, `stopping`, `disposed`],\n processing_result: [`queued`, `disposed`, `stopping`],\n queued: [`wait_for_next`, `disposed`, `stopping`],\n stopping: `idle`,\n disposed: null\n }, `idle`);\n const onExternalSignal = () => {\n log(`onExternalSignal`);\n ourAc?.abort(options.signal?.reason);\n };\n if (options.signal) {\n options.signal.addEventListener(`abort`, onExternalSignal, { once: true });\n }\n ;\n const read = async () => {\n log(`read. State: ${sm.value}`);\n ourAc = new AbortController();\n try {\n sm = StateMachine.to(sm, `wait_for_next`);\n const v = await nextWithTimeout(iterator, { signal: ourAc.signal, millis: readTimeoutMs });\n sm = StateMachine.to(sm, `processing_result`);\n ourAc.abort(`nextWithTimeout completed`);\n if (v.done) {\n log(`read v.done true`);\n events.dispose(`Generator complete`);\n //reading = false;\n sm = StateMachine.to(sm, `disposed`);\n }\n //if (!reading) return;\n if (sm.value === `stopping`) {\n log(`read. sm.value = stopping`);\n sm = StateMachine.to(sm, `idle`);\n return;\n }\n if (sm.value === `disposed`) {\n log(`read. sm.value = disposed`);\n return;\n }\n events.set(v.value);\n }\n catch (error) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n events.dispose(`Generator error: ${error.toString()}`);\n return;\n }\n //if (events.isDisposed()) return;\n //if (!reading) return;\n if (sm.value === `processing_result`) {\n sm = StateMachine.to(sm, `queued`);\n log(`scheduling read. State: ${sm.value}`);\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(read, readIntervalMs);\n }\n else {\n sm = StateMachine.to(sm, `idle`);\n }\n };\n const events = initLazyStream({\n ...options,\n lazy,\n onStart() {\n log(`onStart state: ${sm.value} whenStopped: ${whenStopped}`);\n if (sm.value !== `idle`)\n return;\n if ((sm.value === `idle` && whenStopped === `reset`) || iterator === undefined) {\n iterator = isAsyncIterable(source) ? source[Symbol.asyncIterator]() : source[Symbol.iterator]();\n }\n //reading = true;\n void read();\n },\n onStop() {\n log(`onStop state: ${sm.value} whenStopped: ${whenStopped}`);\n //reading = false;\n sm = StateMachine.to(sm, `stopping`);\n if (whenStopped === `reset`) {\n log(`onStop reiniting iterator`);\n iterator = isAsyncIterable(source) ? source[Symbol.asyncIterator]() : source[Symbol.iterator]();\n }\n },\n onDispose(reason) {\n log(`onDispose (${reason})`);\n ourAc?.abort(`Rx.From.iterator disposed (${reason})`);\n if (options.signal)\n options.signal.removeEventListener(`abort`, onExternalSignal);\n },\n });\n // const readingStart = () => {\n // }\n //if (!lazy) readingStart();\n // return {\n // on: events.on,\n // value: events.value,\n // dispose: events.dispose,\n // isDisposed: events.isDisposed\n // }\n return events;\n}\n","import { isIterable } from \"@ixfx/iterables\";\nexport function messageIsSignal(message) {\n if (message.value !== undefined)\n return false;\n if (`signal` in message && message.signal !== undefined)\n return true;\n return false;\n}\nexport function messageIsDoneSignal(message) {\n if (message.value !== undefined)\n return false;\n if (`signal` in message && message.signal === `done`)\n return true;\n return false;\n}\n/**\n * Returns _true_ if `v` has a non-undefined value. Note that sometimes\n * _undefined_ is a legal value to pass\n * @param v\n * @returns\n */\nexport function messageHasValue(v) {\n if (v.value !== undefined)\n return true;\n return false;\n}\nexport const isPingable = (rx) => {\n if (!isReactive(rx))\n return false;\n if (`ping` in rx) {\n return true;\n }\n return false;\n};\nexport const hasLast = (rx) => {\n if (!isReactive(rx))\n return false;\n if (`last` in rx) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n const v = rx.last();\n if (v !== undefined)\n return true;\n }\n return false;\n};\n/**\n * Returns _true_ if `rx` is a Reactive\n * @param rx\n * @returns\n */\nexport const isReactive = (rx) => {\n if (typeof rx !== `object`)\n return false;\n if (rx === null)\n return false;\n return (`on` in rx && `onValue` in rx);\n};\n/**\n * Returns true if `rx` is a disposable reactive.\n * @param rx\n * @returns\n */\n// export const isDisposable = <V>(rx: Reactive<V> | ReactiveWritable<V>): rx is ReactiveDisposable<V> => {\n// if (!isReactive(rx)) return false;\n// return (`isDisposed` in rx && `dispose` in rx);\n// }\n/**\n * Returns _true_ if `rx` is a writable Reactive\n * @param rx\n * @returns\n */\nexport const isWritable = (rx) => {\n if (!isReactive(rx))\n return false;\n if (`set` in rx)\n return true;\n return false;\n};\nexport const isWrapped = (v) => {\n if (typeof v !== `object`)\n return false;\n if (!(`source` in v))\n return false;\n if (!(`annotate` in v))\n return false;\n return true;\n};\n// export const opify = <TIn, TOut = TIn,>(fn: (source: ReactiveOrSource<TIn>, ...args: Array<any>) => Reactive<TOut>, ...args: Array<any>) => {\n// return (source: ReactiveOrSource<TIn>) => {\n// return fn(source, ...args);\n// }\n// }\nexport const opify = (fn, ...args) => {\n return (source) => {\n return fn(source, ...args);\n };\n};\nexport const isTriggerValue = (t) => (`value` in t);\nexport const isTriggerFunction = (t) => (`fn` in t);\nexport const isTriggerGenerator = (t) => isIterable(t);\nexport const isTrigger = (t) => {\n if (typeof t !== `object`)\n return false;\n if (isTriggerValue(t))\n return true;\n if (isTriggerFunction(t))\n return true;\n if (isTriggerGenerator(t))\n return true;\n return false;\n};\n/**\n * Resolves a trigger value.\n *\n * A trigger can be a value, a function or generator. Value triggers never complete.\n * A trigger function is considered complete if it returns undefined.\n * A trigger generator is considered complete if it returns done.\n *\n * Returns `[value, _false_]` if we have a value and trigger is not completed.\n * Returns `[value, _true_]` trigger is completed\n * @param t\n * @returns\n */\nexport function resolveTriggerValue(t) {\n if (isTriggerValue(t))\n return [t.value, false];\n if (isTriggerFunction(t)) {\n const v = t.fn();\n if (v === undefined)\n return [undefined, true];\n return [v, false];\n }\n if (isTriggerGenerator(t)) {\n const v = t.gen.next();\n if (v.done)\n return [undefined, true];\n return [v.value, false];\n }\n throw new Error(`Invalid trigger. Missing 'value' or 'fn' fields`);\n}\n","import { isAsyncIterable, isIterable } from \"@ixfx/iterables\";\nimport { func } from \"./from/function.js\";\nimport { iterator } from \"./from/iterator.js\";\nimport { isReactive, isWrapped } from \"./util.js\";\n/**\n * Resolves various kinds of sources into a Reactive.\n * If `source` is an iterable/generator, it gets wrapped via `generator()`.\n *\n * Default options:\n * * generator: `{ lazy: true, interval: 5 }`\n * @param source\n * @returns\n */\nexport const resolveSource = (source, options = {}) => {\n if (isReactive(source))\n return source;\n const generatorOptions = options.generator ?? { lazy: `initial`, interval: 5 };\n const functionOptions = options.function ?? { lazy: `very` };\n if (Array.isArray(source)) {\n return iterator(source.values(), generatorOptions);\n }\n else if (typeof source === `function`) {\n return func(source, functionOptions);\n }\n else if (typeof source === `object`) {\n //console.log(`resolveSource is object`);\n if (isWrapped(source)) {\n //console.log(`resolveSource is object - wrapped`);\n return source.source;\n }\n if (isIterable(source) || isAsyncIterable(source)) {\n //console.log(`resolveSource is object - iterable`);\n return iterator(source, generatorOptions);\n }\n }\n throw new TypeError(`Unable to resolve source. Supports: array, Reactive, Async/Iterable. Got type: ${typeof source}`);\n};\n","import { DispatchList } from \"@ixfx/flow\";\nimport { resolveSource } from \"./resolve-source.js\";\nimport { messageHasValue, messageIsSignal } from \"./util.js\";\nimport { cache } from \"./cache.js\";\n/**\n * Initialise a stream based on an upstream source.\n * Calls initLazyStream under the hood.\n *\n * Options:\n * * onValue: called when upstream emits a value (default: does nothing with upstream value)\n * * lazy: laziness of stream (default: 'initial')\n * * disposeIfSourceDone: disposes stream if upstream disposes (default: true)\n * @ignore\n * @param upstreamSource\n * @param options\n * @returns\n */\nexport function initUpstream(upstreamSource, options) {\n const lazy = options.lazy ?? `initial`;\n const disposeIfSourceDone = options.disposeIfSourceDone ?? true;\n const onValue = options.onValue ?? ((_v) => { });\n const source = resolveSource(upstreamSource);\n let unsub;\n const debugLabel = options.debugLabel ? `[${options.debugLabel}]` : ``;\n //console.log(`initUpstream${ debugLabel } creating`);\n const onStop = () => {\n //console.log(`Rx.initStream${ debugLabel } stop`);\n if (unsub === undefined)\n return;\n unsub();\n unsub = undefined;\n if (options.onStop)\n options.onStop();\n };\n const onStart = () => {\n //console.log(`Rx.initStream${ debugLabel } start unsub ${ unsub !== undefined }`);\n if (unsub !== undefined)\n return;\n if (options.onStart)\n options.onStart();\n unsub = source.on(value => {\n //console.log(`Rx.initStream${ debugLabel } onValue`, value);\n if (messageIsSignal(value)) {\n if (value.signal === `done`) {\n onStop();\n events.signal(value.signal, value.context);\n if (disposeIfSourceDone)\n events.dispose(`Upstream source ${debugLabel} has completed (${value.context ?? ``})`);\n }\n else {\n //events.through_(value);\n events.signal(value.signal, value.context);\n }\n }\n else if (messageHasValue(value)) {\n //lastValue = value.value;\n onValue(value.value);\n }\n });\n };\n //const initOpts = \n // const events:ReactiveInitialStream<Out>|ReactiveStream<Out> = ((`initialValue` in options) && options.initialValue !== undefined) ?\n // initLazyStreamWithInitial<Out>({ ...initOpts, initialValue: options.initialValue }) :\n // initLazyStream<Out>(initOpts);\n //console.log(`initUpstream${ debugLabel } creating initLazyStream`);\n const events = initLazyStream({\n ...options,\n lazy,\n onStart,\n onStop\n });\n return events;\n}\n/**\n * Initialises a lazy stream with an initial value.\n * Uses {@link initLazyStream} and {@link cache} together.\n * @param options\n * @returns\n */\nexport function initLazyStreamWithInitial(options) {\n const r = initLazyStream(options);\n const c = cache(r, options.initialValue);\n return c;\n}\n/**\n * Initialises a lazy stream\n * Consider also: {@link initLazyStreamWithInitial}\n *\n * @param options\n * @returns\n */\nexport function initLazyStream(options) {\n const lazy = options.lazy ?? `initial`;\n const onStop = options.onStop ?? (() => { });\n const onStart = options.onStart ?? (() => { });\n const debugLabel = options.debugLabel ? `[${options.debugLabel}]` : ``;\n const events = initStream({\n ...options,\n onFirstSubscribe() {\n if (lazy !== `never`) {\n //console.log(`initLazyStream${ debugLabel } onFirstSubscribe, lazy: ${ lazy }. Calling onStart`);\n onStart();\n }\n },\n onNoSubscribers() {\n if (lazy === `very`) {\n //console.log(`initLazyStream${ debugLabel } onNoSubscribers, lazy: ${ lazy }. Calling onStop`);\n onStop();\n }\n },\n });\n if (lazy === `never`)\n onStart();\n return events;\n}\n/**\n * Initialises a new stream.\n *\n * Options:\n * * onFirstSubscribe: Called when there is a subscriber after there have been no subscribers.\n * * onNoSubscribers: Called when there are no more subscribers. 'onFirstSubscriber' will be called next time a subscriber is added.\n *\n * Alternatives:\n * * {@link initLazyStream} - a stream with callbacks for when there is some/none subscribers\n * @ignore\n * @param options\n * @returns\n */\nexport function initStream(options = {}) {\n let dispatcher;\n let disposed = false;\n let firstSubscribe = false;\n let emptySubscriptions = true;\n const onFirstSubscribe = options.onFirstSubscribe ?? undefined;\n const onNoSubscribers = options.onNoSubscribers ?? undefined;\n const debugLabel = options.debugLabel ? `[${options.debugLabel}]` : ``;\n const isEmpty = () => {\n if (dispatcher === undefined)\n return;\n if (!dispatcher.isEmpty)\n return;\n if (!emptySubscriptions) {\n emptySubscriptions = true;\n firstSubscribe = false;\n if (onNoSubscribers)\n onNoSubscribers();\n }\n };\n const subscribe = (handler) => {\n if (disposed)\n throw new Error(`Disposed, cannot subscribe ${debugLabel}`);\n if (dispatcher === undefined)\n dispatcher = new DispatchList();\n //console.log(`initStream${ debugLabel } subscribe handler:`, handler);\n const id = dispatcher.add(handler);\n emptySubscriptions = false;\n if (!firstSubscribe) {\n firstSubscribe = true;\n //if (onFirstSubscribe) setTimeout(() => { onFirstSubscribe() }, 10);\n if (onFirstSubscribe)\n onFirstSubscribe();\n }\n return () => {\n dispatcher?.remove(id);\n isEmpty();\n };\n };\n return {\n dispose: (reason) => {\n if (disposed)\n return;\n dispatcher?.notify({ value: undefined, signal: `done`, context: `Disposed: ${reason}` });\n disposed = true;\n if (options.onDispose)\n options.onDispose(reason);\n },\n isDisposed: () => {\n return disposed;\n },\n removeAllSubscribers: () => {\n dispatcher?.clear();\n isEmpty();\n },\n set: (v) => {\n if (disposed)\n throw new Error(`${debugLabel} Disposed, cannot set`);\n dispatcher?.notify({ value: v });\n },\n // through: (pass: Passed<V>) => {\n // if (disposed) throw new Error(`Disposed, cannot through`);\n // dispatcher?.notify(pass)\n // },\n signal: (signal, context) => {\n if (disposed)\n throw new Error(`${debugLabel} Disposed, cannot signal`);\n dispatcher?.notify({ signal, value: undefined, context });\n },\n on: (handler) => subscribe(handler),\n onValue: (handler) => {\n const unsub = subscribe(message => {\n //console.log(`initStream${ debugLabel } onValue wrapper`, message);\n if (messageHasValue(message)) {\n handler(message.value);\n }\n });\n return unsub;\n }\n };\n}\n","import { DispatchList } from \"@ixfx/flow\";\nimport { Pathed } from \"@ixfx/core\";\nimport { initStream } from \"../init-stream.js\";\nimport { isEqualContextString } from \"@ixfx/core\";\nimport { wildcard } from \"@ixfx/core/text\";\nimport { resultIsError, resultThrow, resultThrowSingle, resultToError } from \"@ixfx/guards\";\n/**\n * Creates a Reactive wrapper with the shape of the input object.\n *\n * Changing the wrapped object directly does not update the Reactive.\n * Instead, to update values use:\n * * `set()`, 'resets' the whole object\n * * `update()` changes a particular field\n *\n * Consider using {@link From.objectProxy} to return a object with properties that can be\n * set in the usual way yet is also Reactive.\n *\n * ```js\n * const o = Rx.From.object({ name: `bob`, level: 2 });\n * o.onValue(changed => {\n * });\n * o.set({ name: `mary`, level: 3 });\n *\n * // `onValue` will get called, with `changed` having a value of:\n * // { name: `mary`, level: 3 }\n * ```\n *\n * Use `last()` to get the most recently set value.\n *\n * `onDiff` subscribes to a rough diff of the object.\n *\n * ```js\n * const o = Rx.From.object({ name: `bob`, level: 2 });\n * o.onDiff(diffValue => {\n * const diff = diffValue.value;\n * })\n * o.set({ name: `mary`, level: 3 });\n *\n * // onDiff would fire with `diff` of:\n * [\n * { path: `name`, previous: `bob`, value: `mary` },\n * { path: `level`, previous: 2, value: 3 }\n * ]\n * ```\n *\n * You can also listen to updates on a field via `onField`.\n * ```js\n * o.onField(`name`, value => {\n * // Called whenever the 'name' field is updated\n * });\n * ```\n * @param initialValue Initial value\n * @param options Options\n * @returns\n */\nexport function object(initialValue, options = {}) {\n const eq = options.eq ?? isEqualContextString;\n const setEvent = initStream();\n const diffEvent = initStream();\n //const fieldChangeEvents = new Map<string, DispatchList<ObjectFieldHandler>>;\n const fieldChangeEvents = [];\n let value = initialValue;\n let disposed = false;\n const set = (v) => {\n const diff = [...Pathed.compareData(value ?? {}, v, { ...options, includeMissingFromA: true })];\n if (diff.length === 0)\n return;\n value = v;\n setEvent.set(v);\n diffEvent.set(diff);\n };\n const fireFieldUpdate = (field, value) => {\n for (const [matcher, pattern, list] of fieldChangeEvents) {\n if (matcher(field)) {\n list.notify({ fieldName: field, pattern, value });\n }\n }\n //const l = fieldChangeEvents.get(field.toLowerCase());\n //if (l === undefined) return;\n //l.notify(value);\n };\n const updateCompareOptions = {\n asPartial: true,\n includeParents: true\n };\n const update = (toMerge) => {\n //console.log(`Rx.From.object update: toMerge: ${ JSON.stringify(toMerge) } value: ${ JSON.stringify(value) }`);\n if (value === undefined) {\n value = toMerge;\n setEvent.set(value);\n for (const [k, v] of Object.entries(toMerge)) {\n fireFieldUpdate(k, v);\n }\n return value;\n }\n else {\n const diff = [...Pathed.compareData(value, toMerge, updateCompareOptions)];\n //const diffWithoutRemoved = diff.filter(d => d.state !== `removed`);\n if (diff.length === 0)\n return value; // No changes\n value = {\n ...value,\n ...toMerge\n };\n setEvent.set(value);\n diffEvent.set(diff);\n //console.log(`diff`, diff);\n for (const d of diff) {\n fireFieldUpdate(d.path, d.value);\n }\n return value;\n }\n };\n const updateField = (path, valueForField) => {\n if (value === undefined)\n throw new Error(`Cannot update value when it has not already been set`);\n //console.log(`Rx.Sources.Object.updateField path: ${ path } value: ${ JSON.stringify(valueForField) }`);\n const existing = Pathed.getField(value, path);\n //resultThrowSingle(existing);\n if (resultIsError(existing)) {\n throw resultToError(existing);\n }\n //console.log(`Rx.fromObject.updateField path: ${ path } existing: ${ JSON.stringify(existing) }`);\n if (eq(existing.value, valueForField, path)) {\n //console.log(`Rx.object.updateField identical existing: ${ existing } value: ${ valueForField } path: ${ path }`);\n return;\n }\n let diff = [...Pathed.compareData(existing.value, valueForField, { ...options, includeMissingFromA: true })];\n diff = diff.map(d => {\n if (d.path.length > 0)\n return { ...d, path: path + `.` + d.path };\n return { ...d, path };\n });\n //console.log(`Rx.fromObject.updateField diff path: ${ path }`, diff);\n const o = Pathed.updateByPath(value, path, valueForField, true);\n value = o;\n //diffEvent.set([ { path, value: valueForField, previous: existing } ]);\n setEvent.set(o);\n diffEvent.set(diff);\n fireFieldUpdate(path, valueForField);\n //console.log(`Rx.fromObject.updateField: path: '${ path }' value: '${ JSON.stringify(valueForField) }' o: ${ JSON.stringify(o) }`);\n };\n const dispose = (reason) => {\n if (disposed)\n return;\n diffEvent.dispose(reason);\n setEvent.dispose(reason);\n disposed = true;\n };\n return {\n dispose,\n isDisposed() {\n return disposed;\n },\n /**\n * Update a field.\n * Exception is thrown if field does not exist\n */\n updateField,\n last: () => value,\n on: setEvent.on,\n onValue: setEvent.onValue,\n onDiff: diffEvent.onValue,\n onField(fieldPattern, handler) {\n const matcher = wildcard(fieldPattern);\n const listeners = new DispatchList();\n fieldChangeEvents.push([matcher, fieldPattern, listeners]);\n const id = listeners.add(handler);\n return () => listeners.remove(id);\n // let listeners = fieldChangeEvents.get(fieldName.toLowerCase());\n // if (listeners === undefined) {\n // listeners = new DispatchList();\n // fieldChangeEvents.set(fieldName.toLowerCase(), listeners);\n // }\n // const id = listeners.add((value) => {\n // setTimeout(() => { handler(value, fieldName) }, 1);\n // });\n // return () => listeners.remove(id);\n },\n /**\n * Set the whole object\n */\n set,\n /**\n * Update the object with a partial set of fields and values\n */\n update\n };\n}\n","/***\n * Returns a read-only version of `stream`\n */\nexport const toReadable = (stream) => ({\n on: stream.on,\n dispose: stream.dispose,\n isDisposed: stream.isDisposed,\n onValue: stream.onValue\n});\n","import { field } from \"../ops/field.js\";\nimport { object } from \"./object.js\";\nimport { initLazyStream } from \"../init-stream.js\";\nimport { elapsedInterval } from \"@ixfx/core/elapsed\";\n/**\n * Fired when `eventName` fires on `target`.\n *\n * Rather than whole event args being emitted on the stream,\n * it plucks a field from the event args, or if that's missing, from the target.\n *\n * ```js\n * // Emits the the value of a field named 'x'\n * // on the change event args\n * eventField(el, `pointermove`, `x`);\n * ```\n * @param targetOrQuery Event target, HTML element or HTML query (eg '#someId')\n * @param eventName Name of event, eg. 'pointermove'\n * @param fieldName Name of field, eg 'x'\n * @param initialValue Initial data\n * @param options Options for source\n */\nexport function eventField(targetOrQuery, eventName, fieldName, initialValue, options = {}) {\n const initial = {};\n initial[fieldName] = initialValue;\n const rxField = field(event(targetOrQuery, eventName, initial, options), fieldName, options);\n return rxField;\n}\n//export function event<V extends Record<string, any>>(target: EventTarget | null | string, name: string, options: EventOptions<V>): ReactiveNonInitial<V> & ReactiveDisposable<V>;\n//export function event<V extends Record<string, any>>(target: EventTarget | null | string, name: string, options?: Optional<EventOptions<V>, `transform`>): ReactiveNonInitial<V> & ReactiveDisposable<V>;\n/**\n * Subscribes to an event, emitting data\n *\n * @example Print x,y position of mouse as it moves\n * ```js\n * const r = Rx.From.event(document, `pointermove`);\n * r.onValue(event => {\n * const { x, y } = event;\n * });\n * ```\n *\n * If `options.lazy` is _true_ (default: _false_), event will only be subscribed to when the stream\n * itself has a subscriber.\n *\n * `options.debugFiring` and `options.debugLifecycle` can be turned on to troubleshoot behaviour\n * of the stream if necessary.\n * @param targetOrQuery Event emitter, HTML element or string. If a string, it will be queryed as a selector.\n * @param name Event name\n * @param options Options\n * @returns\n */\nexport function event(targetOrQuery, name, initialValue, options = {}) {\n let target;\n if (typeof targetOrQuery === `string`) {\n target = document.querySelector(targetOrQuery);\n if (target === null)\n throw new Error(`Target query did not resolve to an element. Query: '${targetOrQuery}'`);\n }\n else {\n target = targetOrQuery;\n }\n if (target === null)\n throw new Error(`Param 'targetOrQuery' is null`);\n const debugLifecycle = options.debugLifecycle ?? false;\n const debugFiring = options.debugFiring ?? false;\n const lazy = options.lazy ?? false;\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n if (initialValue === undefined)\n initialValue = {};\n const rxObject = object(initialValue, { deepEntries: true });\n let eventAdded = false;\n let disposed = false;\n const callback = (args) => {\n if (debugFiring)\n console.log(`Reactive.event '${name}' firing '${JSON.stringify(args)}`);\n rxObject.set(args);\n };\n const remove = () => {\n if (!eventAdded)\n return;\n eventAdded = false;\n target.removeEventListener(name, callback);\n if (debugLifecycle) {\n console.log(`Rx.From.event remove '${name}'`);\n }\n };\n const add = () => {\n if (eventAdded)\n return;\n eventAdded = true;\n target.addEventListener(name, callback);\n if (debugLifecycle) {\n console.log(`Rx.From.event add '${name}'`);\n }\n };\n if (!lazy)\n add();\n return {\n last: () => {\n if (lazy)\n add();\n return rxObject.last();\n },\n dispose: (reason) => {\n if (disposed)\n return;\n disposed = true;\n remove();\n rxObject.dispose(reason);\n },\n isDisposed() {\n return disposed;\n },\n on: (handler) => {\n if (lazy)\n add();\n return rxObject.on(handler);\n },\n onValue: (handler) => {\n if (lazy)\n add();\n return rxObject.onValue(handler);\n }\n };\n}\n/**\n * Emits a value whenever event happens.\n * Data emitted is `{ sinceLast, total }`, where 'sinceLast'\n * is milliseconds since last event and 'total' is total number of\n * times event has been fired.\n * @param targetOrQuery\n * @param name\n * @param options\n * @returns\n */\nexport function eventTrigger(targetOrQuery, name, options = {}) {\n let target;\n if (typeof targetOrQuery === `string`) {\n target = document.querySelector(targetOrQuery);\n if (target === null)\n throw new Error(`Target query did not resolve to an element. Query: '${targetOrQuery}'`);\n }\n else {\n target = targetOrQuery;\n }\n if (target === null)\n throw new Error(`Param 'targetOrQuery' is null`);\n const debugLifecycle = options.debugLifecycle ?? false;\n const debugFiring = options.debugFiring ?? false;\n const fireInitial = options.fireInitial ?? false;\n let count = 0;\n const elapsed = elapsedInterval();\n const stream = initLazyStream({\n lazy: options.lazy ?? `very`,\n onStart() {\n target.addEventListener(name, callback);\n if (debugLifecycle) {\n console.log(`Rx.From.eventTrigger add '${name}'`);\n }\n if (fireInitial && count === 0) {\n if (debugLifecycle || debugFiring)\n console.log(`Rx.From.eventTrigger: firing initial`);\n callback();\n }\n },\n onStop() {\n target.removeEventListener(name, callback);\n if (debugLifecycle) {\n console.log(`Rx.From.eventTrigger remove '${name}'`);\n }\n },\n });\n const callback = (_args) => {\n if (debugFiring)\n console.log(`Rx.From.eventTrigger '${name}' triggered'`);\n stream.set({\n sinceLast: elapsed(),\n total: ++count\n });\n };\n return stream;\n}\n","import { resultToError } from \"@ixfx/guards\";\n/**\n * Resolves either a string or HTML element to an element.\n * Useful when an argument is either an HTML element or query.\n *\n * ```js\n * resolveEl(`#someId`);\n * resolveEl(someElement);\n * ```\n * @param domQueryOrEl\n * @returns\n */\nexport const resolveEl = (domQueryOrEl) => {\n const r = resolveElementTry(domQueryOrEl);\n if (r.success)\n return r.value;\n throw resultToError(r);\n};\n/**\n * Tries to resolve a query, returning a `Result`.\n *\n * ```js\n * const { success, value, error } = resolveElementTry(`#some-element`);\n * if (success) {\n * // Do something with value\n * } else {\n * console.error(error);\n * }\n * ```\n * @param domQueryOrEl\n * @returns\n */\nexport const resolveElementTry = (domQueryOrEl) => {\n if (typeof domQueryOrEl === `string`) {\n const d = document.querySelector(domQueryOrEl);\n if (d === null) {\n const error = domQueryOrEl.startsWith(`#`) ? `Query '${domQueryOrEl}' did not match anything. Try '#id', 'div', or '.class'`\n : `Query '${domQueryOrEl}' did not match anything. Did you mean '#${domQueryOrEl}?`;\n return { success: false, error };\n }\n domQueryOrEl = d;\n }\n else if (domQueryOrEl === null) {\n return { success: false, error: `Param 'domQueryOrEl' is null` };\n }\n else if (domQueryOrEl === undefined) {\n return { success: false, error: `Param 'domQueryOrEl' is undefined` };\n }\n const el = domQueryOrEl;\n return { success: true, value: el };\n};\n/**\n * Returns a set of elements.\n *\n * Returns an empty list if `selectors` is undefined or null.\n *\n * @param selectors\n * @returns\n */\nexport const resolveEls = (selectors) => {\n if (selectors === undefined)\n return [];\n if (selectors === null)\n return [];\n if (Array.isArray(selectors))\n return selectors;\n if (typeof selectors === `string`) {\n const elements = [...document.querySelectorAll(selectors)];\n return elements;\n }\n return [selectors];\n};\n","import { initUpstream } from \"../init-stream.js\";\nimport { toReadable } from \"../to-readable.js\";\n/**\n * Transforms values from `source` using the `transformer` function.\n * @param transformer\n * @returns\n */\nexport function transform(input, transformer, options = {}) {\n const traceInput = options.traceInput ?? false;\n const traceOutput = options.traceOutput ?? false;\n const upstream = initUpstream(input, {\n lazy: `initial`,\n ...options,\n onValue(value) {\n const t = transformer(value);\n if (traceInput && traceOutput) {\n console.log(`Rx.Ops.transform input: ${JSON.stringify(value)} output: ${JSON.stringify(t)}`);\n }\n else if (traceInput) {\n console.log(`Rx.Ops.transform input: ${JSON.stringify(value)}`);\n }\n else if (traceOutput) {\n console.log(`Rx.Ops.transform output: ${JSON.stringify(t)}`);\n }\n upstream.set(t);\n },\n });\n return toReadable(upstream);\n}\n","import { intervalToMs } from \"@ixfx/core\";\nimport { timeout } from \"@ixfx/flow\";\nimport { initUpstream } from \"../init-stream.js\";\nimport { toReadable } from \"../to-readable.js\";\n/**\n * Debounce waits for `elapsed` time after the last received value before emitting it.\n *\n * If a flurry of values are received that are within the interval, it won't emit anything. But then\n * as soon as there is a gap in the messages that meets the interval, the last received value is sent out.\n *\n * `debounce` always emits with at least `elapsed` as a delay after a value received. While {@link throttle} potentially\n * sends immediately, if it's outside of the elapsed period.\n *\n * This is a subtly different logic to {@link throttle}. `throttle` more eagerly sends the first value, potentially\n * not sending later values. `debouce` however will send later values, potentially ignoring earlier ones.\n * @param source\n * @param options\n * @returns\n */\nexport function debounce(source, options = {}) {\n const elapsed = intervalToMs(options.elapsed, 50);\n let lastValue;\n const timer = timeout(() => {\n const v = lastValue;\n if (v) {\n upstream.set(v);\n lastValue = undefined;\n }\n }, elapsed);\n const upstream = initUpstream(source, {\n ...options,\n onValue(value) {\n lastValue = value;\n timer.start();\n }\n });\n return toReadable(upstream);\n}\n","import { debounce as debounceReactive } from \"../reactives/debounce.js\";\nexport function debounce(options) {\n return (source) => {\n return debounceReactive(source, options);\n };\n}\n","import { intervalToMs } from '@ixfx/core';\nimport { isWritable, messageHasValue, messageIsDoneSignal, opify } from \"./util.js\";\nimport { initStream } from \"./init-stream.js\";\nimport { resolveSource } from './resolve-source.js';\nimport * as SinkFns from './sinks/index.js';\nimport * as OpFns from './ops/index.js';\nexport * as From from './from/index.js';\nexport * as Collections from './collections/index.js';\nexport * from './ops/index.js';\nexport * from './sinks/index.js';\nexport * from './graph.js';\nexport * from './types.js';\nexport * from './to-array.js';\nexport * from './to-generator.js';\nexport * from './util.js';\nexport * from './wrap.js';\nexport * from './resolve-source.js';\nexport * from './cache.js';\nexport * from './init-stream.js';\nexport function run(source, ...ops) {\n let s = resolveSource(source);\n for (const op of ops) {\n // @ts-ignore\n s = op(s);\n }\n return s;\n}\nexport function writable(source, ...ops) {\n let s = resolveSource(source);\n const head = s;\n for (const op of ops) {\n // @ts-ignore\n s = op(s);\n }\n const ss = s;\n return {\n ...ss,\n set(value) {\n if (isWritable(head)) {\n head.set(value);\n }\n else\n throw new Error(`Original source is not writable`);\n }\n };\n //return s as Reactive<T2 | T3 | T4 | T5 | T6>;\n //const raw = chainer<T1, T2, T3, T4, T5, T6>(...ops);\n //return raw(source);\n}\n/**\n * Initialises a reactive that pipes values to listeners directly.\n * @returns\n */\nexport function manual(options = {}) {\n const events = initStream(options);\n return {\n dispose: events.dispose,\n isDisposed: events.isDisposed,\n set(value) {\n events.set(value);\n },\n on: events.on,\n onValue: events.onValue\n };\n}\nexport const Sinks = {\n setHtmlText: (options) => {\n return (source) => {\n SinkFns.setHtmlText(source, options);\n };\n }\n};\nexport const Ops = {\n /**\n * Annotates values with the result of a function.\n * The input value needs to be an object.\n *\n * For every value `input` emits, run it through `annotator`, which should\n * return the original value with additional fields.\n *\n * Conceptually the same as `transform`, just with typing to enforce result\n * values are V & TAnnotation\n * @param annotator\n * @returns\n */\n annotate: (annotator) => opify(OpFns.annotate, annotator),\n /**\n * Annotates the input stream using {@link ReactiveOp} as the source of annotations.\n * The output values will have the shape of `{ value: TIn, annotation: TAnnotation }`.\n * Meaning that the original value is stored under `.value`, and the annotation under `.annotation`.\n *\n * ```js\n * // Emit values from an array\n * const r1 = Rx.run(\n * Rx.From.array([ 1, 2, 3 ]),\n * Rx.Ops.annotateWithOp(\n * // Add the 'max' operator to emit the largest-seen value\n * Rx.Ops.sum()\n * )\n * );\n * const data = await Rx.toArray(r1);\n * // Data = [ { value: 1, annotation: 1 }, { value: 2, annotation: 3 }, { value: 3, annotation: 6 } ]\n * ```\n * @param annotatorOp\n * @returns\n */\n annotateWithOp: (annotatorOp) => opify(OpFns.annotateWithOp, annotatorOp),\n /**\n * Takes a stream of values and chunks them up (by quantity or time elapsed),\n * emitting them as an array.\n * @param options\n * @returns\n */\n chunk: (options) => {\n return (source) => {\n return OpFns.chunk(source, options);\n };\n },\n cloneFromFields: () => {\n return (source) => {\n return OpFns.cloneFromFields(source);\n };\n },\n /**\n * Merges values from several sources into a single source that emits values as an array.\n * @param options\n * @returns\n */\n combineLatestToArray: (options = {}) => {\n return (sources) => {\n return OpFns.combineLatestToArray(sources, options);\n };\n },\n /**\n * Merges values from several sources into a single source that emits values as an object.\n * @param options\n * @returns\n */\n combineLatestToObject: (options = {}) => {\n return (reactiveSources) => {\n return OpFns.combineLatestToObject(reactiveSources, options);\n };\n },\n /**\n * Debounce values from the stream. It will wait until a certain time\n * has elapsed before emitting latest value.\n *\n * Effect is that no values are emitted if input emits faster than the provided\n * timeout.\n *\n * See also: throttle\n * @param options\n * @returns\n */\n // debounce: <V>(options: Partial<DebounceOptions>): ReactiveOp<V, V> => {\n // return (source: ReactiveOrSource<V>) => {\n // return OpFns.debounce(source, options);\n // }\n // },\n /**\n * Drops values from the input stream that match `predicate`\n * @param predicate If it returns _true_ value is ignored\n * @returns\n */\n drop: (predicate) => opify(OpFns.drop, predicate),\n /**\n * Every upstream value is considered the target for interpolation.\n * Output value interpolates by a given amount toward the target.\n * @returns\n */\n elapsed: () => opify(OpFns.elapsed),\n /**\n * Yields the value of a field from an input stream of values.\n * Eg if the source reactive emits `{ colour: string, size: number }`,\n * we might use `field` to pluck out the `colour` field, thus returning\n * a stream of string values.\n * @param fieldName\n * @param options\n * @returns\n */\n field: (fieldName, options) => {\n return (source) => {\n return OpFns.field(source, fieldName, options);\n };\n },\n /**\n * Filters the input stream, only re-emitting values that pass the predicate\n * @param predicate If it returns _true_ value is allowed through\n * @returns\n */\n filter: (predicate) => opify(OpFns.filter, predicate),\n /**\n * Every upstream value is considered the target for interpolation.\n * Output value interpolates by a given amount toward the target.\n * @param options\n * @returns\n */\n interpolate: (options) => opify(OpFns.interpolate, options),\n /**\n * Outputs the minimum numerical value of the stream.\n * A value is only emitted when minimum decreases.\n * @returns\n */\n min: (options) => opify(OpFns.min, options),\n /**\n * Outputs the maxium numerical value of the stream.\n * A value is only emitted when maximum increases.\n * @returns\n */\n max: (options) => opify(OpFns.max, options),\n sum: (options) => opify(OpFns.sum, options),\n average: (options) => opify(OpFns.average, options),\n tally: (options) => opify(OpFns.tally, options),\n rank: (rank, options) => opify(OpFns.rank, rank, options),\n pipe: (...streams) => {\n return (source) => {\n const resolved = resolveSource(source);\n const s = [resolved, ...streams];\n return OpFns.pipe(...s);\n };\n },\n singleFromArray: (options = {}) => {\n return (source) => {\n return OpFns.singleFromArray(source, options);\n };\n },\n split: (options = {}) => {\n return (source) => {\n return OpFns.split(source, options);\n };\n },\n splitLabelled: (labels) => {\n return (source) => {\n return OpFns.splitLabelled(source, labels);\n };\n },\n switcher: (cases, options = {}) => {\n return (source) => {\n return OpFns.switcher(source, cases, options);\n };\n },\n syncToArray: (options = {}) => {\n return (reactiveSources) => {\n return OpFns.syncToArray(reactiveSources, options);\n };\n },\n syncToObject: (options = {}) => {\n return (reactiveSources) => {\n return OpFns.syncToObject(reactiveSources, options);\n };\n },\n tapProcess: (processor) => {\n return (source) => {\n return OpFns.tapProcess(source, processor);\n };\n },\n tapStream: (divergedStream) => {\n return (source) => {\n return OpFns.tapStream(source, divergedStream);\n };\n },\n tapOps: (...ops) => {\n return (source) => {\n return OpFns.tapOps(source, ...ops);\n };\n },\n /**\n * Throttle values from the stream.\n * Only emits a value if some minimum time has elapsed.\n * @param options\n * @returns\n */\n throttle: (options) => opify(OpFns.throttle, options),\n /**\n * Trigger a value if 'source' does not emit a value within an interval.\n * Trigger value can be a fixed value, result of function, or step through an iterator.\n * @param options\n * @returns\n */\n timeoutValue: (options) => {\n return (source) => {\n return OpFns.timeoutValue(source, options);\n };\n },\n timeoutPing: (options) => {\n return (source) => {\n return OpFns.timeoutPing(source, options);\n };\n },\n transform: (transformer, options = {}) => {\n return (source) => {\n return OpFns.transform(source, transformer, options);\n };\n },\n /**\n * Reactive where last (or a given initial) value is available to read\n * @param opts\n * @returns\n */\n withValue: (opts) => {\n return opify(OpFns.withValue, opts);\n },\n};\n// export const chain = <TIn, TOut>(...ops: Array<ReactiveOp<TIn, TOut>>) => {\n// return (source: ReactiveOrSource<TIn>) => {\n// for (const op of ops) {\n// // @ts-expect-error\n// source = op(source);\n// }\n// return source as any as Reactive<TOut>;\n// }\n// }\n// export const chainStream = <TIn, TOut>(...ops: Array<ReactiveOp<TIn, TOut>>): ReactiveStream<TIn, TOut> => {\n// const stream = manual<TIn>();\n// const c = chain(...ops);\n// const x = c(stream);\n// return x;\n// }\n// function chainx<TIn, TOut>(...ops: Array<ReactiveOp<any, any>>) {\n// return (source: ReactiveOrSource<TIn>) => {\n// for (const op of ops) {\n// source = op(source);\n// }\n// return source as any as Reactive<TOut>;\n// }\n// }\n// export function runWithInitial<TIn, TOut>(initial: TOut, source: ReactiveOrSource<TIn>, ...ops: Array<ReactiveOp<any, any>>): ReactiveInitial<TOut> & ReactiveDisposable<TOut> {\n// let lastValue = initial;\n// const raw = prepareOps<TIn, TOut>(...ops);\n// const r = raw(source);\n// let disposed = false;\n// r.onValue(value => {\n// lastValue = value;\n// });\n// return {\n// ...r,\n// isDisposed() {\n// return disposed\n// },\n// dispose(reason) {\n// if (disposed) return;\n// if (isDisposable(r)) {\n// r.dispose(reason);\n// }\n// disposed = true;\n// },\n// last() {\n// return lastValue;\n// },\n// }\n// }\n/**\n * Grabs the next value emitted from `source`.\n * By default waits up to a maximum of one second.\n * Handles subscribing and unsubscribing.\n *\n * ```js\n * const value = await Rx.takeNextValue(source);\n * ```\n *\n * Throws an error if the source closes without\n * a value or the timeout is reached.\n *\n * @param source\n * @param maximumWait\n * @returns\n */\nexport async function takeNextValue(source, maximumWait = 1000) {\n const rx = resolveSource(source);\n let off = () => { };\n let watchdog;\n const p = new Promise((resolve, reject) => {\n off = rx.on(message => {\n if (watchdog)\n clearTimeout(watchdog);\n if (messageHasValue(message)) {\n off();\n resolve(message.value);\n }\n else {\n if (messageIsDoneSignal(message)) {\n reject(new Error(`Source closed. ${message.context ?? ``}`));\n off();\n }\n }\n });\n watchdog = setTimeout(() => {\n watchdog = undefined;\n off();\n reject(new Error(`Timeout waiting for value (${JSON.stringify(maximumWait)})`));\n }, intervalToMs(maximumWait));\n });\n return p;\n}\n/**\n * Connects reactive A to B, optionally transforming the value as it does so.\n *\n * Returns a function to unsubcribe A->B\n * @param a\n * @param b\n * @param transform\n */\nexport const to = (a, b, transform, closeBonA = false) => {\n const unsub = a.on(message => {\n if (messageHasValue(message)) {\n const value = transform ? transform(message.value) : message.value;\n b.set(value);\n }\n else if (messageIsDoneSignal(message)) {\n unsub();\n if (closeBonA) {\n b.dispose(`Source closed (${message.context ?? ``})`);\n }\n }\n else {\n // eslint-disable-nex Unsupported message: ${ JSON.stringify(message) }`);\n }\n });\n return unsub;\n};\n","import { messageHasValue } from \"../util.js\";\nimport { manual } from \"../index.js\";\n/**\n * Creates a RxJs style observable\n * ```js\n * const o = observable(stream => {\n * // Code to run for initialisation when we go from idle to at least one subscriber\n * // Won't run again for additional subscribers, but WILL run again if we lose\n * // all subscribers and then get one\n *\n * // To send a value:\n * stream.set(someValue);\n *\n * // Optional: return function to call when all subscribers are removed\n * return () => {\n * // Code to run when all subscribers are removed\n * }\n * });\n * ```\n *\n * For example:\n * ```js\n * const xy = observable<(stream => {\n * // Send x,y coords from PointerEvent\n * const send = (event) => {\n * stream.set({ x: event.x, y: event.y });\n * }\n * window.addEventListener(`pointermove`, send);\n * return () => {\n * // Unsubscribe\n * window.removeEventListener(`pointermove`, send);\n * }\n * });\n *\n * xy.onValue(value => {\n * console.log(value);\n * });\n * ```\n * @param init\n * @returns\n */\nexport function observable(init) {\n const ow = observableWritable(init);\n return {\n dispose: ow.dispose,\n isDisposed: ow.isDisposed,\n on: ow.on,\n onValue: ow.onValue\n };\n}\n/**\n * As {@link observable}, but returns a Reactive that allows writing\n * @param init\n * @returns\n */\nexport function observableWritable(init) {\n let onCleanup = () => { };\n const ow = manual({\n onFirstSubscribe() {\n onCleanup = init(ow);\n },\n onNoSubscribers() {\n if (onCleanup)\n onCleanup();\n },\n });\n return {\n ...ow,\n onValue: (callback) => {\n return ow.on(message => {\n if (messageHasValue(message)) {\n callback(message.value);\n }\n });\n }\n };\n}\n","import type { Interval } from \"@ixfx/core\";\nimport { observable } from \"@ixfx/rx/from\";\nimport { debounce } from \"@ixfx/rx/op/debounce\";\n\n/**\n * Observe when element resizes. Specify `interval` to debounce, uses 100ms by default.\n *\n * ```\n * const o = resizeObservable(myEl, 500);\n * o.subscribe(() => {\n * // called 500ms after last resize\n * });\n * ```\n * @param elem\n * @param interval Tiemout before event gets triggered\n * @returns\n */\nexport const browserResizeObservable = (\n elem: Readonly<Element>,\n interval?: Interval\n) => {\n if (elem === null) {\n throw new Error(`Param 'elem' is null. Expected element to observe`);\n }\n if (elem === undefined) {\n throw new Error(`Param 'elem' is undefined. Expected element to observe`);\n }\n\n const m = observable<ResizeObserverEntry[]>(stream => {\n const ro = new ResizeObserver((entries) => {\n stream.set(entries);\n });\n ro.observe(elem);\n\n return () => {\n ro.unobserve(elem);\n };\n });\n //return debounce({ elapsed: interval ?? 100 })(m);\n return debounce<ResizeObserverEntry[]>({ elapsed: interval ?? 100 })(m);\n}\n\n/**\n * Returns an Reactive for window resize. Default 100ms debounce.\n * @param elapsed\n * @returns\n */\n// export const windowResize = (elapsed?: Interval) => Rx.Ops.debounce<{ innerWidth: number, innerHeight: number }>({ elapsed: elapsed ?? 100 })(Rx.From.event(window, `resize`, { innerWidth: 0, innerHeight: 0 }));\n","import { observable } from \"@ixfx/rx/from/observable\";\n\n/**\n * Observe when a class changes on a target element, by default the document.\n * Useful for tracking theme changes.\n *\n * ```js\n * const c = cssClassChange();\n * c.on(msg => {\n * // some class has changed on the document\n * });\n * ```\n */\nexport const cssClassChange = (target = document.documentElement) => {\n const m = observable<MutationRecord[]>(stream => {\n const ro = new MutationObserver((entries) => {\n stream.set(entries);\n });\n const opts: MutationObserverInit = {\n attributeFilter: [ `class` ],\n attributes: true,\n };\n ro.observe(target, opts);\n\n return () => {\n ro.disconnect();\n }\n });\n return m;\n}","\nimport { initStream, type ReactiveInitial, type ReactiveNonInitial, type ReactiveWritable } from \"@ixfx/rx\";\nimport type { HslScalar } from \"@ixfx/visual/colour\";\n\nexport type ReactiveColour = ReactiveWritable<HslScalar> & {\n setHsl: (hsl: HslScalar) => void;\n}\n\nexport function colour(initialValue: HslScalar): ReactiveColour & ReactiveInitial<HslScalar>;\nexport function colour(): ReactiveColour & ReactiveNonInitial<HslScalar>;\nexport function colour(initialValue?: HslScalar): ReactiveColour & (ReactiveNonInitial<HslScalar> | ReactiveInitial<HslScalar>) {\n let value = initialValue;\n const events = initStream<HslScalar>();\n\n const set = (v: HslScalar) => {\n value = v;\n events.set(v);\n }\n\n return {\n dispose: events.dispose,\n isDisposed: events.isDisposed,\n last: () => value,\n on: events.on,\n onValue: events.onValue,\n set,\n setHsl: (hsl: HslScalar) => {\n set(hsl);\n }\n }\n}\n","var __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __export = (target, all) => {\n for (var name2 in all)\n __defProp(target, name2, { get: all[name2], enumerable: true });\n};\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\n\n// src/modules/invariant.ts\nfunction invariant(condition, message) {\n if (condition) {\n return;\n }\n if (process.env.NODE_ENV !== \"production\") {\n if (message === void 0) {\n throw new Error(\"invariant requires an error message argument\");\n }\n }\n const error = !message ? new Error(\n \"Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.\"\n ) : new Error(message);\n error.name = \"colorizr\";\n throw error;\n}\n\n// src/modules/constants.ts\nvar COLOR_KEYS = {\n hsl: [\"h\", \"s\", \"l\"],\n oklab: [\"l\", \"a\", \"b\"],\n oklch: [\"l\", \"c\", \"h\"],\n rgb: [\"r\", \"g\", \"b\"]\n};\nvar COLOR_MODELS = [\"hsl\", \"oklab\", \"oklch\", \"rgb\"];\nvar DEG2RAD = Math.PI / 180;\nvar LAB_TO_LMS = {\n l: [0.3963377773761749, 0.2158037573099136],\n m: [-0.1055613458156586, -0.0638541728258133],\n s: [-0.0894841775298119, -1.2914855480194092]\n};\nvar LRGB_TO_LMS = {\n l: [0.4122214708, 0.5363325363, 0.0514459929],\n m: [0.2119034982, 0.6806995451, 0.1073969566],\n s: [0.0883024619, 0.2817188376, 0.6299787005]\n};\nvar LSM_TO_LAB = {\n l: [0.2104542553, 0.793617785, 0.0040720468],\n a: [1.9779984951, 2.428592205, 0.4505937099],\n b: [0.0259040371, 0.7827717662, 0.808675766]\n};\nvar LSM_TO_RGB = {\n r: [4.076741636075958, -3.307711539258063, 0.2309699031821043],\n g: [-1.2684379732850315, 2.609757349287688, -0.341319376002657],\n b: [-0.0041960761386756, -0.7034186179359362, 1.7076146940746117]\n};\nvar SRGB_TO_P3 = [\n [0.8224270476, 0.1775729524, 0],\n [0.0331008087, 0.9668991913, 0],\n [0.0170720188, 0.0723477973, 0.9105801839]\n];\nvar PRECISION = 5;\nvar RAD2DEG = 180 / Math.PI;\nvar MESSAGES = {\n alpha: \"amount must be a number between 0 and 1\",\n hueRange: \"hue must be a number between 0 and 360\",\n input: \"input is required\",\n inputHex: \"input is required and must be a hex\",\n inputNumber: \"input is required and must be a number\",\n inputString: \"input is required and must be a string\",\n invalid: \"invalid input\",\n invalidCSS: \"invalid CSS string\",\n left: \"left is required and must be a string\",\n lightnessRange: \"lightness must be a number between 0 and 1\",\n options: \"invalid options\",\n right: \"right is required and must be a string\",\n threshold: \"threshold must be a number between 0 and 255\"\n};\n\n// src/modules/css-colors.ts\nvar cssColors = {\n aliceblue: \"#f0f8ff\",\n antiquewhite: \"#faebd7\",\n aqua: \"#00ffff\",\n aquamarine: \"#7fffd4\",\n azure: \"#f0ffff\",\n beige: \"#f5f5dc\",\n bisque: \"#ffe4c4\",\n black: \"#000000\",\n blanchedalmond: \"#ffebcd\",\n blue: \"#0000ff\",\n blueviolet: \"#8a2be2\",\n brown: \"#a52a2a\",\n burlywood: \"#deb887\",\n cadetblue: \"#5f9ea0\",\n chartreuse: \"#7fff00\",\n chocolate: \"#d2691e\",\n coral: \"#ff7f50\",\n cornflowerblue: \"#6495ed\",\n cornsilk: \"#fff8dc\",\n crimson: \"#dc143c\",\n cyan: \"#00ffff\",\n darkblue: \"#00008b\",\n darkcyan: \"#008b8b\",\n darkgoldenrod: \"#b8860b\",\n darkgray: \"#a9a9a9\",\n darkgreen: \"#006400\",\n darkkhaki: \"#bdb76b\",\n darkmagenta: \"#8b008b\",\n darkolivegreen: \"#556b2f\",\n darkorange: \"#ff8c00\",\n darkorchid: \"#9932cc\",\n darkred: \"#8b0000\",\n darksalmon: \"#e9967a\",\n darkseagreen: \"#8fbc8f\",\n darkslateblue: \"#483d8b\",\n darkslategray: \"#2f4f4f\",\n darkslategrey: \"#2f4f4f\",\n darkturquoise: \"#00ced1\",\n darkviolet: \"#9400d3\",\n deeppink: \"#ff1493\",\n deepskyblue: \"#00bfff\",\n dimgray: \"#696969\",\n dimgrey: \"#696969\",\n dodgerblue: \"#1e90ff\",\n firebrick: \"#b22222\",\n floralwhite: \"#fffaf0\",\n forestgreen: \"#228b22\",\n fuchsia: \"#ff00ff\",\n gainsboro: \"#dcdcdc\",\n ghostwhite: \"#f8f8ff\",\n gold: \"#ffd700\",\n goldenrod: \"#daa520\",\n gray: \"#808080\",\n grey: \"#808080\",\n green: \"#008000\",\n greenyellow: \"#adff2f\",\n honeydew: \"#f0fff0\",\n hotpink: \"#ff69b4\",\n indianred: \"#cd5c5c\",\n indigo: \"#4b0082\",\n ivory: \"#fffff0\",\n khaki: \"#f0e68c\",\n lavender: \"#e6e6fa\",\n lavenderblush: \"#fff0f5\",\n lawngreen: \"#7cfc00\",\n lemonchiffon: \"#fffacd\",\n lightblue: \"#add8e6\",\n lightcoral: \"#f08080\",\n lightcyan: \"#e0ffff\",\n lightgoldenrodyellow: \"#fafad2\",\n lightgray: \"#d3d3d3\",\n lightgreen: \"#90ee90\",\n lightgrey: \"#d3d3d3\",\n lightpink: \"#ffb6c1\",\n lightsalmon: \"#ffa07a\",\n lightseagreen: \"#20b2aa\",\n lightskyblue: \"#87cefa\",\n lightslategray: \"#778899\",\n lightslategrey: \"#778899\",\n lightsteelblue: \"#b0c4de\",\n lightyellow: \"#ffffe0\",\n lime: \"#00ff00\",\n limegreen: \"#32cd32\",\n linen: \"#faf0e6\",\n magenta: \"#ff00ff\",\n maroon: \"#800000\",\n mediumaquamarine: \"#66cdaa\",\n mediumblue: \"#0000cd\",\n mediumorchid: \"#ba55d3\",\n mediumpurple: \"#9370db\",\n mediumseagreen: \"#3cb371\",\n mediumslateblue: \"#7b68ee\",\n mediumspringgreen: \"#00fa9a\",\n mediumturquoise: \"#48d1cc\",\n mediumvioletred: \"#c71585\",\n midnightblue: \"#191970\",\n mintcream: \"#f5fffa\",\n mistyrose: \"#ffe4e1\",\n moccasin: \"#ffe4b5\",\n navajowhite: \"#ffdead\",\n navy: \"#000080\",\n oldlace: \"#fdf5e6\",\n olive: \"#808000\",\n olivedrab: \"#6b8e23\",\n orange: \"#ffa500\",\n orangered: \"#ff4500\",\n orchid: \"#da70d6\",\n palegoldenrod: \"#eee8aa\",\n palegreen: \"#98fb98\",\n paleturquoise: \"#afeeee\",\n palevioletred: \"#db7093\",\n papayawhip: \"#ffefd5\",\n peachpuff: \"#ffdab9\",\n peru: \"#cd853f\",\n pink: \"#ffc0cb\",\n plum: \"#dda0dd\",\n powderblue: \"#b0e0e6\",\n purple: \"#800080\",\n rebeccapurple: \"#663399\",\n red: \"#ff0000\",\n rosybrown: \"#bc8f8f\",\n royalblue: \"#4169e1\",\n saddlebrown: \"#8b4513\",\n salmon: \"#fa8072\",\n sandybrown: \"#f4a460\",\n seagreen: \"#2e8b57\",\n seashell: \"#fff5ee\",\n sienna: \"#a0522d\",\n silver: \"#c0c0c0\",\n skyblue: \"#87ceeb\",\n slateblue: \"#6a5acd\",\n slategray: \"#708090\",\n slategrey: \"#708090\",\n snow: \"#fffafa\",\n springgreen: \"#00ff7f\",\n steelblue: \"#4682b4\",\n tan: \"#d2b48c\",\n teal: \"#008080\",\n thistle: \"#d8bfd8\",\n tomato: \"#ff6347\",\n turquoise: \"#40e0d0\",\n violet: \"#ee82ee\",\n wheat: \"#f5deb3\",\n white: \"#ffffff\",\n whitesmoke: \"#f5f5f5\",\n yellow: \"#ffff00\",\n yellowgreen: \"#9acd32\"\n};\n\n// src/modules/validators.ts\nfunction hasValidMatches(input) {\n return Array.isArray(input) && input.length === 6;\n}\nfunction isNamedColor(input) {\n return isString(input) && Object.keys(cssColors).includes(input.toLowerCase());\n}\nfunction isNumber(input) {\n return typeof input === \"number\" && !Number.isNaN(input);\n}\nfunction isPlainObject(input) {\n if (!input) {\n return false;\n }\n const { toString } = Object.prototype;\n const prototype = Object.getPrototypeOf(input);\n return toString.call(input) === \"[object Object]\" && (prototype === null || prototype === Object.getPrototypeOf({}));\n}\nfunction isString(input, validate = true) {\n const isValid = typeof input === \"string\";\n if (validate) {\n return isValid && !!input.trim().length;\n }\n return isValid;\n}\nfunction isValidColorModel(input) {\n return isHSL(input) || isRGB(input) || isLAB(input) || isLCH(input);\n}\nfunction isHex(input) {\n if (!isString(input)) {\n return false;\n }\n return /^#([\\da-f]{3,4}|[\\da-f]{6,8})$/i.test(input);\n}\nfunction isHSL(input) {\n if (!isPlainObject(input)) {\n return false;\n }\n const entries = Object.entries(input);\n return !!entries.length && entries.every(([key, value]) => {\n if (key === \"h\") {\n return value >= 0 && value <= 360;\n }\n if (key === \"alpha\") {\n return value >= 0 && value <= 1;\n }\n return COLOR_KEYS.hsl.includes(key) && value >= 0 && value <= 100;\n });\n}\nfunction isLAB(input) {\n if (!isPlainObject(input)) {\n return false;\n }\n const entries = Object.entries(input);\n return !!entries.length && entries.every(([key, value]) => {\n if (key === \"l\") {\n return value >= 0 && value <= 100;\n }\n if (key === \"alpha\") {\n return value >= 0 && value <= 1;\n }\n return COLOR_KEYS.oklab.includes(key) && value >= -1 && value <= 1;\n });\n}\nfunction isLCH(input) {\n if (!isPlainObject(input)) {\n return false;\n }\n const entries = Object.entries(input);\n return !!entries.length && entries.every(([key, value]) => {\n if (key === \"l\") {\n return value >= 0 && value <= 100;\n }\n if (key === \"alpha\") {\n return value >= 0 && value <= 1;\n }\n return COLOR_KEYS.oklch.includes(key) && value >= 0 && value <= (key === \"h\" ? 360 : 1);\n });\n}\nfunction isRGB(input) {\n if (!isPlainObject(input)) {\n return false;\n }\n const entries = Object.entries(input);\n return !!entries.length && entries.every(([key, value]) => {\n if (key === \"alpha\") {\n return value >= 0 && value <= 1;\n }\n return COLOR_KEYS.rgb.includes(key) && value >= 0 && value <= 255;\n });\n}\n\n// src/modules/utils.ts\nfunction addAlpha(input, alpha) {\n invariant(isValidColorModel(input), MESSAGES.invalid);\n let value = alpha;\n if (!value) {\n return input;\n }\n if (value > 1) {\n value /= 100;\n }\n if (value === 1) {\n return input;\n }\n return { ...input, alpha: value };\n}\nfunction clamp(value, min = 0, max = 100) {\n return Math.min(Math.max(value, min), max);\n}\nfunction constrainDegrees(input, amount) {\n invariant(isNumber(input), MESSAGES.inputNumber);\n let value = input + amount;\n if (value > 360) {\n value %= 360;\n }\n if (value < 0) {\n value += 360;\n }\n return Math.abs(value);\n}\nfunction limit(input, model, key) {\n invariant(isNumber(input), \"Input is not a number\");\n invariant(COLOR_MODELS.includes(model), `Invalid model${model ? `: ${model}` : \"\"}`);\n invariant(COLOR_KEYS[model].includes(key), `Invalid key${key ? `: ${key}` : \"\"}`);\n switch (model) {\n case \"hsl\": {\n invariant(COLOR_KEYS.hsl.includes(key), \"Invalid key\");\n if ([\"s\", \"l\"].includes(key)) {\n return clamp(input);\n }\n return clamp(input, 0, 360);\n }\n case \"rgb\": {\n invariant(COLOR_KEYS.rgb.includes(key), \"Invalid key\");\n return clamp(input, 0, 255);\n }\n /* c8 ignore next 3 */\n default: {\n throw new Error(\"Invalid inputs\");\n }\n }\n}\nfunction parseInput(input, model) {\n const keys = COLOR_KEYS[model];\n const validator = {\n hsl: isHSL,\n oklab: isLAB,\n oklch: isLCH,\n rgb: isRGB\n };\n invariant(isPlainObject(input) || Array.isArray(input), MESSAGES.invalid);\n const value = Array.isArray(input) ? { [keys[0]]: input[0], [keys[1]]: input[1], [keys[2]]: input[2] } : input;\n invariant(validator[model](value), `invalid ${model} color`);\n return value;\n}\nfunction restrictValues(input, precision = PRECISION, forcePrecision = true) {\n const output = new Map(Object.entries(input));\n for (const [key, value] of output.entries()) {\n output.set(key, round(value, precision, forcePrecision));\n }\n return Object.fromEntries(output);\n}\nfunction round(input, precision = 2, forcePrecision = true) {\n if (!isNumber(input) || input === 0) {\n return 0;\n }\n if (forcePrecision) {\n const factor2 = 10 ** precision;\n return Math.round(input * factor2) / factor2;\n }\n const absInput = Math.abs(input);\n let digits = Math.abs(Math.ceil(Math.log(absInput) / Math.LN10));\n if (digits === 0) {\n digits = 2;\n } else if (digits > precision) {\n digits = precision;\n }\n let exponent = precision - (digits < 0 ? 0 : digits);\n if (exponent <= 1 && precision > 1) {\n exponent = 2;\n } else if (exponent > precision || exponent === 0) {\n exponent = precision;\n }\n const factor = 10 ** exponent;\n return Math.round(input * factor) / factor;\n}\n\n// src/modules/hex-utils.ts\nfunction addAlphaToHex(input, alpha) {\n invariant(isHex(input), MESSAGES.inputHex);\n invariant(isNumber(alpha), MESSAGES.inputNumber);\n if (alpha >= 1) {\n return removeAlphaFromHex(input);\n }\n return `${removeAlphaFromHex(input)}${convertAlphaToHex(alpha)}`;\n}\nfunction convertAlphaToHex(input) {\n invariant(isNumber(input), MESSAGES.inputNumber);\n let alpha = input;\n if (input > 1) {\n alpha /= 100;\n }\n return Math.round(alpha * 255).toString(16).padStart(2, \"0\");\n}\nfunction extractAlphaFromHex(input) {\n invariant(isHex(input), MESSAGES.inputString);\n const alpha = input.substring(7, 9);\n if (!alpha) {\n return 1;\n }\n return round(parseInt(alpha, 16) / 255);\n}\nfunction hexadecimalToNumber(input) {\n return round(parseInt(input, 16));\n}\nfunction removeAlphaFromHex(input) {\n invariant(isHex(input), MESSAGES.inputHex);\n if (input.length === 5) {\n return input.substring(0, 4);\n }\n return input.substring(0, 7);\n}\n\n// src/converters/index.ts\nvar converters_exports = {};\n__export(converters_exports, {\n hex2hsl: () => hex2hsl,\n hex2oklab: () => hex2oklab,\n hex2oklch: () => hex2oklch,\n hex2rgb: () => hex2rgb,\n hsl2hex: () => hsl2hex,\n hsl2oklab: () => hsl2oklab,\n hsl2oklch: () => hsl2oklch,\n hsl2rgb: () => hsl2rgb,\n oklab2hex: () => oklab2hex,\n oklab2hsl: () => oklab2hsl,\n oklab2oklch: () => oklab2oklch,\n oklab2rgb: () => oklab2rgb,\n oklch2hex: () => oklch2hex,\n oklch2hsl: () => oklch2hsl,\n oklch2oklab: () => oklch2oklab,\n oklch2rgb: () => oklch2rgb,\n rgb2hex: () => rgb2hex,\n rgb2hsl: () => rgb2hsl,\n rgb2oklab: () => rgb2oklab,\n rgb2oklch: () => rgb2oklch\n});\n\n// src/format-hex.ts\nfunction formatHex(input) {\n invariant(isHex(input), MESSAGES.inputHex);\n let color = input.replace(\"#\", \"\");\n if (color.length === 3 || color.length === 4) {\n const values = [...color];\n color = \"\";\n values.forEach((d) => {\n color += `${d}${d}`;\n });\n }\n const hex = `#${color}`;\n invariant(isHex(hex), \"invalid hex\");\n return hex;\n}\n\n// src/converters/hex2rgb.ts\nfunction hex2rgb(input) {\n invariant(isHex(input), MESSAGES.inputHex);\n const hex = formatHex(input).slice(1);\n return {\n r: parseInt(hex.charAt(0) + hex.charAt(1), 16),\n g: parseInt(hex.charAt(2) + hex.charAt(3), 16),\n b: parseInt(hex.charAt(4) + hex.charAt(5), 16)\n };\n}\n\n// src/converters/rgb2hsl.ts\nfunction rgb2hsl(input) {\n const value = parseInput(input, \"rgb\");\n const rLimit = limit(value.r, \"rgb\", \"r\") / 255;\n const gLimit = limit(value.g, \"rgb\", \"g\") / 255;\n const bLimit = limit(value.b, \"rgb\", \"b\") / 255;\n const min = Math.min(rLimit, gLimit, bLimit);\n const max = Math.max(rLimit, gLimit, bLimit);\n const delta = max - min;\n let h = 0;\n let s;\n const l = (max + min) / 2;\n let rate;\n switch (max) {\n case rLimit:\n rate = !delta ? 0 : (gLimit - bLimit) / delta;\n h = 60 * rate;\n break;\n case gLimit:\n rate = (bLimit - rLimit) / delta;\n h = 60 * rate + 120;\n break;\n case bLimit:\n rate = (rLimit - gLimit) / delta;\n h = 60 * rate + 240;\n break;\n /* c8 ignore next 2 */\n default:\n break;\n }\n if (h < 0) {\n h = 360 + h;\n }\n if (min === max) {\n s = 0;\n } else {\n s = l < 0.5 ? delta / (2 * l) : delta / (2 - 2 * l);\n }\n return {\n h: Math.abs(+(h % 360).toFixed(2)),\n s: +(s * 100).toFixed(2),\n l: +(l * 100).toFixed(2)\n };\n}\n\n// src/converters/hex2hsl.ts\nfunction hex2hsl(input) {\n invariant(isHex(input), MESSAGES.inputHex);\n return rgb2hsl(hex2rgb(input));\n}\n\n// src/converters/rgb2oklab.ts\nvar { cbrt, sign } = Math;\nfunction rgb2lrgb(input) {\n const abs2 = Math.abs(input);\n if (abs2 < 0.04045) {\n return input / 12.92;\n }\n return (sign(input) || 1) * ((abs2 + 0.055) / 1.055) ** 2.4;\n}\nfunction rgb2oklab(input, precision = PRECISION) {\n const value = parseInput(input, \"rgb\");\n const [lr, lg, lb] = [rgb2lrgb(value.r / 255), rgb2lrgb(value.g / 255), rgb2lrgb(value.b / 255)];\n const l = cbrt(LRGB_TO_LMS.l[0] * lr + LRGB_TO_LMS.l[1] * lg + LRGB_TO_LMS.l[2] * lb);\n const m = cbrt(LRGB_TO_LMS.m[0] * lr + LRGB_TO_LMS.m[1] * lg + LRGB_TO_LMS.m[2] * lb);\n const s = cbrt(LRGB_TO_LMS.s[0] * lr + LRGB_TO_LMS.s[1] * lg + LRGB_TO_LMS.s[2] * lb);\n const lab = {\n l: LSM_TO_LAB.l[0] * l + LSM_TO_LAB.l[1] * m - LSM_TO_LAB.l[2] * s,\n a: LSM_TO_LAB.a[0] * l - LSM_TO_LAB.a[1] * m + LSM_TO_LAB.a[2] * s,\n b: LSM_TO_LAB.b[0] * l + LSM_TO_LAB.b[1] * m - LSM_TO_LAB.b[2] * s\n };\n return restrictValues(lab, precision);\n}\n\n// src/converters/hex2oklab.ts\nfunction hex2oklab(input, precision) {\n invariant(isHex(input), MESSAGES.inputHex);\n return rgb2oklab(hex2rgb(input), precision);\n}\n\n// src/converters/oklab2oklch.ts\nvar { atan2, sqrt } = Math;\nfunction oklab2oklch(input, precision) {\n const { l, a, b } = restrictValues(parseInput(input, \"oklab\"));\n const c = sqrt(a ** 2 + b ** 2);\n let h = (atan2(b, a) * RAD2DEG + 360) % 360;\n if (round(c * 1e4) === 0) {\n h = 0;\n }\n return restrictValues({ l, c, h }, precision);\n}\n\n// src/converters/rgb2oklch.ts\nfunction rgb2oklch(input, precision) {\n const value = parseInput(input, \"rgb\");\n return oklab2oklch(rgb2oklab(value, precision), precision);\n}\n\n// src/converters/hex2oklch.ts\nfunction hex2oklch(input, precision) {\n invariant(isHex(input), MESSAGES.inputHex);\n return rgb2oklch(hex2rgb(input), precision);\n}\n\n// src/modules/hue2rgb.ts\nfunction hue2rgb(point, chroma2, h) {\n invariant(isNumber(point) && isNumber(chroma2) && isNumber(h), \"point, chroma and h are required\");\n let hue = h;\n if (hue < 0) {\n hue += 1;\n }\n if (hue > 1) {\n hue -= 1;\n }\n if (hue < 1 / 6) {\n return round(point + (chroma2 - point) * 6 * hue, 4);\n }\n if (hue < 1 / 2) {\n return round(chroma2, 4);\n }\n if (hue < 2 / 3) {\n return round(point + (chroma2 - point) * (2 / 3 - hue) * 6, 4);\n }\n return round(point, 4);\n}\n\n// src/converters/hsl2rgb.ts\nfunction hsl2rgb(input) {\n const value = parseInput(input, \"hsl\");\n const h = round(value.h) / 360;\n const s = round(value.s) / 100;\n const l = round(value.l) / 100;\n let r;\n let g;\n let b;\n let point;\n let chroma2;\n if (s === 0) {\n r = l;\n g = l;\n b = l;\n } else {\n chroma2 = l < 0.5 ? l * (1 + s) : l + s - l * s;\n point = 2 * l - chroma2;\n r = hue2rgb(point, chroma2, h + 1 / 3);\n g = hue2rgb(point, chroma2, h);\n b = hue2rgb(point, chroma2, h - 1 / 3);\n }\n return {\n r: Math.round(r * 255),\n g: Math.round(g * 255),\n b: Math.round(b * 255)\n };\n}\n\n// src/converters/rgb2hex.ts\nfunction rgb2hex(input) {\n const rgb = parseInput(input, \"rgb\");\n return `#${Object.values(rgb).map((d) => `0${Math.floor(d).toString(16)}`.slice(-2)).join(\"\")}`;\n}\n\n// src/converters/hsl2hex.ts\nfunction hsl2hex(input) {\n const value = parseInput(input, \"hsl\");\n return rgb2hex(hsl2rgb(value));\n}\n\n// src/converters/hsl2oklab.ts\nfunction hsl2oklab(input, precision) {\n const value = parseInput(input, \"hsl\");\n return rgb2oklab(hsl2rgb(value), precision);\n}\n\n// src/converters/hsl2oklch.ts\nfunction hsl2oklch(input, precision) {\n const value = parseInput(input, \"hsl\");\n return rgb2oklch(hsl2rgb(value), precision);\n}\n\n// src/converters/oklab2rgb.ts\nvar { abs } = Math;\nfunction lrgb2rgb(input) {\n const absoluteNumber = abs(input);\n const sign2 = input < 0 ? -1 : 1;\n if (absoluteNumber > 31308e-7) {\n return sign2 * (absoluteNumber ** (1 / 2.4) * 1.055 - 0.055);\n }\n return input * 12.92;\n}\nfunction oklab2rgb(input, precision = 0) {\n const { l: L, a: A, b: B } = parseInput(input, \"oklab\");\n const l = (L + LAB_TO_LMS.l[0] * A + LAB_TO_LMS.l[1] * B) ** 3;\n const m = (L + LAB_TO_LMS.m[0] * A + LAB_TO_LMS.m[1] * B) ** 3;\n const s = (L + LAB_TO_LMS.s[0] * A + LAB_TO_LMS.s[1] * B) ** 3;\n const r = 255 * lrgb2rgb(LSM_TO_RGB.r[0] * l + LSM_TO_RGB.r[1] * m + LSM_TO_RGB.r[2] * s);\n const g = 255 * lrgb2rgb(LSM_TO_RGB.g[0] * l + LSM_TO_RGB.g[1] * m + LSM_TO_RGB.g[2] * s);\n const b = 255 * lrgb2rgb(LSM_TO_RGB.b[0] * l + LSM_TO_RGB.b[1] * m + LSM_TO_RGB.b[2] * s);\n return {\n r: clamp(round(r, precision), 0, 255),\n g: clamp(round(g, precision), 0, 255),\n b: clamp(round(b, precision), 0, 255)\n };\n}\n\n// src/converters/oklab2hex.ts\nfunction oklab2hex(input) {\n const value = parseInput(input, \"oklab\");\n return rgb2hex(oklab2rgb(value));\n}\n\n// src/converters/oklab2hsl.ts\nfunction oklab2hsl(input) {\n const value = parseInput(input, \"oklab\");\n return rgb2hsl(oklab2rgb(value));\n}\n\n// src/converters/oklch2oklab.ts\nvar { sin, cos } = Math;\nfunction oklch2oklab(input, precision) {\n let { l, c, h } = parseInput(input, \"oklch\");\n if (Number.isNaN(h) || h < 0) {\n h = 0;\n }\n return restrictValues({ l, a: c * cos(h * DEG2RAD), b: c * sin(h * DEG2RAD) }, precision);\n}\n\n// src/converters/oklch2rgb.ts\nfunction oklch2rgb(input, precision = 0) {\n const value = parseInput(input, \"oklch\");\n return oklab2rgb(oklch2oklab(value), precision);\n}\n\n// src/converters/oklch2hex.ts\nfunction oklch2hex(input) {\n const value = parseInput(input, \"oklch\");\n return rgb2hex(oklch2rgb(value));\n}\n\n// src/converters/oklch2hsl.ts\nfunction oklch2hsl(input) {\n const value = parseInput(input, \"oklch\");\n return rgb2hsl(oklch2rgb(value));\n}\n\n// src/extract-color-parts.ts\nfunction extractColorParts(input) {\n invariant(isString(input), MESSAGES.inputString);\n if (isHex(input)) {\n const keys2 = COLOR_KEYS.rgb;\n const { r, g, b } = hex2rgb(input);\n const alpha2 = extractAlphaFromHex(input);\n return {\n model: \"rgb\",\n [keys2[0]]: r,\n [keys2[1]]: g,\n [keys2[2]]: b,\n alpha: alpha2 < 1 ? alpha2 : void 0\n };\n }\n const colorRegex = /(?:(rgb|hsl|oklab|oklch)a?\\s*\\(\\s*([\\d%.-]+)\\s*[ ,/]\\s*([\\d%.-]+)\\s*[ ,/]\\s*([\\d%.-]+)(?:\\s*[ ,/]\\s*([\\d%.-]+))?\\s*\\))/i;\n const matches = colorRegex.exec(input);\n invariant(hasValidMatches(matches), MESSAGES.invalidCSS);\n const model = matches[1];\n const keys = COLOR_KEYS[model];\n let alpha = matches[5] ? parseFloat(matches[5]) : 1;\n if (alpha > 1) {\n alpha /= 100;\n }\n return {\n model,\n [keys[0]]: parseFloat(matches[2]),\n [keys[1]]: parseFloat(matches[3]),\n [keys[2]]: parseFloat(matches[4]),\n alpha: alpha < 1 ? alpha : void 0\n };\n}\n\n// src/parse-css.ts\nfunction parseCSS(input, format) {\n invariant(isString(input), MESSAGES.inputString);\n let result;\n const value = isNamedColor(input) ? cssColors[input.toLowerCase()] : input;\n const output = format ?? (isHex(value) ? \"hex\" : extractColorParts(value).model);\n const colorParams = (params) => Object.values(params);\n if (isHex(value)) {\n const alpha = extractAlphaFromHex(value);\n switch (output) {\n case \"hsl\": {\n result = addAlpha(hex2hsl(value), alpha);\n break;\n }\n case \"oklab\": {\n result = addAlpha(hex2oklab(value), alpha);\n break;\n }\n case \"oklch\": {\n result = addAlpha(hex2oklch(value), alpha);\n break;\n }\n case \"rgb\": {\n result = addAlpha(hex2rgb(value), alpha);\n break;\n }\n default: {\n result = `${removeAlphaFromHex(value)}${alpha !== 1 ? convertAlphaToHex(alpha) : \"\"}`;\n break;\n }\n }\n return result;\n }\n switch (output) {\n case \"hsl\": {\n const { alpha, model, ...color } = extractColorParts(value);\n if ([\"oklab\", \"oklch\"].includes(model) && color.l > 1) {\n color.l = round(color.l / 100, PRECISION);\n }\n result = addAlpha(\n model === \"hsl\" ? color : converters_exports[`${model}2hsl`](colorParams(color)),\n alpha\n );\n break;\n }\n case \"oklab\": {\n const { alpha, model, ...color } = extractColorParts(value);\n if ([\"oklab\", \"oklch\"].includes(model) && color.l > 1) {\n color.l = round(color.l / 100, PRECISION);\n }\n result = addAlpha(\n model === \"oklab\" ? color : converters_exports[`${model}2oklab`](colorParams(color)),\n alpha\n );\n break;\n }\n case \"oklch\": {\n const { alpha, model, ...color } = extractColorParts(value);\n if ([\"oklab\", \"oklch\"].includes(model) && color.l > 1) {\n color.l = round(color.l / 100, PRECISION);\n }\n result = addAlpha(\n model === \"oklch\" ? color : converters_exports[`${model}2oklch`](colorParams(color)),\n alpha\n );\n break;\n }\n case \"rgb\": {\n const { alpha, model, ...color } = extractColorParts(value);\n if ([\"oklab\", \"oklch\"].includes(model) && color.l > 1) {\n color.l /= 100;\n }\n result = addAlpha(\n model === \"rgb\" ? color : converters_exports[`${model}2rgb`](colorParams(color)),\n alpha\n );\n break;\n }\n case \"hex\":\n default: {\n const { alpha, model, ...color } = extractColorParts(value);\n let alphaPrefix = \"\";\n if ([\"oklab\", \"oklch\"].includes(model) && color.l > 1) {\n color.l = round(color.l / 100, PRECISION);\n }\n if (alpha) {\n alphaPrefix = convertAlphaToHex(alpha);\n }\n result = `${converters_exports[`${model}2hex`](colorParams(color))}${alphaPrefix}`;\n break;\n }\n }\n return result;\n}\n\n// src/modules/parse-color.ts\nfunction parseColor(color) {\n invariant(!!color, MESSAGES.input);\n const output = {};\n if (isString(color)) {\n const { alpha = 1 } = extractColorParts(color);\n const type = isHex(color) ? \"hex\" : extractColorParts(color).model;\n output.hex = addAlphaToHex(parseCSS(color, \"hex\"), alpha);\n output.hsl = addAlpha(parseCSS(color, \"hsl\"), alpha);\n output.oklab = addAlpha(parseCSS(color, \"oklab\"), alpha);\n output.oklch = addAlpha(parseCSS(color, \"oklch\"), alpha);\n output.rgb = addAlpha(parseCSS(color, \"rgb\"), alpha);\n output.alpha = alpha;\n output.type = type;\n } else if (isPlainObject(color)) {\n const { alpha = 1 } = color;\n if (isHSL(color)) {\n output.hsl = {\n h: limit(color.h, \"hsl\", \"h\"),\n s: limit(color.s, \"hsl\", \"s\"),\n l: limit(color.l, \"hsl\", \"l\")\n };\n output.rgb = hsl2rgb(output.hsl);\n output.oklab = hsl2oklab(output.hsl);\n output.oklch = hsl2oklch(output.hsl);\n output.type = \"hsl\";\n } else if (isLAB(color)) {\n output.hsl = oklab2hsl(color);\n output.oklab = color;\n output.oklch = oklab2oklch(color);\n output.rgb = oklab2rgb(color);\n output.type = \"oklab\";\n } else if (isLCH(color)) {\n output.hsl = oklch2hsl(color);\n output.oklab = oklch2oklab(color);\n output.oklch = color;\n output.rgb = oklch2rgb(color);\n output.type = \"oklch\";\n } else if (isRGB(color)) {\n output.rgb = {\n r: limit(color.r, \"rgb\", \"r\"),\n g: limit(color.g, \"rgb\", \"g\"),\n b: limit(color.b, \"rgb\", \"b\")\n };\n output.hsl = rgb2hsl(output.rgb);\n output.oklab = rgb2oklab(output.rgb);\n output.oklch = rgb2oklch(output.rgb);\n output.type = \"rgb\";\n } else {\n throw new Error(\"invalid color\");\n }\n output.hex = addAlphaToHex(hsl2hex(output.hsl), alpha);\n output.hsl = addAlpha(output.hsl, alpha);\n output.oklab = addAlpha(output.oklab, alpha);\n output.oklch = addAlpha(output.oklch, alpha);\n output.rgb = addAlpha(output.rgb, alpha);\n output.alpha = alpha;\n } else {\n throw new Error(MESSAGES.input);\n }\n return output;\n}\n\n// src/brightness-difference.ts\nfunction brightnessDifference(left, right, precision = PRECISION) {\n invariant(isString(left), MESSAGES.left);\n invariant(isString(right), MESSAGES.right);\n const RGBLeft = parseCSS(left, \"rgb\");\n const RGBRight = parseCSS(right, \"rgb\");\n const brightnessLeft = (RGBLeft.r * 299 + RGBLeft.g * 587 + RGBLeft.b * 114) / 1e3;\n const brightnessRight = (RGBRight.r * 299 + RGBRight.g * 587 + RGBRight.b * 114) / 1e3;\n return round(Math.abs(brightnessRight - brightnessLeft), precision);\n}\n\n// src/chroma.ts\nfunction chroma(input) {\n invariant(isString(input), MESSAGES.inputString);\n const { r, g, b } = parseCSS(input, \"rgb\");\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n return round((max - min) / 255, 4);\n}\n\n// src/color-difference.ts\nfunction colorDifference(left, right) {\n invariant(isString(left), MESSAGES.left);\n invariant(isString(right), MESSAGES.right);\n const RGBLeft = parseCSS(left, \"rgb\");\n const RGBRight = parseCSS(right, \"rgb\");\n return Math.max(RGBLeft.r, RGBRight.r) - Math.min(RGBLeft.r, RGBRight.r) + (Math.max(RGBLeft.g, RGBRight.g) - Math.min(RGBLeft.g, RGBRight.g)) + (Math.max(RGBLeft.b, RGBRight.b) - Math.min(RGBLeft.b, RGBRight.b));\n}\n\n// src/luminance.ts\nfunction luminance(input) {\n invariant(isString(input), MESSAGES.inputString);\n const { r, g, b } = parseCSS(input, \"rgb\");\n const rgb = [r / 255, g / 255, b / 255];\n for (let index = 0; index < rgb.length; index++) {\n if (rgb[index] <= 0.03928) {\n rgb[index] /= 12.92;\n } else {\n rgb[index] = ((rgb[index] + 0.055) / 1.055) ** 2.4;\n }\n }\n return round(0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2], 4);\n}\n\n// src/contrast.ts\nfunction contrast(left, right) {\n invariant(isString(left), MESSAGES.left);\n invariant(isString(right), MESSAGES.right);\n const LuminanceLeft = luminance(left);\n const LuminanceRight = luminance(right);\n return round(\n LuminanceLeft >= LuminanceRight ? (LuminanceLeft + 0.05) / (LuminanceRight + 0.05) : (LuminanceRight + 0.05) / (LuminanceLeft + 0.05)\n );\n}\n\n// src/compare.ts\nfunction compare(left, right) {\n invariant(isString(left), MESSAGES.left);\n invariant(isString(right), MESSAGES.right);\n const colorThreshold = 500;\n const brightnessThreshold = 125;\n const colorDifference2 = colorDifference(left, right);\n const contrast2 = contrast(left, right);\n const brightnessDifference2 = brightnessDifference(left, right);\n const isBright = brightnessDifference2 >= brightnessThreshold;\n const hasEnoughDifference = colorDifference2 >= colorThreshold;\n let compliant = 0;\n if (isBright && hasEnoughDifference) {\n compliant = 2;\n } else if (isBright || hasEnoughDifference) {\n compliant = 1;\n }\n return {\n brightnessDifference: brightnessDifference2,\n colorDifference: colorDifference2,\n compliant,\n contrast: contrast2,\n largeAA: contrast2 >= 3,\n largeAAA: contrast2 >= 4.5,\n normalAA: contrast2 >= 4.5,\n normalAAA: contrast2 >= 7\n };\n}\n\n// src/format-css.ts\nfunction getColorModel(input) {\n if (isHex(input) || isNamedColor(input)) {\n return \"hex\";\n }\n if (isString(input)) {\n return extractColorParts(input).model;\n } else if (isHSL(input)) {\n return \"hsl\";\n } else if (isLAB(input)) {\n return \"oklab\";\n } else if (isLCH(input)) {\n return \"oklch\";\n } else if (isRGB(input)) {\n return \"rgb\";\n }\n throw new Error(MESSAGES.invalid);\n}\nfunction getColorValue(input, output) {\n const value = isNamedColor(input) ? cssColors[input.toLowerCase()] : input;\n const from = getColorModel(value);\n if (from === output) {\n return value;\n }\n const converterKey = `${from}2${output}`;\n const converter = converters_exports[converterKey];\n if (!converter) {\n throw new Error(`Converter not found for ${from} to ${output}`);\n }\n switch (from) {\n case \"hex\": {\n if (output === \"hex\") {\n return value;\n }\n return converter(value);\n }\n case \"hsl\": {\n if (output === \"hsl\") {\n return value;\n }\n return converter(value);\n }\n case \"oklab\": {\n if (output === \"oklab\") {\n return value;\n }\n return converter(value);\n }\n case \"oklch\": {\n if (output === \"oklch\") {\n return value;\n }\n return converter(value);\n }\n default: {\n if (output === \"rgb\") {\n return value;\n }\n return converter(value);\n }\n }\n}\nfunction formatCSS(input, options = {}) {\n invariant(isHex(input) || isValidColorModel(input), MESSAGES.invalid);\n const { alpha, format = \"hex\", precision = PRECISION, separator: baseSeparator = \" \" } = options;\n const opacity2 = alpha && alpha !== 1 ? `${round(alpha * 100)}%` : null;\n let params = [];\n let separator = baseSeparator;\n switch (format) {\n case \"hsl\": {\n const { h, s, l } = getColorValue(input, \"hsl\");\n params = [h, `${s}%`, `${l}%`];\n break;\n }\n case \"oklab\": {\n separator = \" \";\n const { l, a, b } = restrictValues(getColorValue(input, \"oklab\"), precision);\n params = [`${round(l * 100, precision)}%`, a, b];\n break;\n }\n case \"oklch\": {\n separator = \" \";\n const { l, c, h } = restrictValues(getColorValue(input, \"oklch\"), precision);\n params = [`${round(l * 100, precision)}%`, c, h];\n break;\n }\n case \"rgb\": {\n const { r, g, b } = getColorValue(input, \"rgb\");\n params = [r, g, b];\n break;\n }\n default: {\n const hex = removeAlphaFromHex(getColorValue(input, \"hex\"));\n if (alpha && alpha !== 1) {\n return `${hex}${convertAlphaToHex(alpha)}`;\n }\n return hex;\n }\n }\n return `${format}(${params.join(separator)}${opacity2 ? ` / ${opacity2}` : \"\"})`;\n}\n\n// src/modules/updater.ts\nfunction updater(key, operator, format) {\n return (input, amount) => {\n invariant(isString(input), MESSAGES.inputString);\n invariant(isNumber(amount), MESSAGES.alpha);\n const color = parseCSS(input, \"hsl\");\n const output = isHex(input) || isNamedColor(input) ? \"hex\" : extractColorParts(input).model;\n return formatCSS(\n {\n ...color,\n [key]: clamp(color[key] + (operator === \"+\" ? amount : -amount), 0, 100)\n },\n { format: format ?? output }\n );\n };\n}\n\n// src/darken.ts\nfunction darken(input, amount, format) {\n return updater(\"l\", \"-\", format)(input, amount);\n}\n\n// src/desaturate.ts\nfunction desaturate(input, amount, format) {\n return updater(\"s\", \"-\", format)(input, amount);\n}\n\n// src/rotate.ts\nfunction rotate(input, degrees, format) {\n invariant(isString(input), MESSAGES.inputString);\n invariant(isNumber(degrees), \"degrees must be a number\");\n const color = parseCSS(input, \"hsl\");\n const output = isHex(input) || isNamedColor(input) ? \"hex\" : extractColorParts(input).model;\n return formatCSS(\n {\n ...color,\n h: constrainDegrees(color.h, degrees)\n },\n { format: format ?? output }\n );\n}\n\n// src/invert.ts\nfunction invert(input) {\n invariant(isString(input), MESSAGES.inputString);\n const format = isHex(input) || isNamedColor(input) ? \"hex\" : extractColorParts(input).model;\n const hex = parseCSS(input, \"hex\");\n return formatCSS(rotate(hex, 180), { format });\n}\n\n// src/lighten.ts\nfunction lighten(input, amount, format) {\n return updater(\"l\", \"+\", format)(input, amount);\n}\n\n// src/opacify.ts\nfunction opacify(input, alpha, format) {\n invariant(isString(input), MESSAGES.inputString);\n invariant(isNumber(alpha), MESSAGES.alpha);\n const type = isHex(input) || isNamedColor(input) ? \"hex\" : extractColorParts(input).model;\n const rgb = parseCSS(input, \"rgb\");\n return formatCSS(rgb, { format: format ?? type, alpha });\n}\n\n// src/opacity.ts\nfunction opacity(input) {\n invariant(isString(input), MESSAGES.inputString);\n if (isHex(input)) {\n return extractAlphaFromHex(input);\n } else if (Object.keys(cssColors).includes(input)) {\n return 1;\n }\n const { alpha } = extractColorParts(input);\n if (!alpha) {\n return 1;\n }\n return alpha;\n}\n\n// src/saturate.ts\nfunction saturate(input, amount, format) {\n return updater(\"s\", \"+\", format)(input, amount);\n}\n\n// src/text-color.ts\nfunction textColor(input, options = {}) {\n const { darkColor = \"#000000\", lightColor = \"#ffffff\", threshold = 128 } = options;\n invariant(isString(input), MESSAGES.inputString);\n invariant(threshold >= 0 && threshold <= 255, MESSAGES.threshold);\n try {\n const { r, g, b } = hex2rgb(parseCSS(input, \"hex\"));\n const yiq = (r * 299 + g * 587 + b * 114) / 1e3;\n return yiq >= threshold ? darkColor : lightColor;\n } catch (error) {\n console.warn(`Invalid color input: ${input}`);\n console.warn(error);\n return darkColor;\n }\n}\n\n// src/transparentize.ts\nfunction transparentize(input, alpha, format) {\n invariant(isString(input), MESSAGES.inputString);\n invariant(isNumber(alpha), MESSAGES.alpha);\n invariant(alpha >= -1 && alpha <= 1, MESSAGES.alpha);\n const oklch = parseCSS(input, \"oklab\");\n const value = round(clamp(opacity(input) - alpha, 0, 1));\n return formatCSS(oklch, { format, alpha: value });\n}\n\n// src/colorizr.ts\nvar Colorizr = class {\n constructor(color, options = {}) {\n __publicField(this, \"alpha\");\n __publicField(this, \"hex\");\n __publicField(this, \"hsl\");\n __publicField(this, \"oklab\");\n __publicField(this, \"oklch\");\n __publicField(this, \"rgb\");\n __publicField(this, \"type\");\n invariant(!!color, \"color is required\");\n const { alpha, hex, hsl, oklab, oklch, rgb, type } = parseColor(color);\n this.hex = hex;\n this.hsl = hsl;\n this.oklab = oklab;\n this.oklch = oklch;\n this.rgb = rgb;\n this.alpha = alpha;\n this.type = options.format ?? type;\n }\n /**\n * Get css string\n */\n get css() {\n return this.selectedColor;\n }\n /**\n * Get the red value\n */\n get red() {\n return Number(this.rgb.r);\n }\n /**\n * Get the green value\n */\n get green() {\n return Number(this.rgb.g);\n }\n /**\n * Get the blue value\n */\n get blue() {\n return Number(this.rgb.b);\n }\n /**\n * Get the hue value\n */\n get hue() {\n return Number(this.hsl.h);\n }\n /**\n * Get the saturation value\n */\n get saturation() {\n return Number(this.hsl.s);\n }\n /**\n * Get the lightness value\n */\n get lightness() {\n return Number(this.hsl.l);\n }\n /**\n * Get the luminance value\n */\n get luminance() {\n return luminance(this.selectedColor);\n }\n /**\n * Get the chroma value\n */\n get chroma() {\n return chroma(this.selectedColor);\n }\n get opacity() {\n return opacity(this.selectedColor);\n }\n /**\n * Get the contrasted color\n */\n get textColor() {\n return textColor(this.selectedColor);\n }\n get selectedColor() {\n return formatCSS(this[this.type], { format: this.type, alpha: this.alpha });\n }\n brightnessDifference(input) {\n return brightnessDifference(this.selectedColor, input);\n }\n colorDifference(input) {\n return colorDifference(this.selectedColor, input);\n }\n /**\n * Test 2 colors for compliance\n */\n compare(input) {\n return compare(this.selectedColor, input);\n }\n contrast(input) {\n return contrast(this.selectedColor, input);\n }\n format(type, precision) {\n return formatCSS(this.rgb, {\n alpha: this.alpha,\n format: type,\n precision\n });\n }\n /**\n * Increase lightness\n */\n lighten(amount) {\n return lighten(this.selectedColor, amount);\n }\n /**\n * Decrease lightness\n */\n darken(amount) {\n return darken(this.selectedColor, amount);\n }\n /**\n * Increase saturation\n */\n saturate(amount) {\n return saturate(this.selectedColor, amount);\n }\n /**\n * Decrease saturation\n */\n desaturate(amount) {\n return desaturate(this.selectedColor, amount);\n }\n /**\n * Invert color\n */\n invert() {\n return invert(this.selectedColor);\n }\n /**\n * Add opacity to the color.\n */\n opacify(alpha = 0.9) {\n return opacify(this.selectedColor, alpha, this.type);\n }\n /**\n * Rotate color\n */\n rotate(degrees) {\n return rotate(this.selectedColor, degrees);\n }\n /**\n * Make the color more transparent\n */\n transparentize(alpha = 0.1) {\n return transparentize(this.selectedColor, alpha, this.type);\n }\n};\n\n// src/convert.ts\nfunction convert(input, format) {\n const value = parseCSS(input, format);\n return formatCSS(value, { format });\n}\n\n// src/is-valid-color.ts\nfunction isValidColor(input) {\n try {\n parseCSS(input);\n return true;\n } catch {\n return false;\n }\n}\n\n// src/name.ts\nfunction name(input) {\n invariant(isString(input), MESSAGES.inputString);\n const hex = parseCSS(input, \"hex\");\n const [color] = Object.entries(cssColors).find(([, value]) => value === hex) || [];\n return color ?? hex;\n}\n\n// src/palette.ts\nfunction palette(input, options = {}) {\n invariant(isString(input), MESSAGES.inputString);\n invariant(isPlainObject(options), MESSAGES.options);\n const { format, lightness, saturation, size = 6, type } = options;\n const hsl = parseCSS(input, \"hsl\");\n const colorFormat = isHex(input) || isNamedColor(input) ? \"hex\" : extractColorParts(input).model;\n const output = [];\n if (type === \"monochromatic\") {\n const step = 80 / size;\n for (let index = size; index > 0; index--) {\n output.push(hsl2hex({ ...hsl, l: step * index }));\n }\n } else {\n const step = 360 / size;\n output.push(hsl2hex({ ...hsl, l: lightness ?? hsl.l, s: saturation ?? hsl.s }));\n for (let index = 1; index < size; index++) {\n const color = rotate(input, hsl.h + step * index, \"hex\");\n output.push(hsl2hex({ ...hex2hsl(color), l: lightness ?? hsl.l, s: saturation ?? hsl.s }));\n }\n }\n return output.map((color) => convert(color, format ?? colorFormat));\n}\n\n// src/p3.ts\nfunction multiplyMatrix(matrix, vector) {\n return [\n matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2],\n matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2],\n matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2]\n ];\n}\nfunction isInP3Gamut(color) {\n const epsilon = 1e-6;\n return color.every((component) => component >= 0 - epsilon && component <= 1 + epsilon);\n}\nfunction oklabToLinearSRGB(L, a, b) {\n const l = (L + LAB_TO_LMS.l[0] * a + LAB_TO_LMS.l[1] * b) ** 3;\n const m = (L + LAB_TO_LMS.m[0] * a + LAB_TO_LMS.m[1] * b) ** 3;\n const s = (L + LAB_TO_LMS.s[0] * a + LAB_TO_LMS.s[1] * b) ** 3;\n return [\n LSM_TO_RGB.r[0] * l + LSM_TO_RGB.r[1] * m + LSM_TO_RGB.r[2] * s,\n LSM_TO_RGB.g[0] * l + LSM_TO_RGB.g[1] * m + LSM_TO_RGB.g[2] * s,\n LSM_TO_RGB.b[0] * l + LSM_TO_RGB.b[1] * m + LSM_TO_RGB.b[2] * s\n ];\n}\nfunction oklabToLinearP3(L, a, b) {\n const srgb = oklabToLinearSRGB(L, a, b);\n return multiplyMatrix(SRGB_TO_P3, srgb);\n}\nfunction getOkLCHMaxChroma(input, precision = PRECISION) {\n const { l, h } = isString(input) ? parseCSS(input, \"oklch\") : input;\n invariant(isNumber(l) && l >= 0 && l <= 1, MESSAGES.lightnessRange);\n invariant(isNumber(h) && h >= 0 && h <= 360, MESSAGES.hueRange);\n const epsilon = 1e-6;\n let low = 0;\n let high = 0.5;\n while (high - low > epsilon) {\n const mid = (low + high) / 2;\n const { l: L, a, b } = oklch2oklab({ l, c: mid, h }, 16);\n const p3Color = oklabToLinearP3(L, a, b);\n if (isInP3Gamut(p3Color)) {\n low = mid;\n } else {\n high = mid;\n }\n }\n return round(low, precision);\n}\nfunction getP3Color(input) {\n const lch = isString(input) ? parseCSS(input, \"oklch\") : input;\n return `oklch(${lch.l} ${getOkLCHMaxChroma(lch)} ${lch.h})`;\n}\n\n// src/random.ts\nfunction random(type = \"hex\") {\n const hsl = {\n h: Math.floor(Math.random() * 360) + 1,\n s: Math.floor(Math.random() * 90) + 10,\n l: Math.floor(Math.random() * 80) + 10\n };\n return formatCSS(hsl, { format: type });\n}\n\n// src/scheme.ts\nfunction scheme(input, typeOrOptions) {\n invariant(isString(input), MESSAGES.inputString);\n const { format, type = \"complementary\" } = isString(typeOrOptions) ? { type: typeOrOptions } : typeOrOptions ?? {};\n const output = isHex(input) || isNamedColor(input) ? \"hex\" : extractColorParts(input).model;\n const colors = [];\n switch (type) {\n case \"analogous\": {\n colors.push(rotate(input, -30), input, rotate(input, 30));\n break;\n }\n case \"complementary\": {\n colors.push(input, rotate(input, 180));\n break;\n }\n case \"split\":\n case \"split-complementary\": {\n colors.push(input, rotate(input, 150), rotate(input, 210));\n break;\n }\n case \"triadic\": {\n colors.push(input, rotate(input, 120), rotate(input, 240));\n break;\n }\n case \"tetradic\":\n case \"rectangle\": {\n colors.push(input, rotate(input, 60), rotate(input, 180), rotate(input, 240));\n break;\n }\n case \"square\": {\n colors.push(input, rotate(input, 90), rotate(input, 180), rotate(input, 270));\n break;\n }\n default: {\n throw new TypeError(\"invalid type\");\n }\n }\n return colors.map((color) => convert(color, format ?? output));\n}\n\n// src/swatch.ts\nfunction shadeColor(input, lightness) {\n const { c, h } = input;\n const chromaScale = c === 0 ? 1 : 4 * lightness * (1 - lightness);\n const chroma2 = c * chromaScale;\n const adjustedChroma = clamp(chroma2, 0, 0.4);\n return { l: lightness, c: adjustedChroma, h };\n}\nfunction swatch(input, options = {}) {\n invariant(isString(input), MESSAGES.inputString);\n const {\n format,\n lightnessFactor = 1.5,\n maxLightness = 0.97,\n minLightness = 0.2,\n scale = \"dynamic\",\n variant = \"base\"\n } = options;\n invariant(\n maxLightness > minLightness && maxLightness <= 1 && minLightness >= 0,\n \"maxLightness must be greater than minLightness and within the range [0, 1].\"\n );\n const lch = parseCSS(input, \"oklch\");\n const chromaScale = {\n base: 1,\n deep: 0.8,\n neutral: 0.5,\n pastel: 0.3,\n subtle: 0.2,\n vibrant: 1.25\n }[variant];\n lch.l = 0.7;\n lch.c *= chromaScale;\n if (variant === \"deep\") {\n lch.l *= 0.7;\n }\n const colorFormat = isHex(input) || isNamedColor(input) ? \"hex\" : extractColorParts(input).model;\n const steps = 11;\n let palette2 = {};\n if (scale === \"dynamic\") {\n for (let index = 0; index < steps; index++) {\n const lightness = maxLightness - (maxLightness - minLightness) * (index / (steps - 1)) ** lightnessFactor;\n let tone = index * 100;\n if (index === 0) {\n tone = 50;\n } else if (index === 10) {\n tone = 950;\n }\n palette2[tone] = lightness;\n }\n } else {\n palette2 = {\n 50: 0.97,\n 100: 0.92,\n 200: 0.85,\n 300: 0.78,\n 400: 0.69,\n 500: 0.57,\n 600: 0.46,\n 700: 0.35,\n 800: 0.24,\n 900: 0.18,\n 950: 0.1\n };\n }\n const output = Object.entries(palette2).reduce(\n (acc, [key, value]) => {\n acc[Number(key)] = shadeColor(lch, value);\n return acc;\n },\n {}\n );\n return Object.entries(output).reduce((acc, [key, value]) => {\n return {\n ...acc,\n [key]: formatCSS(value, { format: format ?? colorFormat })\n };\n }, {});\n}\n\n// src/index.ts\nvar index_default = Colorizr;\nexport {\n addAlphaToHex,\n brightnessDifference,\n chroma,\n colorDifference,\n compare,\n contrast,\n convert,\n convertAlphaToHex,\n darken,\n index_default as default,\n desaturate,\n extractAlphaFromHex,\n extractColorParts,\n formatCSS,\n formatHex,\n getOkLCHMaxChroma,\n getP3Color,\n hex2hsl,\n hex2oklab,\n hex2oklch,\n hex2rgb,\n hexadecimalToNumber,\n hsl2hex,\n hsl2oklab,\n hsl2oklch,\n hsl2rgb,\n isHSL,\n isHex,\n isLAB,\n isLCH,\n isRGB,\n isValidColor,\n lighten,\n luminance,\n name,\n oklab2hex,\n oklab2hsl,\n oklab2oklch,\n oklab2rgb,\n oklch2hex,\n oklch2hsl,\n oklch2oklab,\n oklch2rgb,\n opacify,\n opacity,\n palette,\n parseCSS,\n random,\n removeAlphaFromHex,\n rgb2hex,\n rgb2hsl,\n rgb2oklab,\n rgb2oklch,\n rotate,\n saturate,\n scheme,\n swatch,\n textColor,\n transparentize\n};\n//# sourceMappingURL=index.mjs.map","export const isHsl = (v) => {\n if (typeof v === `object`) {\n if (!(`h` in v && `s` in v && `l` in v))\n return false;\n if (!(`unit` in v))\n return false;\n if (`space` in v) {\n if (v.space !== `hsl`)\n return false;\n }\n }\n return false;\n};\nexport const isRgb = (v) => {\n if (typeof v === `object`) {\n if (!(`r` in v && `g` in v && `b` in v))\n return false;\n if (!(`unit` in v))\n return false;\n if (`space` in v) {\n if (v.space !== `srgb`)\n return false;\n }\n }\n return false;\n};\n/**\n * If the input object has r,g&b properties, it will return a fully-\n * formed Rgb type with `unit` and `space` properties.\n *\n * If it lacks these basic three properties or they are out of range,\n * _undefined_ is returned.\n *\n * If RGB values are less than 1 assumes unit:scalar. Otherwise unit:8bit.\n * If RGB values exceed 255, _undefined_ returned.\n * @param v\n * @returns\n */\nexport const tryParseObjectToRgb = (v) => {\n if (!(`r` in v && `g` in v && `b` in v))\n return;\n if (!(`unit` in v)) {\n if (v.r <= 1 && v.g <= 1 && v.b <= 1) {\n v.unit = `scalar`;\n }\n else if (v.r > 255 && v.g <= 255 && v.b <= 255) {\n return; // out of range\n }\n else {\n v.unit = `8bit`;\n }\n }\n if (!(`space` in v)) {\n v.space = `srgb`;\n }\n return v;\n};\nexport const tryParseObjectToHsl = (v) => {\n if (!(`h` in v && `s` in v && `l` in v))\n return;\n if (!(`unit` in v)) {\n if (v.r <= 1 && v.g <= 1 && v.b <= 1) {\n v.unit = `scalar`;\n }\n else if (v.s > 100 && v.l <= 100) {\n return; // out of range\n }\n else {\n v.unit = `absolute`;\n }\n }\n if (!(`space` in v)) {\n v.space = `hsl`;\n }\n return v;\n};\nexport const isLch = (v) => {\n if (typeof v === `object`) {\n if (!(`l` in v && `c` in v && `h` in v))\n return false;\n if (!(`unit` in v))\n return false;\n if (`space` in v) {\n if (v.space === `lch`)\n return true;\n if (v.space == `oklch`)\n return true;\n }\n }\n return false;\n};\nexport const isColourish = (v) => {\n if (typeof v === `string`)\n return true;\n if (typeof v !== `object`)\n return false;\n if (isHsl(v))\n return true;\n if (isLch(v))\n return true;\n if (isRgb(v))\n return true;\n return false;\n};\n","import Colorizr, * as C from \"colorizr\";\nimport { numberInclusiveRangeTest, numberTest, percentTest } from \"@ixfx/guards\";\nimport { resultThrow } from \"@ixfx/guards\";\nimport { cssDefinedHexColours } from \"./css-colours.js\";\nimport { angleConvert, angleParse } from \"@ixfx/geometry\";\nimport { clamp, interpolate } from \"@ixfx/numbers\";\nimport { isRgb } from \"./guards.js\";\nimport { calculateHueDistance, wrapScalarHue } from \"./utility.js\";\nimport { parseCssRgbFunction, to8bit as rgbTo8bit, toLibraryHsl as rgbToLibraryHsl } from \"./srgb.js\";\n/**\n * Scales the opacity value of an input HSL value\n * ```js\n * withOpacity()\n * ```\n * @param value\n * @param fn\n * @returns\n */\nexport const withOpacity = (value, fn) => {\n switch (value.unit) {\n case `absolute`:\n return {\n ...value,\n opacity: fn((value.opacity ?? 100) / 100, value) * 100\n };\n case `scalar`:\n return {\n ...value,\n opacity: fn((value.opacity ?? 1), value)\n };\n }\n};\n/**\n * Increases or decreases lightness by this percentage, returning new colour\n *\n * Amount to change:\n * * 'fixed': a fixed amount\n * * 'delta': increase/decrease by this amount\n * * 'pdelta': proportion of current value to change by ('percentage delta')\n *\n * ```\n * const colour = { h: 0.5, s: 0.5, l: 0.5, space: `hsl`, unit: `scalar` };\n * changeLightness(colour, { pdelta: 0.1 }); // l: 0.55\n * changeLightness(colour, { delta: 0.1 }); // l: 0.6\n * changeLightness(colour, { fixed: 0.5 }); // l: 0.5\n * ```\n *\n * Keep in mind the numerical value will depend on the unit of `value`. If it's scalar,\n * lightness is 0..1 scale, otherwise 0..100 scale.\n *\n * Use negative values to decrease (does not apply to 'fixed')\n * @param value\n * @param amount\n */\nexport const changeLightness = (value, amount) => {\n let newL = 0;\n if (typeof amount.pdelta !== `undefined`) {\n newL = value.l + (value.l * amount.pdelta);\n }\n else if (typeof amount.delta !== `undefined`) {\n newL = amount.delta + value.l;\n }\n else if (typeof amount.fixed !== `undefined`) {\n if (amount.fixed < 0)\n throw new TypeError(`Cannot use negative value with 'fixed'`);\n newL = amount.fixed;\n }\n else {\n throw new TypeError(`Parameter 'amount' is missing 'delta/pdelta/fixed' properties`);\n }\n return {\n ...value,\n l: scaleProperty(value, newL, `l`)\n };\n};\nconst scaleProperty = (hsl, value, property) => {\n if (hsl.unit === `scalar`) {\n // 0..1 scale\n if (value > 1)\n value = 1;\n else if (value < 0)\n value = 0;\n }\n else {\n // 0..100 scale\n if (value > 100)\n value = 100;\n else if (value < 0)\n value = 0;\n }\n return value;\n};\nconst hslTransparent = Object.freeze({\n h: 0, s: 0, l: 0, opacity: 0, unit: `absolute`, space: `hsl`\n});\nexport function fromHexString(hexString, options = {}) {\n return fromLibrary(C.hex2hsl(hexString), options);\n}\nexport function fromCss(value, options = {}) {\n value = value.toLowerCase();\n if (value.startsWith(`hsla(`))\n throw new Error(`hsla() not supported`);\n if (value.startsWith(`rgba(`))\n throw new Error(`rgba() not supported`);\n if (value.startsWith(`#`)) {\n return fromHexString(value, options);\n }\n if (value === `transparent`)\n return hslTransparent;\n if (typeof cssDefinedHexColours[value] !== `undefined`) {\n return fromHexString(cssDefinedHexColours[value], options);\n }\n if (value.startsWith(`rgb(`)) {\n const hsl = rgbToLibraryHsl(value);\n return fromLibrary(hsl, options);\n }\n if (!value.startsWith(`hsl(`)) {\n try {\n value = C.convert(value, `hsl`);\n }\n catch (error) {\n if (options.fallbackString) {\n value = options.fallbackString;\n }\n else {\n throw error;\n }\n }\n }\n try {\n // Hand-rolled hsl() parse because the package is broken\n const hsl = parseCssHslFunction(value);\n if (options.scalar)\n return toScalar(hsl);\n return toAbsolute(hsl);\n }\n catch (error) {\n if (options.fallbackColour)\n return options.fallbackColour;\n throw error;\n }\n}\nexport const toCssString = (hsl) => {\n const abs = toAbsolute(hsl);\n let css = `hsl(${abs.h}deg ${abs.s}% ${abs.l}%`;\n if (`opacity` in abs && abs.opacity !== undefined && abs.opacity < 100) {\n css += ` / ${abs.opacity}%`;\n }\n css += ')';\n return css;\n};\nconst toLibrary = (hsl) => {\n const abs = toAbsolute(hsl);\n return {\n h: abs.h,\n s: abs.s,\n l: abs.l,\n alpha: abs.opacity,\n };\n};\nfunction fromLibrary(hsl, parsingOptions = {}) {\n if (typeof hsl === `undefined` || hsl === null) {\n if (parsingOptions.fallbackColour)\n return parsingOptions.fallbackColour;\n }\n const scalarOpt = parsingOptions.scalar ?? true;\n // Library result is absolute\n resultThrow(numberInclusiveRangeTest(hsl.h, 0, 360, `h`), numberInclusiveRangeTest(hsl.s, 0, 100, `s`), numberInclusiveRangeTest(hsl.l, 0, 100, `l`), percentTest((hsl.alpha ?? 1), `alpha`)\n // () => hsl.alpha !== undefined ? numberInclusiveRangeTest(hsl.alpha, 0, 100, `alpha`) : { success: true, value: hsl },\n );\n if (scalarOpt) {\n return scalar(hsl.h / 360, hsl.s / 100, hsl.l / 100, (hsl.alpha ?? 1));\n }\n else {\n return absolute(hsl.h, hsl.s, hsl.l, (hsl.alpha ?? 1) * 100);\n }\n}\nexport const toAbsolute = (hslOrString) => {\n // if (typeof hslOrString === `string`) {\n // return toAbsolute(fromLibrary(C.parseCSS(hslOrString, `hsl`), { scalar: false }));\n // }\n if (typeof hslOrString === `string`) {\n return fromCss(hslOrString, { scalar: false });\n // try {\n // return toScalar(fromLibrary(C.parseCSS(hslOrString, `hsl`), { scalar: true }));\n // } catch (error) {\n // console.error(`Hsl.toScalar: ${ hslOrString }`);\n // throw error;\n // }\n }\n if (isRgb(hslOrString)) {\n return toAbsolute(fromLibrary(rgbToLibraryHsl(hslOrString), { scalar: false }));\n }\n const hsl = hslOrString;\n guard(hsl);\n if (hsl.unit === `absolute`)\n return hsl;\n return {\n h: hsl.h * 360,\n s: hsl.s * 100,\n l: hsl.l * 100,\n opacity: (hsl.opacity ?? 1) * 100,\n unit: `absolute`,\n space: `hsl`\n };\n};\n/**\n * Generates a {@link HslScalar} value.\n *\n * ```js\n * generateScaler(10); // 10deg, default to full saturation, half lightness and full opacity\n *\n * // Generate HSL value from radian angle and 50% saturation\n * generateScalar(`10rad`, 0.5);\n *\n * // Generate from numeric CSS variable\n * generateScalar(`--hue`);\n * ```\n * @param absoluteHslOrVariable Hue angle or CSS variable\n * @param saturation\n * @param lightness\n * @param opacity\n */\nexport const generateScalar = (absoluteHslOrVariable, saturation = 1, lightness = 0.5, opacity = 1) => {\n if (typeof absoluteHslOrVariable === `string`) {\n if (absoluteHslOrVariable.startsWith(`--`)) {\n absoluteHslOrVariable = getComputedStyle(document.body).getPropertyValue(absoluteHslOrVariable).trim();\n }\n }\n const hue = angleParse(absoluteHslOrVariable);\n if (saturation > 1)\n throw new TypeError(`Param 'saturation' must be between 0..1`);\n if (lightness > 1)\n throw new TypeError(`Param 'lightness' must be between 0..1`);\n if (opacity > 1)\n throw new TypeError(`Param 'opacity' must be between 0..1`);\n const hueDeg = angleConvert(hue, `deg`).value / 360;\n return {\n h: hueDeg,\n s: saturation,\n l: lightness,\n opacity: opacity,\n unit: `scalar`,\n space: `hsl`\n };\n};\n/**\n * Converts a {@link Hsl} value to scalar units, or parses a colour string\n * and converts it.\n *\n * ```js\n * toScalar({ h: 100, s: 50, l: 100, unit: `absolute` });\n * toScalar(`red`);\n * ```\n * @param hslOrString\n * @returns\n */\nexport const toScalar = (hslOrString) => {\n if (typeof hslOrString === `string`) {\n return fromCss(hslOrString, { scalar: true });\n // try {\n // return toScalar(fromLibrary(C.parseCSS(hslOrString, `hsl`), { scalar: true }));\n // } catch (error) {\n // console.error(`Hsl.toScalar: ${ hslOrString }`);\n // throw error;\n // }\n }\n if (isRgb(hslOrString)) {\n return toScalar(fromLibrary(rgbToLibraryHsl(hslOrString), { scalar: true }));\n }\n const hsl = hslOrString;\n guard(hsl);\n if (hsl.unit === `scalar`)\n return hsl;\n return {\n h: hsl.h / 360,\n s: hsl.s / 100,\n l: hsl.l / 100,\n opacity: (hsl.opacity ?? 1) / 100,\n unit: `scalar`,\n space: `hsl`\n };\n};\nexport const guard = (hsl) => {\n const { h, s, l, opacity, space, unit } = hsl;\n if (space !== `hsl`)\n throw new Error(`Space is expected to be 'hsl'. Got: ${space}`);\n if (unit === `absolute`) {\n resultThrow(numberTest(h, `finite`, `h`), numberInclusiveRangeTest(s, 0, 100, `s`), numberInclusiveRangeTest(l, 0, 100, `l`), () => {\n if (typeof opacity === `number`) {\n return numberInclusiveRangeTest(opacity, 0, 100, `opacity`);\n }\n });\n }\n else if (unit === `scalar`) {\n resultThrow(numberTest(h, `percentage`, `h`), numberTest(s, `percentage`, `s`), numberTest(l, `percentage`, `l`), () => {\n if (typeof opacity === `number`) {\n return numberTest(opacity, `percentage`, `opacity`);\n }\n });\n }\n else {\n throw new Error(`Unit is expected to be 'absolute' or 'scalar'. Got: ${unit}`);\n }\n};\nexport const interpolator = (a, b, direction = `shorter`) => {\n a = toScalar(a);\n b = toScalar(b);\n const aOpacity = a.opacity ?? 1;\n const distanceCalc = calculateHueDistance(a.h, b.h, 1);\n const hueDistance = direction === `longer` ? distanceCalc.long : distanceCalc.short;\n const satDistance = b.s - a.s;\n const lightDistance = b.l - a.l;\n const opacityDistance = (b.opacity ?? 1) - aOpacity;\n return (amount) => {\n amount = clamp(amount);\n let h = interpolate(amount, 0, Math.abs(hueDistance));\n if (hueDistance < 0)\n h = a.h - h;\n else\n h = a.h + h;\n const s = interpolate(amount, 0, satDistance);\n const l = interpolate(amount, 0, lightDistance);\n const o = interpolate(amount, 0, opacityDistance);\n return scalar(wrapScalarHue(h), s + a.s, l + a.l, o + aOpacity);\n };\n};\n/**\n * Creates a HslScalar value from scalar (0..1) values\n * @param hue\n * @param sat\n * @param lightness\n * @param opacity\n * @returns\n */\nexport function scalar(hue = 0.5, sat = 1, lightness = 0.5, opacity = 1) {\n const hsl = {\n unit: `scalar`,\n space: `hsl`,\n h: hue,\n s: sat,\n l: lightness,\n opacity: opacity\n };\n guard(hsl);\n return hsl;\n}\nexport function absolute(hue = 200, sat = 100, lightness = 50, opacity = 100) {\n const hsl = {\n unit: `absolute`,\n space: `hsl`,\n h: hue,\n s: sat,\n l: lightness,\n opacity: opacity\n };\n guard(hsl);\n return hsl;\n}\n/**\n * It seems Colorizr can't handle 'deg' units\n * @param value\n */\nexport function parseCssHslFunction(value) {\n if (value.startsWith(`hsla`))\n throw new Error(`hsla() is not supported`);\n if (!value.startsWith(`hsl(`))\n throw new Error(`Expected hsl(..) CSS colour`);\n const start = value.indexOf('(');\n const end = value.indexOf(')');\n if (end < start)\n throw new Error(`Is hsl() not terminated? Missing ')'`);\n const part = value.substring(start + 1, end);\n let split = part.split(/[\\s,]+/);\n if (split.length < 3)\n throw new Error(`Expected three tokens. Got: ${split.length} length`);\n let returnRelative = false;\n if (split[0].endsWith(`%`))\n returnRelative = true;\n if (split[1].endsWith(`%`) && split[2].endsWith(`%`))\n returnRelative = true;\n const valueAsScalar = (v, pos) => {\n if (v === `none`)\n return 0;\n if (v.endsWith(`%`)) {\n return Number.parseFloat(v.substring(0, v.length - 1)) / 100;\n }\n if (v.endsWith(`deg`) && pos === 0) {\n v = v.substring(0, v.length - 3);\n }\n const vf = Number.parseFloat(v);\n if (pos === 0)\n return vf / 360;\n if (pos === 3)\n return vf; // opacity\n return vf / 100;\n };\n const valueAsAbs = (v, pos) => {\n if (v === `none`)\n return 0;\n if (v.endsWith(`%`)) {\n const vf = Number.parseFloat(v.substring(0, v.length - 1));\n if (pos === 0)\n return vf * 360;\n return vf;\n }\n if (v.endsWith(`deg`) && pos === 0) {\n return Number.parseFloat(v.substring(0, v.length - 3));\n }\n const vf = Number.parseFloat(v);\n return vf;\n };\n // Is there opacity?\n if (split.length > 3) {\n if (split[3] === '/') {\n // Remove / part\n split = [split[0], split[1], split[2], split[4]];\n }\n }\n if (returnRelative) {\n return scalar(valueAsScalar(split[0], 0), valueAsScalar(split[1], 1), valueAsScalar(split[2], 2), valueAsScalar(split[3] ?? `100%`, 3));\n }\n else {\n // Return as absolute\n return absolute(valueAsAbs(split[0], 0), valueAsAbs(split[1], 1), valueAsAbs(split[2], 2), valueAsAbs(split[3] ?? `100%`, 3));\n }\n}\n/**\n * Converts a Hsl structure (or CSS string) to Colorizr's RGB format\n * @param rgb\n * @returns\n */\nexport function toLibraryRgb(hsl) {\n if (typeof hsl === `string`) {\n const parseResult = fromCss(hsl, { scalar: false });\n //console.log(`parseResult hsl: ${ hsl } pr: `, parseResult);\n return toLibraryRgb(parseResult);\n }\n hsl = toAbsolute(hsl);\n //console.log(`toLibraryRgb hsl`, hsl);\n const rgb = C.hsl2rgb({ h: hsl.h, s: hsl.s, l: hsl.l });\n return { ...rgb, alpha: (hsl.opacity ?? 100) / 100 * 255 };\n}\n","import { numberInclusiveRangeTest, percentTest, resultThrow } from \"@ixfx/guards\";\nimport Colorizr, * as C from \"colorizr\";\nimport { cssDefinedHexColours } from \"./css-colours.js\";\nimport { angleConvert, angleParse } from \"@ixfx/geometry\";\nimport { calculateHueDistance, wrapScalarHue } from \"./utility.js\";\nimport { clamp, interpolate } from \"@ixfx/numbers\";\nimport { parseCssRgbFunction, to8bit as rgbTo8bit } from \"./srgb.js\";\nexport const OKLCH_CHROMA_MAX = 0.4;\nexport const guard = (lch) => {\n const { l, c, h, opacity, space, unit } = lch;\n if (space !== `oklch`)\n throw new Error(`Space is expected to be 'oklch'. Got: ${space}`);\n if (unit === `absolute`) {\n resultThrow(percentTest(l, `l`), () => {\n if (typeof c === `number`) {\n return numberInclusiveRangeTest(c, 0, OKLCH_CHROMA_MAX, `c`);\n }\n }, () => {\n if (typeof h === `number`) {\n return numberInclusiveRangeTest(c, 0, 360, `h`);\n }\n }, percentTest((opacity ?? 1), `opacity`));\n }\n else if (unit === `scalar`) {\n // Percentage values for L,C,H\n resultThrow(percentTest(l, `l`), percentTest(c, `c`), percentTest(h, `h`), percentTest((lch.opacity ?? 1), `opacity`));\n }\n else {\n throw new Error(`Unit is expected to be 'absolute' or 'scalar'. Got: ${unit}`);\n }\n};\n/**\n * Coverts from the Colorizr library\n * Tests ranges:\n * * l: 0..1\n * * c: 0..1\n * * h: 0..360\n * * alpha: 0..1\n *\n * Default option: { scalar: true }\n * @param lch\n * @param parsingOptions\n * @returns\n */\nexport function fromLibrary(lch, parsingOptions = {}) {\n if (typeof lch === `undefined` || lch === null) {\n if (parsingOptions.fallbackColour)\n return parsingOptions.fallbackColour;\n }\n const scalarReturn = parsingOptions.scalar ?? true;\n // Validate\n resultThrow(percentTest(lch.l, `l`), percentTest(lch.c, `c`), numberInclusiveRangeTest(lch.h, 0, 360, `h`), percentTest((lch.alpha ?? 1), `alpha`));\n if (scalarReturn) {\n return scalar(lch.l, lch.c / OKLCH_CHROMA_MAX, lch.h / 360, (lch.alpha ?? 1));\n }\n else {\n return absolute(lch.l, lch.c, lch.h, (lch.alpha ?? 1));\n }\n}\nexport const fromHexString = (hexString, options = {}) => {\n return fromLibrary(C.hex2oklch(hexString), options);\n};\nconst oklchTransparent = Object.freeze({\n l: 0, c: 0, h: 0, opacity: 0, unit: `absolute`, space: `oklch`\n});\nexport function fromCss(value, options = {}) {\n value = value.toLowerCase();\n if (value.startsWith(`#`)) {\n return fromHexString(value, options);\n }\n if (value === `transparent`)\n return oklchTransparent;\n if (typeof cssDefinedHexColours[value] !== `undefined`) {\n return fromHexString(cssDefinedHexColours[value], options);\n }\n if (value.startsWith(`rgb(`)) {\n const rgb = rgbTo8bit(parseCssRgbFunction(value));\n const lch = C.rgb2oklch({ r: rgb.r, g: rgb.g, b: rgb.b });\n return fromLibrary(lch, options);\n }\n if (!value.startsWith(`hsl(`) && !value.startsWith(`oklch(`)) {\n try {\n const converted = C.convert(value, `oklch`);\n value = converted;\n }\n catch (error) {\n if (options.fallbackString) {\n value = options.fallbackString;\n }\n else {\n throw error;\n }\n }\n }\n const cc = new Colorizr(value);\n const lch = cc.oklch;\n return fromLibrary(lch, options);\n // const c = C.extractColorParts(value);\n // if (c.model !== `oklch`) {\n // if (options.fallbackColour) return options.fallbackColour;\n // throw new Error(`Expecting OKLCH colour space. Got: ${ c.model }`);\n // }\n // return fromLibrary(c as any as C.LCH, options);\n}\n//export const fromCssScalar = (value: string, options: ParsingOptions<OkLchAbsolute> = {}): OkLchScalar => toScalar(fromCssAbsolute(value, options));\n/**\n * Returns a string or {@link OkLch} value to absolute form.\n *\n * This means ranges are:\n * * lightness: 0..1\n * * chroma: 0...CHROMA_MAX (0.4)\n * * hue: 0..360\n * @param lchOrString\n * @returns\n */\nexport const toAbsolute = (lchOrString) => {\n if (typeof lchOrString === `string`) {\n return toAbsolute(fromCss(lchOrString, { scalar: true }));\n }\n guard(lchOrString);\n if (lchOrString.unit === `absolute`)\n return lchOrString;\n return {\n space: `oklch`,\n unit: `absolute`,\n l: lchOrString.l,\n c: lchOrString.c * OKLCH_CHROMA_MAX,\n h: lchOrString.h * 360,\n opacity: lchOrString.opacity\n };\n};\nexport const toScalar = (lchOrString) => {\n if (typeof lchOrString === `string`) {\n return toScalar(fromCss(lchOrString, { scalar: true }));\n }\n const lch = lchOrString;\n guard(lch);\n //console.log(`toScalar input: ${ JSON.stringify(lchOrString) } lch: `, lch);\n // Already relative\n if (lch.unit === `scalar`)\n return lch;\n // Absolute values\n return {\n l: lch.l, // unchanged\n c: lch.c / OKLCH_CHROMA_MAX,\n h: lch.h / 360,\n opacity: (lch.opacity ?? 1),\n unit: `scalar`,\n space: `oklch`\n };\n};\nconst toLibrary = (lch) => {\n const abs = toAbsolute(lch);\n return {\n l: abs.l,\n c: abs.c,\n h: abs.h,\n alpha: abs.opacity,\n };\n};\n// const libraryLchToScalar = (c: C.LCH): OkLchScalar => {\n// return {\n// l: c.h,\n// c: c.c,\n// h: c.h / 360,\n// opacity: c.alpha ?? 1,\n// unit: `scalar`,\n// space: `oklch`\n// }\n// }\n/**\n * Returns the colour as a CSS colour string: `oklch(l c h / opacity)`.\n *\n * @param lch Colour\n * @param precision Set precision of numbers, defaults to 3\n * @returns CSS colour string\n */\nexport const toCssString = (lch, precision = 3) => {\n guard(lch);\n const { l, c, h, opacity } = lch;\n let css = ``;\n switch (lch.unit) {\n case `absolute`:\n css = `oklch(${(l * 100).toFixed(precision)}% ${c.toFixed(precision)} ${h.toFixed(precision)}`;\n break;\n case `scalar`:\n css = `oklch(${l.toFixed(precision)} ${(c * OKLCH_CHROMA_MAX).toFixed(precision)} ${(h * 360).toFixed(precision)}`;\n break;\n }\n if (typeof opacity !== `undefined` && opacity !== 1) {\n css += ` / ${opacity.toFixed(precision)}`;\n }\n css += `)`;\n return css;\n};\n// export const oklchFromCss = (css: string): OkLchScalar => {\n// if (css.startsWith(`#`)) {\n// libraryLchToScalar(C.hex2oklch(css));\n// }\n// const p = C.extractColorParts(css);\n// return libraryToScalar(p);\n// }\n// const libraryToScalar = (colour: unknown): OkLchScalar => {\n// if (C.isLCH(colour)) {\n// return libraryLchToScalar(colour);\n// }\n// if (C.isRGB(colour)) {\n// return libraryToScalar(C.rgb2oklch(colour));\n// }\n// if (C.isLAB(colour)) {\n// return libraryToScalar(C.oklab2oklch(colour));\n// }\n// if (C.isHSL(colour)) {\n// return libraryToScalar(C.hsl2oklch(colour));\n// }\n// if (C.isHex(colour)) {\n// return libraryLchToScalar(C.hex2oklch(colour));\n// }\n// throw new Error(`Unexpected colour format`);\n// }\n// export const oklchToColorJs = (lch: OkLch): ColorConstructor => {\n// throwNumberTest(lch.l, `percentage`, `lch.l`);\n// throwNumberTest(lch.c, `percentage`, `lch.c`);\n// throwNumberTest(lch.h, `percentage`, `lch.h`);\n// throwNumberTest(lch.opacity, `percentage`, `lch.opacity`);\n// return {\n// alpha: lch.opacity,\n// coords: [ lch.l, lch.c * 0.4, lch.h * 360 ],\n// spaceId: `oklch`\n// }\n// }\n// const oklchToColorJs = (oklch: OkLch) => {\n// throwNumberTest(oklch.l, `percentage`, `oklch.l`);\n// throwNumberTest(oklch.c, `percentage`, `oklch.c`);\n// throwNumberTest(oklch.h, `percentage`, `oklch.h`);\n// throwNumberTest(oklch.opacity, `percentage`, `oklch.opacity`);\n// const coords: [ number, number, number ] = [\n// oklch.l,\n// oklch.c * 0.4,\n// oklch.h * 360\n// ]\n// return new ColorJs.default(`oklch`, coords, oklch.opacity);\n// }\n// export const isOklch = (p: Colourish | undefined | null): p is OkLch => {\n// if (typeof p === `undefined` || p === null) return false;\n// if (typeof p !== `object`) return false;\n// // Check if Colourjs\n// //if ((p as ColorJs.ColorObject).spaceId !== undefined) return false;\n// //if ((p as ColorJs.ColorObject).coords !== undefined) return false;\n// if (p.space !== `oklch`) return false;\n// if (typeof p.l === `undefined`) return false;\n// if (typeof p.c === `undefined`) return false;\n// if (typeof p.h === `undefined`) return false;\n// return true;\n// }\nexport const generateScalar = (absoluteHslOrVariable, chroma = 1, lightness = 0.5, opacity = 1) => {\n if (typeof absoluteHslOrVariable === `string`) {\n if (absoluteHslOrVariable.startsWith(`--`)) {\n absoluteHslOrVariable = getComputedStyle(document.body).getPropertyValue(absoluteHslOrVariable).trim();\n }\n }\n if (lightness > 1)\n throw new TypeError(`Param 'lightness' must be between 0..1`);\n if (chroma > 1)\n throw new TypeError(`Param 'chroma' must be between 0..1`);\n const hue = angleParse(absoluteHslOrVariable);\n const hueDeg = angleConvert(hue, `deg`).value / 360;\n if (opacity > 1)\n throw new TypeError(`Param 'opacity' must be between 0..1`);\n return {\n l: lightness,\n c: chroma,\n h: hueDeg,\n opacity: opacity,\n unit: `scalar`,\n space: `oklch`\n };\n};\n/**\n * Scales the opacity value of an input Oklch value\n * ```js\n * withOpacity()\n * ```\n * @param value\n * @param fn\n * @returns\n */\nexport const withOpacity = (value, fn) => {\n switch (value.unit) {\n case `absolute`:\n return {\n ...value,\n opacity: fn((value.opacity ?? 100) / 100, value) * 100\n };\n case `scalar`:\n return {\n ...value,\n opacity: fn((value.opacity ?? 1), value)\n };\n }\n};\nexport const interpolator = (a, b, direction = `shorter`) => {\n a = toScalar(a);\n b = toScalar(b);\n //console.log(`a`, a);\n //console.log(`b`, b);\n const aOpacity = a.opacity ?? 1;\n const distanceCalc = calculateHueDistance(a.h, b.h, 1);\n const hueDistance = direction === `longer` ? distanceCalc.long : distanceCalc.short;\n const chromaDistance = b.c - a.c;\n const lightDistance = b.l - a.l;\n const opacityDistance = (b.opacity ?? 1) - aOpacity;\n //console.log(`distanceCalc`, distanceCalc);\n //console.log(`interpolator distances: hue: ${ hueDistance } c: ${ chromaDistance } light: ${ lightDistance } opacity: ${ opacityDistance }`);\n return (amount) => {\n amount = clamp(amount);\n let h = interpolate(amount, 0, Math.abs(hueDistance));\n if (hueDistance < 0)\n h = a.h - h;\n else\n h = a.h + h;\n const c = interpolate(amount, 0, chromaDistance);\n const l = interpolate(amount, 0, lightDistance);\n const o = interpolate(amount, 0, opacityDistance);\n //console.log(`amount: ${ amount } h: ${ h } s: ${ s } l: ${ l } o: ${ o }`);\n return scalar(l + a.l, c + a.c, wrapScalarHue(h), o + aOpacity);\n };\n};\nexport function scalar(lightness = 0.7, chroma = 0.1, hue = 0.5, opacity = 1) {\n const lch = {\n unit: `scalar`,\n space: `oklch`,\n l: lightness,\n c: chroma,\n h: hue,\n opacity: opacity\n };\n guard(lch);\n return lch;\n}\n/**\n * Create an LCH colour using absolute hue\n * @param l Lightness 0..1\n * @param c Chroma 0..4\n * @param h Hue 0..360\n * @param opacity\n * @returns\n */\nexport const absolute = (l, c, h, opacity = 1) => {\n const lch = {\n space: `oklch`,\n unit: `absolute`,\n opacity,\n l, c, h\n };\n guard(lch);\n return lch;\n};\n","import * as SrgbSpace from \"./srgb.js\";\nimport * as HslSpace from './hsl.js';\nimport * as OklchSpace from './oklch.js';\n/**\n * Converts from some kind of colour that is legal in CSS\n * into a structured Colour type.\n *\n * Handles: hex format, CSS variables, colour names\n * ```js\n * fromCssColour(`#ffffff`);\n * fromCssColour(`blue`);\n * fromCssColour(`--some-variable`);\n * fromCssColour(`hsl(50, 50%, 50%)`);\n * fromCssColour(`rgb(50, 100, 100)`);\n * ```\n * @param colour\n * @returns\n */\nexport const fromCssColour = (colour) => {\n if (colour.startsWith(`#`)) {\n return SrgbSpace.fromHexString(colour, true);\n }\n if (typeof cssDefinedHexColours[colour] !== `undefined`) {\n return SrgbSpace.fromHexString(cssDefinedHexColours[colour], true);\n }\n if (colour.startsWith(`--`)) {\n const fromCss = getComputedStyle(document.body).getPropertyValue(colour).trim();\n if (fromCss.length === 0 || fromCss === null)\n throw new Error(`Variable missing: ${colour}`);\n return fromCssColour(fromCss);\n }\n colour = colour.toLowerCase();\n if (colour.startsWith(`hsl(`)) {\n return HslSpace.fromCss(colour, { scalar: true });\n }\n if (colour.startsWith(`rgb(`)) {\n return SrgbSpace.fromCss(colour, { scalar: true });\n }\n if (colour.startsWith(`oklch(`)) {\n return OklchSpace.fromCss(colour, { scalar: true });\n }\n throw new Error(`String colour is not a hex colour, CSS variable nor well-defined colour. Input: '${colour}'`);\n};\nexport const cssDefinedHexColours = {\n \"aliceblue\": \"#f0f8ff\",\n \"antiquewhite\": \"#faebd7\",\n \"aqua\": \"#00ffff\",\n \"aquamarine\": \"#7fffd4\",\n \"azure\": \"#f0ffff\",\n \"beige\": \"#f5f5dc\",\n \"bisque\": \"#ffe4c4\",\n \"black\": \"#000000\",\n \"blanchedalmond\": \"#ffebcd\",\n \"blue\": \"#0000ff\",\n \"blueviolet\": \"#8a2be2\",\n \"brown\": \"#a52a2a\",\n \"burlywood\": \"#deb887\",\n \"cadetblue\": \"#5f9ea0\",\n \"chartreuse\": \"#7fff00\",\n \"chocolate\": \"#d2691e\",\n \"coral\": \"#ff7f50\",\n \"cornflowerblue\": \"#6495ed\",\n \"cornsilk\": \"#fff8dc\",\n \"crimson\": \"#dc143c\",\n \"cyan\": \"#00ffff\",\n \"darkblue\": \"#00008b\",\n \"darkcyan\": \"#008b8b\",\n \"darkgoldenrod\": \"#b8860b\",\n \"darkgray\": \"#a9a9a9\",\n \"darkgreen\": \"#006400\",\n \"darkkhaki\": \"#bdb76b\",\n \"darkmagenta\": \"#8b008b\",\n \"darkolivegreen\": \"#556b2f\",\n \"darkorange\": \"#ff8c00\",\n \"darkorchid\": \"#9932cc\",\n \"darkred\": \"#8b0000\",\n \"darksalmon\": \"#e9967a\",\n \"darkseagreen\": \"#8fbc8f\",\n \"darkslateblue\": \"#483d8b\",\n \"darkslategray\": \"#2f4f4f\",\n \"darkturquoise\": \"#00ced1\",\n \"darkviolet\": \"#9400d3\",\n \"deeppink\": \"#ff1493\",\n \"deepskyblue\": \"#00bfff\",\n \"dimgray\": \"#696969\",\n \"dodgerblue\": \"#1e90ff\",\n \"firebrick\": \"#b22222\",\n \"floralwhite\": \"#fffaf0\",\n \"forestgreen\": \"#228b22\",\n \"fuchsia\": \"#ff00ff\",\n \"gainsboro\": \"#dcdcdc\",\n \"ghostwhite\": \"#f8f8ff\",\n \"gold\": \"#ffd700\",\n \"goldenrod\": \"#daa520\",\n \"gray\": \"#808080\",\n \"green\": \"#008000\",\n \"greenyellow\": \"#adff2f\",\n \"honeydew\": \"#f0fff0\",\n \"hotpink\": \"#ff69b4\",\n \"indianred\": \"#cd5c5c\",\n \"indigo\": \"#4b0082\",\n \"ivory\": \"#fffff0\",\n \"khaki\": \"#f0e68c\",\n \"lavender\": \"#e6e6fa\",\n \"lavenderblush\": \"#fff0f5\",\n \"lawngreen\": \"#7cfc00\",\n \"lemonchiffon\": \"#fffacd\",\n \"lightblue\": \"#add8e6\",\n \"lightcoral\": \"#f08080\",\n \"lightcyan\": \"#e0ffff\",\n \"lightgoldenrodyellow\": \"#fafad2\",\n \"lightgray\": \"#d3d3d3\",\n \"lightgreen\": \"#90ee90\",\n \"lightpink\": \"#ffb6c1\",\n \"lightsalmon\": \"#ffa07a\",\n \"lightseagreen\": \"#20b2aa\",\n \"lightskyblue\": \"#87cefa\",\n \"lightslategray\": \"#778899\",\n \"lightsteelblue\": \"#b0c4de\",\n \"lightyellow\": \"#ffffe0\",\n \"lime\": \"#00ff00\",\n \"limegreen\": \"#32cd32\",\n \"linen\": \"#faf0e6\",\n \"magenta\": \"#ff00ff\",\n \"maroon\": \"#800000\",\n \"mediumaquamarine\": \"#66cdaa\",\n \"mediumblue\": \"#0000cd\",\n \"mediumorchid\": \"#ba55d3\",\n \"mediumpurple\": \"#9370db\",\n \"mediumseagreen\": \"#3cb371\",\n \"mediumslateblue\": \"#7b68ee\",\n \"mediumspringgreen\": \"#00fa9a\",\n \"mediumturquoise\": \"#48d1cc\",\n \"mediumvioletred\": \"#c71585\",\n \"midnightblue\": \"#191970\",\n \"mintcream\": \"#f5fffa\",\n \"mistyrose\": \"#ffe4e1\",\n \"moccasin\": \"#ffe4b5\",\n \"navajowhite\": \"#ffdead\",\n \"navy\": \"#000080\",\n \"oldlace\": \"#fdf5e6\",\n \"olive\": \"#808000\",\n \"olivedrab\": \"#6b8e23\",\n \"orange\": \"#ffa500\",\n \"orangered\": \"#ff4500\",\n \"orchid\": \"#da70d6\",\n \"palegoldenrod\": \"#eee8aa\",\n \"palegreen\": \"#98fb98\",\n \"paleturquoise\": \"#afeeee\",\n \"palevioletred\": \"#db7093\",\n \"papayawhip\": \"#ffefd5\",\n \"peachpuff\": \"#ffdab9\",\n \"peru\": \"#cd853f\",\n \"pink\": \"#ffc0cb\",\n \"plum\": \"#dda0dd\",\n \"powderblue\": \"#b0e0e6\",\n \"purple\": \"#800080\",\n \"rebeccapurple\": \"#663399\",\n \"red\": \"#ff0000\",\n \"rosybrown\": \"#bc8f8f\",\n \"royalblue\": \"#4169e1\",\n \"saddlebrown\": \"#8b4513\",\n \"salmon\": \"#fa8072\",\n \"sandybrown\": \"#f4a460\",\n \"seagreen\": \"#2e8b57\",\n \"seashell\": \"#fff5ee\",\n \"sienna\": \"#a0522d\",\n \"silver\": \"#c0c0c0\",\n \"skyblue\": \"#87ceeb\",\n \"slateblue\": \"#6a5acd\",\n \"slategray\": \"#708090\",\n \"snow\": \"#fffafa\",\n \"springgreen\": \"#00ff7f\",\n \"steelblue\": \"#4682b4\",\n \"tan\": \"#d2b48c\",\n \"teal\": \"#008080\",\n \"thistle\": \"#d8bfd8\",\n \"tomato\": \"#ff6347\",\n \"turquoise\": \"#40e0d0\",\n \"violet\": \"#ee82ee\",\n \"wheat\": \"#f5deb3\",\n \"white\": \"#ffffff\",\n \"whitesmoke\": \"#f5f5f5\",\n \"yellow\": \"#ffff00\",\n \"yellowgreen\": \"#9acd32\",\n \"transparent\": \"#00000000\"\n};\n","import Colorizr, * as C from \"colorizr\";\nimport { numberInclusiveRangeTest, numberTest } from \"@ixfx/guards\";\nimport { resultThrow } from \"@ixfx/guards\";\nimport { cssDefinedHexColours } from \"./css-colours.js\";\nimport { clamp, interpolate } from \"@ixfx/numbers\";\nimport { toLibraryRgb as hslToLibraryRgb } from \"./hsl.js\";\nimport { isHsl } from \"./guards.js\";\nexport const withOpacity = (value, fn) => {\n switch (value.unit) {\n case `8bit`:\n return {\n ...value,\n opacity: fn((value.opacity ?? 255) / 255, value) * 255\n };\n case `scalar`:\n return {\n ...value,\n opacity: fn((value.opacity ?? 1), value)\n };\n }\n};\nexport function fromHexString(hexString, scalar = true) {\n return fromLibrary(C.hex2rgb(hexString), { scalar });\n}\n;\nconst srgbTansparent = Object.freeze({\n r: 0, g: 0, b: 0, opacity: 0, unit: `8bit`, space: `srgb`\n});\n/**\n * Converts a colour in a legal CSS form into Rgb value, by default RgbScalar (0..1) scale.\n * ```js\n * fromCss(`rebeccapurple`);\n * fromCss(`rgb(40% 20% 60%)`);\n *\n * // Get 8bit version on 0..255 scale\n * fromCss(`blue`, { scalar: false });\n * ```\n *\n * @param value\n * @param options\n * @returns\n */\nexport function fromCss(value, options = {}) {\n value = value.toLowerCase();\n if (value.startsWith(`hsla(`))\n throw new Error(`hsla() not supported`);\n if (value.startsWith(`rgba(`))\n throw new Error(`rgba() not supported`);\n const scalar = options.scalar ?? true;\n // Convert from hex\n if (value.startsWith(`#`))\n return fromHexString(value, scalar);\n // Special-case transparent\n if (value === `transparent`)\n return srgbTansparent;\n // Convert from named colour\n if (typeof cssDefinedHexColours[value] !== `undefined`)\n fromHexString(cssDefinedHexColours[value], scalar);\n if (value.startsWith(`hsl(`)) {\n const rgb = hslToLibraryRgb(value);\n return fromLibrary(rgb, options);\n }\n // if (value.startsWith(`hsl(`)) {\n // const hslRel = hslToScalar(parseCssHslFunction(value));\n // const rgb = C.hsl2rgb({ h: hslRel.h, s: hslRel.s, l: hslRel.l, alpha: hslRel.opacity ?? 1 });\n // return fromLibrary(rgb, options);\n // }\n // Convert to rgb() colour function\n if (!value.startsWith(`rgb(`)) {\n try {\n value = C.convert(value, `rgb`);\n }\n catch (error) {\n if (options.fallbackString) {\n value = options.fallbackString;\n }\n else {\n throw error;\n }\n }\n }\n try {\n // Hand-rolled rgb() parse because the package is broken\n const rgb = parseCssRgbFunction(value);\n if (scalar)\n return toScalar(rgb);\n return to8bit(rgb);\n }\n catch (error) {\n if (options.fallbackColour)\n return options.fallbackColour;\n throw error;\n }\n}\nexport const toCssString = (rgb) => {\n guard(rgb);\n switch (rgb.unit) {\n case `8bit`:\n if (rgb.opacity === undefined || rgb.opacity === 255) {\n return `rgb(${rgb.r} ${rgb.g} ${rgb.b})`;\n }\n return `rgb(${rgb.r} ${rgb.g} ${rgb.b} / ${(rgb.opacity ?? 255) / 255})`;\n case `scalar`:\n if (rgb.opacity === undefined || rgb.opacity === 1) {\n return `rgb(${rgb.r * 100}% ${rgb.g * 100}% ${rgb.b * 100}%)`;\n }\n return `rgb(${rgb.r * 100}% ${rgb.g * 100}% ${rgb.b * 100}% / ${(rgb.opacity ?? 1) * 100}%)`;\n default:\n throw new Error(`Unknown unit: ${rgb.unit}`);\n }\n};\nconst toLibrary = (rgb) => {\n const abs = to8bit(rgb);\n return {\n r: abs.r,\n g: abs.g,\n b: abs.b,\n alpha: abs.opacity,\n };\n};\nfunction fromLibrary(rgb, parsingOptions = {}) {\n if (parsingOptions.scalar) {\n return {\n r: rgb.r / 255,\n g: rgb.g / 255,\n b: rgb.b / 255,\n opacity: rgb.alpha ?? 1,\n unit: `scalar`,\n space: `srgb`\n };\n }\n else {\n return {\n r: rgb.r,\n g: rgb.g,\n b: rgb.b,\n opacity: rgb.alpha ?? 255,\n unit: `8bit`,\n space: `srgb`\n };\n }\n}\nexport const to8bit = (rgbOrString) => {\n if (typeof rgbOrString === `string`) {\n return fromCss(rgbOrString, { scalar: false });\n }\n if (isHsl(rgbOrString)) {\n return to8bit(fromLibrary(hslToLibraryRgb(rgbOrString), { scalar: false }));\n }\n guard(rgbOrString);\n if (rgbOrString.unit === `8bit`)\n return rgbOrString;\n return {\n r: rgbOrString.r * 255,\n g: rgbOrString.g * 255,\n b: rgbOrString.b * 255,\n opacity: (rgbOrString.opacity ?? 1) * 255,\n unit: `8bit`,\n space: `srgb`\n };\n};\nexport const toScalar = (rgbOrString) => {\n if (typeof rgbOrString === `string`) {\n return fromCss(rgbOrString, { scalar: true });\n }\n if (isHsl(rgbOrString)) {\n return toScalar(fromLibrary(hslToLibraryRgb(rgbOrString), { scalar: true }));\n }\n guard(rgbOrString);\n if (rgbOrString.unit === `scalar`)\n return rgbOrString;\n return {\n r: rgbOrString.r / 255,\n g: rgbOrString.g / 255,\n b: rgbOrString.b / 255,\n opacity: (rgbOrString.opacity ?? 1) / 255,\n unit: `scalar`,\n space: `srgb`\n };\n};\nexport const guard = (rgb) => {\n const { r, g, b, opacity, space, unit } = rgb;\n if (space !== `srgb`)\n throw new Error(`Space is expected to be 'srgb'. Got: ${space}`);\n if (unit === `8bit`) {\n resultThrow(numberInclusiveRangeTest(r, 0, 255, `r`), numberInclusiveRangeTest(g, 0, 255, `g`), numberInclusiveRangeTest(b, 0, 255, `b`), () => {\n if (typeof opacity === `number`) {\n return numberInclusiveRangeTest(opacity, 0, 255, `opacity`);\n }\n });\n }\n else if (unit === `scalar`) {\n resultThrow(numberTest(r, `percentage`, `r`), numberTest(g, `percentage`, `g`), numberTest(b, `percentage`, `b`), () => {\n if (typeof opacity === `number`) {\n return numberTest(opacity, `percentage`, `opacity`);\n }\n });\n }\n else {\n throw new Error(`Unit is expected to be '8bit' or 'scalar'. Got: ${unit}`);\n }\n};\n/**\n * Sets the lightness value.\n *\n * Amount to change:\n * * 'fixed': a fixed amount\n * * 'delta': increase/decrease by this amount\n * * 'pdelta': proportion of current value to change by ('percentage delta')\n *\n * Use negative values to decrease\n * @param value\n * @param amount\n */\nexport const changeLightness = (rgb, amount) => {\n let newL = 0;\n const co = new Colorizr(toCssString(rgb));\n const scalarUnit = rgb.unit === `scalar`;\n if (typeof amount.pdelta !== `undefined`) {\n newL = co.oklab.l + (co.oklab.l * amount.pdelta);\n }\n else if (typeof amount.delta !== `undefined`) {\n newL = co.oklab.l + amount.delta;\n }\n else if (typeof amount.fixed !== `undefined`) {\n if (amount.fixed < 0)\n throw new TypeError(`Amount cannot be negative when using 'fixed'`);\n newL = amount.fixed;\n }\n else {\n throw new TypeError(`Parameter 'amount' is missing 'pdelta/delta/fixed' properties`);\n }\n if (newL < 0)\n newL = 0;\n else if (newL > 1)\n newL = 1;\n const rgbResult = C.oklab2rgb({ a: co.oklab.a, b: co.oklab.b, l: newL, alpha: co.oklab.alpha });\n return fromLibrary(rgbResult, { scalar: scalarUnit });\n //return eightBit ? fromLibrary8bit(rgbResult) : fromLibraryScalar(rgbResult);\n};\n/**\n * Returns a lightness value (0..1) for an RGB input\n *\n * Calculates lightness by converting to Oklab and using the 'L' value\n * @param rgb\n * @returns\n */\nexport function lightness(rgb) {\n const co = new Colorizr(toCssString(rgb));\n return co.oklab.l;\n}\nconst scaleProperty = (rgb, value, property) => {\n if (rgb.unit === `scalar`) {\n // 0..1 scale\n if (value > 1)\n value = 1;\n else if (value < 0)\n value = 0;\n }\n else {\n // 0..255 scale\n if (value > 255)\n value = 255;\n else if (value < 0)\n value = 0;\n }\n return value;\n};\n/**\n * Creates a Rgb8Bit value from 8bit (0..255) values\n * @param red\n * @param green\n * @param blue\n * @param opacity\n * @returns\n */\nexport function eightBit(red = 100, green = 100, blue = 100, opacity = 255) {\n const rgb = {\n unit: `8bit`,\n space: `srgb`,\n r: red,\n g: green,\n b: blue,\n opacity: opacity\n };\n guard(rgb);\n return rgb;\n}\n/**\n * Creates a RgbScalar value from scalar (0..1) values\n * @param red\n * @param green\n * @param blue\n * @param opacity\n * @returns\n */\nexport function scalar(red = 0.5, green = 0.5, blue = 0.5, opacity = 1) {\n const rgb = {\n unit: `scalar`,\n space: `srgb`,\n r: red,\n g: green,\n b: blue,\n opacity: opacity\n };\n guard(rgb);\n return rgb;\n}\n/**\n * It seems Colorizr can't handle % values properly :'(\n * @param value\n */\nexport function parseCssRgbFunction(value) {\n if (value.startsWith(`rgba`))\n throw new Error(`RGBA is not supported`);\n if (!value.startsWith(`rgb(`))\n throw new Error(`Expected rgb(..) CSS colour`);\n const start = value.indexOf('(');\n const end = value.indexOf(')');\n if (end < start)\n throw new Error(`Is rgb() not terminated? Missing ')'`);\n const part = value.substring(start + 1, end);\n let split = part.split(/[\\s,]+/);\n if (split.length < 3)\n throw new Error(`Expected three tokens. Got: ${split.length} length`);\n let relativeCount = 0;\n for (const s of split) {\n if (s.endsWith('%'))\n relativeCount++;\n }\n const valueAsScalar = (v, pos) => {\n if (v.endsWith(`%`)) {\n return Number.parseFloat(v.substring(0, v.length - 1)) / 100;\n }\n if (pos < 3) {\n // r, g or b\n return Number.parseFloat(v) / 255;\n }\n else {\n // opacity should already be in scalar value\n return Number.parseFloat(v);\n }\n };\n const valueAs8bit = (v, pos) => {\n if (v.endsWith(`%`)) {\n return Number.parseFloat(v.substring(0, v.length - 1)) / 100 * 255;\n }\n if (pos < 3) {\n // r, g or b\n return Number.parseFloat(v);\n }\n else {\n // opacity should already be in scalar value\n return Number.parseFloat(v) * 255;\n }\n };\n // Is there opacity?\n if (split.length > 3) {\n if (split[3] === '/') {\n // Remove / part\n split = [split[0], split[1], split[2], split[4]];\n }\n }\n if (relativeCount > 1) {\n // Return as scalar\n return scalar(valueAsScalar(split[0], 0), valueAsScalar(split[1], 1), valueAsScalar(split[2], 2), valueAsScalar(split[3] ?? `1`, 3));\n }\n else {\n // Return as 8bit\n return eightBit(valueAs8bit(split[0], 0), valueAs8bit(split[1], 1), valueAs8bit(split[2], 2), valueAs8bit(split[3] ?? `1`, 3));\n }\n}\n/**\n * Interpolates colours in Srgb space. Probably\n * really ugly, use OkLch space isntead.\n *\n * ```js\n * const i = interpolator(`red`, `blue`);\n * i(0.5); // Get 50% between these colours\n * ```\n * @param colourA\n * @param colourB\n * @returns\n */\nexport const interpolator = (colourA, colourB) => {\n const aa = toScalar(colourA);\n const bb = toScalar(colourB);\n const aOpacity = aa.opacity ?? 1;\n const opacityDistance = (bb.opacity ?? 1) - aOpacity;\n const r = bb.r - aa.r;\n const g = bb.g - aa.g;\n const b = bb.b - aa.b;\n return (amount) => {\n amount = clamp(amount);\n return scalar(aa.r + interpolate(amount, 0, r), aa.g + interpolate(amount, 0, g), aa.b + interpolate(amount, 0, b), aOpacity + interpolate(amount, 0, opacityDistance));\n };\n};\n/**\n * Converts a Rgb structure (or CSS string) to Colorizr's HSL format\n * @param rgb\n * @returns\n */\nexport function toLibraryHsl(rgb) {\n if (typeof rgb === `string`) {\n const parseResult = fromCss(rgb, { scalar: false });\n return toLibraryHsl(parseResult);\n }\n rgb = to8bit(rgb);\n const hsl = C.rgb2hsl({ r: rgb.r, g: rgb.g, b: rgb.b });\n return { ...hsl, alpha: (rgb.opacity ?? 255) / 255 };\n}\n","import Colorizr, * as C from \"colorizr\";\nimport {} from \"./types.js\";\nimport * as SrgbSpace from \"./srgb.js\";\nimport * as HslSpace from './hsl.js';\nimport * as OkLchSpace from './oklch.js';\nimport { fromCssColour } from \"./css-colours.js\";\nimport { isHsl, isRgb, tryParseObjectToRgb, tryParseObjectToHsl, isColourish, isLch } from \"./guards.js\";\nimport { OklchSpace } from \"./index.js\";\n/**\n * Converts an object or string representation of colour to ixfx's\n * structured colour.\n * Use {@link convertToString} if you want a CSS colour string instead.\n * @param colour\n * @param destination\n * @returns\n */\nexport function convert(colour, destination) {\n if (destination === `hsl-scalar`) {\n if (typeof colour === `string` || isHsl(colour) || isRgb(colour)) {\n return HslSpace.toScalar(colour);\n }\n }\n else if (destination === `hsl-absolute`) {\n if (typeof colour === `string` || isHsl(colour)) {\n return HslSpace.toAbsolute(colour);\n }\n }\n else if (destination === `oklch-scalar`) {\n if (typeof colour === `string` || isLch(colour)) {\n return OkLchSpace.toScalar(colour);\n }\n }\n else if (destination === `oklch-absolute`) {\n if (typeof colour === `string` || isLch(colour)) {\n return OkLchSpace.toAbsolute(colour);\n }\n }\n else if (destination === `srgb-8bit`) {\n if (typeof colour === `string` || isRgb(colour)) {\n return SrgbSpace.to8bit(colour);\n }\n }\n else if (destination === `srgb-scalar`) {\n if (typeof colour === `string` || isRgb(colour)) {\n return SrgbSpace.toScalar(colour);\n }\n }\n else {\n throw new Error(`Destination '${destination}' not supported for input: ${JSON.stringify(colour)}`);\n }\n return convert(toCssColour(colour), destination);\n}\n/**\n * Like {@link convert}, but result is a CSS colour string\n * @param colour\n * @param destination\n * @returns\n */\nexport function convertToString(colour, destination) {\n const c = convert(colour, destination);\n return toCssColour(c);\n}\nexport function convertScalar(colour, destination) {\n if (destination === `oklch`)\n return convert(colour, `oklch-scalar`);\n if (destination === `srgb`)\n return convert(colour, `srgb-scalar`);\n if (destination === `hsl`)\n return convert(colour, `hsl-scalar`);\n throw new Error(`Unknown destination: '${destination}'`);\n}\nexport const toCssColour = (colour) => {\n if (typeof colour === `string`)\n return colour;\n if (isHsl(colour)) {\n return HslSpace.toCssString(colour);\n }\n if (isRgb(colour)) {\n return SrgbSpace.toCssString(colour);\n }\n if (isLch(colour)) {\n return OklchSpace.toCssString(colour);\n }\n const asRgb = tryParseObjectToRgb(colour);\n if (asRgb)\n return SrgbSpace.toCssString(asRgb);\n const asHsl = tryParseObjectToHsl(colour);\n if (asHsl)\n return HslSpace.toCssString(asHsl);\n throw new Error(`Unknown colour format: '${JSON.stringify(colour)}'`);\n};\nexport const toLibraryColour = (colour) => {\n const asCss = toCssColour(colour);\n return new Colorizr(asCss);\n};\n// export const convertColourString = (colour: string, destination: 'hex' | 'hsl' | 'oklab' | 'oklch' | 'srgb' | `rgb`): string => {\n// if (destination === `srgb`) destination = `rgb`;\n// return C.convert(colour, destination);\n// }\nexport const guard = (colour) => {\n switch (colour.space) {\n case `hsl`:\n HslSpace.guard(colour);\n break;\n case `srgb`:\n SrgbSpace.guard(colour);\n break;\n default:\n throw new Error(`Unknown colour space: '${colour.space}'`);\n }\n};\nexport const toColour = (colourish) => {\n if (!isColourish(colourish))\n throw new Error(`Could not parse input. Expected CSS colour string or structured colour {r,g,b}, {h,s,l} etc.`);\n let c;\n if (typeof colourish === `string`)\n c = fromCssColour(colourish);\n else\n c = colourish;\n if (c === undefined)\n throw new Error(`Could not parse input. Expected CSS colour string or structured colour {r,g,b}, {h,s,l} etc.`);\n guard(c);\n return c;\n};\n/**\n * Returns a CSS-ready string\n * representation.\n * ```js\n * element.style.backgroundColor = resolveToString(`red`);\n * ```\n *\n * Tries each parameter in turn, returning the value\n * for the first that resolves. This can be useful for\n * having fallback values.\n *\n * ```js\n * // Try a CSS variable, a object property or finally fallback to red.\n * element.style.backgroundColor = toStringFirst('--some-var', opts.background, `red`);\n * ```\n * @param colours Array of colours to resolve\n * @returns\n */\nexport const toStringFirst = (...colours) => {\n for (const colour of colours) {\n if (colour === undefined)\n continue;\n if (colour === null)\n continue;\n try {\n const c = toColour(colour);\n return toCssColour(c);\n }\n catch { /* empty */ }\n }\n return `rebeccapurple`;\n};\nexport function rgbToHsl(rgb, scalarResult) {\n // Needed because the Colorizr package has broken RGB to HSL\n // Converts rgb { model: 'rgb', r: 40, g: 20, b: 60, alpha: undefined }\n // to : { h: 270, s: 50, l: 0.06 }\n // when it should be: { h: 270, s: 50, l: 40 }\n // Source: https://www.jameslmilner.com/posts/converting-rgb-hex-hsl-colors/\n let { r, g, b } = rgb;\n const opacity = rgb.opacity ?? 1;\n if (rgb.unit === `8bit`) {\n r /= 255;\n g /= 255;\n b /= 255;\n }\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let h = (max + min) / 2;\n let s = h;\n const l = h;\n if (max === min) {\n // Achromatic\n if (scalarResult) {\n return HslSpace.scalar(0, 0, 0, opacity);\n }\n else {\n return HslSpace.absolute(0, 0, 0, opacity);\n }\n }\n const d = max - min;\n s = l >= 0.5 ? d / (2 - (max + min)) : d / (max + min);\n switch (max) {\n case r:\n h = ((g - b) / d + 0) * 60;\n break;\n case g:\n h = ((b - r) / d + 2) * 60;\n break;\n case b:\n h = ((r - g) / d + 4) * 60;\n break;\n }\n if (scalarResult) {\n return HslSpace.scalar(h / 360, s, l, opacity);\n }\n else {\n return HslSpace.absolute(h, s * 100, l * 100, opacity);\n }\n}\n","//import {Colour} from '@ixfx/visual';\nimport type { ReactiveInitial, ReactiveWritable, Reactive } from \"@ixfx/rx\";\nimport type { DomFormOptions, DomNumberInputValueOptions, DomValueOptions } from \"./dom-types.js\";\nimport { resolveEl } from '@ixfx/dom';\nimport { transform } from '@ixfx/rx';\nimport { hasLast } from '@ixfx/rx';\nimport { Colour } from \"@ixfx/visual\";\nimport { eventTrigger } from \"@ixfx/rx/from\";\n//import type { Colourish } from '@ixfx/visual/colour';\n\n/**\n * Reactive getting/setting of values to a HTML INPUT element.\n * \n * Options:\n * - relative: if _true_, values are 0..1 (default: false)\n * - inverted: if _true_, values are 1..0 (default: false)\n * \n * If element is missing a 'type' attribute, this will be set to 'range'.\n * @param targetOrQuery \n * @param options \n * @returns \n */\nexport function domNumberInputValue(targetOrQuery: HTMLInputElement | string, options: Partial<DomNumberInputValueOptions> = {}): ReactiveInitial<number> & ReactiveWritable<number> {\n const input = domInputValue(targetOrQuery, options);\n const el = input.el;\n const relative = options.relative ?? false;\n const inverted = options.inverted ?? false;\n\n const rx = transform(input, v => {\n return Number.parseFloat(v);\n });\n\n if (relative) {\n //el.setAttribute(`max`, inverted ? \"0\" : \"1\");\n el.max = inverted ? \"0\" : \"1\";\n //el.setAttribute(`min`, inverted ? \"1\" : \"0\");\n el.min = inverted ? \"1\" : \"0\";\n if (!el.hasAttribute(`step`)) {\n //el.setAttribute(`step`, \"0.1\");\n el.step = \"0.1\";\n }\n }\n if (el.getAttribute(`type`) === null) {\n el.type = `range`;\n }\n\n const set = (value: number) => {\n input.set(value.toString());\n }\n\n return {\n ...rx,\n last() {\n //console.log(`domNumberInputValue last: ${ input.last() }`);\n return Number.parseFloat(input.last())\n },\n set\n };\n}\n\nexport function domHslInputValue(targetOrQuery: HTMLInputElement | string, options: Partial<DomValueOptions> = {}): ReactiveInitial<Colour.HslScalar> & Reactive<Colour.HslScalar> & ReactiveWritable<Colour.HslScalar> {\n\n const input = domInputValue(targetOrQuery, {\n ...options,\n upstreamFilter: (value) => {\n return (typeof value === `object`) ? Colour.toCssColour(value as Colour.HslScalar) : value as string;\n },\n });\n const rx = transform(input, v => {\n return Colour.HslSpace.fromCss(v, { scalar: true, ensureSafe: true });\n });\n return {\n ...rx,\n last() {\n return Colour.HslSpace.fromCss(input.last(), { scalar: true, ensureSafe: true })\n },\n set(value) {\n input.set(Colour.HslSpace.toCssString(value));\n },\n };\n}\n\n/**\n * A stream of values when the a HTMLInputElement changes. Eg a <input type=\"range\">\n * ```js\n * const r = Rx.From.domInputValue(`#myEl`);\n * r.onValue(value => {\n * // value will be string\n * });\n * ```\n * \n * Options:\n * * emitInitialValue: If _true_ emits the HTML value of element (default: false)\n * * attributeName: If set, this is the HTML attribute value is set to when writing to stream (default: 'value')\n * * fieldName: If set, this is the DOM object field set when writing to stream (default: 'value')\n * * when: 'changed'|'changing' when values are emitted. (default: 'changed')\n * * fallbackValue: Fallback value to use if field/attribute cannot be read (default: '')\n * @param targetOrQuery \n * @param options \n * @returns \n */\nexport function domInputValue(targetOrQuery: HTMLInputElement | string, options: Partial<DomValueOptions> = {}): { el: HTMLInputElement } & ReactiveInitial<string> & ReactiveWritable<string> {\n const target: HTMLInputElement | null = (typeof targetOrQuery === `string` ? document.querySelector(targetOrQuery) : targetOrQuery);\n if (target === null && typeof targetOrQuery === `string`) throw new Error(`Element query could not be resolved '${ targetOrQuery }'`);\n if (target === null) throw new Error(`targetOrQuery is null`)\n\n const el = resolveEl(targetOrQuery);\n const when = options.when ?? `changed`;\n const eventName = when === `changed` ? `change` : `input`;\n const emitInitialValue = options.emitInitialValue ?? false;\n const fallbackValue = options.fallbackValue ?? ``;\n const upstreamSource = options.upstreamSource;\n let upstreamSourceUnsub = () => {}\n\n let attribName = options.attributeName;\n let fieldName = options.fieldName;\n\n if (fieldName === undefined && attribName === undefined) {\n attribName = fieldName = `value`;\n }\n\n const readValue = () => {\n let value: string | null | undefined;\n if (attribName) {\n value = el.getAttribute(attribName);\n //console.log(` attrib: ${ attribName } value: ${ value }`);\n }\n if (fieldName) {\n value = (el as any)[ fieldName ]\n }\n if (value === undefined || value === null) value = fallbackValue;\n //console.log(`domInputValue readValue: ${ value }. attrib: ${ attribName } field: ${ fieldName }`);\n return value;\n }\n\n const setValue = (value: string) => {\n if (attribName) {\n el.setAttribute(attribName, value);\n }\n if (fieldName) {\n (el as any)[ fieldName ] = value;\n }\n }\n\n const setUpstream = (v: any) => {\n v = options.upstreamFilter ? options.upstreamFilter(v) : v;\n setValue(v);\n }\n if (upstreamSource) {\n upstreamSourceUnsub = upstreamSource.onValue(setUpstream);\n if (hasLast(upstreamSource)) {\n setUpstream(upstreamSource.last());\n }\n }\n\n // Input element change event stream\n const rxEvents = eventTrigger(el, eventName, {\n fireInitial: emitInitialValue,\n debugFiring: options.debugFiring ?? false,\n debugLifecycle: options.debugLifecycle ?? false,\n });\n\n // Transform to get values\n const rxValues = transform(rxEvents, _trigger => readValue());\n\n return {\n ...rxValues,\n el,\n last() {\n return readValue()\n },\n set(value) {\n setValue(value);\n },\n dispose(reason) {\n upstreamSourceUnsub();\n rxValues.dispose(reason);\n rxEvents.dispose(reason);\n },\n }\n}\n\n/**\n * Listens for data changes from elements within a HTML form element.\n * Input elements must have a 'name' attribute.\n * \n * Simple usage:\n * ```js\n * const rx = Rx.From.domForm(`#my-form`);\n * rx.onValue(value => {\n * // Object containing values from form\n * });\n * \n * rx.last(); // Read current values of form\n * ```\n * \n * UI can be updated\n * ```js\n * // Set using an object of key-value pairs\n * rx.set({\n * size: 'large'\n * });\n * \n * // Or set a single name-value pair\n * rx.setNamedValue(`size`, `large`);\n * ```\n * \n * If an 'upstream' reactive is provided, this is used to set initial values of the UI, overriding\n * whatever may be in the HTML. Upstream changes modify UI elements, but UI changes do not modify the upstream\n * source.\n * \n * ```js\n * // Create a reactive object\n * const obj = Rx.From.object({\n * when: `2024-10-03`,\n * size: 12,\n * checked: true\n * });\n * \n * // Use this as initial values for a HTML form\n * // (assuming appropriate INPUT/SELECT elements exist)\n * const rx = Rx.From.domForm(`form`, { \n * upstreamSource: obj\n * });\n * \n * // Listen for changes in the UI\n * rx.onValue(value => {\n * \n * });\n * ```\n * @param formElOrQuery \n * @param options \n * @returns \n */\nexport function domForm<T extends Record<string, any>>(formElOrQuery: HTMLFormElement | string, options: Partial<DomFormOptions<T>> = {}): {\n setNamedValue: (name: string, value: any) => void,\n el: HTMLFormElement\n} & ReactiveInitial<T> & ReactiveWritable<T> {\n const formEl = resolveEl<HTMLFormElement>(formElOrQuery);\n const when = options.when ?? `changed`;\n const eventName = when === `changed` ? `change` : `input`;\n\n const emitInitialValue = options.emitInitialValue ?? false;\n const upstreamSource = options.upstreamSource;\n\n const typeHints = new Map<string, string>();\n\n let upstreamSourceUnsub = () => {}\n\n const readValue = (): T => {\n const fd = new FormData(formEl);\n const entries: [ string, unknown ][] = [];\n for (const [ k, v ] of fd.entries()) {\n const vString = v.toString();\n\n // Get type hint for key\n let typeHint = typeHints.get(k);\n if (!typeHint) {\n // If not found, use the kind of input element as a hint\n const el = getFormElement(k, vString);\n if (el) {\n if (el.type === `range` || el.type === `number`) {\n typeHint = `number`;\n } else if (el.type === `color`) {\n typeHint = `colour`;\n } else if (el.type === `checkbox` && (v === `true` || v === `on`)) {\n typeHint = `boolean`;\n } else {\n typeHint = `string`;\n }\n typeHints.set(k, typeHint);\n }\n }\n\n if (typeHint === `number`) {\n entries.push([ k, Number.parseFloat(vString) ]);\n } else if (typeHint === `boolean`) {\n const vBool = (vString === `true`) ? true : false;\n entries.push([ k, vBool ]);\n } else if (typeHint === `colour`) {\n const vRgb = Colour.toCssColour(vString);\n entries.push([ k, Colour.SrgbSpace.fromCss(vRgb, { scalar: false }) ]);\n } else {\n entries.push([ k, v.toString() ]);\n }\n }\n\n // Checkboxes that aren't checked don't give a value, so find those\n for (const el of formEl.querySelectorAll<HTMLInputElement>(`input[type=\"checkbox\"]`)) {\n if (!el.checked && el.value === `true`) {\n entries.push([ el.name, false ]);\n }\n }\n const asObject = Object.fromEntries(entries);\n //console.log(`readValue`, asObj);\n return asObject as any as T;\n }\n\n const getFormElement = (name: string, value: string): HTMLSelectElement | HTMLInputElement | undefined => {\n const el = formEl.querySelector<HTMLInputElement | HTMLSelectElement>(`[name=\"${ name }\"]`);\n if (!el) {\n console.warn(`Form does not contain an element with name=\"${ name }\"`);\n return;\n }\n if (el.type === `radio`) {\n // Get right radio option\n const radioEl = formEl.querySelector<HTMLInputElement>(`[name=\"${ name }\"][value=\"${ value }\"]`);\n if (!radioEl) {\n console.warn(`Form does not contain radio option for name=${ name } value=${ value }`);\n return;\n }\n return radioEl;\n }\n return el;\n }\n const setNamedValue = (name: string, value: any) => {\n const el = getFormElement(name, value);\n if (!el) return;\n\n //let typeHint = typeHints.get(name);\n // if (typeHint) {\n // console.log(`${ name } hint: ${ typeHint } input type: ${ el.type }`);\n // } else {\n // console.warn(`Rx.Sources.Dom.domForm no type hint for: ${ name }`);\n // }\n if (el.nodeName === `INPUT` || el.nodeName === `SELECT`) {\n if (el.type === `color`) {\n if (typeof value === `object`) {\n // Try to parse colour if value is an object\n value = Colour.toCssColour(value);\n }\n } else if (el.type === `checkbox`) {\n if (typeof value === `boolean`) {\n el.checked = value;\n return;\n } else {\n console.warn(`Rx.Sources.domForm: Trying to set non boolean type to a checkbox. Name: ${ name } Value: ${ value } (${ typeof value })`);\n }\n } else if (el.type === `radio`) {\n el.checked = true;\n return;\n }\n el.value = value;\n }\n }\n\n const setFromUpstream = (value: T) => {\n //console.log(`setUpstream`, value);\n for (const [ name, v ] of Object.entries(value)) {\n let hint = typeHints.get(name);\n if (!hint) {\n hint = typeof v;\n if (hint === `object`) {\n const rgb = Colour.toColour(v);\n hint = `colour`;\n // const rgb = Colour.toColour(v);\n // if (rgb.success) {\n // hint = `colour`;\n // }\n }\n typeHints.set(name, hint);\n }\n const valueFiltered = options.upstreamFilter ? options.upstreamFilter(name, v) : v;\n setNamedValue(name, valueFiltered);\n }\n }\n\n if (upstreamSource) {\n upstreamSourceUnsub = upstreamSource.onValue(setFromUpstream);\n if (hasLast(upstreamSource)) {\n setFromUpstream(upstreamSource.last());\n }\n }\n\n // Input element change event stream\n const rxEvents = eventTrigger(formEl, eventName, {\n fireInitial: emitInitialValue,\n debugFiring: options.debugFiring ?? false,\n debugLifecycle: options.debugLifecycle ?? false,\n });\n\n // Transform to get values\n const rxValues = transform(rxEvents, _trigger => readValue());\n\n return {\n ...rxValues,\n el: formEl,\n last() {\n return readValue()\n },\n set: setFromUpstream,\n setNamedValue,\n dispose(reason) {\n upstreamSourceUnsub();\n rxValues.dispose(reason);\n rxEvents.dispose(reason);\n },\n }\n}","import { resolveEl } from \"@ixfx/dom\";\nimport { Pathed } from \"@ixfx/core\";\nimport * as Rx from \"@ixfx/rx\";\nimport * as RxFrom from \"@ixfx/rx/from\";\nimport type { ElementsOptions, PipeDomBinding, BindUpdateOpts, DomBindResolvedSource, DomBindSourceValue, DomBindValueTarget, ElementBind, DomBindUnresolvedSource } from './dom-types.js';\nimport { findBySomeKey as mapFindBySomeKey } from \"@ixfx/core/maps\";\nimport { afterMatch, beforeMatch, stringSegmentsWholeToEnd, stringSegmentsWholeToFirst } from \"@ixfx/core/text\";\nimport { QueueMutable } from \"@ixfx/collections\";\n\n/**\n * Reactive stream of array of elements that match `query`.\n * @param query \n * @returns \n */\nexport function fromDomQuery(query: string) {\n const elements = [ ...document.querySelectorAll(query) ] as HTMLElement[];\n\n return Rx.From.object(elements);\n /// TODO: MutationObserver to update element list\n}\n\n/**\n * Updates an element's `textContent` when the source value changes.\n * ```js\n * bindText(source, `#blah`);\n * ```\n * @param elOrQuery \n * @param source \n * @param bindOpts \n */\nexport const bindText = <TSource>(source: Rx.Reactive<TSource>, elOrQuery: string | HTMLElement | null, bindOpts: Partial<DomBindSourceValue<TSource, string>> = {}) => {\n return bindElement(source, elOrQuery, { ...bindOpts, elField: `textContent` });\n}\n\n/**\n * Updates an element's `value` (as well as the 'value' attribute) when the source value changes.s\n * @param source \n * @param elOrQuery \n * @param bindOpts \n * @returns \n */\nexport const bindValueText = <TSource>(source: Rx.Reactive<TSource>, elOrQuery: string | HTMLInputElement | null, bindOpts: Partial<DomBindSourceValue<TSource, string>> = {}) => {\n return bindElement(source, elOrQuery, { ...bindOpts, elField: `value`, attribName: `value` });\n}\n\n/**\n * Updates an element's `valueAsNumber` (as well as the 'value' attribute) when the source value changes.\n * ```js\n * // Create a reactive number, with a default value of 10\n * const r1 = Rx.From.number(10);\n * // Bind reactive to HTML input element with id 'inputRange'\n * const b1 = Rx.Dom.bindValueRange(r1,`#inputRange`);\n *\n * // Demo: Change the reactive value every second\n * // ...changing the reactive in turn updates the HTML\n * setInterval(() => {\n * r1.set(Math.floor(Math.random()*100));\n * }, 1000);\n * ```\n * @param source \n * @param elOrQuery \n * @param bindOpts \n * @returns \n */\n// export const bindValueRange = (source: Rx.Reactive<number>, elOrQuery: string | HTMLInputElement | null, bindOpts: Partial<Rx.DomBindInputOptions<number, number>> = {}) => {\n// const el = validateElement(elOrQuery, `range`);\n// const b = bindElement<number, number>(source, el, { ...bindOpts, elField: `valueAsNumber`, attribName: `value` });\n// const twoway = bindOpts.twoway ?? false;\n\n// const transformFromInput = bindOpts.transformFromInput ?? ((value) => {\n// if (typeof value === `number`) return value;\n// return Number.parseFloat(value);\n// });\n// const input = Rx.From.domValueAsNumber(el);\n// return setupInput(b, input, source, twoway, transformFromInput);\n// }\n\n// export const bindValueColour = (source: Rx.Reactive<Colour.Colourish>, elOrQuery: string | HTMLInputElement | null, bindOpts: Partial<Rx.DomBindInputOptions<Colour.Colourish, string>> = {}) => {\n// const el = validateElement(elOrQuery, `color`);\n// const b = bindElement<Colour.Colourish, string>(source, el, {\n// ...bindOpts,\n// elField: `value`,\n// attribName: `value`,\n// transform(input) {\n// console.log(`transform from: ${ JSON.stringify(input) } to hex`);\n// const c = Colour.resolve(input);\n// return c.to(`srgb`).toString({ format: `hex`, collapse: false });\n// },\n// });\n\n// const twoway = bindOpts.twoway ?? false;\n\n// const transformFromInput = bindOpts.transformFromInput ?? ((value) => {\n// const x = Colour.toHsl(value);\n// console.log(`transformFromInput: ${ value } x: ${ JSON.stringify(x) }`);\n// return x;\n// });\n\n// const input = Rx.From.domValue<Colour.Hsl>(el, {\n// domToValue: transformFromInput\n// });\n// return setupInput(b, input, source, twoway, transformFromInput);\n// }\n\nconst setupInput = <TSource, TDestination>(b: PipeDomBinding, input: Rx.Reactive<TDestination>, source: Rx.Reactive<TSource>, twoway: boolean, transformFromInput: (value: TDestination) => TSource) => {\n input.onValue(value => {\n const v = transformFromInput(value);\n if (twoway && Rx.isWritable(source)) {\n source.set(v);\n }\n });\n const dispose = () => {\n input.dispose(`bindInput twoway dispose`);\n b.remove(false);\n }\n return { ...b, dispose, input };\n}\n\nconst validateElement = (elOrQuery: string | HTMLInputElement | null, type?: string): HTMLInputElement => {\n const el = resolveEl(elOrQuery);\n if (el.nodeName !== `INPUT`) throw new Error(`HTML INPUT element expected. Got: ${ el.nodeName }`);\n if (type !== undefined && el.type !== type) throw new Error(`HTML INPUT element expected with type 'range'. Got: ${ el.type }`);\n return el;\n}\n\n\n/**\n * Updates an element's `innerHTML` when the source value changes\n * ```js\n * bindHtml(source, `#blah`);\n * ```\n * \n * Uses {@link bindElement}, with `{elField:'innerHTML'}` as the options.\n * @param elOrQuery\n * @param source \n * @param bindOpts \n * @returns \n */\nexport const bindHtml = <TSource>(source: Rx.Reactive<TSource>, elOrQuery: string | HTMLElement | null, bindOpts: DomBindSourceValue<TSource, string> = {}) => {\n return bindElement(source, elOrQuery, { ...bindOpts, elField: `innerHTML` });\n}\n\n\n/**\n * Shortcut to bind to an elements attribute\n * @param elOrQuery\n * @param source \n * @param attribute \n * @param bindOpts \n * @returns \n */\n// export const bindAttribute = <V>(elOrQuery: string | HTMLElement, source: Rx.Reactive<V>, attribute: string, bindOpts: Partial<DomBindOptions<V>> = {}) => {\n// return bind(elOrQuery, source, { ...bindOpts, attribName: attribute });\n// }\n\n/**\n * Shortcut to bind to a CSS variable\n * @param elOrQuery\n * @param source \n * @param cssVariable \n * @param bindOpts \n * @returns \n */\n// export const bindCssVariable = <V>(elOrQuery: string | HTMLElement, source: Rx.Reactive<V>, cssVariable: string, bindOpts: Partial<DomBindOptions<V>> = {}) => {\n// return bind(elOrQuery, source, { ...bindOpts, cssVariable: cssVariable });\n// }\n\n/**\n * Creates a new HTML element, calling {@link bind} on it to update when `source` emits new values.\n * \n * \n * ```js\n * // Set textContent of a SPAN with values from `source`\n * create(source, { tagName: `span`, parentEl: document.body })\n * ```\n * \n * If `parentEl` is not given in the options, the created element needs to be manually added\n * ```js\n * const b = create(source);\n * someEl.append(b.el); // Append manually\n * ```\n * \n * ```\n * // Set 'title' attribute based on values from `source`\n * create(source, { parentEl: document.body, attribName: `title` })\n * ```\n * @param source \n * @param options \n * @returns \n */\n// export const create = <V>(source: Rx.Reactive<V>, options: Partial<DomCreateOptions> & Partial<DomBindOptions<V>> = {}): PipeDomBinding => {\n// const nodeType = options.tagName ?? `DIV`;\n\n// const el = document.createElement(nodeType);\n// const b = bind(el, source, options);\n\n// if (options.parentEl) {\n// const parentElementOrQuery = resolveEl(options.parentEl);\n// if (parentElementOrQuery === undefined) throw new Error(`Parent element could not be resolved`);\n// parentElementOrQuery.append(el);\n// }\n// return b;\n// }\n\n/**\n * Update a DOM element's field, attribute or CSS variable when `source` produces a value.\n * \n * ```js\n * // Access via DOM query. Binds to 'textContent' by default\n * bind(readableSource, `#someEl`);\n * \n * // Set innerHTML instead\n * bind(readableSource, someEl, { elField: `innerHTML` });\n * \n * // An attribute\n * bind(readableSource, someEl, { attribName: `width` });\n * \n * // A css variable ('--' optiona)\n * bind(readableSource, someEl, { cssVariable: `hue` });\n * \n * // Pluck a particular field from source data.\n * // Ie someEl.textContent = value.colour\n * bind(readableSource, someEl, { sourceField: `colour` });\n * \n * // Transform value before setting it to field\n * bind(readableSource, someEl, { \n * field: `innerHTML`, \n * transform: (v) => `Colour: ${v.colour}`\n * })\n * ```\n * \n * If `source` has an initial value, this is used when first bound.\n * \n * Returns {@link PipeDomBinding} to control binding:\n * ```js\n * const bind = bind(source, `#someEl`);\n * bind.remove(); // Unbind\n * bind.remove(true); // Unbind and remove HTML element\n * ```\n * \n * If several fields need to be updated based on a new value, consider using {@link bindUpdate} instead.\n * @param elOrQuery Element to update to, or query string such as '#someid'\n * @param source Source of data\n * @param binds Bindings\n */\nexport const bindElement = <TSource, TDestination>(source: Rx.Reactive<TSource>, elOrQuery: string | HTMLElement | null, ...binds: (DomBindSourceValue<TSource, TDestination> & DomBindValueTarget)[]): PipeDomBinding => {\n if (elOrQuery === null) throw new Error(`Param 'elOrQuery' is null`);\n if (elOrQuery === undefined) throw new Error(`Param 'elOrQuery' is undefined`);\n\n const el = resolveEl(elOrQuery);\n let b: DomBindValueTarget[] = [];\n if (binds.length === 0) {\n b.push({ elField: `textContent` });\n } else {\n b = [ ...binds ];\n }\n const bb = b.map(bind => {\n if (`element` in bind) return bind as DomBindResolvedSource<TSource, TDestination>;\n return { ...bind, element: el } as DomBindResolvedSource<TSource, TDestination>\n });\n return bind<TSource, TDestination>(source, ...bb);\n}\n\nconst resolveBindUpdater = (bind: DomBindValueTarget, element: HTMLElement): (value: any) => void => {\n const b = resolveBindUpdaterBase(bind);\n return (value: any) => {\n b(value, element);\n }\n}\n\nconst resolveBindUpdaterBase = (bind: DomBindValueTarget): (value: any, element: HTMLElement) => void => {\n if (bind.elField !== undefined || (bind.cssVariable === undefined && bind.attribName === undefined && bind.cssProperty === undefined && bind.textContent === undefined && bind.htmlContent === undefined)) {\n const field = bind.elField ?? `textContent`;\n return (v: any, element: HTMLElement) => {\n (element as any)[ field ] = v;\n }\n }\n if (bind.attribName !== undefined) {\n const attrib = bind.attribName;\n return (v: any, element: HTMLElement) => {\n element.setAttribute(attrib, v as string);\n }\n }\n if (bind.textContent) {\n return (v: any, element: HTMLElement) => {\n element.textContent = v;\n }\n }\n if (bind.htmlContent) {\n return (v: any, element: HTMLElement) => {\n element.innerHTML = v;\n }\n }\n if (bind.cssVariable !== undefined) {\n let css = bind.cssVariable;\n if (!css.startsWith(`--`)) css = `--` + css;\n return (v: any, element: HTMLElement) => {\n element.style.setProperty(css, v as string);\n }\n }\n if (bind.cssProperty !== undefined) {\n return (v: any, element: HTMLElement) => {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n (element.style as any)[ bind.cssProperty! ] = v;\n }\n }\n return (_: any, _element: HTMLElement) => {\n /** no-op */\n }\n}\n\nconst resolveTransform = <TSource, TDestination>(bind: DomBindSourceValue<TSource, TDestination>) => {\n if (!bind.transform && !bind.transformValue) return;\n if (bind.transformValue) {\n if (bind.sourceField === undefined) throw new Error(`Expects 'sourceField' to be set when 'transformValue' is set`);\n return (value: TSource) => {\n const fieldValue = (value as any)[ bind.sourceField ]\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return bind.transformValue!(fieldValue);\n }\n } else if (bind.transform) {\n if (bind.sourceField !== undefined) throw new Error(`If 'transform' is set, 'sourceField' is ignored`);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return (value: TSource) => bind.transform!(value);\n }\n}\n\n/**\n * Binds `source` to one or more element(s). One or more bindings for the same source\n * can be provided.\n * \n * ```js\n * bind(source, \n * // Binds .name field of source values to textContent of #some-element\n * { query: `#some-element`, sourceField: `name` },\n * { query: `section`, }\n * );\n * ```\n * \n * Can update\n * * CSS variables\n * * CSS styles\n * * textContent / innerHTML\n * * HTML DOM attributes and object fields\n * \n * Can use a particular field on source values, or use the whole value. These can\n * pass through `transformValue` or `transform` respectively.\n * \n * Returns a function to unbind from source and optionally remove HTML element\n * ```js\n * const unbind = bind( . . . );\n * unbind(); // Unbind\n * unbind(true); // Unbind and remove HTML element(s)\n * ```\n * @param source \n * @param bindsUnresolvedElements \n * @returns \n */\nexport const bind = <TSource, TDestination>(source: Rx.Reactive<TSource>, ...bindsUnresolvedElements: DomBindUnresolvedSource<TSource, TDestination>[]): PipeDomBinding => {\n const binds: DomBindResolvedSource<TSource, TDestination>[] = bindsUnresolvedElements.map(bind => {\n if (bind.element && bind.element !== undefined) return bind as DomBindResolvedSource<TSource, TDestination>;\n if (bind.query) return {\n ...bind,\n element: resolveEl<HTMLElement>(bind.query)\n }\n throw new Error(`Unable to resolve element. Missing 'element' or 'query' values on bind. ${ JSON.stringify(bind) }`);\n });\n\n const bindsResolved = binds.map(bind => ({\n update: resolveBindUpdater(bind, bind.element),\n transformer: resolveTransform(bind),\n sourceField: bind.sourceField\n }));\n\n const update = (value: TSource) => {\n for (const bind of bindsResolved) {\n if (bind.transformer) {\n bind.update(bind.transformer(value));\n } else {\n const v = (bind.sourceField) ? value[ bind.sourceField ] : value;\n\n if (typeof v === `object`) {\n if (bind.sourceField) {\n bind.update(JSON.stringify(v));\n } else {\n bind.update(JSON.stringify(v));\n }\n } else bind.update(v as string);\n }\n }\n }\n const unsub = source.on(message => {\n if (Rx.messageHasValue(message)) {\n update(message.value);\n } else if (Rx.messageIsSignal(message)) {\n console.warn(message);\n }\n });\n\n if (Rx.hasLast(source)) {\n update(source.last());\n }\n\n return {\n remove: (removeElements: boolean) => {\n unsub();\n if (removeElements) {\n for (const bind of binds) {\n bind.element.remove();\n }\n }\n }\n }\n}\n\n/**\n * Calls `updater` whenever `source` produces a value. Useful when several fields from a value\n * are needed to update an element.\n * ```js\n * bindUpdate(source, `#someEl`, (v, el) => {\n * el.setAttribute(`width`, v.width);\n * el.setAttribute(`height`, v.height);\n * });\n * ```\n * \n * Returns a {@link PipeDomBinding} to manage binding\n * ```js\n * const b = bindUpdate(...);\n * b.remove(); // Disconnect binding\n * b.remove(true); // Disconnect binding and remove element\n * b.el; // HTML element\n * ```\n * @param elOrQuery \n * @param source \n * @param updater \n * @returns \n */\nexport const bindUpdate = <V>(source: Rx.Reactive<V>, elOrQuery: string | HTMLElement, updater: (v: V, el: HTMLElement) => void): PipeDomBinding => {\n const el = resolveEl(elOrQuery);\n\n const update = (value: V) => {\n updater(value, el);\n }\n\n const unsub = source.on(message => {\n if (Rx.messageHasValue(message)) {\n console.log(message);\n update(message.value);\n } else {\n console.warn(message);\n }\n });\n\n if (Rx.hasLast(source)) {\n update(source.last());\n }\n\n return {\n remove: (removeElement: boolean) => {\n unsub();\n if (removeElement) {\n el.remove();\n }\n }\n }\n}\n\n/**\n * Updates a HTML element based on diffs on an object.\n * ```js\n * // Wrap an object\n * const o = Rx.object({ name: `Jane`, ticks: 0 });\n * const b = bindDiffUpdate(`#test`, o, (diffs, el) => {\n * // el = reference to #test\n * // diff = Array of Changes, \n * // eg [ { path: `ticks`, value: 797, previous: 0 } ]\n * for (const diff of diffs) {\n * if (diff.path === `ticks`) el.textContent = `${diff.previous} -> ${diff.value}`\n * }\n * })\n * \n * // Eg. update field\n * o.updateField(`ticks`, Math.floor(Math.random()*1000));\n * ```\n * \n * If `initial` is provided as an option, this will be called if `source` has an initial value. Without this, the DOM won't be updated until the first data\n * update happens.\n * ```js\n * bindDiffUpdate(el, source, updater, { \n * initial: (v, el) => {\n * el.innerHTML = v.name;\n * }\n * })\n * ```\n * @param elOrQuery \n * @param source \n * @param updater \n * @param opts \n * @returns \n */\nexport const bindDiffUpdate = <V>(\n source: Rx.ReactiveDiff<V>,\n elOrQuery: string | HTMLElement | null,\n updater: (diffs: Pathed.PathDataChange<any>[], el: HTMLElement) => void,\n opts: Partial<BindUpdateOpts<V>> = {}\n): PipeDomBinding & { refresh: () => void } => {\n if (elOrQuery === null) throw new Error(`Param 'elOrQuery' is null`);\n if (elOrQuery === undefined) throw new Error(`Param 'elOrQuery' is undefined`);\n\n const el = resolveEl(elOrQuery);\n //const binds = opts.binds;\n const update = (value: Pathed.PathDataChange<any>[]) => {\n updater(value, el);\n }\n\n const unsub = source.onDiff(value => {\n update(value);\n });\n\n const init = () => {\n if (Rx.hasLast(source) && opts.initial) opts.initial(source.last(), el);\n }\n\n init();\n\n return {\n refresh: () => {\n init();\n },\n remove: (removeElement: boolean) => {\n unsub();\n if (removeElement) {\n el.remove();\n }\n }\n }\n}\n\n/**\n * Creates a new HTML element and calls `bindUpdate` so values from `source` can be used\n * to update it.\n * \n * \n * ```js\n * // Creates a span, adding it to <body>\n * const b = createUpdate(dataSource, (value, el) => {\n * el.width = value.width;\n * el.height = value.height;\n * }, { \n * tagName: `SPAN`,\n * parentEl: document.body\n * })\n * ```\n * @param source \n * @param updater \n * @param options \n * @returns \n */\n// export const createUpdate = <V>(source: Rx.Reactive<V>, updater: (v: V, el: HTMLElement) => void, options: Partial<DomCreateOptions> = {}): PipeDomBinding => {\n// const tag = options.tagName ?? `DIV`;\n// const el = document.createElement(tag);\n// if (options.parentEl) {\n// const parent = resolveEl(options.parentEl);\n// parent.append(el);\n// }\n// const b = bindUpdate(source, el, updater);\n// return b;\n// }\n\n\n/**\n * Creates, updates & deletes elements based on pathed values from a reactive.\n * \n * This means that elements are only manipulated if its associated data changes,\n * and elements are not modified if there's no need to.\n * @param source \n * @param options \n */\nexport const elements = <T>(source: Rx.ReactiveDiff<T> | (Rx.ReactiveDiff<T> & Rx.ReactiveInitial<T>), options: Partial<ElementsOptions>) => {\n const containerEl = options.container ? resolveEl(options.container) : document.body;\n const defaultTag = options.defaultTag ?? `div`\n const elByField = new Map<string, HTMLElement>();\n const binds = new Map<string, ElementBind & {\n update: ((value: any, el: HTMLElement) => void)\n path: string\n }>();\n\n for (const [ key, value ] of Object.entries(options.binds ?? {})) {\n const tagName = value.tagName ?? defaultTag;\n //console.log(`key: ${ key }`);\n binds.set(key, {\n ...value,\n update: resolveBindUpdaterBase(value),\n transform: resolveTransform(value),\n tagName,\n path: key\n });\n }\n\n const findBind = (path: string) => {\n const bind = mapFindBySomeKey(binds, stringSegmentsWholeToEnd(path));\n if (bind !== undefined) return bind;\n if (!path.includes(`.`)) return binds.get(`_root`);\n }\n\n function* ancestorBinds(path: string) {\n for (const p of stringSegmentsWholeToFirst(path)) {\n //console.log(` ancestorBinds path: ${ path } segment: ${ p }`)\n\n if (binds.has(p)) {\n //console.log(` bind: ${ p } found: ${ JSON.stringify(binds.get(p)) }`);\n yield binds.get(p);\n } else {\n //console.log(` bind: ${ p } not found`);\n }\n }\n if (binds.has(`_root`) && path.includes(`.`)) yield binds.get(`_root`);\n }\n\n\n const create = (path: string, value: any) => {\n const rootedPath = getRootedPath(path);\n console.log(`Rx.Dom.elements.create: ${ path } rooted: ${ rootedPath } value: ${ JSON.stringify(value) }`);\n\n // Create\n const bind = findBind(getRootedPath(path));\n let tagName = defaultTag;\n if (bind?.tagName) tagName = bind.tagName;\n\n const el = document.createElement(tagName);\n el.setAttribute(`data-path`, path);\n update(path, el, value);\n\n let parentForEl;\n for (const b of ancestorBinds(rootedPath)) {\n //console.log(` path: ${ rootedPath } b: ${ JSON.stringify(b) }`);\n if (b?.nestChildren) {\n // Get root of path\n const absoluteRoot = beforeMatch(path, `.`);\n const findBy = b.path.replace(`_root`, absoluteRoot);\n\n parentForEl = elByField.get(findBy);\n if (parentForEl === undefined) {\n //console.log(` could not find parent. path: ${ path } b.path: ${ b.path } findBy: ${ findBy }`);\n } else {\n //console.log(` found parent`);\n break;\n }\n }\n }\n (parentForEl ?? containerEl).append(el);\n elByField.set(path, el);\n console.log(`Added el: ${ path }`);\n }\n\n const update = (path: string, el: HTMLElement, value: any) => {\n console.log(`Rx.dom.update path: ${ path } value:`, value);\n\n const bind = findBind(getRootedPath(path));\n if (bind === undefined) {\n //console.log(`Rx.dom.update no bind for ${ path }`)\n if (typeof value === `object`) value = JSON.stringify(value);\n el.textContent = value;\n } else {\n //console.log(`Rx.dom.update got bind! ${ path } `);\n if (bind.transform) value = bind.transform(value);\n bind.update(value, el);\n }\n }\n\n const changes = (changes: (Pathed.PathDataChange<any> | Pathed.PathData<any>)[]) => {\n const queue = new QueueMutable({}, changes);\n let d = queue.dequeue();\n const seenPaths = new Set<string>();\n while (d !== undefined) {\n //for (const d of changes) {\n const path = d.path;\n if (!(`previous` in d) || d.previous === undefined) {\n // Create\n console.log(`Rx.Dom.elements.changes no previous. path: ${ path }`);\n\n create(path, d.value);\n const subdata = [ ...Pathed.getPathsAndData(d.value, false, Number.MAX_SAFE_INTEGER, path) ];\n console.log(subdata);\n for (const dd of subdata) {\n if (!seenPaths.has(dd.path)) {\n queue.enqueue(dd);\n seenPaths.add(dd.path);\n }\n }\n } else if (d.value === undefined) {\n // Delete\n const el = elByField.get(path);\n if (el === undefined) {\n console.warn(`No element to delete? ${ path } `);\n } else {\n console.log(`Rx.Dom.elements.changes delete ${ path }`);\n el.remove();\n }\n } else {\n // Update\n const el = elByField.get(path);\n if (el === undefined) {\n console.warn(`Rx.Dom.elements.changes No element to update ? ${ path } `);\n create(path, d.value);\n } else {\n //console.log(`Rx.Dom.elements.changes Updating ${ path } `, el);\n update(path, el, d.value);\n }\n }\n d = queue.dequeue();\n }\n }\n\n /**\n * Source has changed\n */\n source.onDiff(value => {\n //console.log(`Rx.Dom.elements diff ${ JSON.stringify(value) } `);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n changes(value);\n });\n\n // Source has an initial value, use that\n if (Rx.hasLast(source)) {\n const last = source.last();\n // Get data of value as a set of paths and data\n // but only at first level of depth, because changes() will probe\n // deeper itself\n changes([ ...Pathed.getPathsAndData(last as object, false, 1) ]);\n }\n};\n\n/**\n * Replaces the root portion of `path` with the magic keyword `_root`\n * @param path \n * @returns \n */\nconst getRootedPath = (path: string) => {\n const after = afterMatch(path, `.`);\n return after === path ? `_root` : `_root.` + after;\n}\n\nexport function win() {\n const generateRect = () => ({ width: window.innerWidth, height: window.innerHeight });\n\n const size = RxFrom.event(window, `resize`, {\n lazy: `very`,\n transform: () => generateRect(),\n });\n const pointer = RxFrom.event(window, `pointermove`, {\n lazy: `very`,\n transform: (args: Event | undefined) => {\n if (args === undefined) return { x: 0, y: 0 };\n const pe = args as PointerEvent;\n return { x: pe.x, y: pe.y }\n }\n });\n const dispose = (reason = `Reactive.win.dispose`) => {\n size.dispose(reason);\n pointer.dispose(reason);\n }\n return { dispose, size, pointer };\n}\n","export * from './browser-resize.js';\nexport * from './browser-theme-change.js';\nexport * from './colour.js';\nexport * from './dom-source.js';\nexport type * from './dom-types.js';\nexport * from './dom.js';\n"],"x_google_ignoreList":[44],"mappings":"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"}