@staticcanvas/typeflow 0.34.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.
Files changed (178) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +637 -0
  3. package/branding/dist/ico/typeflow-logo-16x16.ico +0 -0
  4. package/branding/dist/ico/typeflow-logo-256x256.ico +0 -0
  5. package/branding/dist/ico/typeflow-logo-32x32.ico +0 -0
  6. package/branding/dist/ico/typeflow-logo-48x48.ico +0 -0
  7. package/branding/dist/png/typeflow-logo-1024x1024.png +0 -0
  8. package/branding/dist/png/typeflow-logo-128x128.png +0 -0
  9. package/branding/dist/png/typeflow-logo-16x16.png +0 -0
  10. package/branding/dist/png/typeflow-logo-256x256.png +0 -0
  11. package/branding/dist/png/typeflow-logo-512x512.png +0 -0
  12. package/branding/dist/png/typeflow-logo-64x64.png +0 -0
  13. package/branding/dist/webp/typeflow-logo-1024x1024.webp +0 -0
  14. package/branding/dist/webp/typeflow-logo-128x128.webp +0 -0
  15. package/branding/dist/webp/typeflow-logo-16x16.webp +0 -0
  16. package/branding/dist/webp/typeflow-logo-256x256.webp +0 -0
  17. package/branding/dist/webp/typeflow-logo-32x32.webp +0 -0
  18. package/branding/dist/webp/typeflow-logo-48x48.webp +0 -0
  19. package/branding/dist/webp/typeflow-logo-512x512.webp +0 -0
  20. package/branding/dist/webp/typeflow-logo-64x64.webp +0 -0
  21. package/branding/gen-logo.ps1 +14 -0
  22. package/branding/typeflow-logo.svg +162 -0
  23. package/dist/typeflow/LICENSE +21 -0
  24. package/dist/typeflow/README.md +231 -0
  25. package/dist/typeflow/branding/dist/ico/typeflow-logo-16x16.ico +0 -0
  26. package/dist/typeflow/branding/dist/ico/typeflow-logo-256x256.ico +0 -0
  27. package/dist/typeflow/branding/dist/ico/typeflow-logo-32x32.ico +0 -0
  28. package/dist/typeflow/branding/dist/ico/typeflow-logo-48x48.ico +0 -0
  29. package/dist/typeflow/branding/dist/png/typeflow-logo-1024x1024.png +0 -0
  30. package/dist/typeflow/branding/dist/png/typeflow-logo-128x128.png +0 -0
  31. package/dist/typeflow/branding/dist/png/typeflow-logo-16x16.png +0 -0
  32. package/dist/typeflow/branding/dist/png/typeflow-logo-256x256.png +0 -0
  33. package/dist/typeflow/branding/dist/png/typeflow-logo-512x512.png +0 -0
  34. package/dist/typeflow/branding/dist/png/typeflow-logo-64x64.png +0 -0
  35. package/dist/typeflow/branding/dist/webp/typeflow-logo-1024x1024.webp +0 -0
  36. package/dist/typeflow/branding/dist/webp/typeflow-logo-128x128.webp +0 -0
  37. package/dist/typeflow/branding/dist/webp/typeflow-logo-16x16.webp +0 -0
  38. package/dist/typeflow/branding/dist/webp/typeflow-logo-256x256.webp +0 -0
  39. package/dist/typeflow/branding/dist/webp/typeflow-logo-32x32.webp +0 -0
  40. package/dist/typeflow/branding/dist/webp/typeflow-logo-48x48.webp +0 -0
  41. package/dist/typeflow/branding/dist/webp/typeflow-logo-512x512.webp +0 -0
  42. package/dist/typeflow/branding/dist/webp/typeflow-logo-64x64.webp +0 -0
  43. package/dist/typeflow/branding/gen-logo.ps1 +14 -0
  44. package/dist/typeflow/branding/typeflow-logo.svg +162 -0
  45. package/dist/typeflow/dist/typeflow-caret.cjs +47 -0
  46. package/dist/typeflow/dist/typeflow-caret.cjs.map +1 -0
  47. package/dist/typeflow/dist/typeflow-caret.esm.js +47 -0
  48. package/dist/typeflow/dist/typeflow-caret.esm.js.map +1 -0
  49. package/dist/typeflow/dist/typeflow-caret.esm.min.js +2 -0
  50. package/dist/typeflow/dist/typeflow-caret.esm.min.js.map +1 -0
  51. package/dist/typeflow/dist/typeflow-caret.js +47 -0
  52. package/dist/typeflow/dist/typeflow-caret.js.map +1 -0
  53. package/dist/typeflow/dist/typeflow-caret.min.js +2 -0
  54. package/dist/typeflow/dist/typeflow-caret.min.js.map +1 -0
  55. package/dist/typeflow/dist/typeflow-caret.mjs +47 -0
  56. package/dist/typeflow/dist/typeflow-caret.mjs.map +1 -0
  57. package/dist/typeflow/dist/typeflow-debug.cjs +109 -0
  58. package/dist/typeflow/dist/typeflow-debug.cjs.map +1 -0
  59. package/dist/typeflow/dist/typeflow-debug.esm.js +109 -0
  60. package/dist/typeflow/dist/typeflow-debug.esm.js.map +1 -0
  61. package/dist/typeflow/dist/typeflow-debug.esm.min.js +2 -0
  62. package/dist/typeflow/dist/typeflow-debug.esm.min.js.map +1 -0
  63. package/dist/typeflow/dist/typeflow-debug.js +109 -0
  64. package/dist/typeflow/dist/typeflow-debug.js.map +1 -0
  65. package/dist/typeflow/dist/typeflow-debug.min.js +2 -0
  66. package/dist/typeflow/dist/typeflow-debug.min.js.map +1 -0
  67. package/dist/typeflow/dist/typeflow-debug.mjs +109 -0
  68. package/dist/typeflow/dist/typeflow-debug.mjs.map +1 -0
  69. package/dist/typeflow/dist/typeflow-extchars.cjs +66 -0
  70. package/dist/typeflow/dist/typeflow-extchars.cjs.map +1 -0
  71. package/dist/typeflow/dist/typeflow-extchars.esm.js +66 -0
  72. package/dist/typeflow/dist/typeflow-extchars.esm.js.map +1 -0
  73. package/dist/typeflow/dist/typeflow-extchars.esm.min.js +2 -0
  74. package/dist/typeflow/dist/typeflow-extchars.esm.min.js.map +1 -0
  75. package/dist/typeflow/dist/typeflow-extchars.js +66 -0
  76. package/dist/typeflow/dist/typeflow-extchars.js.map +1 -0
  77. package/dist/typeflow/dist/typeflow-extchars.min.js +2 -0
  78. package/dist/typeflow/dist/typeflow-extchars.min.js.map +1 -0
  79. package/dist/typeflow/dist/typeflow-extchars.mjs +66 -0
  80. package/dist/typeflow/dist/typeflow-extchars.mjs.map +1 -0
  81. package/dist/typeflow/dist/typeflow-keystroke.cjs +47 -0
  82. package/dist/typeflow/dist/typeflow-keystroke.cjs.map +1 -0
  83. package/dist/typeflow/dist/typeflow-keystroke.esm.js +47 -0
  84. package/dist/typeflow/dist/typeflow-keystroke.esm.js.map +1 -0
  85. package/dist/typeflow/dist/typeflow-keystroke.esm.min.js +2 -0
  86. package/dist/typeflow/dist/typeflow-keystroke.esm.min.js.map +1 -0
  87. package/dist/typeflow/dist/typeflow-keystroke.js +47 -0
  88. package/dist/typeflow/dist/typeflow-keystroke.js.map +1 -0
  89. package/dist/typeflow/dist/typeflow-keystroke.min.js +2 -0
  90. package/dist/typeflow/dist/typeflow-keystroke.min.js.map +1 -0
  91. package/dist/typeflow/dist/typeflow-keystroke.mjs +47 -0
  92. package/dist/typeflow/dist/typeflow-keystroke.mjs.map +1 -0
  93. package/dist/typeflow/dist/typeflow-metrics.cjs +76 -0
  94. package/dist/typeflow/dist/typeflow-metrics.cjs.map +1 -0
  95. package/dist/typeflow/dist/typeflow-metrics.esm.js +76 -0
  96. package/dist/typeflow/dist/typeflow-metrics.esm.js.map +1 -0
  97. package/dist/typeflow/dist/typeflow-metrics.esm.min.js +2 -0
  98. package/dist/typeflow/dist/typeflow-metrics.esm.min.js.map +1 -0
  99. package/dist/typeflow/dist/typeflow-metrics.js +76 -0
  100. package/dist/typeflow/dist/typeflow-metrics.js.map +1 -0
  101. package/dist/typeflow/dist/typeflow-metrics.min.js +2 -0
  102. package/dist/typeflow/dist/typeflow-metrics.min.js.map +1 -0
  103. package/dist/typeflow/dist/typeflow-metrics.mjs +76 -0
  104. package/dist/typeflow/dist/typeflow-metrics.mjs.map +1 -0
  105. package/dist/typeflow/dist/typeflow-parallel.cjs +3 -0
  106. package/dist/typeflow/dist/typeflow-parallel.cjs.map +1 -0
  107. package/dist/typeflow/dist/typeflow-parallel.esm.js +3 -0
  108. package/dist/typeflow/dist/typeflow-parallel.esm.js.map +1 -0
  109. package/dist/typeflow/dist/typeflow-parallel.esm.min.js +2 -0
  110. package/dist/typeflow/dist/typeflow-parallel.esm.min.js.map +1 -0
  111. package/dist/typeflow/dist/typeflow-parallel.js +3 -0
  112. package/dist/typeflow/dist/typeflow-parallel.js.map +1 -0
  113. package/dist/typeflow/dist/typeflow-parallel.min.js +2 -0
  114. package/dist/typeflow/dist/typeflow-parallel.min.js.map +1 -0
  115. package/dist/typeflow/dist/typeflow-parallel.mjs +3 -0
  116. package/dist/typeflow/dist/typeflow-parallel.mjs.map +1 -0
  117. package/dist/typeflow/dist/typeflow-webaudio.cjs +81 -0
  118. package/dist/typeflow/dist/typeflow-webaudio.cjs.map +1 -0
  119. package/dist/typeflow/dist/typeflow-webaudio.esm.js +81 -0
  120. package/dist/typeflow/dist/typeflow-webaudio.esm.js.map +1 -0
  121. package/dist/typeflow/dist/typeflow-webaudio.esm.min.js +2 -0
  122. package/dist/typeflow/dist/typeflow-webaudio.esm.min.js.map +1 -0
  123. package/dist/typeflow/dist/typeflow-webaudio.js +81 -0
  124. package/dist/typeflow/dist/typeflow-webaudio.js.map +1 -0
  125. package/dist/typeflow/dist/typeflow-webaudio.min.js +2 -0
  126. package/dist/typeflow/dist/typeflow-webaudio.min.js.map +1 -0
  127. package/dist/typeflow/dist/typeflow-webaudio.mjs +81 -0
  128. package/dist/typeflow/dist/typeflow-webaudio.mjs.map +1 -0
  129. package/dist/typeflow/dist/typeflow.cjs +277 -0
  130. package/dist/typeflow/dist/typeflow.cjs.map +1 -0
  131. package/dist/typeflow/dist/typeflow.esm.js +277 -0
  132. package/dist/typeflow/dist/typeflow.esm.js.map +1 -0
  133. package/dist/typeflow/dist/typeflow.esm.min.js +2 -0
  134. package/dist/typeflow/dist/typeflow.esm.min.js.map +1 -0
  135. package/dist/typeflow/dist/typeflow.js +277 -0
  136. package/dist/typeflow/dist/typeflow.js.map +1 -0
  137. package/dist/typeflow/dist/typeflow.min.js +2 -0
  138. package/dist/typeflow/dist/typeflow.min.js.map +1 -0
  139. package/dist/typeflow/dist/typeflow.mjs +277 -0
  140. package/dist/typeflow/dist/typeflow.mjs.map +1 -0
  141. package/dist/typeflow/jsr.jsonc +27 -0
  142. package/dist/typeflow/package.json +79 -0
  143. package/dist/typeflow/src/typeflow-audio-presets.js +137 -0
  144. package/dist/typeflow/src/typeflow-caret.d.ts +65 -0
  145. package/dist/typeflow/src/typeflow-caret.js +303 -0
  146. package/dist/typeflow/src/typeflow-debug.d.ts +34 -0
  147. package/dist/typeflow/src/typeflow-debug.js +223 -0
  148. package/dist/typeflow/src/typeflow-extchars.d.ts +28 -0
  149. package/dist/typeflow/src/typeflow-extchars.js +132 -0
  150. package/dist/typeflow/src/typeflow-keystroke.d.ts +28 -0
  151. package/dist/typeflow/src/typeflow-keystroke.js +220 -0
  152. package/dist/typeflow/src/typeflow-metrics.d.ts +38 -0
  153. package/dist/typeflow/src/typeflow-metrics.js +556 -0
  154. package/dist/typeflow/src/typeflow-parallel.d.ts +36 -0
  155. package/dist/typeflow/src/typeflow-parallel.js +157 -0
  156. package/dist/typeflow/src/typeflow-webaudio.d.ts +83 -0
  157. package/dist/typeflow/src/typeflow-webaudio.js +517 -0
  158. package/dist/typeflow/src/typeflow.d.ts +328 -0
  159. package/dist/typeflow/src/typeflow.js +2119 -0
  160. package/jsr.jsonc +27 -0
  161. package/package.json +133 -0
  162. package/src/typeflow-audio-presets.js +137 -0
  163. package/src/typeflow-caret.d.ts +65 -0
  164. package/src/typeflow-caret.js +303 -0
  165. package/src/typeflow-debug.d.ts +34 -0
  166. package/src/typeflow-debug.js +223 -0
  167. package/src/typeflow-extchars.d.ts +28 -0
  168. package/src/typeflow-extchars.js +132 -0
  169. package/src/typeflow-keystroke.d.ts +28 -0
  170. package/src/typeflow-keystroke.js +220 -0
  171. package/src/typeflow-metrics.d.ts +38 -0
  172. package/src/typeflow-metrics.js +556 -0
  173. package/src/typeflow-parallel.d.ts +36 -0
  174. package/src/typeflow-parallel.js +157 -0
  175. package/src/typeflow-webaudio.d.ts +83 -0
  176. package/src/typeflow-webaudio.js +517 -0
  177. package/src/typeflow.d.ts +328 -0
  178. package/src/typeflow.js +2119 -0
