@pixerate/editor 0.125.0 → 0.127.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation/index.d.cts +2 -3
- package/dist/animation/index.d.ts +2 -3
- package/dist/animation-editor/index.cjs +71 -73
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +6 -8
- package/dist/animation-editor/index.d.ts +6 -8
- package/dist/animation-editor/index.js +11 -13
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/{bezier-CBzKKDjl.d.cts → bezier-DBz0IgEt.d.cts} +22 -2
- package/dist/{bezier-CWv6LQal.d.ts → bezier-DWI5MEkI.d.ts} +22 -2
- package/dist/{brushstrokeRender-LRV7GXGD.js → brushstrokeRender-7RUITO42.js} +3 -3
- package/dist/{brushstrokeRender-EELTV7U4.cjs → brushstrokeRender-OW6ENCZG.cjs} +7 -7
- package/dist/{brushstrokeRender-EELTV7U4.cjs.map → brushstrokeRender-OW6ENCZG.cjs.map} +1 -1
- package/dist/canvas/index.cjs +423 -37
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +189 -11
- package/dist/canvas/index.d.ts +189 -11
- package/dist/canvas/index.js +395 -9
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-7LQO6OHH.cjs → chunk-33SO3QWP.cjs} +4 -4
- package/dist/{chunk-7LQO6OHH.cjs.map → chunk-33SO3QWP.cjs.map} +1 -1
- package/dist/{chunk-MPQAO33O.js → chunk-A6KHMKI4.js} +3 -3
- package/dist/{chunk-V5YGPRCZ.cjs → chunk-BEGEWQHD.cjs} +41 -41
- package/dist/{chunk-V5YGPRCZ.cjs.map → chunk-BEGEWQHD.cjs.map} +1 -1
- package/dist/{chunk-N3FVUOZD.cjs → chunk-BJTCSLF6.cjs} +7 -7
- package/dist/{chunk-N3FVUOZD.cjs.map → chunk-BJTCSLF6.cjs.map} +1 -1
- package/dist/{chunk-WUDPFWAN.js → chunk-F7Q2NE2Y.js} +3 -3
- package/dist/{chunk-G6WXWS4Y.js → chunk-FICSDDDF.js} +2 -2
- package/dist/{chunk-GUZ47CJM.cjs → chunk-IZ4WRXZA.cjs} +1 -1
- package/dist/{chunk-GUZ47CJM.cjs.map → chunk-IZ4WRXZA.cjs.map} +1 -1
- package/dist/{chunk-QDJKUBWE.cjs → chunk-JODTP4DP.cjs} +176 -5
- package/dist/chunk-JODTP4DP.cjs.map +1 -0
- package/dist/{chunk-GLWZXQ4Q.js → chunk-KHNZ6MOU.js} +1 -1
- package/dist/chunk-KHNZ6MOU.js.map +1 -0
- package/dist/{chunk-GCJWMEYW.cjs → chunk-KSJLDRHK.cjs} +46 -46
- package/dist/{chunk-GCJWMEYW.cjs.map → chunk-KSJLDRHK.cjs.map} +1 -1
- package/dist/{chunk-QQKTOA4U.cjs → chunk-ORE334I6.cjs} +132 -132
- package/dist/{chunk-QQKTOA4U.cjs.map → chunk-ORE334I6.cjs.map} +1 -1
- package/dist/{chunk-X6KTSFAE.js → chunk-Q4NBEVV5.js} +2 -2
- package/dist/{chunk-XZWOLXWA.js → chunk-QFSTQHZY.js} +174 -3
- package/dist/chunk-QFSTQHZY.js.map +1 -0
- package/dist/{chunk-FPRIUR4T.js → chunk-ROZFX4QI.js} +3 -3
- package/dist/{chunk-UXFI3CDZ.cjs → chunk-SFCPGMCT.cjs} +8 -8
- package/dist/{chunk-UXFI3CDZ.cjs.map → chunk-SFCPGMCT.cjs.map} +1 -1
- package/dist/{chunk-J67OLQUQ.js → chunk-UABQTYQF.js} +3 -3
- package/dist/{chunk-O5RVCDEC.cjs → chunk-XLUYXUBD.cjs} +88 -88
- package/dist/{chunk-O5RVCDEC.cjs.map → chunk-XLUYXUBD.cjs.map} +1 -1
- package/dist/{chunk-FG274FYT.js → chunk-YGJIER2R.js} +2 -2
- package/dist/effects/index.cjs +32 -34
- package/dist/effects/index.cjs.map +1 -1
- package/dist/effects/index.d.cts +6 -38
- package/dist/effects/index.d.ts +6 -38
- package/dist/effects/index.js +3 -5
- package/dist/effects/index.js.map +1 -1
- package/dist/evaluate-BbCeF6pt.d.ts +114 -0
- package/dist/evaluate-BsxYieLN.d.cts +114 -0
- package/dist/{export-DVl4fWy5.d.cts → export-Cbr9IqpJ.d.cts} +1 -1
- package/dist/{export-Bp7ji2r4.d.cts → export-CcldobdN.d.cts} +3 -3
- package/dist/{export-C1s4eolZ.d.ts → export-ClPKUB-v.d.ts} +1 -1
- package/dist/{export-DAyPY94f.d.ts → export-PGhOpDmz.d.ts} +3 -3
- package/dist/{helpers-i95Ob6Vi.d.cts → helpers-C5aAd44p.d.cts} +67 -4
- package/dist/{helpers-BBLlekuM.d.ts → helpers-CPWcK504.d.ts} +67 -4
- package/dist/image-editor/index.cjs +619 -621
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +9 -11
- package/dist/image-editor/index.d.ts +9 -11
- package/dist/image-editor/index.js +6 -8
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{opentype-14PDI5D2.d.ts → opentype-01rMIuQR.d.ts} +1 -1
- package/dist/{opentype-D80AVmMu.d.cts → opentype-BgqvmGT-.d.cts} +1 -1
- package/dist/paint-editor/index.cjs +737 -117
- package/dist/paint-editor/index.cjs.map +1 -1
- package/dist/paint-editor/index.d.cts +248 -13
- package/dist/paint-editor/index.d.ts +248 -13
- package/dist/paint-editor/index.js +635 -15
- package/dist/paint-editor/index.js.map +1 -1
- package/dist/{pathfinder-DjISxkUv.d.ts → pathfinder-D-h0Imus.d.ts} +1 -1
- package/dist/{pathfinder-C0UoFypx.d.cts → pathfinder-DgG0Z9Lr.d.cts} +1 -1
- package/dist/{player-cGLrngL_.d.ts → player-BK2kKbfd.d.ts} +1 -1
- package/dist/{player-CBtEoU2x.d.cts → player-CmbY3218.d.cts} +1 -1
- package/dist/pool-C7GtrL34.d.cts +34 -0
- package/dist/pool-CTrtciaN.d.ts +34 -0
- package/dist/{svg-DJKriJ4A.d.ts → svg-BRLwcibA.d.ts} +2 -3
- package/dist/{svg-BkRL-fZJ.d.cts → svg-DLBBPQP9.d.cts} +2 -3
- package/dist/{tools-CM8Oe8F3.d.ts → tools-AugT22z3.d.ts} +1 -1
- package/dist/{tools-DZCv2kX1.d.cts → tools-BpCmUNxb.d.cts} +1 -1
- package/dist/vector/index.cjs +923 -925
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +10 -12
- package/dist/vector/index.d.ts +10 -12
- package/dist/vector/index.js +11 -13
- package/dist/vector/index.js.map +1 -1
- package/dist/video-editor/index.cjs +269 -271
- package/dist/video-editor/index.cjs.map +1 -1
- package/dist/video-editor/index.d.cts +6 -8
- package/dist/video-editor/index.d.ts +6 -8
- package/dist/video-editor/index.js +3 -5
- package/dist/video-editor/index.js.map +1 -1
- package/dist/{warp-CH9MM435.d.cts → warp-C13L_GRn.d.cts} +1 -1
- package/dist/{warp-k_PdtXOG.d.ts → warp-q8FK5HHi.d.ts} +1 -1
- package/package.json +1 -1
- package/skills/pixerate-canvas/SKILL.md +19 -0
- package/skills/pixerate-paint-editor/SKILL.md +40 -1
- package/dist/behavior-Ymbld6jL.d.cts +0 -60
- package/dist/behavior-Ymbld6jL.d.ts +0 -60
- package/dist/chunk-GLWZXQ4Q.js.map +0 -1
- package/dist/chunk-IOXKXQNW.cjs +0 -178
- package/dist/chunk-IOXKXQNW.cjs.map +0 -1
- package/dist/chunk-QDJKUBWE.cjs.map +0 -1
- package/dist/chunk-TGKT5QAB.js +0 -178
- package/dist/chunk-TGKT5QAB.js.map +0 -1
- package/dist/chunk-XZWOLXWA.js.map +0 -1
- package/dist/evaluate-2S3vSPLy.d.cts +0 -55
- package/dist/evaluate-CfmT6xA3.d.ts +0 -55
- package/dist/gradient-KDfCvhuj.d.cts +0 -66
- package/dist/gradient-KDfCvhuj.d.ts +0 -66
- /package/dist/{brushstrokeRender-LRV7GXGD.js.map → brushstrokeRender-7RUITO42.js.map} +0 -0
- /package/dist/{chunk-MPQAO33O.js.map → chunk-A6KHMKI4.js.map} +0 -0
- /package/dist/{chunk-WUDPFWAN.js.map → chunk-F7Q2NE2Y.js.map} +0 -0
- /package/dist/{chunk-G6WXWS4Y.js.map → chunk-FICSDDDF.js.map} +0 -0
- /package/dist/{chunk-X6KTSFAE.js.map → chunk-Q4NBEVV5.js.map} +0 -0
- /package/dist/{chunk-FPRIUR4T.js.map → chunk-ROZFX4QI.js.map} +0 -0
- /package/dist/{chunk-J67OLQUQ.js.map → chunk-UABQTYQF.js.map} +0 -0
- /package/dist/{chunk-FG274FYT.js.map → chunk-YGJIER2R.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/effects/conformance.ts","../../src/effects/fake.ts","../../src/effects/ui.ts"],"sourcesContent":["/**\n * `checkEffectProvider`: a conformance check any provider can run in its own tests, so editors\n * can rely on the contract (strict control schemas, valid defaults, typed errors, renderers that\n * return the size they were asked for).\n */\n\nimport { isEffectError } from './errors.js';\nimport { createEffectPixels, effectValueErrors, isEffectPixels } from './helpers.js';\nimport { EFFECT_KINDS, EFFECT_USES, type EffectDescription, type EffectPixels, type EffectProvider, type EffectSummary } from './types.js';\n\nexport interface EffectConformanceIssue {\n\teffectId?: string;\n\tmessage: string;\n}\n\nexport interface EffectConformanceOptions {\n\t/** Effects to check in depth (default: every listed effect). */\n\tids?: readonly string[];\n\t/** Also create renderers and render one small frame of each pixel effect (default true). */\n\trender?: boolean;\n\t/** Renderer size for the render check (default 8). */\n\tsize?: number;\n}\n\nconst codeOf = (e: unknown) => (isEffectError(e) ? e.code : e instanceof Error ? `untyped ${e.name}: ${e.message}` : String(e));\n\nasync function rejectsWith(code: string, run: () => unknown): Promise<string | null> {\n\ttry {\n\t\tawait run();\n\t\treturn `did not fail (expected ${code})`;\n\t} catch (e) {\n\t\tconst got = codeOf(e);\n\t\treturn got === code ? null : `failed with ${got} (expected ${code})`;\n\t}\n}\n\nfunction checkSummary(e: EffectSummary, issues: EffectConformanceIssue[]) {\n\tconst at = (message: string) => issues.push({ effectId: e.id, message });\n\tif (!e.id || typeof e.id !== 'string') at('summary has no id');\n\tif (!e.name) at('summary has no name');\n\tif (!EFFECT_KINDS.includes(e.kind)) at(`kind \"${e.kind}\" is not one of ${EFFECT_KINDS.join(', ')}`);\n\tif (!e.category) at('summary has no category');\n\tif (!Array.isArray(e.uses) || !e.uses.length) at('summary has no uses');\n\tfor (const u of e.uses ?? []) if (!EFFECT_USES.includes(u)) at(`use \"${u}\" is not one of ${EFFECT_USES.join(', ')}`);\n\tif (typeof e.transparent !== 'boolean') at('transparent is not a boolean');\n\tif (typeof e.loop !== 'boolean') at('loop is not a boolean');\n\tif (e.duration !== undefined && !(e.duration > 0)) at('duration must be a positive number of ms when present');\n}\n\nfunction checkDescription(id: string, d: EffectDescription, issues: EffectConformanceIssue[]) {\n\tconst at = (message: string) => issues.push({ effectId: id, message });\n\tif (d.id !== id) at(`describe(\"${id}\") returned id \"${d.id}\"`);\n\tconst c = d.controls;\n\tif (!c || c.type !== 'object') at('controls is not an object schema');\n\tif (c?.additionalProperties !== false) at('controls must set additionalProperties: false');\n\tfor (const [name, schema] of Object.entries(c?.properties ?? {})) {\n\t\tif (!schema.description || !String(schema.description).trim()) at(`control \"${name}\" has no description`);\n\t\tif (!(name in (d.defaults ?? {}))) at(`control \"${name}\" has no default`);\n\t}\n\tfor (const name of Object.keys(d.defaults ?? {})) if (!(name in (c?.properties ?? {}))) at(`default \"${name}\" is not a control`);\n\tfor (const e of effectValueErrors(d, d.defaults)) at(`default ${e.path}: ${e.message}`);\n\tfor (const p of d.presets ?? []) for (const e of effectValueErrors(d, p.values)) at(`preset \"${p.name}\" ${e.path}: ${e.message}`);\n\tfor (const input of d.inputs ?? []) {\n\t\tif (!input.name || !input.description) at('every input needs a name and a description');\n\t\tif (input.kind !== 'image' && input.kind !== 'audio') at(`input \"${input.name}\" has kind \"${input.kind}\"`);\n\t}\n\tif (d.uses.includes('filter') && !d.inputs.some((i) => i.name === 'source')) at('a filter must read an input named \"source\"');\n\tif (d.uses.includes('transition') && !(d.inputs.some((i) => i.name === 'from') && d.inputs.some((i) => i.name === 'to'))) {\n\t\tat('a transition must read inputs named \"from\" and \"to\"');\n\t}\n}\n\nfunction grey(size: number): EffectPixels {\n\tconst p = createEffectPixels(size, size);\n\tp.data.fill(128);\n\treturn p;\n}\n\nasync function checkRender(provider: EffectProvider, d: EffectDescription, size: number, issues: EffectConformanceIssue[]) {\n\tconst at = (message: string) => issues.push({ effectId: d.id, message });\n\tconst inputs = Object.fromEntries(d.inputs.filter((i) => i.kind === 'image').map((i) => [i.name, grey(size)]));\n\tlet renderer;\n\ttry {\n\t\trenderer = await provider.createRenderer(d.id, { width: size, height: size });\n\t} catch (e) {\n\t\t// A vector effect may need the host's help to become pixels (a Worker has no DOM to lay out SVG).\n\t\tif (!(d.kind === 'vector' && codeOf(e) === 'unsupported')) at(`createRenderer failed: ${codeOf(e)}`);\n\t\treturn;\n\t}\n\ttry {\n\t\tconst out = await renderer.render({ time: 0, inputs });\n\t\tif (!isEffectPixels(out)) at('render did not return EffectPixels');\n\t\telse if (out.width !== size || out.height !== size || out.data.length !== size * size * 4) at(`render returned ${out.width}×${out.height}, not ${size}×${size}`);\n\t} catch (e) {\n\t\tat(`render failed: ${codeOf(e)}`);\n\t}\n\tconst bad = await rejectsWith('invalid_values', () => renderer.render({ time: 0, inputs, values: { __not_a_control__: 1 } }));\n\tif (bad) at(`render with an unknown control ${bad}`);\n\trenderer.dispose();\n\tconst after = await rejectsWith('disposed', () => renderer.render({ time: 0, inputs }));\n\tif (after) at(`render after dispose ${after}`);\n}\n\n/** Runs the contract checks against `provider` and returns every issue found (empty when it conforms). */\nexport async function checkEffectProvider(provider: EffectProvider, options: EffectConformanceOptions = {}): Promise<EffectConformanceIssue[]> {\n\tconst issues: EffectConformanceIssue[] = [];\n\tconst top = (message: string) => issues.push({ message });\n\tif (!provider.id) top('provider has no id');\n\tconst caps = provider.capabilities;\n\tfor (const k of ['supportsWorker', 'supportsFloat', 'supportsMask', 'supportsHostImages', 'supportsVector'] as const) {\n\t\tif (typeof caps?.[k] !== 'boolean') top(`capabilities.${k} is not a boolean`);\n\t}\n\tif (caps?.supportsVector && typeof provider.applyVectorEffect !== 'function') top('supportsVector is set but applyVectorEffect is missing');\n\n\tconst list = await provider.list();\n\tconst ids = new Set<string>();\n\tfor (const e of list) {\n\t\tif (ids.has(e.id)) top(`duplicate id \"${e.id}\"`);\n\t\tids.add(e.id);\n\t\tcheckSummary(e, issues);\n\t}\n\tconst all = await provider.search('');\n\tif (all.length !== list.length) top(`search(\"\") returned ${all.length} effects, list() ${list.length}`);\n\tconst firstUse = list[0]?.uses[0];\n\tif (firstUse) {\n\t\tconst filtered = await provider.search('', { use: firstUse });\n\t\tif (filtered.some((e) => !e.uses.includes(firstUse))) top(`search(\"\", { use: \"${firstUse}\" }) returned effects without that use`);\n\t}\n\tconst unknown = await rejectsWith('unknown_effect', () => provider.describe('__no_such_effect__'));\n\tif (unknown) top(`describe of an unknown id ${unknown}`);\n\tconst unknownRenderer = await rejectsWith('unknown_effect', () => provider.createRenderer('__no_such_effect__', { width: 4, height: 4 }));\n\tif (unknownRenderer) top(`createRenderer of an unknown id ${unknownRenderer}`);\n\n\tconst size = options.size ?? 8;\n\tfor (const id of options.ids ?? [...ids]) {\n\t\tlet d: EffectDescription;\n\t\ttry {\n\t\t\td = await provider.describe(id);\n\t\t} catch (e) {\n\t\t\tissues.push({ effectId: id, message: `describe failed: ${codeOf(e)}` });\n\t\t\tcontinue;\n\t\t}\n\t\tcheckDescription(id, d, issues);\n\t\tif (options.render !== false && d.kind !== 'motion') await checkRender(provider, d, size, issues);\n\t\tif ((d.kind === 'vector' || d.kind === 'motion') && caps.supportsVector && provider.applyVectorEffect) {\n\t\t\ttry {\n\t\t\t\tconst m = await provider.applyVectorEffect(id, '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 10 10\"><rect id=\"r\" width=\"10\" height=\"10\"/></svg>');\n\t\t\t\tif (typeof m.svg !== 'string' || !m.svg.includes('<svg')) issues.push({ effectId: id, message: 'applyVectorEffect returned no SVG' });\n\t\t\t\tif (!(m.duration >= 0)) issues.push({ effectId: id, message: 'applyVectorEffect returned no duration' });\n\t\t\t} catch (e) {\n\t\t\t\t// The probe target is a bare <rect>; an effect that needs more (a path to follow, a fill colour) may refuse it.\n\t\t\t\tif (codeOf(e) !== 'unsupported') issues.push({ effectId: id, message: `applyVectorEffect failed: ${codeOf(e)}` });\n\t\t\t}\n\t\t\tconst bad = await rejectsWith('invalid_values', () => provider.applyVectorEffect!(id, '<svg xmlns=\"http://www.w3.org/2000/svg\"/>', { __not_a_control__: 1 }));\n\t\t\tif (bad) issues.push({ effectId: id, message: `applyVectorEffect with an unknown control ${bad}` });\n\t\t}\n\t}\n\treturn issues;\n}\n","/**\n * `createFakeEffectProvider`: a small, deterministic, CPU-only provider implementing the whole\n * contract. Tests and the demo use it; it is also a reference for real providers.\n *\n * Effects (ids prefixed `fake.`):\n * - `invert` (filter), `tint` (filter)\n * - `gradient` (generator, loops)\n * - `bar` (title / overlay: a lower-third bar that slides in, transparent)\n * - `crossfade` (transition)\n * - `fade-in` (motion, vector only)\n * - `badge` (a vector effect with its own picture: a disc that fades in; vector only)\n */\n\nimport { EffectDisposedError, EffectUnsupportedError, UnknownEffectError } from './errors.js';\nimport { createEffectPixels, encodeEffectFloat, isEffectPixels, resolveEffectValues, searchEffectSummaries, srgbToLinear } from './helpers.js';\nimport type {\n\tEffectDescription,\n\tEffectImageSource,\n\tEffectPixels,\n\tEffectProvider,\n\tEffectProviderCapabilities,\n\tEffectRenderer,\n\tEffectRendererOptions,\n\tEffectRenderRequest,\n\tEffectSummary,\n\tEffectValues,\n\tEffectVectorMotion,\n\tEffectVectorTarget\n} from './types.js';\n\nconst HEX = '^#[0-9a-fA-F]{6}$';\nconst colour = (description: string) => ({ type: 'string' as const, pattern: HEX, description });\nconst amount = (description: string) => ({ type: 'number' as const, minimum: 0, maximum: 1, description });\n\nconst DESCRIPTIONS: readonly EffectDescription[] = [\n\t{\n\t\tid: 'fake.invert',\n\t\tname: 'Invert',\n\t\tkind: 'shader',\n\t\tcategory: 'image',\n\t\tuses: ['filter'],\n\t\tdescription: 'Inverts the colours of the source.',\n\t\ttags: ['negative', 'colour'],\n\t\ttransparent: false,\n\t\tloop: false,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: { amount: amount('How far to invert, 0 (unchanged) to 1 (fully inverted). Default 1.') }\n\t\t},\n\t\tdefaults: { amount: 1 },\n\t\tpresets: [{ name: 'Half', values: { amount: 0.5 } }],\n\t\tinputs: [{ name: 'source', kind: 'image', description: 'The picture to invert.', required: true }]\n\t},\n\t{\n\t\tid: 'fake.tint',\n\t\tname: 'Tint',\n\t\tkind: 'shader',\n\t\tcategory: 'image',\n\t\tuses: ['filter'],\n\t\tdescription: 'Mixes the source towards a colour.',\n\t\ttags: ['colour', 'wash'],\n\t\ttransparent: false,\n\t\tloop: false,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tcolor: colour('Tint colour as #rrggbb. Default #ff8800.'),\n\t\t\t\tamount: amount('How far to mix towards the colour, 0–1. Default 0.5.')\n\t\t\t}\n\t\t},\n\t\tdefaults: { color: '#ff8800', amount: 0.5 },\n\t\tpresets: [\n\t\t\t{ name: 'Sepia', values: { color: '#704214', amount: 0.4 } },\n\t\t\t{ name: 'Cool', values: { color: '#2060ff', amount: 0.25 } }\n\t\t],\n\t\tinputs: [{ name: 'source', kind: 'image', description: 'The picture to tint.', required: true }]\n\t},\n\t{\n\t\tid: 'fake.gradient',\n\t\tname: 'Gradient',\n\t\tkind: 'shader',\n\t\tcategory: 'gradient',\n\t\tuses: ['generator'],\n\t\tdescription: 'A linear gradient between two colours that can turn over time.',\n\t\ttags: ['background'],\n\t\ttransparent: false,\n\t\tloop: true,\n\t\tduration: 4000,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tfrom: colour('Start colour as #rrggbb. Default #1e3a8a.'),\n\t\t\t\tto: colour('End colour as #rrggbb. Default #f472b6.'),\n\t\t\t\tangle: { type: 'number', minimum: 0, maximum: 360, description: 'Direction in degrees, 0 = left to right, 90 = top to bottom. Default 90.' },\n\t\t\t\tspin: { type: 'number', minimum: -360, maximum: 360, description: 'Turn per loop (4 s) in degrees. Default 0.' }\n\t\t\t}\n\t\t},\n\t\tdefaults: { from: '#1e3a8a', to: '#f472b6', angle: 90, spin: 0 },\n\t\tpresets: [{ name: 'Sunset', values: { from: '#f97316', to: '#7c3aed' } }],\n\t\tinputs: []\n\t},\n\t{\n\t\tid: 'fake.bar',\n\t\tname: 'Lower-third bar',\n\t\tkind: 'shader',\n\t\tcategory: 'broadcast',\n\t\tuses: ['title', 'overlay'],\n\t\tdescription: 'A coloured bar that slides in from the left in the lower third. Transparent elsewhere.',\n\t\ttags: ['lower third', 'title'],\n\t\ttransparent: true,\n\t\tloop: false,\n\t\tduration: 2000,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tcolor: colour('Bar colour as #rrggbb. Default #0ea5e9.'),\n\t\t\t\theight: { type: 'number', minimum: 0.02, maximum: 0.5, description: 'Bar height as a fraction of the picture height. Default 0.12.' },\n\t\t\t\tslide: { type: 'number', minimum: 0, maximum: 5000, description: 'Slide-in time (ms). Default 500.' }\n\t\t\t}\n\t\t},\n\t\tdefaults: { color: '#0ea5e9', height: 0.12, slide: 500 },\n\t\tpresets: [],\n\t\tinputs: []\n\t},\n\t{\n\t\tid: 'fake.crossfade',\n\t\tname: 'Crossfade',\n\t\tkind: 'shader',\n\t\tcategory: 'transition',\n\t\tuses: ['transition'],\n\t\tdescription: 'Dissolves from one picture to the next.',\n\t\ttags: ['dissolve', 'mix'],\n\t\ttransparent: false,\n\t\tloop: false,\n\t\tduration: 1000,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: { curve: { type: 'string', enum: ['linear', 'smooth'], description: 'Mix curve: linear, or smooth (ease in and out). Default smooth.' } }\n\t\t},\n\t\tdefaults: { curve: 'smooth' },\n\t\tpresets: [],\n\t\tinputs: [\n\t\t\t{ name: 'from', kind: 'image', description: 'The outgoing picture.', required: true },\n\t\t\t{ name: 'to', kind: 'image', description: 'The incoming picture.', required: true }\n\t\t]\n\t},\n\t{\n\t\tid: 'fake.fade-in',\n\t\tname: 'Fade in',\n\t\tkind: 'motion',\n\t\tcategory: 'morph',\n\t\tuses: ['motion'],\n\t\tdescription: 'Fades vector elements in from transparent, one after another.',\n\t\ttags: ['appear', 'entrance'],\n\t\ttransparent: true,\n\t\tloop: false,\n\t\tduration: 600,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tms: { type: 'number', minimum: 0, maximum: 10000, description: 'Fade time per element (ms). Default 600.' },\n\t\t\t\tstagger: { type: 'number', minimum: 0, maximum: 5000, description: 'Delay between elements (ms). Default 0.' }\n\t\t\t}\n\t\t},\n\t\tdefaults: { ms: 600, stagger: 0 },\n\t\tpresets: [{ name: 'Cascade', values: { ms: 400, stagger: 120 } }],\n\t\tinputs: []\n\t},\n\t{\n\t\tid: 'fake.badge',\n\t\tname: 'Badge',\n\t\tkind: 'vector',\n\t\tcategory: 'sticker',\n\t\tuses: ['title'],\n\t\tdescription: 'A coloured disc that fades in: a vector effect that brings its own picture.',\n\t\ttags: ['sticker', 'disc'],\n\t\ttransparent: true,\n\t\tloop: false,\n\t\tduration: 500,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tcolor: colour('Disc colour as #rrggbb. Default #f43f5e.'),\n\t\t\t\tms: { type: 'number', minimum: 0, maximum: 10000, description: 'Fade-in time (ms). Default 500.' }\n\t\t\t}\n\t\t},\n\t\tdefaults: { color: '#f43f5e', ms: 500 },\n\t\tpresets: [],\n\t\tinputs: []\n\t}\n];\n\nconst summaryOf = ({ controls: _c, defaults: _d, presets: _p, inputs: _i, ...summary }: EffectDescription): EffectSummary => summary;\n\nconst hexToRgb = (hex: string): [number, number, number] => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16)) as [number, number, number];\nconst smooth = (t: number) => t * t * (3 - 2 * t);\nconst clamp01 = (v: number) => (v < 0 ? 0 : v > 1 ? 1 : v);\n\nfunction input(request: EffectRenderRequest, name: string, id: string, width: number, height: number): EffectPixels {\n\tconst src: EffectImageSource | undefined = request.inputs?.[name];\n\tif (!src) throw new EffectUnsupportedError(`Effect \"${id}\" needs an input named \"${name}\".`, id);\n\tif (!isEffectPixels(src)) throw new EffectUnsupportedError(`The fake provider only takes EffectPixels inputs (\"${name}\").`, id);\n\tif (src.width !== width || src.height !== height) {\n\t\tthrow new EffectUnsupportedError(`Input \"${name}\" is ${src.width}×${src.height}; the renderer is ${width}×${height}.`, id);\n\t}\n\treturn src;\n}\n\n/** Per-pixel colour work in 8-bit sRGB; float output (when asked) is derived from it. */\nfunction renderPixels(d: EffectDescription, v: Record<string, EffectValues[string]>, request: EffectRenderRequest, width: number, height: number): EffectPixels {\n\tconst out = createEffectPixels(width, height);\n\tconst o = out.data;\n\tswitch (d.id) {\n\t\tcase 'fake.invert': {\n\t\t\tconst s = input(request, 'source', d.id, width, height).data;\n\t\t\tconst k = v.amount as number;\n\t\t\tfor (let i = 0; i < o.length; i += 4) {\n\t\t\t\tfor (let c = 0; c < 3; c++) o[i + c] = s[i + c] + (255 - 2 * s[i + c]) * k;\n\t\t\t\to[i + 3] = s[i + 3];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 'fake.tint': {\n\t\t\tconst s = input(request, 'source', d.id, width, height).data;\n\t\t\tconst rgb = hexToRgb(v.color as string);\n\t\t\tconst k = v.amount as number;\n\t\t\tfor (let i = 0; i < o.length; i += 4) {\n\t\t\t\tfor (let c = 0; c < 3; c++) o[i + c] = s[i + c] + (rgb[c] - s[i + c]) * k;\n\t\t\t\to[i + 3] = s[i + 3];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 'fake.gradient': {\n\t\t\tconst a = hexToRgb(v.from as string);\n\t\t\tconst b = hexToRgb(v.to as string);\n\t\t\tconst turn = ((request.time % (d.duration ?? 4000)) / (d.duration ?? 4000)) * (v.spin as number);\n\t\t\tconst rad = (((v.angle as number) + turn) * Math.PI) / 180;\n\t\t\tconst dx = Math.cos(rad);\n\t\t\tconst dy = Math.sin(rad);\n\t\t\tconst half = (Math.abs(dx) * width + Math.abs(dy) * height) / 2 || 1;\n\t\t\tfor (let y = 0, i = 0; y < height; y++) {\n\t\t\t\tfor (let x = 0; x < width; x++, i += 4) {\n\t\t\t\t\tconst t = clamp01(((x + 0.5 - width / 2) * dx + (y + 0.5 - height / 2) * dy) / (2 * half) + 0.5);\n\t\t\t\t\tfor (let c = 0; c < 3; c++) o[i + c] = a[c] + (b[c] - a[c]) * t;\n\t\t\t\t\to[i + 3] = 255;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 'fake.bar': {\n\t\t\tconst rgb = hexToRgb(v.color as string);\n\t\t\tconst slide = v.slide as number;\n\t\t\tconst shown = slide > 0 ? smooth(clamp01(request.time / slide)) : 1;\n\t\t\tconst top = Math.round(height * (0.75 - (v.height as number) / 2));\n\t\t\tconst bottom = Math.round(height * (0.75 + (v.height as number) / 2));\n\t\t\tconst right = Math.round(width * 0.7 * shown);\n\t\t\tfor (let y = Math.max(0, top); y < Math.min(height, bottom); y++) {\n\t\t\t\tfor (let x = 0; x < right; x++) {\n\t\t\t\t\tconst i = (y * width + x) * 4;\n\t\t\t\t\to[i] = rgb[0];\n\t\t\t\t\to[i + 1] = rgb[1];\n\t\t\t\t\to[i + 2] = rgb[2];\n\t\t\t\t\to[i + 3] = 255;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 'fake.crossfade': {\n\t\t\tconst from = input(request, 'from', d.id, width, height).data;\n\t\t\tconst to = input(request, 'to', d.id, width, height).data;\n\t\t\tconst p = clamp01(request.progress ?? request.time / (d.duration ?? 1000));\n\t\t\tconst k = v.curve === 'smooth' ? smooth(p) : p;\n\t\t\tfor (let i = 0; i < o.length; i++) o[i] = from[i] + (to[i] - from[i]) * k;\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tthrow new EffectUnsupportedError(`\"${d.id}\" is a ${d.kind} effect; use applyVectorEffect.`, d.id);\n\t}\n\treturn out;\n}\n\nfunction toFloat(p: EffectPixels): EffectPixels {\n\tconst f = new Float32Array(p.data.length);\n\tfor (let i = 0; i < f.length; i += 4) {\n\t\tf[i] = srgbToLinear(p.data[i] / 255);\n\t\tf[i + 1] = srgbToLinear(p.data[i + 1] / 255);\n\t\tf[i + 2] = srgbToLinear(p.data[i + 2] / 255);\n\t\tf[i + 3] = p.data[i + 3] / 255;\n\t}\n\treturn encodeEffectFloat({ ...p, float: f });\n}\n\nfunction maskResult(out: EffectPixels, mask: EffectImageSource, source: EffectPixels | undefined, id: string): void {\n\tif (!isEffectPixels(mask) || mask.width !== out.width || mask.height !== out.height) {\n\t\tthrow new EffectUnsupportedError('The mask must be EffectPixels the size of the renderer.', id);\n\t}\n\tconst o = out.data;\n\tfor (let i = 0; i < o.length; i += 4) {\n\t\tconst k = mask.data[i + 3] / 255;\n\t\tif (source) for (let c = 0; c < 4; c++) o[i + c] = source.data[i + c] + (o[i + c] - source.data[i + c]) * k;\n\t\telse o[i + 3] *= k;\n\t}\n}\n\nexport interface FakeEffectProviderOptions {\n\t/** Overrides of the capability flags, to test how editors degrade. */\n\tcapabilities?: Partial<EffectProviderCapabilities>;\n\t/** Called on every render (tests count frames with it). */\n\tonRender?: (effectId: string, request: EffectRenderRequest) => void;\n}\n\n/** A deterministic CPU effects provider with six effects (see the module comment). */\nexport function createFakeEffectProvider(options: FakeEffectProviderOptions = {}): EffectProvider {\n\tconst capabilities: EffectProviderCapabilities = {\n\t\tsupportsWorker: false,\n\t\tsupportsFloat: true,\n\t\tsupportsMask: true,\n\t\tsupportsHostImages: false,\n\t\tsupportsVector: true,\n\t\tmaxSize: 8192,\n\t\t...options.capabilities\n\t};\n\tconst byId = new Map(DESCRIPTIONS.map((d) => [d.id, d]));\n\tconst get = (id: string) => {\n\t\tconst d = byId.get(id);\n\t\tif (!d) throw new UnknownEffectError(id, 'the fake provider');\n\t\treturn d;\n\t};\n\tconst summaries = DESCRIPTIONS.map(summaryOf);\n\n\tconst provider: EffectProvider = {\n\t\tid: 'fake',\n\t\tname: 'Fake effects',\n\t\tversion: '1',\n\t\tcapabilities,\n\t\tlist: (o) => searchEffectSummaries(summaries, '', o),\n\t\tsearch: (q, o) => searchEffectSummaries(summaries, q, o),\n\t\tdescribe: (id) => structuredClone(get(id)),\n\t\tcreateRenderer(id: string, ro: EffectRendererOptions): EffectRenderer {\n\t\t\tconst d = get(id);\n\t\t\tif (d.kind !== 'shader') throw new EffectUnsupportedError(`\"${id}\" is a ${d.kind} effect; use applyVectorEffect.`, id);\n\t\t\tconst { width, height } = ro;\n\t\t\tconst depth = ro.depth ?? 8;\n\t\t\tif (!(width > 0 && height > 0) || width > capabilities.maxSize! || height > capabilities.maxSize!) {\n\t\t\t\tthrow new EffectUnsupportedError(`Renderer size ${width}×${height} is outside 1–${capabilities.maxSize}.`, id);\n\t\t\t}\n\t\t\tlet disposed = false;\n\t\t\treturn {\n\t\t\t\teffectId: id,\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tdepth,\n\t\t\t\tasync render(request) {\n\t\t\t\t\tif (disposed) throw new EffectDisposedError(id);\n\t\t\t\t\tif (!Number.isFinite(request.time) || request.time < 0) {\n\t\t\t\t\t\tthrow new EffectUnsupportedError(`time must be a finite number of ms ≥ 0, got ${request.time}.`, id);\n\t\t\t\t\t}\n\t\t\t\t\tconst values = resolveEffectValues(d, request.values);\n\t\t\t\t\toptions.onRender?.(id, request);\n\t\t\t\t\tconst out = renderPixels(d, values, request, width, height);\n\t\t\t\t\tif (request.mask) {\n\t\t\t\t\t\tif (!capabilities.supportsMask) throw new EffectUnsupportedError('This provider does not take masks.', id);\n\t\t\t\t\t\tconst source = d.uses.includes('filter') ? (request.inputs?.source as EffectPixels) : undefined;\n\t\t\t\t\t\tmaskResult(out, request.mask, source, id);\n\t\t\t\t\t}\n\t\t\t\t\treturn depth > 8 && capabilities.supportsFloat ? toFloat(out) : out;\n\t\t\t\t},\n\t\t\t\tdispose() {\n\t\t\t\t\tdisposed = true;\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tapplyVectorEffect(id: string, target: EffectVectorTarget, values?: EffectValues): EffectVectorMotion {\n\t\t\tconst d = get(id);\n\t\t\tif (d.kind !== 'motion' && d.kind !== 'vector') throw new EffectUnsupportedError(`\"${id}\" is a ${d.kind} effect, not a vector one.`, id);\n\t\t\tconst v = resolveEffectValues(d, values);\n\t\t\tif (d.kind === 'vector') {\n\t\t\t\t// Its own picture: the target is not used.\n\t\t\t\treturn { svg: `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\" width=\"100\" height=\"100\"><circle id=\"badge\" cx=\"50\" cy=\"50\" r=\"40\" fill=\"${v.color}\"/></svg>`, animate: [{ id: 'badge', ms: v.ms as number, attrs: { opacity: [0, 1] as const } }], duration: v.ms as number, loop: false };\n\t\t\t}\n\t\t\tconst svg = typeof target === 'string' ? target : target.svg;\n\t\t\tconst ids = typeof target === 'string' || !target.nodeIds ? [...svg.matchAll(/\\sid=\"([^\"]+)\"/g)].map((m) => m[1]) : [...target.nodeIds];\n\t\t\tconst ms = v.ms as number;\n\t\t\tconst stagger = v.stagger as number;\n\t\t\treturn {\n\t\t\t\tsvg,\n\t\t\t\tanimate: ids.map((elementId, i) => ({ id: elementId, delay: i * stagger, ms, attrs: { opacity: [0, 1] as const } })),\n\t\t\t\tduration: ms + Math.max(0, ids.length - 1) * stagger,\n\t\t\t\tloop: false\n\t\t\t};\n\t\t}\n\t};\n\treturn provider;\n}\n","/**\n * Framework-free helpers for effects UIs (the React and Svelte effects browser and parameter\n * panel): control schemas as parameter fields, preview thumbnails from a provider's renderer,\n * and labels.\n */\n\nimport type { JsonSchema } from '../tools/schema.js';\nimport type { ParameterField, ParameterValue } from '../parameters/types.js';\nimport { createEffectPixels } from './helpers.js';\nimport type { EffectDescription, EffectPixels, EffectProvider, EffectSummary, EffectUse, EffectValue } from './types.js';\n\n/** Names for the uses, for filters and badges. */\nexport const EFFECT_USE_LABELS: Readonly<Record<EffectUse, string>> = {\n\tfilter: 'Filter',\n\ttransition: 'Transition',\n\tgenerator: 'Generator',\n\toverlay: 'Overlay',\n\ttitle: 'Title',\n\tmotion: 'Motion',\n\tinteractive: 'Interactive'\n};\n\nconst HEX = /^#[0-9a-f]{6}([0-9a-f]{2})?$/i;\nconst typeOf = (s: JsonSchema) => (Array.isArray(s.type) ? s.type.find((t) => t !== 'null') : s.type);\n\n/**\n * One control as a parameter field: numbers and integers (sliders when bounded), switches,\n * choices (`enum`), colours (strings whose default is `#rrggbb`), vectors (2–4 numbers) and text.\n * `null` for a control no field can edit (objects, long lists).\n */\nexport function effectControlField(name: string, schema: JsonSchema, fallback: EffectValue | undefined): ParameterField | null {\n\tconst base = { id: name, ...(schema.title ? { label: schema.title } : {}), ...(schema.description ? { description: schema.description } : {}) };\n\tconst def = (schema.default ?? fallback) as EffectValue | undefined;\n\tconst type = typeOf(schema);\n\tif (Array.isArray(schema.enum) && schema.enum.length) {\n\t\tconst options = schema.enum.filter((v): v is string | number => typeof v === 'string' || typeof v === 'number');\n\t\treturn { ...base, type: 'choice', options, default: (typeof def === 'string' || typeof def === 'number' ? def : options[0]) as string | number, control: options.length <= 4 ? 'segmented' : 'select' };\n\t}\n\tif (type === 'number' || type === 'integer') {\n\t\tconst min = schema.minimum ?? schema.exclusiveMinimum;\n\t\tconst max = schema.maximum ?? schema.exclusiveMaximum;\n\t\treturn { ...base, type: type === 'integer' ? 'int' : 'number', default: typeof def === 'number' ? def : (min ?? 0), ...(min !== undefined ? { min } : {}), ...(max !== undefined ? { max } : {}), ...(schema.multipleOf ? { step: schema.multipleOf } : {}) };\n\t}\n\tif (type === 'boolean') return { ...base, type: 'boolean', default: def === true };\n\tif (type === 'string') {\n\t\tif (typeof def === 'string' && HEX.test(def)) return { ...base, type: 'color', alpha: def.length === 9, default: def };\n\t\treturn { ...base, type: 'text', default: typeof def === 'string' ? def : '', ...(schema.maxLength ? { maxLength: schema.maxLength } : {}) };\n\t}\n\tif (type === 'array' && Array.isArray(def) && def.length >= 2 && def.length <= 4 && def.every((n) => typeof n === 'number')) {\n\t\tconst items = schema.items ?? {};\n\t\treturn { ...base, type: 'vector', size: def.length as 2 | 3 | 4, default: [...def], ...(items.minimum !== undefined ? { min: items.minimum } : {}), ...(items.maximum !== undefined ? { max: items.maximum } : {}) };\n\t}\n\treturn null;\n}\n\n/** An effect's controls as parameter fields, in schema order (controls no field can edit are left out). */\nexport function effectParameterFields(description: Pick<EffectDescription, 'controls' | 'defaults'>): ParameterField[] {\n\treturn Object.entries(description.controls.properties)\n\t\t.map(([name, schema]) => effectControlField(name, schema, description.defaults[name]))\n\t\t.filter((f): f is ParameterField => !!f);\n}\n\n/** A saved value as a field shows it (`ParameterValue`), or the field's default. */\nexport const effectFieldValue = (field: ParameterField, value: unknown): ParameterValue =>\n\tvalue === undefined || value === null || (typeof value === 'object' && !Array.isArray(value)) ? field.default : (value as ParameterValue);\n\n/**\n * A colourful, deterministic picture for previews of filters and transitions (`variant` 0 and 1\n * differ, for a transition's two sides).\n */\nexport function effectSamplePicture(width: number, height: number, variant = 0): EffectPixels {\n\tconst p = createEffectPixels(width, height);\n\tfor (let y = 0, i = 0; y < height; y++) {\n\t\tfor (let x = 0; x < width; x++, i += 4) {\n\t\t\tconst u = x / Math.max(1, width - 1);\n\t\t\tconst v = y / Math.max(1, height - 1);\n\t\t\tconst check = (Math.floor(u * 4) + Math.floor(v * 4)) % 2;\n\t\t\tif (variant === 0) p.data.set([Math.round(40 + 200 * u), Math.round(80 + 120 * v), Math.round(200 - 120 * u) + check * 30, 255], i);\n\t\t\telse p.data.set([Math.round(230 - 60 * v), Math.round(190 - 100 * u), 60 + check * 40, 255], i);\n\t\t}\n\t}\n\treturn p;\n}\n\n/**\n * A small preview of an effect from the provider's own renderer: filters run on a sample picture,\n * transitions go half way between two, generators and overlays draw at `time` (default half\n * their length, or 1 s). Thumbnails render one at a time (each renderer is disposed before the\n * next is made) and are kept per provider. Rejects like the provider does (motion effects have\n * no pixels).\n */\nexport function renderEffectThumbnail(provider: EffectProvider, effect: EffectSummary | EffectDescription, size: { width: number; height: number } = { width: 96, height: 54 }): Promise<EffectPixels> {\n\tlet cache = thumbnails.get(provider);\n\tif (!cache) thumbnails.set(provider, (cache = new Map()));\n\tconst key = `${effect.id}@${size.width}x${size.height}`;\n\tlet out = cache.get(key);\n\tif (!out) {\n\t\t// One at a time: a browser full of previews would otherwise open a graphics context each.\n\t\tout = thumbnailQueue.then(() => renderThumbnail(provider, effect, size));\n\t\tthumbnailQueue = out.catch(() => undefined);\n\t\tout.catch(() => cache!.delete(key));\n\t\tcache.set(key, out);\n\t}\n\treturn out;\n}\n\nconst thumbnails = new WeakMap<EffectProvider, Map<string, Promise<EffectPixels>>>();\nlet thumbnailQueue: Promise<unknown> = Promise.resolve();\n\nasync function renderThumbnail(provider: EffectProvider, effect: EffectSummary | EffectDescription, size: { width: number; height: number }): Promise<EffectPixels> {\n\tconst d = 'inputs' in effect ? effect : await provider.describe(effect.id);\n\tconst renderer = await provider.createRenderer(d.id, size);\n\ttry {\n\t\tconst time = d.duration ? d.duration / 2 : 1000;\n\t\tconst inputs: Record<string, EffectPixels> = {};\n\t\tfor (const input of d.inputs) if (input.kind === 'image') inputs[input.name] = effectSamplePicture(size.width, size.height, input.name === 'to' ? 1 : 0);\n\t\treturn await renderer.render({ time, inputs, ...(d.uses.includes('transition') ? { progress: 0.5 } : {}) });\n\t} finally {\n\t\trenderer.dispose();\n\t}\n}\n\n/** Effects grouped by category, categories in first-seen order. */\nexport function groupEffectsByCategory<T extends EffectSummary>(effects: readonly T[]): { category: string; effects: T[] }[] {\n\tconst groups = new Map<string, T[]>();\n\tfor (const e of effects) {\n\t\tconst g = groups.get(e.category);\n\t\tif (g) g.push(e);\n\t\telse groups.set(e.category, [e]);\n\t}\n\treturn [...groups].map(([category, list]) => ({ category, effects: list }));\n}\n"],"mappings":"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","names":["input","HEX","input"]}
|
|
1
|
+
{"version":3,"sources":["../../src/effects/conformance.ts","../../src/effects/fake.ts","../../src/effects/ui.ts"],"sourcesContent":["/**\n * `checkEffectProvider`: a conformance check any provider can run in its own tests, so editors\n * can rely on the contract (strict control schemas, valid defaults, typed errors, renderers that\n * return the size they were asked for).\n */\n\nimport { isEffectError } from './errors.js';\nimport { createEffectPixels, effectValueErrors, isEffectPixels } from './helpers.js';\nimport { EFFECT_KINDS, EFFECT_USES, type EffectDescription, type EffectPixels, type EffectProvider, type EffectSummary } from './types.js';\n\nexport interface EffectConformanceIssue {\n\teffectId?: string;\n\tmessage: string;\n}\n\nexport interface EffectConformanceOptions {\n\t/** Effects to check in depth (default: every listed effect). */\n\tids?: readonly string[];\n\t/** Also create renderers and render one small frame of each pixel effect (default true). */\n\trender?: boolean;\n\t/** Renderer size for the render check (default 8). */\n\tsize?: number;\n}\n\nconst codeOf = (e: unknown) => (isEffectError(e) ? e.code : e instanceof Error ? `untyped ${e.name}: ${e.message}` : String(e));\n\nasync function rejectsWith(code: string, run: () => unknown): Promise<string | null> {\n\ttry {\n\t\tawait run();\n\t\treturn `did not fail (expected ${code})`;\n\t} catch (e) {\n\t\tconst got = codeOf(e);\n\t\treturn got === code ? null : `failed with ${got} (expected ${code})`;\n\t}\n}\n\nfunction checkSummary(e: EffectSummary, issues: EffectConformanceIssue[]) {\n\tconst at = (message: string) => issues.push({ effectId: e.id, message });\n\tif (!e.id || typeof e.id !== 'string') at('summary has no id');\n\tif (!e.name) at('summary has no name');\n\tif (!EFFECT_KINDS.includes(e.kind)) at(`kind \"${e.kind}\" is not one of ${EFFECT_KINDS.join(', ')}`);\n\tif (!e.category) at('summary has no category');\n\tif (!Array.isArray(e.uses) || !e.uses.length) at('summary has no uses');\n\tfor (const u of e.uses ?? []) if (!EFFECT_USES.includes(u)) at(`use \"${u}\" is not one of ${EFFECT_USES.join(', ')}`);\n\tif (typeof e.transparent !== 'boolean') at('transparent is not a boolean');\n\tif (typeof e.loop !== 'boolean') at('loop is not a boolean');\n\tif (e.duration !== undefined && !(e.duration > 0)) at('duration must be a positive number of ms when present');\n}\n\nfunction checkDescription(id: string, d: EffectDescription, issues: EffectConformanceIssue[]) {\n\tconst at = (message: string) => issues.push({ effectId: id, message });\n\tif (d.id !== id) at(`describe(\"${id}\") returned id \"${d.id}\"`);\n\tconst c = d.controls;\n\tif (!c || c.type !== 'object') at('controls is not an object schema');\n\tif (c?.additionalProperties !== false) at('controls must set additionalProperties: false');\n\tfor (const [name, schema] of Object.entries(c?.properties ?? {})) {\n\t\tif (!schema.description || !String(schema.description).trim()) at(`control \"${name}\" has no description`);\n\t\tif (!(name in (d.defaults ?? {}))) at(`control \"${name}\" has no default`);\n\t}\n\tfor (const name of Object.keys(d.defaults ?? {})) if (!(name in (c?.properties ?? {}))) at(`default \"${name}\" is not a control`);\n\tfor (const e of effectValueErrors(d, d.defaults)) at(`default ${e.path}: ${e.message}`);\n\tfor (const p of d.presets ?? []) for (const e of effectValueErrors(d, p.values)) at(`preset \"${p.name}\" ${e.path}: ${e.message}`);\n\tfor (const input of d.inputs ?? []) {\n\t\tif (!input.name || !input.description) at('every input needs a name and a description');\n\t\tif (input.kind !== 'image' && input.kind !== 'audio') at(`input \"${input.name}\" has kind \"${input.kind}\"`);\n\t}\n\tif (d.uses.includes('filter') && !d.inputs.some((i) => i.name === 'source')) at('a filter must read an input named \"source\"');\n\tif (d.uses.includes('transition') && !(d.inputs.some((i) => i.name === 'from') && d.inputs.some((i) => i.name === 'to'))) {\n\t\tat('a transition must read inputs named \"from\" and \"to\"');\n\t}\n}\n\nfunction grey(size: number): EffectPixels {\n\tconst p = createEffectPixels(size, size);\n\tp.data.fill(128);\n\treturn p;\n}\n\nasync function checkRender(provider: EffectProvider, d: EffectDescription, size: number, issues: EffectConformanceIssue[]) {\n\tconst at = (message: string) => issues.push({ effectId: d.id, message });\n\tconst inputs = Object.fromEntries(d.inputs.filter((i) => i.kind === 'image').map((i) => [i.name, grey(size)]));\n\tlet renderer;\n\ttry {\n\t\trenderer = await provider.createRenderer(d.id, { width: size, height: size });\n\t} catch (e) {\n\t\t// A vector effect may need the host's help to become pixels (a Worker has no DOM to lay out SVG).\n\t\tif (!(d.kind === 'vector' && codeOf(e) === 'unsupported')) at(`createRenderer failed: ${codeOf(e)}`);\n\t\treturn;\n\t}\n\ttry {\n\t\tconst out = await renderer.render({ time: 0, inputs });\n\t\tif (!isEffectPixels(out)) at('render did not return EffectPixels');\n\t\telse if (out.width !== size || out.height !== size || out.data.length !== size * size * 4) at(`render returned ${out.width}×${out.height}, not ${size}×${size}`);\n\t} catch (e) {\n\t\tat(`render failed: ${codeOf(e)}`);\n\t}\n\tconst bad = await rejectsWith('invalid_values', () => renderer.render({ time: 0, inputs, values: { __not_a_control__: 1 } }));\n\tif (bad) at(`render with an unknown control ${bad}`);\n\trenderer.dispose();\n\tconst after = await rejectsWith('disposed', () => renderer.render({ time: 0, inputs }));\n\tif (after) at(`render after dispose ${after}`);\n}\n\n/** Runs the contract checks against `provider` and returns every issue found (empty when it conforms). */\nexport async function checkEffectProvider(provider: EffectProvider, options: EffectConformanceOptions = {}): Promise<EffectConformanceIssue[]> {\n\tconst issues: EffectConformanceIssue[] = [];\n\tconst top = (message: string) => issues.push({ message });\n\tif (!provider.id) top('provider has no id');\n\tconst caps = provider.capabilities;\n\tfor (const k of ['supportsWorker', 'supportsFloat', 'supportsMask', 'supportsHostImages', 'supportsVector'] as const) {\n\t\tif (typeof caps?.[k] !== 'boolean') top(`capabilities.${k} is not a boolean`);\n\t}\n\tif (caps?.supportsVector && typeof provider.applyVectorEffect !== 'function') top('supportsVector is set but applyVectorEffect is missing');\n\n\tconst list = await provider.list();\n\tconst ids = new Set<string>();\n\tfor (const e of list) {\n\t\tif (ids.has(e.id)) top(`duplicate id \"${e.id}\"`);\n\t\tids.add(e.id);\n\t\tcheckSummary(e, issues);\n\t}\n\tconst all = await provider.search('');\n\tif (all.length !== list.length) top(`search(\"\") returned ${all.length} effects, list() ${list.length}`);\n\tconst firstUse = list[0]?.uses[0];\n\tif (firstUse) {\n\t\tconst filtered = await provider.search('', { use: firstUse });\n\t\tif (filtered.some((e) => !e.uses.includes(firstUse))) top(`search(\"\", { use: \"${firstUse}\" }) returned effects without that use`);\n\t}\n\tconst unknown = await rejectsWith('unknown_effect', () => provider.describe('__no_such_effect__'));\n\tif (unknown) top(`describe of an unknown id ${unknown}`);\n\tconst unknownRenderer = await rejectsWith('unknown_effect', () => provider.createRenderer('__no_such_effect__', { width: 4, height: 4 }));\n\tif (unknownRenderer) top(`createRenderer of an unknown id ${unknownRenderer}`);\n\n\tconst size = options.size ?? 8;\n\tfor (const id of options.ids ?? [...ids]) {\n\t\tlet d: EffectDescription;\n\t\ttry {\n\t\t\td = await provider.describe(id);\n\t\t} catch (e) {\n\t\t\tissues.push({ effectId: id, message: `describe failed: ${codeOf(e)}` });\n\t\t\tcontinue;\n\t\t}\n\t\tcheckDescription(id, d, issues);\n\t\tif (options.render !== false && d.kind !== 'motion') await checkRender(provider, d, size, issues);\n\t\tif ((d.kind === 'vector' || d.kind === 'motion') && caps.supportsVector && provider.applyVectorEffect) {\n\t\t\ttry {\n\t\t\t\tconst m = await provider.applyVectorEffect(id, '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 10 10\"><rect id=\"r\" width=\"10\" height=\"10\"/></svg>');\n\t\t\t\tif (typeof m.svg !== 'string' || !m.svg.includes('<svg')) issues.push({ effectId: id, message: 'applyVectorEffect returned no SVG' });\n\t\t\t\tif (!(m.duration >= 0)) issues.push({ effectId: id, message: 'applyVectorEffect returned no duration' });\n\t\t\t} catch (e) {\n\t\t\t\t// The probe target is a bare <rect>; an effect that needs more (a path to follow, a fill colour) may refuse it.\n\t\t\t\tif (codeOf(e) !== 'unsupported') issues.push({ effectId: id, message: `applyVectorEffect failed: ${codeOf(e)}` });\n\t\t\t}\n\t\t\tconst bad = await rejectsWith('invalid_values', () => provider.applyVectorEffect!(id, '<svg xmlns=\"http://www.w3.org/2000/svg\"/>', { __not_a_control__: 1 }));\n\t\t\tif (bad) issues.push({ effectId: id, message: `applyVectorEffect with an unknown control ${bad}` });\n\t\t}\n\t}\n\treturn issues;\n}\n","/**\n * `createFakeEffectProvider`: a small, deterministic, CPU-only provider implementing the whole\n * contract. Tests and the demo use it; it is also a reference for real providers.\n *\n * Effects (ids prefixed `fake.`):\n * - `invert` (filter), `tint` (filter)\n * - `gradient` (generator, loops)\n * - `bar` (title / overlay: a lower-third bar that slides in, transparent)\n * - `crossfade` (transition)\n * - `fade-in` (motion, vector only)\n * - `badge` (a vector effect with its own picture: a disc that fades in; vector only)\n */\n\nimport { EffectDisposedError, EffectUnsupportedError, UnknownEffectError } from './errors.js';\nimport { createEffectPixels, encodeEffectFloat, isEffectPixels, resolveEffectValues, searchEffectSummaries, srgbToLinear } from './helpers.js';\nimport type {\n\tEffectDescription,\n\tEffectImageSource,\n\tEffectPixels,\n\tEffectProvider,\n\tEffectProviderCapabilities,\n\tEffectRenderer,\n\tEffectRendererOptions,\n\tEffectRenderRequest,\n\tEffectSummary,\n\tEffectValues,\n\tEffectVectorMotion,\n\tEffectVectorTarget\n} from './types.js';\n\nconst HEX = '^#[0-9a-fA-F]{6}$';\nconst colour = (description: string) => ({ type: 'string' as const, pattern: HEX, description });\nconst amount = (description: string) => ({ type: 'number' as const, minimum: 0, maximum: 1, description });\n\nconst DESCRIPTIONS: readonly EffectDescription[] = [\n\t{\n\t\tid: 'fake.invert',\n\t\tname: 'Invert',\n\t\tkind: 'shader',\n\t\tcategory: 'image',\n\t\tuses: ['filter'],\n\t\tdescription: 'Inverts the colours of the source.',\n\t\ttags: ['negative', 'colour'],\n\t\ttransparent: false,\n\t\tloop: false,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: { amount: amount('How far to invert, 0 (unchanged) to 1 (fully inverted). Default 1.') }\n\t\t},\n\t\tdefaults: { amount: 1 },\n\t\tpresets: [{ name: 'Half', values: { amount: 0.5 } }],\n\t\tinputs: [{ name: 'source', kind: 'image', description: 'The picture to invert.', required: true }]\n\t},\n\t{\n\t\tid: 'fake.tint',\n\t\tname: 'Tint',\n\t\tkind: 'shader',\n\t\tcategory: 'image',\n\t\tuses: ['filter'],\n\t\tdescription: 'Mixes the source towards a colour.',\n\t\ttags: ['colour', 'wash'],\n\t\ttransparent: false,\n\t\tloop: false,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tcolor: colour('Tint colour as #rrggbb. Default #ff8800.'),\n\t\t\t\tamount: amount('How far to mix towards the colour, 0–1. Default 0.5.')\n\t\t\t}\n\t\t},\n\t\tdefaults: { color: '#ff8800', amount: 0.5 },\n\t\tpresets: [\n\t\t\t{ name: 'Sepia', values: { color: '#704214', amount: 0.4 } },\n\t\t\t{ name: 'Cool', values: { color: '#2060ff', amount: 0.25 } }\n\t\t],\n\t\tinputs: [{ name: 'source', kind: 'image', description: 'The picture to tint.', required: true }]\n\t},\n\t{\n\t\tid: 'fake.gradient',\n\t\tname: 'Gradient',\n\t\tkind: 'shader',\n\t\tcategory: 'gradient',\n\t\tuses: ['generator'],\n\t\tdescription: 'A linear gradient between two colours that can turn over time.',\n\t\ttags: ['background'],\n\t\ttransparent: false,\n\t\tloop: true,\n\t\tduration: 4000,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tfrom: colour('Start colour as #rrggbb. Default #1e3a8a.'),\n\t\t\t\tto: colour('End colour as #rrggbb. Default #f472b6.'),\n\t\t\t\tangle: { type: 'number', minimum: 0, maximum: 360, description: 'Direction in degrees, 0 = left to right, 90 = top to bottom. Default 90.' },\n\t\t\t\tspin: { type: 'number', minimum: -360, maximum: 360, description: 'Turn per loop (4 s) in degrees. Default 0.' }\n\t\t\t}\n\t\t},\n\t\tdefaults: { from: '#1e3a8a', to: '#f472b6', angle: 90, spin: 0 },\n\t\tpresets: [{ name: 'Sunset', values: { from: '#f97316', to: '#7c3aed' } }],\n\t\tinputs: []\n\t},\n\t{\n\t\tid: 'fake.bar',\n\t\tname: 'Lower-third bar',\n\t\tkind: 'shader',\n\t\tcategory: 'broadcast',\n\t\tuses: ['title', 'overlay'],\n\t\tdescription: 'A coloured bar that slides in from the left in the lower third. Transparent elsewhere.',\n\t\ttags: ['lower third', 'title'],\n\t\ttransparent: true,\n\t\tloop: false,\n\t\tduration: 2000,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tcolor: colour('Bar colour as #rrggbb. Default #0ea5e9.'),\n\t\t\t\theight: { type: 'number', minimum: 0.02, maximum: 0.5, description: 'Bar height as a fraction of the picture height. Default 0.12.' },\n\t\t\t\tslide: { type: 'number', minimum: 0, maximum: 5000, description: 'Slide-in time (ms). Default 500.' }\n\t\t\t}\n\t\t},\n\t\tdefaults: { color: '#0ea5e9', height: 0.12, slide: 500 },\n\t\tpresets: [],\n\t\tinputs: []\n\t},\n\t{\n\t\tid: 'fake.crossfade',\n\t\tname: 'Crossfade',\n\t\tkind: 'shader',\n\t\tcategory: 'transition',\n\t\tuses: ['transition'],\n\t\tdescription: 'Dissolves from one picture to the next.',\n\t\ttags: ['dissolve', 'mix'],\n\t\ttransparent: false,\n\t\tloop: false,\n\t\tduration: 1000,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: { curve: { type: 'string', enum: ['linear', 'smooth'], description: 'Mix curve: linear, or smooth (ease in and out). Default smooth.' } }\n\t\t},\n\t\tdefaults: { curve: 'smooth' },\n\t\tpresets: [],\n\t\tinputs: [\n\t\t\t{ name: 'from', kind: 'image', description: 'The outgoing picture.', required: true },\n\t\t\t{ name: 'to', kind: 'image', description: 'The incoming picture.', required: true }\n\t\t]\n\t},\n\t{\n\t\tid: 'fake.fade-in',\n\t\tname: 'Fade in',\n\t\tkind: 'motion',\n\t\tcategory: 'morph',\n\t\tuses: ['motion'],\n\t\tdescription: 'Fades vector elements in from transparent, one after another.',\n\t\ttags: ['appear', 'entrance'],\n\t\ttransparent: true,\n\t\tloop: false,\n\t\tduration: 600,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tms: { type: 'number', minimum: 0, maximum: 10000, description: 'Fade time per element (ms). Default 600.' },\n\t\t\t\tstagger: { type: 'number', minimum: 0, maximum: 5000, description: 'Delay between elements (ms). Default 0.' }\n\t\t\t}\n\t\t},\n\t\tdefaults: { ms: 600, stagger: 0 },\n\t\tpresets: [{ name: 'Cascade', values: { ms: 400, stagger: 120 } }],\n\t\tinputs: []\n\t},\n\t{\n\t\tid: 'fake.badge',\n\t\tname: 'Badge',\n\t\tkind: 'vector',\n\t\tcategory: 'sticker',\n\t\tuses: ['title'],\n\t\tdescription: 'A coloured disc that fades in: a vector effect that brings its own picture.',\n\t\ttags: ['sticker', 'disc'],\n\t\ttransparent: true,\n\t\tloop: false,\n\t\tduration: 500,\n\t\tcontrols: {\n\t\t\ttype: 'object',\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tcolor: colour('Disc colour as #rrggbb. Default #f43f5e.'),\n\t\t\t\tms: { type: 'number', minimum: 0, maximum: 10000, description: 'Fade-in time (ms). Default 500.' }\n\t\t\t}\n\t\t},\n\t\tdefaults: { color: '#f43f5e', ms: 500 },\n\t\tpresets: [],\n\t\tinputs: []\n\t}\n];\n\nconst summaryOf = ({ controls: _c, defaults: _d, presets: _p, inputs: _i, ...summary }: EffectDescription): EffectSummary => summary;\n\nconst hexToRgb = (hex: string): [number, number, number] => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16)) as [number, number, number];\nconst smooth = (t: number) => t * t * (3 - 2 * t);\nconst clamp01 = (v: number) => (v < 0 ? 0 : v > 1 ? 1 : v);\n\nfunction input(request: EffectRenderRequest, name: string, id: string, width: number, height: number): EffectPixels {\n\tconst src: EffectImageSource | undefined = request.inputs?.[name];\n\tif (!src) throw new EffectUnsupportedError(`Effect \"${id}\" needs an input named \"${name}\".`, id);\n\tif (!isEffectPixels(src)) throw new EffectUnsupportedError(`The fake provider only takes EffectPixels inputs (\"${name}\").`, id);\n\tif (src.width !== width || src.height !== height) {\n\t\tthrow new EffectUnsupportedError(`Input \"${name}\" is ${src.width}×${src.height}; the renderer is ${width}×${height}.`, id);\n\t}\n\treturn src;\n}\n\n/** Per-pixel colour work in 8-bit sRGB; float output (when asked) is derived from it. */\nfunction renderPixels(d: EffectDescription, v: Record<string, EffectValues[string]>, request: EffectRenderRequest, width: number, height: number): EffectPixels {\n\tconst out = createEffectPixels(width, height);\n\tconst o = out.data;\n\tswitch (d.id) {\n\t\tcase 'fake.invert': {\n\t\t\tconst s = input(request, 'source', d.id, width, height).data;\n\t\t\tconst k = v.amount as number;\n\t\t\tfor (let i = 0; i < o.length; i += 4) {\n\t\t\t\tfor (let c = 0; c < 3; c++) o[i + c] = s[i + c] + (255 - 2 * s[i + c]) * k;\n\t\t\t\to[i + 3] = s[i + 3];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 'fake.tint': {\n\t\t\tconst s = input(request, 'source', d.id, width, height).data;\n\t\t\tconst rgb = hexToRgb(v.color as string);\n\t\t\tconst k = v.amount as number;\n\t\t\tfor (let i = 0; i < o.length; i += 4) {\n\t\t\t\tfor (let c = 0; c < 3; c++) o[i + c] = s[i + c] + (rgb[c] - s[i + c]) * k;\n\t\t\t\to[i + 3] = s[i + 3];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 'fake.gradient': {\n\t\t\tconst a = hexToRgb(v.from as string);\n\t\t\tconst b = hexToRgb(v.to as string);\n\t\t\tconst turn = ((request.time % (d.duration ?? 4000)) / (d.duration ?? 4000)) * (v.spin as number);\n\t\t\tconst rad = (((v.angle as number) + turn) * Math.PI) / 180;\n\t\t\tconst dx = Math.cos(rad);\n\t\t\tconst dy = Math.sin(rad);\n\t\t\tconst half = (Math.abs(dx) * width + Math.abs(dy) * height) / 2 || 1;\n\t\t\tfor (let y = 0, i = 0; y < height; y++) {\n\t\t\t\tfor (let x = 0; x < width; x++, i += 4) {\n\t\t\t\t\tconst t = clamp01(((x + 0.5 - width / 2) * dx + (y + 0.5 - height / 2) * dy) / (2 * half) + 0.5);\n\t\t\t\t\tfor (let c = 0; c < 3; c++) o[i + c] = a[c] + (b[c] - a[c]) * t;\n\t\t\t\t\to[i + 3] = 255;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 'fake.bar': {\n\t\t\tconst rgb = hexToRgb(v.color as string);\n\t\t\tconst slide = v.slide as number;\n\t\t\tconst shown = slide > 0 ? smooth(clamp01(request.time / slide)) : 1;\n\t\t\tconst top = Math.round(height * (0.75 - (v.height as number) / 2));\n\t\t\tconst bottom = Math.round(height * (0.75 + (v.height as number) / 2));\n\t\t\tconst right = Math.round(width * 0.7 * shown);\n\t\t\tfor (let y = Math.max(0, top); y < Math.min(height, bottom); y++) {\n\t\t\t\tfor (let x = 0; x < right; x++) {\n\t\t\t\t\tconst i = (y * width + x) * 4;\n\t\t\t\t\to[i] = rgb[0];\n\t\t\t\t\to[i + 1] = rgb[1];\n\t\t\t\t\to[i + 2] = rgb[2];\n\t\t\t\t\to[i + 3] = 255;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 'fake.crossfade': {\n\t\t\tconst from = input(request, 'from', d.id, width, height).data;\n\t\t\tconst to = input(request, 'to', d.id, width, height).data;\n\t\t\tconst p = clamp01(request.progress ?? request.time / (d.duration ?? 1000));\n\t\t\tconst k = v.curve === 'smooth' ? smooth(p) : p;\n\t\t\tfor (let i = 0; i < o.length; i++) o[i] = from[i] + (to[i] - from[i]) * k;\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tthrow new EffectUnsupportedError(`\"${d.id}\" is a ${d.kind} effect; use applyVectorEffect.`, d.id);\n\t}\n\treturn out;\n}\n\nfunction toFloat(p: EffectPixels): EffectPixels {\n\tconst f = new Float32Array(p.data.length);\n\tfor (let i = 0; i < f.length; i += 4) {\n\t\tf[i] = srgbToLinear(p.data[i] / 255);\n\t\tf[i + 1] = srgbToLinear(p.data[i + 1] / 255);\n\t\tf[i + 2] = srgbToLinear(p.data[i + 2] / 255);\n\t\tf[i + 3] = p.data[i + 3] / 255;\n\t}\n\treturn encodeEffectFloat({ ...p, float: f });\n}\n\nfunction maskResult(out: EffectPixels, mask: EffectImageSource, source: EffectPixels | undefined, id: string): void {\n\tif (!isEffectPixels(mask) || mask.width !== out.width || mask.height !== out.height) {\n\t\tthrow new EffectUnsupportedError('The mask must be EffectPixels the size of the renderer.', id);\n\t}\n\tconst o = out.data;\n\tfor (let i = 0; i < o.length; i += 4) {\n\t\tconst k = mask.data[i + 3] / 255;\n\t\tif (source) for (let c = 0; c < 4; c++) o[i + c] = source.data[i + c] + (o[i + c] - source.data[i + c]) * k;\n\t\telse o[i + 3] *= k;\n\t}\n}\n\nexport interface FakeEffectProviderOptions {\n\t/** Overrides of the capability flags, to test how editors degrade. */\n\tcapabilities?: Partial<EffectProviderCapabilities>;\n\t/** Called on every render (tests count frames with it). */\n\tonRender?: (effectId: string, request: EffectRenderRequest) => void;\n}\n\n/** A deterministic CPU effects provider with six effects (see the module comment). */\nexport function createFakeEffectProvider(options: FakeEffectProviderOptions = {}): EffectProvider {\n\tconst capabilities: EffectProviderCapabilities = {\n\t\tsupportsWorker: false,\n\t\tsupportsFloat: true,\n\t\tsupportsMask: true,\n\t\tsupportsHostImages: false,\n\t\tsupportsVector: true,\n\t\tmaxSize: 8192,\n\t\t...options.capabilities\n\t};\n\tconst byId = new Map(DESCRIPTIONS.map((d) => [d.id, d]));\n\tconst get = (id: string) => {\n\t\tconst d = byId.get(id);\n\t\tif (!d) throw new UnknownEffectError(id, 'the fake provider');\n\t\treturn d;\n\t};\n\tconst summaries = DESCRIPTIONS.map(summaryOf);\n\n\tconst provider: EffectProvider = {\n\t\tid: 'fake',\n\t\tname: 'Fake effects',\n\t\tversion: '1',\n\t\tcapabilities,\n\t\tlist: (o) => searchEffectSummaries(summaries, '', o),\n\t\tsearch: (q, o) => searchEffectSummaries(summaries, q, o),\n\t\tdescribe: (id) => structuredClone(get(id)),\n\t\tcreateRenderer(id: string, ro: EffectRendererOptions): EffectRenderer {\n\t\t\tconst d = get(id);\n\t\t\tif (d.kind !== 'shader') throw new EffectUnsupportedError(`\"${id}\" is a ${d.kind} effect; use applyVectorEffect.`, id);\n\t\t\tconst { width, height } = ro;\n\t\t\tconst depth = ro.depth ?? 8;\n\t\t\tif (!(width > 0 && height > 0) || width > capabilities.maxSize! || height > capabilities.maxSize!) {\n\t\t\t\tthrow new EffectUnsupportedError(`Renderer size ${width}×${height} is outside 1–${capabilities.maxSize}.`, id);\n\t\t\t}\n\t\t\tlet disposed = false;\n\t\t\treturn {\n\t\t\t\teffectId: id,\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tdepth,\n\t\t\t\tasync render(request) {\n\t\t\t\t\tif (disposed) throw new EffectDisposedError(id);\n\t\t\t\t\tif (!Number.isFinite(request.time) || request.time < 0) {\n\t\t\t\t\t\tthrow new EffectUnsupportedError(`time must be a finite number of ms ≥ 0, got ${request.time}.`, id);\n\t\t\t\t\t}\n\t\t\t\t\tconst values = resolveEffectValues(d, request.values);\n\t\t\t\t\toptions.onRender?.(id, request);\n\t\t\t\t\tconst out = renderPixels(d, values, request, width, height);\n\t\t\t\t\tif (request.mask) {\n\t\t\t\t\t\tif (!capabilities.supportsMask) throw new EffectUnsupportedError('This provider does not take masks.', id);\n\t\t\t\t\t\tconst source = d.uses.includes('filter') ? (request.inputs?.source as EffectPixels) : undefined;\n\t\t\t\t\t\tmaskResult(out, request.mask, source, id);\n\t\t\t\t\t}\n\t\t\t\t\treturn depth > 8 && capabilities.supportsFloat ? toFloat(out) : out;\n\t\t\t\t},\n\t\t\t\tdispose() {\n\t\t\t\t\tdisposed = true;\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tapplyVectorEffect(id: string, target: EffectVectorTarget, values?: EffectValues): EffectVectorMotion {\n\t\t\tconst d = get(id);\n\t\t\tif (d.kind !== 'motion' && d.kind !== 'vector') throw new EffectUnsupportedError(`\"${id}\" is a ${d.kind} effect, not a vector one.`, id);\n\t\t\tconst v = resolveEffectValues(d, values);\n\t\t\tif (d.kind === 'vector') {\n\t\t\t\t// Its own picture: the target is not used.\n\t\t\t\treturn { svg: `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\" width=\"100\" height=\"100\"><circle id=\"badge\" cx=\"50\" cy=\"50\" r=\"40\" fill=\"${v.color}\"/></svg>`, animate: [{ id: 'badge', ms: v.ms as number, attrs: { opacity: [0, 1] as const } }], duration: v.ms as number, loop: false };\n\t\t\t}\n\t\t\tconst svg = typeof target === 'string' ? target : target.svg;\n\t\t\tconst ids = typeof target === 'string' || !target.nodeIds ? [...svg.matchAll(/\\sid=\"([^\"]+)\"/g)].map((m) => m[1]) : [...target.nodeIds];\n\t\t\tconst ms = v.ms as number;\n\t\t\tconst stagger = v.stagger as number;\n\t\t\treturn {\n\t\t\t\tsvg,\n\t\t\t\tanimate: ids.map((elementId, i) => ({ id: elementId, delay: i * stagger, ms, attrs: { opacity: [0, 1] as const } })),\n\t\t\t\tduration: ms + Math.max(0, ids.length - 1) * stagger,\n\t\t\t\tloop: false\n\t\t\t};\n\t\t}\n\t};\n\treturn provider;\n}\n","/**\n * Framework-free helpers for effects UIs (the React and Svelte effects browser and parameter\n * panel): control schemas as parameter fields, preview thumbnails from a provider's renderer,\n * and labels.\n */\n\nimport type { JsonSchema } from '../tools/schema.js';\nimport type { ParameterField, ParameterValue } from '../parameters/types.js';\nimport { createEffectPixels } from './helpers.js';\nimport type { EffectDescription, EffectPixels, EffectProvider, EffectSummary, EffectUse, EffectValue } from './types.js';\n\n/** Names for the uses, for filters and badges. */\nexport const EFFECT_USE_LABELS: Readonly<Record<EffectUse, string>> = {\n\tfilter: 'Filter',\n\ttransition: 'Transition',\n\tgenerator: 'Generator',\n\toverlay: 'Overlay',\n\ttitle: 'Title',\n\tmotion: 'Motion',\n\tinteractive: 'Interactive'\n};\n\nconst HEX = /^#[0-9a-f]{6}([0-9a-f]{2})?$/i;\nconst typeOf = (s: JsonSchema) => (Array.isArray(s.type) ? s.type.find((t) => t !== 'null') : s.type);\n\n/**\n * One control as a parameter field: numbers and integers (sliders when bounded), switches,\n * choices (`enum`), colours (strings whose default is `#rrggbb`), vectors (2–4 numbers) and text.\n * `null` for a control no field can edit (objects, long lists).\n */\nexport function effectControlField(name: string, schema: JsonSchema, fallback: EffectValue | undefined): ParameterField | null {\n\tconst base = { id: name, ...(schema.title ? { label: schema.title } : {}), ...(schema.description ? { description: schema.description } : {}) };\n\tconst def = (schema.default ?? fallback) as EffectValue | undefined;\n\tconst type = typeOf(schema);\n\tif (Array.isArray(schema.enum) && schema.enum.length) {\n\t\tconst options = schema.enum.filter((v): v is string | number => typeof v === 'string' || typeof v === 'number');\n\t\treturn { ...base, type: 'choice', options, default: (typeof def === 'string' || typeof def === 'number' ? def : options[0]) as string | number, control: options.length <= 4 ? 'segmented' : 'select' };\n\t}\n\tif (type === 'number' || type === 'integer') {\n\t\tconst min = schema.minimum ?? schema.exclusiveMinimum;\n\t\tconst max = schema.maximum ?? schema.exclusiveMaximum;\n\t\treturn { ...base, type: type === 'integer' ? 'int' : 'number', default: typeof def === 'number' ? def : (min ?? 0), ...(min !== undefined ? { min } : {}), ...(max !== undefined ? { max } : {}), ...(schema.multipleOf ? { step: schema.multipleOf } : {}) };\n\t}\n\tif (type === 'boolean') return { ...base, type: 'boolean', default: def === true };\n\tif (type === 'string') {\n\t\tif (typeof def === 'string' && HEX.test(def)) return { ...base, type: 'color', alpha: def.length === 9, default: def };\n\t\treturn { ...base, type: 'text', default: typeof def === 'string' ? def : '', ...(schema.maxLength ? { maxLength: schema.maxLength } : {}) };\n\t}\n\tif (type === 'array' && Array.isArray(def) && def.length >= 2 && def.length <= 4 && def.every((n) => typeof n === 'number')) {\n\t\tconst items = schema.items ?? {};\n\t\treturn { ...base, type: 'vector', size: def.length as 2 | 3 | 4, default: [...def], ...(items.minimum !== undefined ? { min: items.minimum } : {}), ...(items.maximum !== undefined ? { max: items.maximum } : {}) };\n\t}\n\treturn null;\n}\n\n/** An effect's controls as parameter fields, in schema order (controls no field can edit are left out). */\nexport function effectParameterFields(description: Pick<EffectDescription, 'controls' | 'defaults'>): ParameterField[] {\n\treturn Object.entries(description.controls.properties)\n\t\t.map(([name, schema]) => effectControlField(name, schema, description.defaults[name]))\n\t\t.filter((f): f is ParameterField => !!f);\n}\n\n/** A saved value as a field shows it (`ParameterValue`), or the field's default. */\nexport const effectFieldValue = (field: ParameterField, value: unknown): ParameterValue =>\n\tvalue === undefined || value === null || (typeof value === 'object' && !Array.isArray(value)) ? field.default : (value as ParameterValue);\n\n/**\n * A colourful, deterministic picture for previews of filters and transitions (`variant` 0 and 1\n * differ, for a transition's two sides).\n */\nexport function effectSamplePicture(width: number, height: number, variant = 0): EffectPixels {\n\tconst p = createEffectPixels(width, height);\n\tfor (let y = 0, i = 0; y < height; y++) {\n\t\tfor (let x = 0; x < width; x++, i += 4) {\n\t\t\tconst u = x / Math.max(1, width - 1);\n\t\t\tconst v = y / Math.max(1, height - 1);\n\t\t\tconst check = (Math.floor(u * 4) + Math.floor(v * 4)) % 2;\n\t\t\tif (variant === 0) p.data.set([Math.round(40 + 200 * u), Math.round(80 + 120 * v), Math.round(200 - 120 * u) + check * 30, 255], i);\n\t\t\telse p.data.set([Math.round(230 - 60 * v), Math.round(190 - 100 * u), 60 + check * 40, 255], i);\n\t\t}\n\t}\n\treturn p;\n}\n\n/**\n * A small preview of an effect from the provider's own renderer: filters run on a sample picture,\n * transitions go half way between two, generators and overlays draw at `time` (default half\n * their length, or 1 s). Thumbnails render one at a time (each renderer is disposed before the\n * next is made) and are kept per provider. Rejects like the provider does (motion effects have\n * no pixels).\n */\nexport function renderEffectThumbnail(provider: EffectProvider, effect: EffectSummary | EffectDescription, size: { width: number; height: number } = { width: 96, height: 54 }): Promise<EffectPixels> {\n\tlet cache = thumbnails.get(provider);\n\tif (!cache) thumbnails.set(provider, (cache = new Map()));\n\tconst key = `${effect.id}@${size.width}x${size.height}`;\n\tlet out = cache.get(key);\n\tif (!out) {\n\t\t// One at a time: a browser full of previews would otherwise open a graphics context each.\n\t\tout = thumbnailQueue.then(() => renderThumbnail(provider, effect, size));\n\t\tthumbnailQueue = out.catch(() => undefined);\n\t\tout.catch(() => cache!.delete(key));\n\t\tcache.set(key, out);\n\t}\n\treturn out;\n}\n\nconst thumbnails = new WeakMap<EffectProvider, Map<string, Promise<EffectPixels>>>();\nlet thumbnailQueue: Promise<unknown> = Promise.resolve();\n\nasync function renderThumbnail(provider: EffectProvider, effect: EffectSummary | EffectDescription, size: { width: number; height: number }): Promise<EffectPixels> {\n\tconst d = 'inputs' in effect ? effect : await provider.describe(effect.id);\n\tconst renderer = await provider.createRenderer(d.id, size);\n\ttry {\n\t\tconst time = d.duration ? d.duration / 2 : 1000;\n\t\tconst inputs: Record<string, EffectPixels> = {};\n\t\tfor (const input of d.inputs) if (input.kind === 'image') inputs[input.name] = effectSamplePicture(size.width, size.height, input.name === 'to' ? 1 : 0);\n\t\treturn await renderer.render({ time, inputs, ...(d.uses.includes('transition') ? { progress: 0.5 } : {}) });\n\t} finally {\n\t\trenderer.dispose();\n\t}\n}\n\n/** Effects grouped by category, categories in first-seen order. */\nexport function groupEffectsByCategory<T extends EffectSummary>(effects: readonly T[]): { category: string; effects: T[] }[] {\n\tconst groups = new Map<string, T[]>();\n\tfor (const e of effects) {\n\t\tconst g = groups.get(e.category);\n\t\tif (g) g.push(e);\n\t\telse groups.set(e.category, [e]);\n\t}\n\treturn [...groups].map(([category, list]) => ({ category, effects: list }));\n}\n"],"mappings":"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","names":["input","HEX","input"]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { b as AnimationEasing } from './easing-lM0Xo9Ni.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Behaviours: how a change gets from `from` to `to` other than straight along its ease (a
|
|
5
|
+
* pulse there and back, an oscillation, a seeded wriggle, a springy overshoot). Ported from
|
|
6
|
+
* `@pixerate/flair` (MIT): `SvgBehavior` and `behaviorProgress` in `vector/motion.ts`, the
|
|
7
|
+
* oscillate and overshoot evaluators in `scene/behavior.ts` and the noise in `time/noise.ts`.
|
|
8
|
+
* The numbers must stay identical to Flair's, so a behaviour exported to Flair plays the same
|
|
9
|
+
* frames there as here (the animation editor writes them as Flair `behavior`s, Flair ≥ 0.38).
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* A behaviour: its progress `u` at each moment, where 0 is `from`, 1 is `to`, and numbers go
|
|
13
|
+
* past either. `t` is the change's time, 0–1, through its ease (linear unless given).
|
|
14
|
+
*
|
|
15
|
+
* - `pulse`: there and back `count` times (default 1): u = sin²(π·count·t).
|
|
16
|
+
* - `oscillate`: swings round `from`, out to `to` and as far the other way, `count` times
|
|
17
|
+
* (default 1), dying away by (1 − t)^`decay` (default 0, no decay).
|
|
18
|
+
* - `wriggle`: wanders round `from` by up to about `to − from`, as seeded smooth fractal noise
|
|
19
|
+
* at `frequency` Hz (default 2) with `octaves` layers (default 2); each number in a value
|
|
20
|
+
* wanders on its own channel. It eases out of and back to rest over the first and last 15%
|
|
21
|
+
* of its time. The same `seed` (default 42) gives the same wander.
|
|
22
|
+
* - `overshoot`: goes to `to`, past it and back, settling like a spring:
|
|
23
|
+
* u = 1 − e^(−damping·t)·cos(cycles·π·t) (default 3 cycles, damping 4).
|
|
24
|
+
*/
|
|
25
|
+
type MotionBehavior = {
|
|
26
|
+
type: 'pulse';
|
|
27
|
+
count?: number;
|
|
28
|
+
} | {
|
|
29
|
+
type: 'oscillate';
|
|
30
|
+
count?: number;
|
|
31
|
+
decay?: number;
|
|
32
|
+
wave?: 'sine' | 'triangle' | 'square' | 'sawtooth';
|
|
33
|
+
} | {
|
|
34
|
+
type: 'wriggle';
|
|
35
|
+
frequency?: number;
|
|
36
|
+
octaves?: number;
|
|
37
|
+
seed?: number;
|
|
38
|
+
} | {
|
|
39
|
+
type: 'overshoot';
|
|
40
|
+
cycles?: number;
|
|
41
|
+
damping?: number;
|
|
42
|
+
};
|
|
43
|
+
/** Every `MotionBehavior` type. */
|
|
44
|
+
declare const MOTION_BEHAVIORS: readonly ["pulse", "oscillate", "wriggle", "overshoot"];
|
|
45
|
+
/**
|
|
46
|
+
* A behaviour's progress at `t` (0–1, eased) of a change lasting `ms`, for the `index`-th number
|
|
47
|
+
* in a value (only a wriggle tells numbers apart).
|
|
48
|
+
*/
|
|
49
|
+
declare function behaviorProgress(behavior: MotionBehavior, t: number, index?: number, ms?: number): number;
|
|
50
|
+
/** Whether `value` is a well-formed `MotionBehavior`. */
|
|
51
|
+
declare function isMotionBehavior(value: unknown): value is MotionBehavior;
|
|
52
|
+
/** A seed from an id (FNV-1a), so each element wriggles its own way: Flair's `seedOf`. */
|
|
53
|
+
declare function motionSeedFromId(id: string): number;
|
|
54
|
+
/** 6t⁵ − 15t⁴ + 10t³: zero slope and curvature at 0 and 1. */
|
|
55
|
+
declare function quinticFade(t: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Multi-octave smooth noise (After Effects' `wiggle`): the sum over `octaves` of
|
|
58
|
+
* amp·ampMult^k · noise(freq·2^k·t), each octave and `dimension` seeded apart. `t` in seconds.
|
|
59
|
+
*/
|
|
60
|
+
declare function fractalWiggle(freq: number, amp: number, octaves?: number, ampMult?: number, t?: number, seed?: number, dimension?: number): number;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Keyframe tracks, independent of what they animate: each track is a list of keyframes
|
|
64
|
+
* `{ time (ms), value, easing }`, where the easing governs the segment *leaving* the keyframe
|
|
65
|
+
* (filmcraft / After Effects convention).
|
|
66
|
+
*/
|
|
67
|
+
/** Keyframe times closer than this (ms) are the same time. */
|
|
68
|
+
declare const ANIMATION_TIME_EPSILON = 0.000001;
|
|
69
|
+
/** A keyframe value: a number, or a CSS colour for colour properties. */
|
|
70
|
+
type AnimationValue = number | string;
|
|
71
|
+
interface AnimationKeyframe {
|
|
72
|
+
/** Time in milliseconds from the start of the timeline. */
|
|
73
|
+
time: number;
|
|
74
|
+
value: AnimationValue;
|
|
75
|
+
/** Easing of the segment from this keyframe to the next (default `linear`). */
|
|
76
|
+
easing?: AnimationEasing;
|
|
77
|
+
}
|
|
78
|
+
interface AnimationTrack {
|
|
79
|
+
keyframes: AnimationKeyframe[];
|
|
80
|
+
/** Disabled tracks keep their keyframes but do not animate (default `true`). */
|
|
81
|
+
enabled?: boolean;
|
|
82
|
+
}
|
|
83
|
+
/** How a track's values interpolate: numbers linearly, colours in OKLab. */
|
|
84
|
+
type AnimationValueType = 'number' | 'color';
|
|
85
|
+
/** Whether `value` is a well-formed keyframe. */
|
|
86
|
+
declare function isAnimationKeyframe(value: unknown): value is AnimationKeyframe;
|
|
87
|
+
/**
|
|
88
|
+
* Keyframes sorted by time, invalid entries dropped and duplicate times merged (the *later*
|
|
89
|
+
* entry in the array wins, so appending a keyframe replaces one at the same time). Cached per
|
|
90
|
+
* array (revalidated by element identity), so evaluating every frame does not re-sort; treat
|
|
91
|
+
* keyframe objects as immutable.
|
|
92
|
+
*/
|
|
93
|
+
declare function normalizeKeyframes(keyframes: readonly AnimationKeyframe[] | undefined | null): AnimationKeyframe[];
|
|
94
|
+
|
|
95
|
+
/** How time past the end of the timeline maps back into it. */
|
|
96
|
+
type AnimationLoopMode = 'none' | 'loop' | 'ping-pong';
|
|
97
|
+
/**
|
|
98
|
+
* Interpolates between two keyframe values: numbers linearly, colours in OKLab (premultiplied
|
|
99
|
+
* alpha). Mismatched or unreadable values hold `from` until `t` reaches 1.
|
|
100
|
+
*/
|
|
101
|
+
declare function interpolateAnimationValue(from: AnimationValue, to: AnimationValue, t: number, type?: AnimationValueType): AnimationValue;
|
|
102
|
+
/**
|
|
103
|
+
* A track's value at `time`. Before the first keyframe it holds the first value, after the
|
|
104
|
+
* last the last value. Keyframes may be unsorted or share times (see `normalizeKeyframes`).
|
|
105
|
+
* Returns `undefined` for a track without valid keyframes.
|
|
106
|
+
*/
|
|
107
|
+
declare function evaluateTrack(track: AnimationTrack | readonly AnimationKeyframe[] | undefined | null, time: number, type?: AnimationValueType): AnimationValue | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* Maps a running time onto the timeline `[0, duration]`: clamped (`none`), wrapped (`loop`)
|
|
110
|
+
* or bounced (`ping-pong`).
|
|
111
|
+
*/
|
|
112
|
+
declare function wrapAnimationTime(time: number, duration: number, loop?: AnimationLoopMode): number;
|
|
113
|
+
|
|
114
|
+
export { ANIMATION_TIME_EPSILON as A, MOTION_BEHAVIORS as M, type AnimationKeyframe as a, type AnimationLoopMode as b, type AnimationTrack as c, type AnimationValue as d, type AnimationValueType as e, type MotionBehavior as f, behaviorProgress as g, evaluateTrack as h, fractalWiggle as i, interpolateAnimationValue as j, isAnimationKeyframe as k, isMotionBehavior as l, motionSeedFromId as m, normalizeKeyframes as n, quinticFade as q, wrapAnimationTime as w };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { b as AnimationEasing } from './easing-lM0Xo9Ni.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Behaviours: how a change gets from `from` to `to` other than straight along its ease (a
|
|
5
|
+
* pulse there and back, an oscillation, a seeded wriggle, a springy overshoot). Ported from
|
|
6
|
+
* `@pixerate/flair` (MIT): `SvgBehavior` and `behaviorProgress` in `vector/motion.ts`, the
|
|
7
|
+
* oscillate and overshoot evaluators in `scene/behavior.ts` and the noise in `time/noise.ts`.
|
|
8
|
+
* The numbers must stay identical to Flair's, so a behaviour exported to Flair plays the same
|
|
9
|
+
* frames there as here (the animation editor writes them as Flair `behavior`s, Flair ≥ 0.38).
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* A behaviour: its progress `u` at each moment, where 0 is `from`, 1 is `to`, and numbers go
|
|
13
|
+
* past either. `t` is the change's time, 0–1, through its ease (linear unless given).
|
|
14
|
+
*
|
|
15
|
+
* - `pulse`: there and back `count` times (default 1): u = sin²(π·count·t).
|
|
16
|
+
* - `oscillate`: swings round `from`, out to `to` and as far the other way, `count` times
|
|
17
|
+
* (default 1), dying away by (1 − t)^`decay` (default 0, no decay).
|
|
18
|
+
* - `wriggle`: wanders round `from` by up to about `to − from`, as seeded smooth fractal noise
|
|
19
|
+
* at `frequency` Hz (default 2) with `octaves` layers (default 2); each number in a value
|
|
20
|
+
* wanders on its own channel. It eases out of and back to rest over the first and last 15%
|
|
21
|
+
* of its time. The same `seed` (default 42) gives the same wander.
|
|
22
|
+
* - `overshoot`: goes to `to`, past it and back, settling like a spring:
|
|
23
|
+
* u = 1 − e^(−damping·t)·cos(cycles·π·t) (default 3 cycles, damping 4).
|
|
24
|
+
*/
|
|
25
|
+
type MotionBehavior = {
|
|
26
|
+
type: 'pulse';
|
|
27
|
+
count?: number;
|
|
28
|
+
} | {
|
|
29
|
+
type: 'oscillate';
|
|
30
|
+
count?: number;
|
|
31
|
+
decay?: number;
|
|
32
|
+
wave?: 'sine' | 'triangle' | 'square' | 'sawtooth';
|
|
33
|
+
} | {
|
|
34
|
+
type: 'wriggle';
|
|
35
|
+
frequency?: number;
|
|
36
|
+
octaves?: number;
|
|
37
|
+
seed?: number;
|
|
38
|
+
} | {
|
|
39
|
+
type: 'overshoot';
|
|
40
|
+
cycles?: number;
|
|
41
|
+
damping?: number;
|
|
42
|
+
};
|
|
43
|
+
/** Every `MotionBehavior` type. */
|
|
44
|
+
declare const MOTION_BEHAVIORS: readonly ["pulse", "oscillate", "wriggle", "overshoot"];
|
|
45
|
+
/**
|
|
46
|
+
* A behaviour's progress at `t` (0–1, eased) of a change lasting `ms`, for the `index`-th number
|
|
47
|
+
* in a value (only a wriggle tells numbers apart).
|
|
48
|
+
*/
|
|
49
|
+
declare function behaviorProgress(behavior: MotionBehavior, t: number, index?: number, ms?: number): number;
|
|
50
|
+
/** Whether `value` is a well-formed `MotionBehavior`. */
|
|
51
|
+
declare function isMotionBehavior(value: unknown): value is MotionBehavior;
|
|
52
|
+
/** A seed from an id (FNV-1a), so each element wriggles its own way: Flair's `seedOf`. */
|
|
53
|
+
declare function motionSeedFromId(id: string): number;
|
|
54
|
+
/** 6t⁵ − 15t⁴ + 10t³: zero slope and curvature at 0 and 1. */
|
|
55
|
+
declare function quinticFade(t: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Multi-octave smooth noise (After Effects' `wiggle`): the sum over `octaves` of
|
|
58
|
+
* amp·ampMult^k · noise(freq·2^k·t), each octave and `dimension` seeded apart. `t` in seconds.
|
|
59
|
+
*/
|
|
60
|
+
declare function fractalWiggle(freq: number, amp: number, octaves?: number, ampMult?: number, t?: number, seed?: number, dimension?: number): number;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Keyframe tracks, independent of what they animate: each track is a list of keyframes
|
|
64
|
+
* `{ time (ms), value, easing }`, where the easing governs the segment *leaving* the keyframe
|
|
65
|
+
* (filmcraft / After Effects convention).
|
|
66
|
+
*/
|
|
67
|
+
/** Keyframe times closer than this (ms) are the same time. */
|
|
68
|
+
declare const ANIMATION_TIME_EPSILON = 0.000001;
|
|
69
|
+
/** A keyframe value: a number, or a CSS colour for colour properties. */
|
|
70
|
+
type AnimationValue = number | string;
|
|
71
|
+
interface AnimationKeyframe {
|
|
72
|
+
/** Time in milliseconds from the start of the timeline. */
|
|
73
|
+
time: number;
|
|
74
|
+
value: AnimationValue;
|
|
75
|
+
/** Easing of the segment from this keyframe to the next (default `linear`). */
|
|
76
|
+
easing?: AnimationEasing;
|
|
77
|
+
}
|
|
78
|
+
interface AnimationTrack {
|
|
79
|
+
keyframes: AnimationKeyframe[];
|
|
80
|
+
/** Disabled tracks keep their keyframes but do not animate (default `true`). */
|
|
81
|
+
enabled?: boolean;
|
|
82
|
+
}
|
|
83
|
+
/** How a track's values interpolate: numbers linearly, colours in OKLab. */
|
|
84
|
+
type AnimationValueType = 'number' | 'color';
|
|
85
|
+
/** Whether `value` is a well-formed keyframe. */
|
|
86
|
+
declare function isAnimationKeyframe(value: unknown): value is AnimationKeyframe;
|
|
87
|
+
/**
|
|
88
|
+
* Keyframes sorted by time, invalid entries dropped and duplicate times merged (the *later*
|
|
89
|
+
* entry in the array wins, so appending a keyframe replaces one at the same time). Cached per
|
|
90
|
+
* array (revalidated by element identity), so evaluating every frame does not re-sort; treat
|
|
91
|
+
* keyframe objects as immutable.
|
|
92
|
+
*/
|
|
93
|
+
declare function normalizeKeyframes(keyframes: readonly AnimationKeyframe[] | undefined | null): AnimationKeyframe[];
|
|
94
|
+
|
|
95
|
+
/** How time past the end of the timeline maps back into it. */
|
|
96
|
+
type AnimationLoopMode = 'none' | 'loop' | 'ping-pong';
|
|
97
|
+
/**
|
|
98
|
+
* Interpolates between two keyframe values: numbers linearly, colours in OKLab (premultiplied
|
|
99
|
+
* alpha). Mismatched or unreadable values hold `from` until `t` reaches 1.
|
|
100
|
+
*/
|
|
101
|
+
declare function interpolateAnimationValue(from: AnimationValue, to: AnimationValue, t: number, type?: AnimationValueType): AnimationValue;
|
|
102
|
+
/**
|
|
103
|
+
* A track's value at `time`. Before the first keyframe it holds the first value, after the
|
|
104
|
+
* last the last value. Keyframes may be unsorted or share times (see `normalizeKeyframes`).
|
|
105
|
+
* Returns `undefined` for a track without valid keyframes.
|
|
106
|
+
*/
|
|
107
|
+
declare function evaluateTrack(track: AnimationTrack | readonly AnimationKeyframe[] | undefined | null, time: number, type?: AnimationValueType): AnimationValue | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* Maps a running time onto the timeline `[0, duration]`: clamped (`none`), wrapped (`loop`)
|
|
110
|
+
* or bounced (`ping-pong`).
|
|
111
|
+
*/
|
|
112
|
+
declare function wrapAnimationTime(time: number, duration: number, loop?: AnimationLoopMode): number;
|
|
113
|
+
|
|
114
|
+
export { ANIMATION_TIME_EPSILON as A, MOTION_BEHAVIORS as M, type AnimationKeyframe as a, type AnimationLoopMode as b, type AnimationTrack as c, type AnimationValue as d, type AnimationValueType as e, type MotionBehavior as f, behaviorProgress as g, evaluateTrack as h, fractalWiggle as i, interpolateAnimationValue as j, isAnimationKeyframe as k, isMotionBehavior as l, motionSeedFromId as m, normalizeKeyframes as n, quinticFade as q, wrapAnimationTime as w };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { e as EffectValue, v as EffectsSlot, b as EffectPixels, E as EffectProvider, f as EffectDescription } from './helpers-C5aAd44p.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Keyframes for a clip's opacity, volume and transform. A property is either a plain number or
|
|
@@ -2,9 +2,9 @@ import { a2 as RasterLayerBase, a3 as RasterMask$1, a5 as RasterPixelLayer, H as
|
|
|
2
2
|
import { c as PixelSurface, a as BlendMode, T as TiledSurface, R as RasterRect } from './surface-1MRncXpF.cjs';
|
|
3
3
|
import { b as BuiltinProfileId, j as Intent, P as Profile, T as Transform, d as ColorSpace } from './builtin-CY97ppKM.cjs';
|
|
4
4
|
import { A as AffineMatrix, Q as Quad, a as WarpMesh, V as Vec2, H as Homography } from './types-CwMPoRMU.cjs';
|
|
5
|
-
import { B as BezierPath } from './bezier-
|
|
6
|
-
import { b as TextRun, P as ParagraphRun, T as TextShaper, c as ParagraphStyle, d as TextStyle, L as LaidFragment, W as WarpPreset, e as TextLayout } from './warp-
|
|
7
|
-
import {
|
|
5
|
+
import { B as BezierPath } from './bezier-DBz0IgEt.cjs';
|
|
6
|
+
import { b as TextRun, P as ParagraphRun, T as TextShaper, c as ParagraphStyle, d as TextStyle, L as LaidFragment, W as WarpPreset, e as TextLayout } from './warp-C13L_GRn.cjs';
|
|
7
|
+
import { e as EffectValue, a3 as VectorSubpath, v as EffectsSlot, E as EffectProvider, b as EffectPixels, f as EffectDescription, X as Vec2$1 } from './helpers-C5aAd44p.cjs';
|
|
8
8
|
import { B as BrushSettings, P as PaintSource, M as MixerSettings, a as MixerLoad, R as RetouchSettings, S as StrokeCoverage, b as MixerTarget, c as MixerStroke, d as RetouchApply, e as StrokePoint, f as RetouchPaint, C as CoverageMap, g as PaintTileTarget, h as StrokeApply } from './rand-CfinE-1c.cjs';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { e as EffectValue, v as EffectsSlot, b as EffectPixels, E as EffectProvider, f as EffectDescription } from './helpers-CPWcK504.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Keyframes for a clip's opacity, volume and transform. A property is either a plain number or
|
|
@@ -2,9 +2,9 @@ import { a2 as RasterLayerBase, a3 as RasterMask$1, a5 as RasterPixelLayer, H as
|
|
|
2
2
|
import { c as PixelSurface, a as BlendMode, T as TiledSurface, R as RasterRect } from './surface-1MRncXpF.js';
|
|
3
3
|
import { b as BuiltinProfileId, j as Intent, P as Profile, T as Transform, d as ColorSpace } from './builtin-CY97ppKM.js';
|
|
4
4
|
import { A as AffineMatrix, Q as Quad, a as WarpMesh, V as Vec2, H as Homography } from './types-CwMPoRMU.js';
|
|
5
|
-
import { B as BezierPath } from './bezier-
|
|
6
|
-
import { b as TextRun, P as ParagraphRun, T as TextShaper, c as ParagraphStyle, d as TextStyle, L as LaidFragment, W as WarpPreset, e as TextLayout } from './warp-
|
|
7
|
-
import {
|
|
5
|
+
import { B as BezierPath } from './bezier-DWI5MEkI.js';
|
|
6
|
+
import { b as TextRun, P as ParagraphRun, T as TextShaper, c as ParagraphStyle, d as TextStyle, L as LaidFragment, W as WarpPreset, e as TextLayout } from './warp-q8FK5HHi.js';
|
|
7
|
+
import { e as EffectValue, a3 as VectorSubpath, v as EffectsSlot, E as EffectProvider, b as EffectPixels, f as EffectDescription, X as Vec2$1 } from './helpers-CPWcK504.js';
|
|
8
8
|
import { B as BrushSettings, P as PaintSource, M as MixerSettings, a as MixerLoad, R as RetouchSettings, S as StrokeCoverage, b as MixerTarget, c as MixerStroke, d as RetouchApply, e as StrokePoint, f as RetouchPaint, C as CoverageMap, g as PaintTileTarget, h as StrokeApply } from './rand-DtazXGOB.js';
|
|
9
9
|
|
|
10
10
|
/**
|