@riverflowpkg/riverflow 1.0.2 → 1.0.5

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.
@@ -1,309 +1,309 @@
1
- (function () {
2
-
3
- /* ── Styles ─────────────────────────────────────────────────── */
4
- function injectStyles() {
5
- if (document.getElementById('terminal-styles')) return;
6
- const s = document.createElement('style');
7
- s.id = 'terminal-styles';
8
- s.textContent = `
9
- .terminal {
10
- display: flex;
11
- flex-direction: column;
12
- font-family: 'Consolas', 'Fira Code', 'Menlo', monospace;
13
- font-size: 13.5px;
14
- line-height: 1.65;
15
- background: #0d0d0d;
16
- color: #e2e8f0;
17
- border: 0.5px solid #2a2a2a;
18
- border-radius: 10px;
19
- overflow: hidden;
20
- position: relative;
21
- }
22
-
23
- /* ── Header ── */
24
- .t-header {
25
- display: flex;
26
- align-items: center;
27
- gap: 8px;
28
- padding: 8px 14px;
29
- background: #161616;
30
- border-bottom: 0.5px solid #222;
31
- flex-shrink: 0;
32
- }
33
- .t-dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
34
- .t-dot-r { background: #ff5f57; }
35
- .t-dot-y { background: #febc2e; }
36
- .t-dot-g { background: #28c840; }
37
- .t-title {
38
- margin-left: 8px;
39
- font-size: 12px;
40
- color: #4a5568;
41
- letter-spacing: 0.04em;
42
- flex: 1;
43
- text-align: center;
44
- margin-right: 30px; /* optical center past the dots */
45
- }
46
-
47
- /* ── Body ── */
48
- .t-body {
49
- flex: 1;
50
- overflow-y: auto;
51
- padding: 14px 16px;
52
- min-height: 120px;
53
- }
54
-
55
- .t-body::-webkit-scrollbar { width: 4px; }
56
- .t-body::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 4px; }
57
-
58
- /* ── Lines ── */
59
- .t-line {
60
- display: flex;
61
- gap: 8px;
62
- white-space: pre-wrap;
63
- word-break: break-all;
64
- }
65
-
66
- .t-line-output { padding-left: 4px; }
67
-
68
- /* Output types */
69
- .t-info { color: #e2e8f0; }
70
- .t-success { color: #c3e88d; }
71
- .t-error { color: #f07178; }
72
- .t-warn { color: #ffcb6b; }
73
- .t-system { color: #4a5568; font-style: italic; }
74
- .t-cmd { color: #82aaff; }
75
-
76
- /* Prompt */
77
- .t-prompt { color: #c792ea; user-select: none; flex-shrink: 0; }
78
-
79
- /* ── Input row (interactive mode) ── */
80
- .t-input-row {
81
- display: flex;
82
- align-items: center;
83
- gap: 8px;
84
- padding: 0 16px 14px;
85
- flex-shrink: 0;
86
- }
87
-
88
- .t-input-prompt { color: #c792ea; user-select: none; flex-shrink: 0; }
89
-
90
- .t-input {
91
- flex: 1;
92
- background: transparent;
93
- border: none;
94
- outline: none;
95
- color: #82aaff;
96
- font-family: inherit;
97
- font-size: inherit;
98
- line-height: inherit;
99
- caret-color: #c792ea;
100
- }
101
-
102
- /* motion mode — animated caret */
103
- .terminal-motion .t-input { caret-color: transparent; }
104
- .terminal-motion .t-fake-caret {
105
- display: inline-block;
106
- width: 2px;
107
- height: 1em;
108
- background: #c792ea;
109
- border-radius: 1px;
110
- vertical-align: text-bottom;
111
- margin-left: 1px;
112
- animation: t-blink 1s steps(1) infinite;
113
- }
114
- @keyframes t-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }
115
-
116
- /* motion — new output lines fade in */
117
- .terminal-motion .t-line {
118
- animation: t-fadeIn 0.18s ease both;
119
- }
120
- @keyframes t-fadeIn { from{opacity:0;transform:translateY(4px)} to{opacity:1;transform:translateY(0)} }
121
- `;
122
- document.head.appendChild(s);
123
- }
124
-
125
- /* ── Token colours for command echo ─────────────────────────── */
126
- function colorizeCommand(text) {
127
- return text
128
- .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
129
- .replace(/^(\S+)/, '<span style="color:#c3e88d">$1</span>') /* command */
130
- .replace(/ (-{1,2}[\w-]+)/g,' <span style="color:#ffcb6b">$1</span>') /* flags */
131
- .replace(/ ("([^"]*)")/g,' <span style="color:#f78c6c">$1</span>'); /* strings */
132
- }
133
-
134
- /* ── Build terminal ──────────────────────────────────────────── */
135
- function initTerminal(el) {
136
- if (el.dataset.termInit) return;
137
- el.dataset.termInit = '1';
138
-
139
- const isInteractive = el.classList.contains('terminal-interactive');
140
- const isMotion = el.classList.contains('terminal-motion');
141
- const prompt = el.dataset.prompt || '~$';
142
- const title = el.dataset.title || 'bash';
143
-
144
- /* parse initial lines from innerHTML */
145
- const rawLines = el.innerHTML
146
- .split('\n')
147
- .map(l => l.trim())
148
- .filter(l => l.length);
149
-
150
- el.innerHTML = '';
151
-
152
- /* header */
153
- const header = document.createElement('div');
154
- header.className = 't-header';
155
- header.innerHTML = `
156
- <span class="t-dot t-dot-r"></span>
157
- <span class="t-dot t-dot-y"></span>
158
- <span class="t-dot t-dot-g"></span>
159
- <span class="t-title">${title}</span>`;
160
- el.appendChild(header);
161
-
162
- /* body */
163
- const body = document.createElement('div');
164
- body.className = 't-body';
165
- el.appendChild(body);
166
-
167
- /* ── Render a line ── */
168
- /*
169
- Line syntax for the developer:
170
- $ command args → shown with prompt + blue text
171
- > output text → plain output (info)
172
- + success message → green
173
- ! error message → red
174
- ? warn message → yellow
175
- # system / comment → muted italic
176
- (anything else) → plain info
177
- */
178
- function parseLine(raw) {
179
- const first = raw[0];
180
- const rest = raw.slice(1).trimStart();
181
- if (first === '$') return { type: 'cmd', text: rest };
182
- if (first === '>') return { type: 'info', text: rest };
183
- if (first === '+') return { type: 'success', text: rest };
184
- if (first === '!') return { type: 'error', text: rest };
185
- if (first === '?') return { type: 'warn', text: rest };
186
- if (first === '#') return { type: 'system', text: rest };
187
- return { type: 'info', text: raw };
188
- }
189
-
190
- function appendLine(raw) {
191
- const { type, text } = parseLine(raw);
192
- const row = document.createElement('div');
193
- row.className = 't-line';
194
-
195
- if (type === 'cmd') {
196
- row.innerHTML = `<span class="t-prompt">${prompt}</span><span class="t-cmd">${colorizeCommand(text)}</span>`;
197
- } else {
198
- row.className += ' t-line-output';
199
- row.innerHTML = `<span class="t-${type}">${text.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}</span>`;
200
- }
201
-
202
- body.appendChild(row);
203
- body.scrollTop = body.scrollHeight;
204
- }
205
-
206
- /* render preset lines */
207
- rawLines.forEach(l => appendLine(l));
208
-
209
- /* ── Interactive mode ── */
210
- if (isInteractive) {
211
- const inputRow = document.createElement('div');
212
- inputRow.className = 't-input-row';
213
-
214
- const inputPrompt = document.createElement('span');
215
- inputPrompt.className = 't-input-prompt';
216
- inputPrompt.textContent = prompt;
217
-
218
- const input = document.createElement('input');
219
- input.className = 't-input';
220
- input.type = 'text';
221
- input.autocomplete = 'off';
222
- input.spellcheck = false;
223
- input.setAttribute('autocorrect', 'off');
224
- input.setAttribute('autocapitalize', 'off');
225
- input.placeholder = 'type a command...';
226
-
227
- inputRow.appendChild(inputPrompt);
228
- inputRow.appendChild(input);
229
-
230
- /* fake caret for motion mode */
231
- if (isMotion) {
232
- const fakeCaret = document.createElement('span');
233
- fakeCaret.className = 't-fake-caret';
234
- inputRow.appendChild(fakeCaret);
235
- }
236
-
237
- el.appendChild(inputRow);
238
-
239
- /* command history */
240
- const history = [];
241
- let histIdx = -1;
242
-
243
- /* built-in commands */
244
- const builtins = {
245
- clear() { body.innerHTML = ''; },
246
- help() {
247
- ['+ Available commands:', '> clear — clears the terminal', '> help — shows this message'].forEach(appendLine);
248
- },
249
- };
250
-
251
- /* custom commands — developer sets window.TerminalCommands */
252
- function runCommand(cmd) {
253
- const trimmed = cmd.trim();
254
- if (!trimmed) return;
255
-
256
- /* echo the command */
257
- appendLine(`$ ${trimmed}`);
258
-
259
- history.unshift(trimmed);
260
- histIdx = -1;
261
-
262
- const [name, ...args] = trimmed.split(/\s+/);
263
-
264
- if (builtins[name]) {
265
- builtins[name](args);
266
- } else if (window.TerminalCommands && window.TerminalCommands[name]) {
267
- const result = window.TerminalCommands[name](args, appendLine);
268
- if (typeof result === 'string') appendLine(`> ${result}`);
269
- } else {
270
- appendLine(`! command not found: ${name}`);
271
- }
272
- }
273
-
274
- input.addEventListener('keydown', e => {
275
- if (e.key === 'Enter') {
276
- runCommand(input.value);
277
- input.value = '';
278
- } else if (e.key === 'ArrowUp') {
279
- e.preventDefault();
280
- histIdx = Math.min(histIdx + 1, history.length - 1);
281
- input.value = history[histIdx] || '';
282
- } else if (e.key === 'ArrowDown') {
283
- e.preventDefault();
284
- histIdx = Math.max(histIdx - 1, -1);
285
- input.value = histIdx === -1 ? '' : history[histIdx];
286
- }
287
- });
288
-
289
- /* click anywhere on terminal focuses input */
290
- el.addEventListener('click', () => input.focus());
291
- }
292
- }
293
-
294
- /* ── Boot ────────────────────────────────────────────────────── */
295
- function init() {
296
- injectStyles();
297
- document.querySelectorAll('.terminal').forEach(initTerminal);
298
- new MutationObserver(muts => muts.forEach(m =>
299
- m.addedNodes.forEach(n => {
300
- if (n.nodeType !== 1) return;
301
- if (n.classList.contains('terminal')) initTerminal(n);
302
- n.querySelectorAll?.('.terminal').forEach(initTerminal);
303
- })
304
- )).observe(document.body, { childList: true, subtree: true });
305
- }
306
-
307
- if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
308
- else init();
309
- })();
1
+ (function () {
2
+
3
+ /* ── Styles ─────────────────────────────────────────────────── */
4
+ function injectStyles() {
5
+ if (document.getElementById('terminal-styles')) return;
6
+ const s = document.createElement('style');
7
+ s.id = 'terminal-styles';
8
+ s.textContent = `
9
+ .terminal {
10
+ display: flex;
11
+ flex-direction: column;
12
+ font-family: 'Consolas', 'Fira Code', 'Menlo', monospace;
13
+ font-size: 13.5px;
14
+ line-height: 1.65;
15
+ background: #0d0d0d;
16
+ color: #e2e8f0;
17
+ border: 0.5px solid #2a2a2a;
18
+ border-radius: 10px;
19
+ overflow: hidden;
20
+ position: relative;
21
+ }
22
+
23
+ /* ── Header ── */
24
+ .t-header {
25
+ display: flex;
26
+ align-items: center;
27
+ gap: 8px;
28
+ padding: 8px 14px;
29
+ background: #161616;
30
+ border-bottom: 0.5px solid #222;
31
+ flex-shrink: 0;
32
+ }
33
+ .t-dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
34
+ .t-dot-r { background: #ff5f57; }
35
+ .t-dot-y { background: #febc2e; }
36
+ .t-dot-g { background: #28c840; }
37
+ .t-title {
38
+ margin-left: 8px;
39
+ font-size: 12px;
40
+ color: #4a5568;
41
+ letter-spacing: 0.04em;
42
+ flex: 1;
43
+ text-align: center;
44
+ margin-right: 30px; /* optical center past the dots */
45
+ }
46
+
47
+ /* ── Body ── */
48
+ .t-body {
49
+ flex: 1;
50
+ overflow-y: auto;
51
+ padding: 14px 16px;
52
+ min-height: 120px;
53
+ }
54
+
55
+ .t-body::-webkit-scrollbar { width: 4px; }
56
+ .t-body::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 4px; }
57
+
58
+ /* ── Lines ── */
59
+ .t-line {
60
+ display: flex;
61
+ gap: 8px;
62
+ white-space: pre-wrap;
63
+ word-break: break-all;
64
+ }
65
+
66
+ .t-line-output { padding-left: 4px; }
67
+
68
+ /* Output types */
69
+ .t-info { color: #e2e8f0; }
70
+ .t-success { color: #c3e88d; }
71
+ .t-error { color: #f07178; }
72
+ .t-warn { color: #ffcb6b; }
73
+ .t-system { color: #4a5568; font-style: italic; }
74
+ .t-cmd { color: #82aaff; }
75
+
76
+ /* Prompt */
77
+ .t-prompt { color: #c792ea; user-select: none; flex-shrink: 0; }
78
+
79
+ /* ── Input row (interactive mode) ── */
80
+ .t-input-row {
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 8px;
84
+ padding: 0 16px 14px;
85
+ flex-shrink: 0;
86
+ }
87
+
88
+ .t-input-prompt { color: #c792ea; user-select: none; flex-shrink: 0; }
89
+
90
+ .t-input {
91
+ flex: 1;
92
+ background: transparent;
93
+ border: none;
94
+ outline: none;
95
+ color: #82aaff;
96
+ font-family: inherit;
97
+ font-size: inherit;
98
+ line-height: inherit;
99
+ caret-color: #c792ea;
100
+ }
101
+
102
+ /* motion mode — animated caret */
103
+ .terminal-motion .t-input { caret-color: transparent; }
104
+ .terminal-motion .t-fake-caret {
105
+ display: inline-block;
106
+ width: 2px;
107
+ height: 1em;
108
+ background: #c792ea;
109
+ border-radius: 1px;
110
+ vertical-align: text-bottom;
111
+ margin-left: 1px;
112
+ animation: t-blink 1s steps(1) infinite;
113
+ }
114
+ @keyframes t-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }
115
+
116
+ /* motion — new output lines fade in */
117
+ .terminal-motion .t-line {
118
+ animation: t-fadeIn 0.18s ease both;
119
+ }
120
+ @keyframes t-fadeIn { from{opacity:0;transform:translateY(4px)} to{opacity:1;transform:translateY(0)} }
121
+ `;
122
+ document.head.appendChild(s);
123
+ }
124
+
125
+ /* ── Token colours for command echo ─────────────────────────── */
126
+ function colorizeCommand(text) {
127
+ return text
128
+ .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
129
+ .replace(/^(\S+)/, '<span style="color:#c3e88d">$1</span>') /* command */
130
+ .replace(/ (-{1,2}[\w-]+)/g,' <span style="color:#ffcb6b">$1</span>') /* flags */
131
+ .replace(/ ("([^"]*)")/g,' <span style="color:#f78c6c">$1</span>'); /* strings */
132
+ }
133
+
134
+ /* ── Build terminal ──────────────────────────────────────────── */
135
+ function initTerminal(el) {
136
+ if (el.dataset.termInit) return;
137
+ el.dataset.termInit = '1';
138
+
139
+ const isInteractive = el.classList.contains('terminal-interactive');
140
+ const isMotion = el.classList.contains('terminal-motion');
141
+ const prompt = el.dataset.prompt || '~$';
142
+ const title = el.dataset.title || 'bash';
143
+
144
+ /* parse initial lines from innerHTML */
145
+ const rawLines = el.innerHTML
146
+ .split('\n')
147
+ .map(l => l.trim())
148
+ .filter(l => l.length);
149
+
150
+ el.innerHTML = '';
151
+
152
+ /* header */
153
+ const header = document.createElement('div');
154
+ header.className = 't-header';
155
+ header.innerHTML = `
156
+ <span class="t-dot t-dot-r"></span>
157
+ <span class="t-dot t-dot-y"></span>
158
+ <span class="t-dot t-dot-g"></span>
159
+ <span class="t-title">${title}</span>`;
160
+ el.appendChild(header);
161
+
162
+ /* body */
163
+ const body = document.createElement('div');
164
+ body.className = 't-body';
165
+ el.appendChild(body);
166
+
167
+ /* ── Render a line ── */
168
+ /*
169
+ Line syntax for the developer:
170
+ $ command args → shown with prompt + blue text
171
+ > output text → plain output (info)
172
+ + success message → green
173
+ ! error message → red
174
+ ? warn message → yellow
175
+ # system / comment → muted italic
176
+ (anything else) → plain info
177
+ */
178
+ function parseLine(raw) {
179
+ const first = raw[0];
180
+ const rest = raw.slice(1).trimStart();
181
+ if (first === '$') return { type: 'cmd', text: rest };
182
+ if (first === '>') return { type: 'info', text: rest };
183
+ if (first === '+') return { type: 'success', text: rest };
184
+ if (first === '!') return { type: 'error', text: rest };
185
+ if (first === '?') return { type: 'warn', text: rest };
186
+ if (first === '#') return { type: 'system', text: rest };
187
+ return { type: 'info', text: raw };
188
+ }
189
+
190
+ function appendLine(raw) {
191
+ const { type, text } = parseLine(raw);
192
+ const row = document.createElement('div');
193
+ row.className = 't-line';
194
+
195
+ if (type === 'cmd') {
196
+ row.innerHTML = `<span class="t-prompt">${prompt}</span><span class="t-cmd">${colorizeCommand(text)}</span>`;
197
+ } else {
198
+ row.className += ' t-line-output';
199
+ row.innerHTML = `<span class="t-${type}">${text.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}</span>`;
200
+ }
201
+
202
+ body.appendChild(row);
203
+ body.scrollTop = body.scrollHeight;
204
+ }
205
+
206
+ /* render preset lines */
207
+ rawLines.forEach(l => appendLine(l));
208
+
209
+ /* ── Interactive mode ── */
210
+ if (isInteractive) {
211
+ const inputRow = document.createElement('div');
212
+ inputRow.className = 't-input-row';
213
+
214
+ const inputPrompt = document.createElement('span');
215
+ inputPrompt.className = 't-input-prompt';
216
+ inputPrompt.textContent = prompt;
217
+
218
+ const input = document.createElement('input');
219
+ input.className = 't-input';
220
+ input.type = 'text';
221
+ input.autocomplete = 'off';
222
+ input.spellcheck = false;
223
+ input.setAttribute('autocorrect', 'off');
224
+ input.setAttribute('autocapitalize', 'off');
225
+ input.placeholder = 'type a command...';
226
+
227
+ inputRow.appendChild(inputPrompt);
228
+ inputRow.appendChild(input);
229
+
230
+ /* fake caret for motion mode */
231
+ if (isMotion) {
232
+ const fakeCaret = document.createElement('span');
233
+ fakeCaret.className = 't-fake-caret';
234
+ inputRow.appendChild(fakeCaret);
235
+ }
236
+
237
+ el.appendChild(inputRow);
238
+
239
+ /* command history */
240
+ const history = [];
241
+ let histIdx = -1;
242
+
243
+ /* built-in commands */
244
+ const builtins = {
245
+ clear() { body.innerHTML = ''; },
246
+ help() {
247
+ ['+ Available commands:', '> clear — clears the terminal', '> help — shows this message'].forEach(appendLine);
248
+ },
249
+ };
250
+
251
+ /* custom commands — developer sets window.TerminalCommands */
252
+ function runCommand(cmd) {
253
+ const trimmed = cmd.trim();
254
+ if (!trimmed) return;
255
+
256
+ /* echo the command */
257
+ appendLine(`$ ${trimmed}`);
258
+
259
+ history.unshift(trimmed);
260
+ histIdx = -1;
261
+
262
+ const [name, ...args] = trimmed.split(/\s+/);
263
+
264
+ if (builtins[name]) {
265
+ builtins[name](args);
266
+ } else if (window.TerminalCommands && window.TerminalCommands[name]) {
267
+ const result = window.TerminalCommands[name](args, appendLine);
268
+ if (typeof result === 'string') appendLine(`> ${result}`);
269
+ } else {
270
+ appendLine(`! command not found: ${name}`);
271
+ }
272
+ }
273
+
274
+ input.addEventListener('keydown', e => {
275
+ if (e.key === 'Enter') {
276
+ runCommand(input.value);
277
+ input.value = '';
278
+ } else if (e.key === 'ArrowUp') {
279
+ e.preventDefault();
280
+ histIdx = Math.min(histIdx + 1, history.length - 1);
281
+ input.value = history[histIdx] || '';
282
+ } else if (e.key === 'ArrowDown') {
283
+ e.preventDefault();
284
+ histIdx = Math.max(histIdx - 1, -1);
285
+ input.value = histIdx === -1 ? '' : history[histIdx];
286
+ }
287
+ });
288
+
289
+ /* click anywhere on terminal focuses input */
290
+ el.addEventListener('click', () => input.focus());
291
+ }
292
+ }
293
+
294
+ /* ── Boot ────────────────────────────────────────────────────── */
295
+ function init() {
296
+ injectStyles();
297
+ document.querySelectorAll('.terminal').forEach(initTerminal);
298
+ new MutationObserver(muts => muts.forEach(m =>
299
+ m.addedNodes.forEach(n => {
300
+ if (n.nodeType !== 1) return;
301
+ if (n.classList.contains('terminal')) initTerminal(n);
302
+ n.querySelectorAll?.('.terminal').forEach(initTerminal);
303
+ })
304
+ )).observe(document.body, { childList: true, subtree: true });
305
+ }
306
+
307
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
308
+ else init();
309
+ })();