@@ -0,0 +1,157 @@
1
+ /**
2
+ * EXPERIMENTAL opt-in parallel orchestration for TypeFlow.
3
+ * This module intentionally does not import core, keeping stable bundles small.
4
+ */
5
+
6
+ export const parallelStep = (steps, options) => ({ kind: 'parallel', steps, options });
7
+
8
+ export function createParallel(engine) {
9
+ if (!engine?.type || !engine?.erase)
10
+ throw new TypeError('TypeFlow parallel: a TypeFlow engine instance is required.');
11
+
12
+ const parallel = (steps, options = {}) => {
13
+ const input = Array.isArray(steps) ? steps : [];
14
+ if (input.length === 0)
15
+ return {
16
+ stop: () => {},
17
+ promise: Promise.resolve({ completed: true, text: '', results: [] }),
18
+ };
19
+
20
+ const requested = Number(options.concurrency);
21
+ const concurrency = Number.isFinite(requested)
22
+ ? Math.max(1, Math.min(input.length, Math.floor(requested)))
23
+ : input.length;
24
+ const settlement = options.settlement === 'fail-fast' ? 'fail-fast' : 'all-settled';
25
+ const activeChildren = new Set();
26
+ const cancelWaits = new Set();
27
+ const results = new Array(input.length);
28
+ let nextIndex = 0;
29
+ let interrupted = false;
30
+ let halted = false;
31
+
32
+ const stopActive = () => {
33
+ activeChildren.forEach((child) => child.stop());
34
+ cancelWaits.forEach((cancel) => cancel());
35
+ activeChildren.clear();
36
+ cancelWaits.clear();
37
+ };
38
+ const controller = {
39
+ stop: () => {
40
+ if (interrupted) return;
41
+ interrupted = true;
42
+ halted = true;
43
+ stopActive();
44
+ },
45
+ promise: null,
46
+ };
47
+ const targetFor = (step) => {
48
+ const target = step.target ?? options.target;
49
+ if (!target)
50
+ throw new Error('TypeFlow parallel: a step requires a target or default `target`.');
51
+ return target;
52
+ };
53
+ const wait = (duration) =>
54
+ new Promise((resolve) => {
55
+ let done = false;
56
+ const finish = (completed) => {
57
+ if (done) return;
58
+ done = true;
59
+ clearTimeout(id);
60
+ cancelWaits.delete(cancel);
61
+ resolve(completed);
62
+ };
63
+ const id = setTimeout(() => finish(true), Math.max(0, Number(duration) || 0));
64
+ const cancel = () => finish(false);
65
+ cancelWaits.add(cancel);
66
+ });
67
+ const visible = (step) =>
68
+ new Promise((resolve) => {
69
+ if (typeof IntersectionObserver === 'undefined') return resolve(true);
70
+ let done = false;
71
+ const observer = new IntersectionObserver(
72
+ (entries) => {
73
+ if (entries.some((entry) => entry.isIntersecting)) finish(true);
74
+ },
75
+ { threshold: step.threshold ?? 0.1 }
76
+ );
77
+ const finish = (completed) => {
78
+ if (done) return;
79
+ done = true;
80
+ observer.disconnect();
81
+ cancelWaits.delete(cancel);
82
+ resolve(completed);
83
+ };
84
+ const cancel = () => finish(false);
85
+ cancelWaits.add(cancel);
86
+ const target =
87
+ typeof targetFor(step) === 'string'
88
+ ? document.querySelector(targetFor(step))
89
+ : targetFor(step);
90
+ if (!target) throw new Error('TypeFlow parallel: visibility target not found.');
91
+ observer.observe(target);
92
+ });
93
+ const runStep = async (step) => {
94
+ if (!step || typeof step !== 'object')
95
+ throw new TypeError('TypeFlow parallel: invalid step.');
96
+ if (step.kind === 'pause') return { completed: await wait(step.duration), text: '' };
97
+ if (step.kind === 'visible') return { completed: await visible(step), text: '' };
98
+ if (step.kind === 'call') {
99
+ await step.fn();
100
+ return { completed: true, text: '' };
101
+ }
102
+ let child;
103
+ if (step.kind === 'type') child = engine.type(targetFor(step), step.text, step.config);
104
+ else if (step.kind === 'erase') child = engine.erase(targetFor(step), step.config);
105
+ else if (step.kind === 'parallel')
106
+ child = parallel(step.steps, {
107
+ ...step.options,
108
+ target: step.options?.target ?? options.target,
109
+ });
110
+ else
111
+ throw new TypeError(`TypeFlow parallel: unsupported step kind \`${String(step.kind)}\`.`);
112
+ activeChildren.add(child);
113
+ try {
114
+ return await child.promise;
115
+ } finally {
116
+ activeChildren.delete(child);
117
+ }
118
+ };
119
+ const worker = async () => {
120
+ while (!halted) {
121
+ const index = nextIndex++;
122
+ if (index >= input.length) return;
123
+ try {
124
+ const value = await runStep(input[index]);
125
+ results[index] = { status: value.completed ? 'fulfilled' : 'interrupted', value };
126
+ } catch (error) {
127
+ results[index] = { status: 'rejected', reason: error };
128
+ }
129
+ if (results[index].status !== 'fulfilled' && settlement === 'fail-fast') {
130
+ halted = true;
131
+ stopActive();
132
+ }
133
+ }
134
+ };
135
+ controller.promise = Promise.all(Array.from({ length: concurrency }, worker)).then(() => {
136
+ for (let index = 0; index < input.length; index += 1) {
137
+ results[index] ??= { status: 'interrupted', value: { completed: false, text: '' } };
138
+ }
139
+ return {
140
+ completed: !interrupted && results.every(({ status }) => status === 'fulfilled'),
141
+ text: '',
142
+ results,
143
+ };
144
+ });
145
+ return controller;
146
+ };
147
+ return parallel;
148
+ }
149
+
150
+ /** Explicitly installs the experimental methods onto caller-provided core objects. */
151
+ export function installParallel(engine, sequenceHelpers) {
152
+ const parallel = createParallel(engine);
153
+ Object.defineProperty(engine, 'parallel', { configurable: true, value: parallel });
154
+ if (sequenceHelpers)
155
+ Object.defineProperty(sequenceHelpers, 'parallel', { configurable: true, value: parallelStep });
156
+ return engine;
157
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * TypeFlow WebAudio - Procedural Audio Synthesis for Typing Interfaces.
3
+ */
4
+ export type WebAudioProfile =
5
+ | 'mechanical-blue'
6
+ | 'clicky'
7
+ | 'mechanical-red'
8
+ | 'mechanical-brown'
9
+ | 'tactile'
10
+ | 'mechanical'
11
+ | 'teletype'
12
+ | 'vintage'
13
+ | 'typewriter'
14
+ | 'cyber-synth'
15
+ | 'synth'
16
+ | 'neon'
17
+ | 'terminal-8bit'
18
+ | '8bit'
19
+ | 'beep'
20
+ | 'bubble'
21
+ | 'pop';
22
+
23
+ export interface WebAudioPlayOptions {
24
+ char?: string;
25
+ pan?: number;
26
+ pitchVariance?: number;
27
+ action?: 'type' | 'erase';
28
+ /** Suppress keystrokes when prefers-reduced-motion is active. Default: false. */
29
+ respectReducedMotion?: boolean;
30
+ }
31
+
32
+ export interface KeystrokeAudioCallback {
33
+ (): void;
34
+ /** Stops and disconnects voices created by this callback only. */
35
+ stop(): void;
36
+ }
37
+
38
+ export interface AudioPresetLayer {
39
+ oscillator: OscillatorType;
40
+ frequency: { start: number; end: number };
41
+ gain: { start: number; end: number };
42
+ duration: number;
43
+ filter: { type: BiquadFilterType; frequency: number; q: number } | null;
44
+ detune: { base: number; variance: number };
45
+ }
46
+
47
+ export interface AudioPreset {
48
+ version: 1;
49
+ actions: { type: AudioPresetLayer[]; erase: AudioPresetLayer[] };
50
+ }
51
+
52
+ export const AUDIO_PRESET_SCHEMA_VERSION: 1;
53
+ export const AUDIO_PRESETS: Readonly<Record<string, AudioPreset>>;
54
+ export const AUDIO_PRESET_ALIASES: Readonly<Record<string, string>>;
55
+ export function validateAudioPreset(config: AudioPreset): Readonly<AudioPreset>;
56
+
57
+ export class TypeFlowWebAudio {
58
+ static ctx: AudioContext | null;
59
+ static isMuted: boolean;
60
+ static volume: number;
61
+ static maxPolyphony: number;
62
+
63
+ static getContext(): AudioContext | null;
64
+ static setVolume(volume: number): void;
65
+ static mute(force?: boolean): void;
66
+ static play(profile?: WebAudioProfile | string, options?: WebAudioPlayOptions): void;
67
+ static registerAudioPreset(
68
+ name: string,
69
+ config: AudioPreset,
70
+ options?: { overwrite?: boolean }
71
+ ): string;
72
+ static removeAudioPreset(name: string): boolean;
73
+ static resetAudioPresets(): void;
74
+ static getAudioPreset(name: string): Readonly<AudioPreset> | null;
75
+ static stopVoices(voices: Set<unknown>): void;
76
+ static stopAll(): void;
77
+ static destroy(): Promise<void>;
78
+ }
79
+
80
+ export function createKeystrokeAudio(
81
+ profile?: WebAudioProfile | string,
82
+ options?: WebAudioPlayOptions
83
+ ): KeystrokeAudioCallback;