Spaces:
Sleeping
Sleeping
| import { BlockDefinition } from '../../types/blocks'; | |
| export const WEB_BLOCKS: BlockDefinition[] = [ | |
| // ============================================================ | |
| // β‘ EVENTS β "when something happens, do something" | |
| // ============================================================ | |
| { | |
| id: 'js_event_listener', type: 'js_events', label: 'when element', category: 'events', | |
| description: 'When you click an element on the page, run the code inside', | |
| framework: 'web', shape: 'hat', color: '#FFD500', icon: 'β‘', | |
| inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'selector', label: 'element', type: 'element', default: '#myButton' }, | |
| { id: 'event', label: 'event type', type: 'select', default: 'click', options: [ | |
| { label: 'clicked', value: 'click' }, { label: 'double click', value: 'dblclick' }, | |
| { label: 'hovered', value: 'mouseenter' }, { label: 'mouse leave', value: 'mouseleave' }, | |
| { label: 'key press', value: 'keydown' }, { label: 'key release', value: 'keyup' }, | |
| { label: 'change', value: 'change' }, { label: 'type', value: 'input' }, | |
| { label: 'form submit', value: 'submit' }, { label: 'focus', value: 'focus' }, | |
| { label: 'blur', value: 'blur' }, { label: 'scroll', value: 'scroll' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => | |
| `document.querySelector('${cfg.selector || '#myButton'}').addEventListener('${cfg.event || 'click'}', () => {\n${inputs.handler || ''}\n});`, | |
| }, | |
| { | |
| id: 'js_window_event', type: 'js_events', label: 'when', category: 'events', | |
| description: 'Run code when the selected event occurs', | |
| framework: 'web', shape: 'hat', color: '#FFD500', icon: 'π', | |
| inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'event', label: 'when', type: 'select', default: 'DOMContentLoaded', options: [ | |
| { label: 'DOM ready', value: 'DOMContentLoaded' }, | |
| { label: 'page fully loaded', value: 'load' }, | |
| { label: 'window resized', value: 'resize' }, | |
| { label: 'page scrolled', value: 'scroll' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => | |
| `window.addEventListener('${cfg.event || 'DOMContentLoaded'}', () => {\n${inputs.handler || ''}\n});`, | |
| }, | |
| { | |
| id: 'js_keyboard_event', type: 'js_events', label: 'when key', category: 'events', | |
| description: 'Run code when a keyboard action happens', | |
| framework: 'web', shape: 'hat', color: '#FFD500', icon: 'β¨', | |
| inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'key', label: 'key', type: 'text', default: 'Enter', placeholder: 'Enter, Space, a, etc.' }, | |
| { id: 'eventType', label: 'action', type: 'select', default: 'keydown', options: [ | |
| { label: 'pressed down', value: 'keydown' }, { label: 'released', value: 'keyup' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => | |
| `document.addEventListener('${cfg.eventType || 'keydown'}', (e) => {\n if (e.key === '${cfg.key || 'Enter'}') {\n${inputs.handler || ''}\n }\n});`, | |
| }, | |
| { | |
| id: 'js_mouse_event', type: 'js_events', label: 'when mouse', category: 'events', | |
| description: 'Run code when the mouse is clicked anywhere on the page', | |
| framework: 'web', shape: 'hat', color: '#FFD500', icon: 'π±', | |
| inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'button', label: 'button clicked', type: 'select', default: '0', options: [ | |
| { label: 'left button', value: '0' }, { label: 'middle button', value: '1' }, { label: 'right button', value: '2' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => | |
| `document.addEventListener('click', (e) => {\n if (e.button === ${cfg.button || 0}) {\n${inputs.handler || ''}\n }\n});`, | |
| }, | |
| { | |
| id: 'js_form_submit', type: 'js_events', label: 'when form submitted', category: 'events', | |
| description: 'Run code when a form is submitted', | |
| framework: 'web', shape: 'hat', color: '#FFD500', icon: 'π', | |
| inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'selector', label: 'form', type: 'element', default: '#myForm' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `document.querySelector('${cfg.selector || '#myForm'}').addEventListener('submit', (e) => {\n e.preventDefault();\n${inputs.handler || ''}\n});`, | |
| }, | |
| { | |
| id: 'js_input_change', type: 'js_events', label: 'when input changes', category: 'events', | |
| description: 'Run code when a text input field changes', | |
| framework: 'web', shape: 'hat', color: '#FFD500', icon: 'β', | |
| inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'selector', label: 'input', type: 'element', default: '#myInput' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `document.querySelector('${cfg.selector || '#myInput'}').addEventListener('input', () => {\n${inputs.handler || ''}\n});`, | |
| }, | |
| { | |
| id: 'js_timer_timeout', type: 'js_events', label: 'wait then run', category: 'events', | |
| description: 'Wait some seconds then run code once', | |
| framework: 'web', shape: 'hat', color: '#FFD500', icon: 'β°', | |
| inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'seconds', label: 'seconds', type: 'number', default: 1 }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `setTimeout(() => {\n${inputs.handler || ''}\n}, ${(cfg.seconds ?? 1) * 1000});`, | |
| }, | |
| { | |
| id: 'js_timer_interval', type: 'js_events', label: 'every N seconds', category: 'events', | |
| description: 'Run code over and over, every N seconds', | |
| framework: 'web', shape: 'hat', color: '#FFD500', icon: 'π', | |
| inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'seconds', label: 'seconds', type: 'number', default: 1 }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `setInterval(() => {\n${inputs.handler || ''}\n}, ${(cfg.seconds ?? 1) * 1000});`, | |
| }, | |
| // ============================================================ | |
| // π BROWSER β "navigate, reload, open tabs" | |
| // ============================================================ | |
| { | |
| id: 'js_open_tab', type: 'js_browser', label: 'open URL in new tab', category: 'browser', | |
| description: 'Open a website in a new browser tab', | |
| framework: 'web', shape: 'stack', color: '#FF7043', icon: 'π', | |
| inputs: [], outputs: [], config: [ | |
| { id: 'url', label: 'URL', type: 'text', default: 'https://example.com' }, | |
| ], | |
| compile: (cfg) => `window.open('${cfg.url || 'https://example.com'}', '_blank');`, | |
| }, | |
| { | |
| id: 'js_reload', type: 'js_browser', label: 'reload page', category: 'browser', | |
| description: 'Reload the current page', | |
| framework: 'web', shape: 'stack', color: '#FF7043', icon: 'π', | |
| inputs: [], outputs: [], config: [], | |
| compile: () => 'location.reload();', | |
| }, | |
| { | |
| id: 'js_go_back', type: 'js_browser', label: 'go back', category: 'browser', | |
| description: 'Go to the previous page', | |
| framework: 'web', shape: 'stack', color: '#FF7043', icon: 'β¬ ', | |
| inputs: [], outputs: [], config: [], | |
| compile: () => 'history.back();', | |
| }, | |
| { | |
| id: 'js_go_forward', type: 'js_browser', label: 'go forward', category: 'browser', | |
| description: 'Go to the next page (if you went back)', | |
| framework: 'web', shape: 'stack', color: '#FF7043', icon: 'β‘', | |
| inputs: [], outputs: [], config: [], | |
| compile: () => 'history.forward();', | |
| }, | |
| { | |
| id: 'js_set_url', type: 'js_browser', label: 'go to URL', category: 'browser', | |
| description: 'Navigate to a different page', | |
| framework: 'web', shape: 'stack', color: '#FF7043', icon: 'π', | |
| inputs: [], outputs: [], config: [ | |
| { id: 'url', label: 'URL', type: 'text', default: 'https://example.com' }, | |
| ], | |
| compile: (cfg) => `window.location.href = '${cfg.url || 'https://example.com'}';`, | |
| }, | |
| // ============================================================ | |
| // π WEBSOCKET β "real-time connections" | |
| // ============================================================ | |
| { | |
| id: 'js_websocket_connect', type: 'js_websocket', label: 'connect to WebSocket', category: 'websocket', | |
| description: 'Connect to a WebSocket server for real-time messages', | |
| framework: 'web', shape: 'stack', color: '#22d3ee', icon: 'π', | |
| inputs: [{ id: 'onMessage', label: 'when message arrives', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'url', label: 'server URL', type: 'text', default: 'ws://localhost:8080' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `const ws = new WebSocket('${cfg.url || 'ws://localhost:8080'}');\nws.onmessage = (event) => {\n const data = JSON.parse(event.data);\n${inputs.onMessage || ''}\n};`, | |
| }, | |
| { | |
| id: 'js_websocket_send', type: 'js_websocket', label: 'send via WebSocket', category: 'websocket', | |
| description: 'Send a message through a WebSocket connection', | |
| framework: 'web', shape: 'stack', color: '#22d3ee', icon: 'π€', | |
| inputs: [], outputs: [], config: [ | |
| { id: 'data', label: 'data to send', type: 'text', default: '{ "message": "hello" }' }, | |
| ], | |
| compile: (cfg) => `ws.send(JSON.stringify(${cfg.data || '{}'}));`, | |
| }, | |
| { | |
| id: 'js_websocket_close', type: 'js_websocket', label: 'close WebSocket', category: 'websocket', | |
| description: 'Close a WebSocket connection', | |
| framework: 'web', shape: 'stack', color: '#22d3ee', icon: 'π', | |
| inputs: [], outputs: [], config: [], | |
| compile: () => 'ws.close();', | |
| }, | |
| // ============================================================ | |
| // π§ VARIABLES β "remember a value" | |
| // ============================================================ | |
| { | |
| id: 'js_var', type: 'js_variables', label: 'make variable name', category: 'variables', | |
| description: 'Create a new variable that remembers a value. Pick a name and give it a starting value.', | |
| framework: 'web', shape: 'stack', color: '#FF8C1A', icon: 'π§', | |
| inputs: [{ id: 'value', label: '=', type: 'any', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'name', label: 'name', type: 'text', default: 'myVar' }, | |
| { id: 'varType', label: 'type', type: 'select', default: 'any', options: [ | |
| { label: 'Any', value: 'any' }, { label: 'Text', value: 'string' }, | |
| { label: 'Number', value: 'number' }, { label: 'True/False', value: 'boolean' }, | |
| { label: 'List', value: 'array' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => { | |
| const defVal = inputs.value || (cfg.varType === 'number' ? '0' : cfg.varType === 'boolean' ? 'false' : cfg.varType === 'array' ? '[]' : cfg.varType === 'string' ? "''" : 'undefined'); | |
| return `let ${cfg.name || 'myVar'} = ${defVal};`; | |
| }, | |
| }, | |
| { | |
| id: 'js_set_var', type: 'js_variables', label: 'set variable = value', category: 'variables', | |
| description: 'Change what a variable remembers', | |
| framework: 'web', shape: 'stack', color: '#FF8C1A', icon: 'β', | |
| inputs: [{ id: 'value', label: '=', type: 'any', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'name', label: 'variable', type: 'variable', default: 'myVar' }, | |
| ], | |
| compile: (cfg, inputs) => `${cfg.name || 'myVar'} = ${inputs.value || 'undefined'};`, | |
| }, | |
| { | |
| id: 'js_var_get', type: 'js_variables', label: 'get variable', category: 'variables', | |
| description: 'Get the value a variable remembers', | |
| framework: 'web', shape: 'reporter', color: '#FF8C1A', icon: 'π§', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'any', position: 'right' }], | |
| config: [ | |
| { id: 'name', label: 'variable', type: 'variable', default: 'myVar' }, | |
| ], | |
| compile: (cfg) => `${cfg.name || 'myVar'}`, | |
| }, | |
| { | |
| id: 'js_change_var', type: 'js_variables', label: 'change variable by N', category: 'variables', | |
| description: 'Add a number to a variable', | |
| framework: 'web', shape: 'stack', color: '#FF8C1A', icon: 'β', | |
| inputs: [], outputs: [], config: [ | |
| { id: 'name', label: 'variable', type: 'variable', default: 'myVar' }, | |
| { id: 'amount', label: 'by', type: 'number', default: 1 }, | |
| ], | |
| compile: (cfg) => `${cfg.name || 'myVar'} += ${cfg.amount ?? 1};`, | |
| }, | |
| { | |
| id: 'js_get_var', type: 'js_variables', label: 'variable value', category: 'variables', | |
| description: 'Get the value a variable remembers', | |
| framework: 'web', shape: 'reporter', color: '#FF8C1A', icon: 'π§', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'any', position: 'right' }], | |
| config: [ | |
| { id: 'name', label: 'variable', type: 'variable', default: 'myVar' }, | |
| ], | |
| compile: (cfg) => cfg.name || 'myVar', | |
| }, | |
| { | |
| id: 'js_const_string', type: 'js_variables', label: 'text hello', category: 'variables', | |
| description: 'A piece of text like "hello" or "hi there"', | |
| framework: 'web', shape: 'reporter', color: '#FF8C1A', icon: 'π', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'string', position: 'right' }], | |
| config: [ | |
| { id: 'value', label: 'text', type: 'text', default: 'hello' }, | |
| ], | |
| compile: (cfg) => JSON.stringify(cfg.value || ''), | |
| }, | |
| { | |
| id: 'js_const_number', type: 'js_variables', label: 'number 0', category: 'variables', | |
| description: 'A number like 5 or 100', | |
| framework: 'web', shape: 'reporter', color: '#FF8C1A', icon: '#', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'number', position: 'right' }], | |
| config: [ | |
| { id: 'value', label: 'number', type: 'number', default: 0 }, | |
| ], | |
| compile: (cfg) => String(cfg.value ?? 0), | |
| }, | |
| { | |
| id: 'js_const_boolean', type: 'js_variables', label: 'true false', category: 'variables', | |
| description: 'A true/false (yes/no) value', | |
| framework: 'web', shape: 'boolean', color: '#FF8C1A', icon: 'β', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'boolean', position: 'right' }], | |
| config: [ | |
| { id: 'value', label: 'value', type: 'select', default: 'true', options: [ | |
| { label: 'true', value: 'true' }, { label: 'false', value: 'false' }, | |
| ]}, | |
| ], | |
| compile: (cfg) => cfg.value || 'false', | |
| }, | |
| { | |
| id: 'js_null', type: 'js_variables', label: 'null', category: 'variables', | |
| description: 'An empty value that means nothing', | |
| framework: 'web', shape: 'reporter', color: '#FF8C1A', icon: 'β ', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'any', position: 'right' }], | |
| config: [], | |
| compile: () => 'null', | |
| }, | |
| // ============================================================ | |
| // β LOGIC β "make decisions" | |
| // ============================================================ | |
| { | |
| id: 'js_if', type: 'js_logic', label: 'if condition then else run', category: 'logic', | |
| description: 'If the condition is true, run the first code. Otherwise run the second.', | |
| framework: 'web', shape: 'c-block', color: '#4A97FF', icon: 'β', | |
| inputs: [ | |
| { id: 'condition', label: 'if this is true', type: 'boolean', position: 'left', shape: 'diamond' }, | |
| { id: 'bodyThen', label: 'run this', type: 'code', position: 'bottom' }, | |
| { id: 'bodyElse', label: 'otherwise run this', type: 'code', position: 'bottom' }, | |
| ], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `if (${inputs.condition || 'true'}) {\n${inputs.bodyThen || ''}\n} else {\n${inputs.bodyElse || ''}\n}`, | |
| }, | |
| { | |
| id: 'js_if_then', type: 'js_logic', label: 'if condition then run', category: 'logic', | |
| description: 'If the condition is true, run some code', | |
| framework: 'web', shape: 'c-block', color: '#4A97FF', icon: 'β', | |
| inputs: [ | |
| { id: 'condition', label: 'if this is true', type: 'boolean', position: 'left', shape: 'diamond' }, | |
| { id: 'body', label: 'run this', type: 'code', position: 'bottom' }, | |
| ], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `if (${inputs.condition || 'true'}) {\n${inputs.body || ''}\n}`, | |
| }, | |
| { | |
| id: 'js_and', type: 'js_logic', label: 'and', category: 'logic', | |
| description: 'True only if both sides are true', | |
| framework: 'web', shape: 'boolean', color: '#4A97FF', icon: 'β§', | |
| inputs: [ | |
| { id: 'a', label: '', type: 'boolean', position: 'left', shape: 'diamond' }, | |
| { id: 'b', label: '', type: 'boolean', position: 'left', shape: 'diamond' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `(${inputs.a || 'true'} && ${inputs.b || 'true'})`, | |
| }, | |
| { | |
| id: 'js_or', type: 'js_logic', label: 'or', category: 'logic', | |
| description: 'True if either side is true', | |
| framework: 'web', shape: 'boolean', color: '#4A97FF', icon: 'β¨', | |
| inputs: [ | |
| { id: 'a', label: '', type: 'boolean', position: 'left', shape: 'diamond' }, | |
| { id: 'b', label: '', type: 'boolean', position: 'left', shape: 'diamond' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `(${inputs.a || 'true'} || ${inputs.b || 'true'})`, | |
| }, | |
| { | |
| id: 'js_not', type: 'js_logic', label: 'not', category: 'logic', | |
| description: 'Flip true to false, or false to true', | |
| framework: 'web', shape: 'boolean', color: '#4A97FF', icon: 'Β¬', | |
| inputs: [{ id: 'value', label: '', type: 'boolean', position: 'left', shape: 'diamond' }], | |
| outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `!(${inputs.value || 'true'})`, | |
| }, | |
| { | |
| id: 'js_comparison', type: 'js_logic', label: 'compare', category: 'logic', | |
| description: 'Compare two values (equal, not equal, bigger, smaller)', | |
| framework: 'web', shape: 'boolean', color: '#4A97FF', icon: 'β', | |
| inputs: [ | |
| { id: 'a', label: '', type: 'any', position: 'left' }, | |
| { id: 'b', label: '', type: 'any', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [ | |
| { id: 'operator', label: 'compare', type: 'select', default: '===', options: [ | |
| { label: '=', value: '===' }, { label: 'β ', value: '!==' }, | |
| { label: '>', value: '>' }, { label: '<', value: '<' }, | |
| { label: 'β₯', value: '>=' }, { label: 'β€', value: '<=' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => | |
| `(${inputs.a || 'a'} ${cfg.operator || '==='} ${inputs.b || 'b'})`, | |
| }, | |
| { | |
| id: 'js_is_null', type: 'js_logic', label: 'is null?', category: 'logic', | |
| description: 'Check if a value is null (nothing)', | |
| framework: 'web', shape: 'boolean', color: '#4A97FF', icon: 'β ', | |
| inputs: [{ id: 'value', label: '', type: 'any', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `(${inputs.value || 'null'} === null)`, | |
| }, | |
| { | |
| id: 'js_ternary', type: 'js_logic', label: 'if true use A else use B', category: 'logic', | |
| description: 'Pick one of two values based on a condition', | |
| framework: 'web', shape: 'reporter', color: '#4A97FF', icon: 'β', | |
| inputs: [ | |
| { id: 'condition', label: 'if', type: 'boolean', position: 'left', shape: 'diamond' }, | |
| { id: 'a', label: 'then use', type: 'any', position: 'left' }, | |
| { id: 'b', label: 'else use', type: 'any', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => | |
| `(${inputs.condition || 'true'} ? ${inputs.a || 'null'} : ${inputs.b || 'null'})`, | |
| }, | |
| // ============================================================ | |
| // β» LOOPS β "do something many times" | |
| // ============================================================ | |
| { | |
| id: 'js_for', type: 'js_loops', label: 'repeat N times', category: 'loops', | |
| description: 'Run the code inside a number of times', | |
| framework: 'web', shape: 'c-block', color: '#4CAF50', icon: 'β»', | |
| inputs: [{ id: 'body', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'times', label: 'times', type: 'number', default: 10 }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `for (let i = 0; i < ${cfg.times ?? 10}; i++) {\n${inputs.body || ''}\n}`, | |
| }, | |
| { | |
| id: 'js_while', type: 'js_loops', label: 'repeat while true', category: 'loops', | |
| description: 'Keep running the code as long as the condition is true', | |
| framework: 'web', shape: 'c-block', color: '#4CAF50', icon: 'β»', | |
| inputs: [ | |
| { id: 'condition', label: 'while this is true', type: 'boolean', position: 'left', shape: 'diamond' }, | |
| { id: 'body', label: 'run', type: 'code', position: 'bottom' }, | |
| ], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `while (${inputs.condition || 'true'}) {\n${inputs.body || ''}\n}`, | |
| }, | |
| { | |
| id: 'js_for_of', type: 'js_loops', label: 'for each item in array', category: 'loops', | |
| description: 'Run code for each item in a list', | |
| framework: 'web', shape: 'c-block', color: '#4CAF50', icon: 'β»', | |
| inputs: [{ id: 'body', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'variable', label: 'item name', type: 'text', default: 'item' }, | |
| { id: 'array', label: 'array name', type: 'text', default: 'myArray' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `for (const ${cfg.variable || 'item'} of ${cfg.array || 'myArray'}) {\n${inputs.body || ''}\n}`, | |
| }, | |
| { | |
| id: 'js_break', type: 'js_loops', label: 'stop loop now', category: 'loops', | |
| description: 'Exit the loop early', | |
| framework: 'web', shape: 'cap', color: '#4CAF50', icon: 'β ', | |
| inputs: [], outputs: [], config: [], | |
| compile: () => 'break;', | |
| }, | |
| { | |
| id: 'js_continue', type: 'js_loops', label: 'skip to next loop', category: 'loops', | |
| description: 'Skip the rest of this loop and go to the next one', | |
| framework: 'web', shape: 'cap', color: '#4CAF50', icon: 'β', | |
| inputs: [], outputs: [], config: [], | |
| compile: () => 'continue;', | |
| }, | |
| // ============================================================ | |
| // β MATH β "do math" | |
| // ============================================================ | |
| { | |
| id: 'js_math_op', type: 'js_math', label: 'a + b', category: 'math', | |
| description: 'Add, subtract, multiply, or divide two numbers', | |
| framework: 'web', shape: 'reporter', color: '#00BCD4', icon: '+', | |
| inputs: [ | |
| { id: 'a', label: '', type: 'number', position: 'left' }, | |
| { id: 'b', label: '', type: 'number', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [ | |
| { id: 'op', label: 'operator', type: 'select', default: '+', options: [ | |
| { label: '+', value: '+' }, { label: '-', value: '-' }, | |
| { label: 'Γ', value: '*' }, { label: 'Γ·', value: '/' }, | |
| { label: '^ power', value: '**' }, { label: '% remainder', value: '%' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => `(${inputs.a || '0'} ${cfg.op || '+'} ${inputs.b || '0'})`, | |
| }, | |
| { | |
| id: 'js_math_random', type: 'js_math', label: 'random from A to B', category: 'math', | |
| description: 'Pick a random whole number between two numbers', | |
| framework: 'web', shape: 'reporter', color: '#00BCD4', icon: 'π²', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [ | |
| { id: 'min', label: 'from', type: 'number', default: 1 }, | |
| { id: 'max', label: 'to', type: 'number', default: 10 }, | |
| ], | |
| compile: (cfg) => | |
| `Math.floor(Math.random() * (${cfg.max ?? 10} - ${cfg.min ?? 1} + 1)) + ${cfg.min ?? 1}`, | |
| }, | |
| { | |
| id: 'js_math_round', type: 'js_math', label: 'round number', category: 'math', | |
| description: 'Round a number up, down, or to the nearest whole number', | |
| framework: 'web', shape: 'reporter', color: '#00BCD4', icon: 'β', | |
| inputs: [{ id: 'value', label: '', type: 'number', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [ | |
| { id: 'method', label: 'method', type: 'select', default: 'round', options: [ | |
| { label: 'round to nearest', value: 'round' }, { label: 'round down', value: 'floor' }, | |
| { label: 'round up', value: 'ceil' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => `Math.${cfg.method || 'round'}(${inputs.value || '0'})`, | |
| }, | |
| { | |
| id: 'js_math_min', type: 'js_math', label: 'smallest of A and B', category: 'math', | |
| description: 'Get the smallest number', | |
| framework: 'web', shape: 'reporter', color: '#00BCD4', icon: 'β', | |
| inputs: [ | |
| { id: 'a', label: '', type: 'number', position: 'left' }, | |
| { id: 'b', label: '', type: 'number', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `Math.min(${inputs.a || '0'}, ${inputs.b || '0'})`, | |
| }, | |
| { | |
| id: 'js_math_max', type: 'js_math', label: 'biggest of A and B', category: 'math', | |
| description: 'Get the biggest number', | |
| framework: 'web', shape: 'reporter', color: '#00BCD4', icon: 'β', | |
| inputs: [ | |
| { id: 'a', label: '', type: 'number', position: 'left' }, | |
| { id: 'b', label: '', type: 'number', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `Math.max(${inputs.a || '0'}, ${inputs.b || '0'})`, | |
| }, | |
| { | |
| id: 'js_math_abs', type: 'js_math', label: 'absolute value of', category: 'math', | |
| description: 'Make a number positive (distance from zero)', | |
| framework: 'web', shape: 'reporter', color: '#00BCD4', icon: '| |', | |
| inputs: [{ id: 'value', label: '', type: 'number', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `Math.abs(${inputs.value || '0'})`, | |
| }, | |
| { | |
| id: 'js_math_sqrt', type: 'js_math', label: 'square root of', category: 'math', | |
| description: 'Get the square root of a number', | |
| framework: 'web', shape: 'reporter', color: '#00BCD4', icon: 'β', | |
| inputs: [{ id: 'value', label: '', type: 'number', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `Math.sqrt(${inputs.value || '0'})`, | |
| }, | |
| { | |
| id: 'js_math_pi', type: 'js_math', label: 'Ο pi', category: 'math', | |
| description: 'The number pi (3.14159...)', | |
| framework: 'web', shape: 'reporter', color: '#00BCD4', icon: 'Ο', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [], | |
| compile: () => 'Math.PI', | |
| }, | |
| // ============================================================ | |
| // π TEXT β "work with words" | |
| // ============================================================ | |
| { | |
| id: 'js_string_concat', type: 'js_text', label: 'join text A and B', category: 'text', | |
| description: 'Join two pieces of text together', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: 'π', | |
| inputs: [ | |
| { id: 'a', label: '', type: 'string', position: 'left' }, | |
| { id: 'b', label: '', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `(${inputs.a || "''"} + ${inputs.b || "''"})`, | |
| }, | |
| { | |
| id: 'js_string_append', type: 'js_text', label: 'add text to end', category: 'text', | |
| description: 'Add text to the end of a value (like +=)', | |
| framework: 'web', shape: 'stack', color: '#AB47BC', icon: 'β', | |
| inputs: [{ id: 'value', label: 'add', type: 'string', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'target', label: 'target', type: 'text', default: 'myVar' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${cfg.target || 'myVar'} += ${inputs.value || "''"};`, | |
| }, | |
| { | |
| id: 'js_string_length', type: 'js_text', label: 'length of text', category: 'text', | |
| description: 'Count how many characters are in the text', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: 'π', | |
| inputs: [{ id: 'string', label: '', type: 'string', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `(${inputs.string || "''"}).length`, | |
| }, | |
| { | |
| id: 'js_string_uppercase', type: 'js_text', label: 'make UPPERCASE', category: 'text', | |
| description: 'Convert text to ALL CAPITAL LETTERS', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: 'β²', | |
| inputs: [{ id: 'string', label: '', type: 'string', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `(${inputs.string || "''"}).toUpperCase()`, | |
| }, | |
| { | |
| id: 'js_string_lowercase', type: 'js_text', label: 'make lowercase', category: 'text', | |
| description: 'Convert text to all lowercase letters', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: 'βΌ', | |
| inputs: [{ id: 'string', label: '', type: 'string', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `(${inputs.string || "''"}).toLowerCase()`, | |
| }, | |
| { | |
| id: 'js_string_contains', type: 'js_text', label: 'text contains word?', category: 'text', | |
| description: 'Check if some text contains a word or letter', | |
| framework: 'web', shape: 'boolean', color: '#AB47BC', icon: 'π', | |
| inputs: [ | |
| { id: 'string', label: 'text', type: 'string', position: 'left' }, | |
| { id: 'substr', label: 'contains', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => | |
| `(${inputs.string || "''"}).includes(${inputs.substr || "''"})`, | |
| }, | |
| { | |
| id: 'js_string_starts', type: 'js_text', label: 'text starts with?', category: 'text', | |
| description: 'Check if text starts with certain letters', | |
| framework: 'web', shape: 'boolean', color: '#AB47BC', icon: 'π °', | |
| inputs: [ | |
| { id: 'string', label: 'text', type: 'string', position: 'left' }, | |
| { id: 'prefix', label: 'starts with', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => | |
| `(${inputs.string || "''"}).startsWith(${inputs.prefix || "''"})`, | |
| }, | |
| { | |
| id: 'js_string_trim', type: 'js_text', label: 'trim spaces', category: 'text', | |
| description: 'Remove extra spaces from the start and end of text', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: 'β', | |
| inputs: [{ id: 'string', label: '', type: 'string', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `(${inputs.string || "''"}).trim()`, | |
| }, | |
| { | |
| id: 'js_string_char_at', type: 'js_text', label: 'letter at position', category: 'text', | |
| description: 'Get the letter at a certain spot in the text', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: 'π€', | |
| inputs: [ | |
| { id: 'string', label: 'text', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [ | |
| { id: 'index', label: 'position', type: 'number', default: 0 }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `(${inputs.string || "''"}).charAt(${cfg.index ?? 0})`, | |
| }, | |
| { | |
| id: 'js_string_split', type: 'js_text', label: 'split text by separator', category: 'text', | |
| description: 'Split text into a list, using a separator', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: 'β', | |
| inputs: [ | |
| { id: 'string', label: 'text', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'array', position: 'right' }], | |
| config: [ | |
| { id: 'separator', label: 'separator', type: 'text', default: ',' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `(${inputs.string || "''"}).split('${cfg.separator || ','}')`, | |
| }, | |
| { | |
| id: 'js_string_replace', type: 'js_text', label: 'find and replace', category: 'text', | |
| description: 'Replace a word or letter in text with something else', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: 'π', | |
| inputs: [{ id: 'string', label: 'text', type: 'string', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [ | |
| { id: 'search', label: 'find', type: 'text', default: 'old' }, | |
| { id: 'replace', label: 'replace with', type: 'text', default: 'new' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `(${inputs.string || "''"}).replaceAll('${cfg.search || 'old'}', '${cfg.replace || 'new'}')`, | |
| }, | |
| { | |
| id: 'js_template_literal', type: 'js_text', label: 'template text', category: 'text', | |
| description: 'Combine text and variables in one piece of text. Use $ variableName to put a variable inside.', | |
| framework: 'web', shape: 'reporter', color: '#AB47BC', icon: '``', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [ | |
| { id: 'template', label: 'text', type: 'text', default: 'Hello, ${name}!' }, | |
| ], | |
| compile: (cfg) => `\`${cfg.template || ''}\``, | |
| }, | |
| // ============================================================ | |
| // β FUNCTIONS β "make your own command" | |
| // ============================================================ | |
| { | |
| id: 'js_function', type: 'js_functions', label: 'make function name', category: 'functions', | |
| description: 'Create a reusable command that you can run later', | |
| framework: 'web', shape: 'hat', color: '#E91E63', icon: 'Ζ', | |
| inputs: [{ id: 'body', label: 'run', type: 'code', position: 'bottom' }], | |
| outputs: [], config: [ | |
| { id: 'name', label: 'name', type: 'text', default: 'myFunction' }, | |
| { id: 'params', label: 'inputs', type: 'text', placeholder: 'a, b' }, | |
| { id: 'asyncFn', label: 'async', type: 'boolean', default: false }, | |
| ], | |
| compile: (cfg, inputs) => { | |
| const asyncKw = cfg.asyncFn === 'true' || cfg.asyncFn === 'TRUE' || cfg.asyncFn === true ? 'async ' : ''; | |
| return `${asyncKw}function ${cfg.name || 'myFunction'}(${cfg.params || ''}) {\n${inputs.body || ''}\n}`; | |
| }, | |
| }, | |
| { | |
| id: 'js_arrow_fn', type: 'js_functions', label: 'make arrow function', category: 'functions', | |
| description: 'Create a short function with =>', | |
| framework: 'web', shape: 'reporter', color: '#E91E63', icon: 'β', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], | |
| config: [ | |
| { id: 'params', label: 'inputs', type: 'text', default: 'x' }, | |
| { id: 'body', label: 'body', type: 'text', default: 'x * 2' }, | |
| ], | |
| compile: (cfg) => `((${cfg.params || 'x'}) => ${cfg.body || 'x'})`, | |
| }, | |
| { | |
| id: 'js_call_fn', type: 'js_functions', label: 'call function name', category: 'functions', | |
| description: 'Run a function you made earlier', | |
| framework: 'web', shape: 'stack', color: '#E91E63', icon: 'βΆ', | |
| inputs: [], outputs: [], config: [ | |
| { id: 'name', label: 'function', type: 'text', default: 'myFunction' }, | |
| { id: 'args', label: 'with inputs', type: 'text', placeholder: 'arg1, arg2' }, | |
| ], | |
| compile: (cfg) => `${cfg.name || 'myFunction'}(${cfg.args || ''});`, | |
| }, | |
| { | |
| id: 'js_call_fn_value', type: 'js_functions', label: 'function call result', category: 'functions', | |
| description: 'Run a function and use its returned value', | |
| framework: 'web', shape: 'reporter', color: '#E91E63', icon: 'Ζ', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], | |
| config: [ | |
| { id: 'name', label: 'function', type: 'text', default: 'myFunction' }, | |
| { id: 'args', label: 'inputs', type: 'text', placeholder: 'arg1, arg2' }, | |
| ], | |
| compile: (cfg) => `${cfg.name || 'myFunction'}(${cfg.args || ''})`, | |
| }, | |
| { | |
| id: 'js_return', type: 'js_functions', label: 'return value', category: 'functions', | |
| description: 'Give back a value from a function and stop', | |
| framework: 'web', shape: 'cap', color: '#E91E63', icon: 'β©', | |
| inputs: [{ id: 'value', label: '', type: 'any', position: 'left' }], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => `return ${inputs.value || ''};`, | |
| }, | |
| { | |
| id: 'js_return_void', type: 'js_functions', label: 'stop function', category: 'functions', | |
| description: 'Stop running the function early (no return value)', | |
| framework: 'web', shape: 'cap', color: '#E91E63', icon: 'β ', | |
| inputs: [], outputs: [], config: [], | |
| compile: () => 'return;', | |
| }, | |
| // ============================================================ | |
| // β ELEMENTS (DOM) β "find and change things on the page" | |
| // ============================================================ | |
| { | |
| id: 'js_get_element', type: 'js_dom', label: 'find element by CSS', category: 'dom', | |
| description: 'Find one element on the page by its CSS selector (like #id or .class)', | |
| framework: 'web', shape: 'reporter', color: '#607D8B', icon: 'π', | |
| inputs: [], outputs: [{ id: 'element', label: '', type: 'element', position: 'right' }], | |
| config: [ | |
| { id: 'selector', label: 'CSS selector', type: 'element', default: '#myElement' }, | |
| ], | |
| compile: (cfg) => `document.querySelector('${cfg.selector || '#myElement'}')`, | |
| }, | |
| { | |
| id: 'js_get_elements', type: 'js_dom', label: 'find all elements', category: 'dom', | |
| description: 'Find ALL elements matching a CSS selector', | |
| framework: 'web', shape: 'reporter', color: '#607D8B', icon: 'β', | |
| inputs: [], outputs: [{ id: 'elements', label: '', type: 'array', position: 'right' }], | |
| config: [ | |
| { id: 'selector', label: 'CSS selector', type: 'element', default: '.item' }, | |
| ], | |
| compile: (cfg) => `document.querySelectorAll('${cfg.selector || '.item'}')`, | |
| }, | |
| { | |
| id: 'js_create_element', type: 'js_dom', label: 'make new element', category: 'dom', | |
| description: 'Create a brand new HTML element', | |
| framework: 'web', shape: 'reporter', color: '#607D8B', icon: 'β¨', | |
| inputs: [], outputs: [{ id: 'element', label: '', type: 'element', position: 'right' }], | |
| config: [ | |
| { id: 'tag', label: 'tag', type: 'text', default: 'div' }, | |
| ], | |
| compile: (cfg) => `document.createElement('${cfg.tag || 'div'}')`, | |
| }, | |
| { | |
| id: 'js_append_child', type: 'js_dom', label: 'put inside', category: 'dom', | |
| description: 'Put one element inside another element', | |
| framework: 'web', shape: 'stack', color: '#607D8B', icon: 'β', | |
| inputs: [ | |
| { id: 'parent', label: 'element', type: 'element', position: 'left' }, | |
| { id: 'child', label: 'put this inside', type: 'element', position: 'left' }, | |
| ], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `${inputs.parent || 'parent'}.appendChild(${inputs.child || 'child'});`, | |
| }, | |
| { | |
| id: 'js_remove_element', type: 'js_dom', label: 'remove element', category: 'dom', | |
| description: 'Remove an element from the page', | |
| framework: 'web', shape: 'stack', color: '#607D8B', icon: 'β', | |
| inputs: [{ id: 'element', label: '', type: 'element', position: 'left' }], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => `${inputs.element || 'element'}.remove();`, | |
| }, | |
| { | |
| id: 'js_set_text', type: 'js_dom', label: 'change text to', category: 'dom', | |
| description: 'Change the text inside an element', | |
| framework: 'web', shape: 'stack', color: '#607D8B', icon: 'T', | |
| inputs: [ | |
| { id: 'element', label: 'element', type: 'element', position: 'left' }, | |
| { id: 'text', label: 'text', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `${inputs.element || 'element'}.textContent = ${inputs.text || "''"};`, | |
| }, | |
| { | |
| id: 'js_get_text', type: 'js_dom', label: 'get text', category: 'dom', | |
| description: 'Get the text from inside an element', | |
| framework: 'web', shape: 'reporter', color: '#607D8B', icon: 'T', | |
| inputs: [{ id: 'element', label: 'element', type: 'element', position: 'left' }], | |
| outputs: [{ id: 'text', label: '', type: 'string', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `${inputs.element || 'element'}.textContent`, | |
| }, | |
| { | |
| id: 'js_set_html', type: 'js_dom', label: 'change HTML to', category: 'dom', | |
| description: 'Set the inner HTML of an element (can include <b>bold</b> tags)', | |
| framework: 'web', shape: 'stack', color: '#607D8B', icon: '</>', | |
| inputs: [ | |
| { id: 'element', label: 'element', type: 'element', position: 'left' }, | |
| { id: 'html', label: 'HTML', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `${inputs.element || 'element'}.innerHTML = ${inputs.html || "''"};`, | |
| }, | |
| { | |
| id: 'js_get_html', type: 'js_dom', label: 'get HTML', category: 'dom', | |
| description: 'Get the inner HTML of an element', | |
| framework: 'web', shape: 'reporter', color: '#607D8B', icon: '</>', | |
| inputs: [{ id: 'element', label: 'element', type: 'element', position: 'left' }], | |
| outputs: [{ id: 'html', label: '', type: 'string', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `${inputs.element || 'element'}.innerHTML`, | |
| }, | |
| { | |
| id: 'js_set_attr', type: 'js_dom', label: 'set attribute to', category: 'dom', | |
| description: 'Set an attribute (like src, href, class) on an element', | |
| framework: 'web', shape: 'stack', color: '#607D8B', icon: 'β', | |
| inputs: [ | |
| { id: 'element', label: 'element', type: 'element', position: 'left' }, | |
| { id: 'value', label: 'to', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [], config: [ | |
| { id: 'attr', label: 'attribute', type: 'text', default: 'class' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.setAttribute('${cfg.attr || 'class'}', ${inputs.value || "''"});`, | |
| }, | |
| { | |
| id: 'js_get_attr', type: 'js_dom', label: 'get attribute', category: 'dom', | |
| description: 'Get the value of an attribute on an element', | |
| framework: 'web', shape: 'reporter', color: '#607D8B', icon: 'β', | |
| inputs: [{ id: 'element', label: 'element', type: 'element', position: 'left' }], | |
| outputs: [{ id: 'value', label: '', type: 'string', position: 'right' }], | |
| config: [ | |
| { id: 'attr', label: 'attribute', type: 'text', default: 'href' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.getAttribute('${cfg.attr || 'href'}')`, | |
| }, | |
| { | |
| id: 'js_clone_element', type: 'js_dom', label: 'clone element', category: 'dom', | |
| description: 'Make a copy of an element', | |
| framework: 'web', shape: 'reporter', color: '#607D8B', icon: 'π', | |
| inputs: [{ id: 'element', label: 'element', type: 'element', position: 'left' }], | |
| outputs: [{ id: 'clone', label: '', type: 'element', position: 'right' }], | |
| config: [ | |
| { id: 'deep', label: 'copy children too?', type: 'boolean', default: true }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.cloneNode(${cfg.deep !== false})`, | |
| }, | |
| { | |
| id: 'js_insert_before', type: 'js_dom', label: 'insert before', category: 'dom', | |
| description: 'Insert an element before another element', | |
| framework: 'web', shape: 'stack', color: '#607D8B', icon: 'β¬', | |
| inputs: [ | |
| { id: 'newChild', label: 'new element', type: 'element', position: 'left' }, | |
| { id: 'refChild', label: 'before', type: 'element', position: 'left' }, | |
| ], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `${inputs.refChild || 'ref'}.parentNode.insertBefore(${inputs.newChild || 'newEl'}, ${inputs.refChild || 'ref'});`, | |
| }, | |
| { | |
| id: 'js_replace_element', type: 'js_dom', label: 'replace element', category: 'dom', | |
| description: 'Replace an old element with a new one', | |
| framework: 'web', shape: 'stack', color: '#607D8B', icon: 'β', | |
| inputs: [ | |
| { id: 'newChild', label: 'new element', type: 'element', position: 'left' }, | |
| { id: 'oldChild', label: 'replace', type: 'element', position: 'left' }, | |
| ], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `${inputs.oldChild || 'old'}.replaceWith(${inputs.newChild || 'newEl'});`, | |
| }, | |
| // ============================================================ | |
| // π¨ STYLES (CSS) β "change how things look" | |
| // ============================================================ | |
| { | |
| id: 'js_set_style', type: 'js_css', label: 'set style property', category: 'css', | |
| description: 'Change a CSS style on an element (like color, size, position)', | |
| framework: 'web', shape: 'stack', color: '#3F51B5', icon: 'π¨', | |
| inputs: [ | |
| { id: 'element', label: 'element', type: 'element', position: 'left' }, | |
| { id: 'value', label: 'to', type: 'string', position: 'left' }, | |
| ], | |
| outputs: [], config: [ | |
| { id: 'property', label: 'style property', type: 'select', default: 'color', options: [ | |
| { label: 'text color', value: 'color' }, | |
| { label: 'background color', value: 'background' }, | |
| { label: 'width', value: 'width' }, | |
| { label: 'height', value: 'height' }, | |
| { label: 'font size', value: 'fontSize' }, | |
| { label: 'font family', value: 'fontFamily' }, | |
| { label: 'text align', value: 'textAlign' }, | |
| { label: 'margin', value: 'margin' }, | |
| { label: 'padding', value: 'padding' }, | |
| { label: 'border', value: 'border' }, | |
| { label: 'display', value: 'display' }, | |
| { label: 'opacity', value: 'opacity' }, | |
| { label: 'transform', value: 'transform' }, | |
| ]}, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.style.${cfg.property || 'color'} = ${inputs.value || "''"};`, | |
| }, | |
| { | |
| id: 'js_add_class', type: 'js_css', label: 'add CSS class', category: 'css', | |
| description: 'Add a CSS class to an element', | |
| framework: 'web', shape: 'stack', color: '#3F51B5', icon: '+C', | |
| inputs: [ | |
| { id: 'element', label: 'element', type: 'element', position: 'left' }, | |
| ], | |
| outputs: [], config: [ | |
| { id: 'class', label: 'class', type: 'text', default: 'active' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.classList.add('${cfg.class || 'active'}');`, | |
| }, | |
| { | |
| id: 'js_remove_class', type: 'js_css', label: 'remove CSS class', category: 'css', | |
| description: 'Remove a CSS class from an element', | |
| framework: 'web', shape: 'stack', color: '#3F51B5', icon: '-C', | |
| inputs: [ | |
| { id: 'element', label: 'element', type: 'element', position: 'left' }, | |
| ], | |
| outputs: [], config: [ | |
| { id: 'class', label: 'class', type: 'text', default: 'active' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.classList.remove('${cfg.class || 'active'}');`, | |
| }, | |
| { | |
| id: 'js_toggle_class', type: 'js_css', label: 'toggle CSS class', category: 'css', | |
| description: 'Turn a CSS class on/off (if on, turn off; if off, turn on)', | |
| framework: 'web', shape: 'stack', color: '#3F51B5', icon: 'β', | |
| inputs: [ | |
| { id: 'element', label: 'element', type: 'element', position: 'left' }, | |
| ], | |
| outputs: [], config: [ | |
| { id: 'class', label: 'class', type: 'text', default: 'active' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.classList.toggle('${cfg.class || 'active'}');`, | |
| }, | |
| { | |
| id: 'js_has_class', type: 'js_css', label: 'has CSS class?', category: 'css', | |
| description: 'Check if an element has a CSS class', | |
| framework: 'web', shape: 'boolean', color: '#3F51B5', icon: 'β', | |
| inputs: [ | |
| { id: 'element', label: 'element', type: 'element', position: 'left' }, | |
| ], | |
| outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [ | |
| { id: 'class', label: 'class', type: 'text', default: 'active' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.classList.contains('${cfg.class || 'active'}')`, | |
| }, | |
| { | |
| id: 'js_show_element', type: 'js_css', label: 'show element', category: 'css', | |
| description: 'Make a hidden element visible', | |
| framework: 'web', shape: 'stack', color: '#3F51B5', icon: 'π', | |
| inputs: [{ id: 'element', label: 'element', type: 'element', position: 'left' }], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `${inputs.element || 'element'}.style.display = '';`, | |
| }, | |
| { | |
| id: 'js_hide_element', type: 'js_css', label: 'hide element', category: 'css', | |
| description: 'Make an element invisible (still takes up space)', | |
| framework: 'web', shape: 'stack', color: '#3F51B5', icon: 'π«', | |
| inputs: [{ id: 'element', label: 'element', type: 'element', position: 'left' }], | |
| outputs: [], config: [], | |
| compile: (_cfg, inputs) => | |
| `${inputs.element || 'element'}.style.display = 'none';`, | |
| }, | |
| { | |
| id: 'js_set_opacity', type: 'js_css', label: 'set opacity to %', category: 'css', | |
| description: 'Make an element see-through (0=invisible, 100=fully visible)', | |
| framework: 'web', shape: 'stack', color: '#3F51B5', icon: 'β', | |
| inputs: [{ id: 'element', label: 'element', type: 'element', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'value', label: 'opacity 0-100', type: 'number', default: 50 }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${inputs.element || 'element'}.style.opacity = ${(cfg.value ?? 50) / 100};`, | |
| }, | |
| // ============================================================ | |
| // β DATA β "save, show, and fetch data" | |
| // ============================================================ | |
| { | |
| id: 'js_console', type: 'js_data', label: 'log to console', category: 'data', | |
| description: 'Print a message to the JavaScript console (F12 > Console tab)', | |
| framework: 'web', shape: 'stack', color: '#795548', icon: 'π₯', | |
| inputs: [{ id: 'value', label: '', type: 'any', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'message', label: 'message', type: 'text', default: 'hello' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `console.log(${inputs.value || JSON.stringify(cfg.message || '')});`, | |
| }, | |
| { | |
| id: 'js_console_warn', type: 'js_data', label: 'log warning', category: 'data', | |
| description: 'Print a warning in yellow', | |
| framework: 'web', shape: 'stack', color: '#795548', icon: 'β ', | |
| inputs: [{ id: 'value', label: '', type: 'any', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'message', label: 'message', type: 'text', default: 'warning' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `console.warn(${inputs.value || JSON.stringify(cfg.message || '')});`, | |
| }, | |
| { | |
| id: 'js_console_error', type: 'js_data', label: 'log error', category: 'data', | |
| description: 'Print an error in red', | |
| framework: 'web', shape: 'stack', color: '#795548', icon: 'π«', | |
| inputs: [{ id: 'value', label: '', type: 'any', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'message', label: 'message', type: 'text', default: 'error' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `console.error(${inputs.value || JSON.stringify(cfg.message || '')});`, | |
| }, | |
| { | |
| id: 'js_alert', type: 'js_data', label: 'show popup message', category: 'data', | |
| description: 'Show a popup window with a message', | |
| framework: 'web', shape: 'stack', color: '#795548', icon: 'π¬', | |
| inputs: [{ id: 'message', label: '', type: 'string', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'text', label: 'message', type: 'text', default: 'Hello!' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `alert(${inputs.message || JSON.stringify(cfg.text || '')});`, | |
| }, | |
| { | |
| id: 'js_confirm', type: 'js_data', label: 'ask yes or no', category: 'data', | |
| description: 'Show a popup with OK and Cancel buttons, returns true if OK pressed', | |
| framework: 'web', shape: 'reporter', color: '#795548', icon: 'β', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'boolean', position: 'right' }], | |
| config: [ | |
| { id: 'question', label: 'question', type: 'text', default: 'Are you sure?' }, | |
| ], | |
| compile: (cfg) => `confirm('${cfg.question || 'Are you sure?'}')`, | |
| }, | |
| { | |
| id: 'js_prompt', type: 'js_data', label: 'ask for text', category: 'data', | |
| description: 'Show a popup that asks the user to type something', | |
| framework: 'web', shape: 'reporter', color: '#795548', icon: 'β', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [ | |
| { id: 'question', label: 'question', type: 'text', default: 'What is your name?' }, | |
| { id: 'default', label: 'default answer', type: 'text', default: '' }, | |
| ], | |
| compile: (cfg) => `prompt('${cfg.question || ''}', '${cfg.default || ''}')`, | |
| }, | |
| { | |
| id: 'js_fetch', type: 'js_data', label: 'fetch data from URL', category: 'data', | |
| description: 'Get data from a website or API. Returns the response data so you can use it in other blocks.', | |
| framework: 'web', shape: 'reporter', color: '#795548', icon: 'π‘', | |
| inputs: [], outputs: [{ id: 'data', label: '', type: 'any', position: 'right' }], | |
| config: [ | |
| { id: 'url', label: 'URL', type: 'text', default: 'https://api.example.com/data' }, | |
| { id: 'method', label: 'method', type: 'select', default: 'GET', options: [ | |
| { label: 'GET', value: 'GET' }, { label: 'POST', value: 'POST' }, | |
| { label: 'PUT', value: 'PUT' }, { label: 'DELETE', value: 'DELETE' }, | |
| ]}, | |
| { id: 'useAwait', label: 'await?', type: 'boolean', default: true }, | |
| ], | |
| compile: (cfg) => { | |
| const prefix = cfg.useAwait ? 'await ' : ''; | |
| return `${prefix}fetch('${cfg.url || ''}', { method: '${cfg.method || 'GET'}' }).then(r => r.json())`; | |
| }, | |
| }, | |
| { | |
| id: 'js_local_storage_set', type: 'js_data', label: 'save to storage', category: 'data', | |
| description: 'Save a value in the browser so it remembers even after you close the page', | |
| framework: 'web', shape: 'stack', color: '#795548', icon: 'πΎ', | |
| inputs: [{ id: 'value', label: 'value', type: 'string', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'key', label: 'save as', type: 'text', default: 'myKey' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `localStorage.setItem('${cfg.key || 'myKey'}', ${inputs.value || "''"});`, | |
| }, | |
| { | |
| id: 'js_local_storage_get', type: 'js_data', label: 'load from storage', category: 'data', | |
| description: 'Get a saved value from the browser storage', | |
| framework: 'web', shape: 'reporter', color: '#795548', icon: 'πΎ', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'string', position: 'right' }], | |
| config: [ | |
| { id: 'key', label: 'key', type: 'text', default: 'myKey' }, | |
| ], | |
| compile: (cfg) => `localStorage.getItem('${cfg.key || 'myKey'}')`, | |
| }, | |
| { | |
| id: 'js_local_storage_remove', type: 'js_data', label: 'remove from storage', category: 'data', | |
| description: 'Delete a saved value from browser storage', | |
| framework: 'web', shape: 'stack', color: '#795548', icon: 'π', | |
| inputs: [], outputs: [], config: [ | |
| { id: 'key', label: 'key', type: 'text', default: 'myKey' }, | |
| ], | |
| compile: (cfg) => `localStorage.removeItem('${cfg.key || 'myKey'}');`, | |
| }, | |
| { | |
| id: 'js_json_parse', type: 'js_data', label: 'parse JSON text', category: 'data', | |
| description: 'Convert text to a structured object (JSON)', | |
| framework: 'web', shape: 'reporter', color: '#795548', icon: '{}', | |
| inputs: [{ id: 'text', label: '', type: 'string', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `JSON.parse(${inputs.text || "''"})`, | |
| }, | |
| { | |
| id: 'js_json_stringify', type: 'js_data', label: 'make JSON text', category: 'data', | |
| description: 'Convert a value to JSON text format', | |
| framework: 'web', shape: 'reporter', color: '#795548', icon: '{}', | |
| inputs: [{ id: 'value', label: '', type: 'any', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [], | |
| compile: (_cfg, inputs) => `JSON.stringify(${inputs.value || 'null'})`, | |
| }, | |
| // ============================================================ | |
| // β° LISTS (ARRAYS) β "work with lists of things" | |
| // ============================================================ | |
| { | |
| id: 'js_array', type: 'js_lists', label: 'list of items', category: 'lists', | |
| description: 'Create a new list with items separated by commas', | |
| framework: 'web', shape: 'reporter', color: '#FF661A', icon: 'β°', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'array', position: 'right' }], | |
| config: [ | |
| { id: 'values', label: 'items', type: 'text', placeholder: '1, 2, 3' }, | |
| ], | |
| compile: (cfg) => `[${cfg.values || ''}]`, | |
| }, | |
| { | |
| id: 'js_array_empty', type: 'js_lists', label: 'empty list', category: 'lists', | |
| description: 'Create a new empty list', | |
| framework: 'web', shape: 'reporter', color: '#FF661A', icon: 'β°', | |
| inputs: [], outputs: [{ id: 'value', label: '', type: 'array', position: 'right' }], | |
| config: [], | |
| compile: () => '[]', | |
| }, | |
| { | |
| id: 'js_array_push', type: 'js_lists', label: 'add item to list', category: 'lists', | |
| description: 'Add an item to the end of a list', | |
| framework: 'web', shape: 'stack', color: '#FF661A', icon: 'β', | |
| inputs: [{ id: 'value', label: 'item', type: 'any', position: 'left' }], | |
| outputs: [], config: [ | |
| { id: 'array', label: 'list', type: 'text', default: 'myArray' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${cfg.array || 'myArray'}.push(${inputs.value || 'undefined'});`, | |
| }, | |
| { | |
| id: 'js_array_pop', type: 'js_lists', label: 'remove last item', category: 'lists', | |
| description: 'Remove and get the last item from a list', | |
| framework: 'web', shape: 'reporter', color: '#FF661A', icon: 'β', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], | |
| config: [ | |
| { id: 'array', label: 'list', type: 'text', default: 'myArray' }, | |
| ], | |
| compile: (cfg) => `${cfg.array || 'myArray'}.pop()`, | |
| }, | |
| { | |
| id: 'js_array_length', type: 'js_lists', label: 'length of list', category: 'lists', | |
| description: 'Count how many items are in a list', | |
| framework: 'web', shape: 'reporter', color: '#FF661A', icon: 'π', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [ | |
| { id: 'array', label: 'list', type: 'text', default: 'myArray' }, | |
| ], | |
| compile: (cfg) => `${cfg.array || 'myArray'}.length`, | |
| }, | |
| { | |
| id: 'js_array_index_of', type: 'js_lists', label: 'find item in list', category: 'lists', | |
| description: 'Find where an item is in a list (returns position, or -1 if not found)', | |
| framework: 'web', shape: 'reporter', color: '#FF661A', icon: 'π', | |
| inputs: [{ id: 'value', label: 'item', type: 'any', position: 'left' }], | |
| outputs: [{ id: 'result', label: '', type: 'number', position: 'right' }], | |
| config: [ | |
| { id: 'array', label: 'list', type: 'text', default: 'myArray' }, | |
| ], | |
| compile: (cfg, inputs) => | |
| `${cfg.array || 'myArray'}.indexOf(${inputs.value || 'undefined'})`, | |
| }, | |
| { | |
| id: 'js_array_join', type: 'js_lists', label: 'join list into text', category: 'lists', | |
| description: 'Combine all items in a list into a single piece of text', | |
| framework: 'web', shape: 'reporter', color: '#FF661A', icon: 'β', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], | |
| config: [ | |
| { id: 'array', label: 'list', type: 'text', default: 'myArray' }, | |
| { id: 'separator', label: 'with separator', type: 'text', default: ', ' }, | |
| ], | |
| compile: (cfg) => | |
| `${cfg.array || 'myArray'}.join('${cfg.separator || ', '}')`, | |
| }, | |
| { | |
| id: 'js_array_slice', type: 'js_lists', label: 'get part of list', category: 'lists', | |
| description: 'Get a portion of a list from start to end', | |
| framework: 'web', shape: 'reporter', color: '#FF661A', icon: 'β', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'array', position: 'right' }], | |
| config: [ | |
| { id: 'array', label: 'list', type: 'text', default: 'myArray' }, | |
| { id: 'start', label: 'start at', type: 'number', default: 0 }, | |
| { id: 'end', label: 'end at', type: 'number', default: 5 }, | |
| ], | |
| compile: (cfg) => | |
| `${cfg.array || 'myArray'}.slice(${cfg.start ?? 0}, ${cfg.end ?? 5})`, | |
| }, | |
| // ============================================================ | |
| // π DATE/TIME β "work with dates and times" | |
| // ============================================================ | |
| { | |
| id: 'js_date_now', type: 'js_date', label: 'current date and time', category: 'date', | |
| description: 'Get the current date and time', | |
| framework: 'web', shape: 'reporter', color: '#9C27B0', icon: 'π ', | |
| inputs: [], outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], | |
| config: [ | |
| { id: 'format', label: 'format', type: 'select', default: 'iso', options: [ | |
| { label: 'full date string', value: 'iso' }, | |
| { label: 'timestamp (ms)', value: 'timestamp' }, | |
| { label: 'year', value: 'year' }, | |
| { label: 'month (1-12)', value: 'month' }, | |
| { label: 'day of month', value: 'day' }, | |
| { label: 'hours', value: 'hours' }, | |
| { label: 'minutes', value: 'minutes' }, | |
| { label: 'seconds', value: 'seconds' }, | |
| { label: 'day of week (0=Sun)', value: 'weekday' }, | |
| ]}, | |
| ], | |
| compile: (cfg) => { | |
| switch (cfg.format) { | |
| case 'timestamp': return 'Date.now()'; | |
| case 'year': return 'new Date().getFullYear()'; | |
| case 'month': return 'new Date().getMonth() + 1'; | |
| case 'day': return 'new Date().getDate()'; | |
| case 'hours': return 'new Date().getHours()'; | |
| case 'minutes': return 'new Date().getMinutes()'; | |
| case 'seconds': return 'new Date().getSeconds()'; | |
| case 'weekday': return 'new Date().getDay()'; | |
| default: return 'new Date().toISOString()'; | |
| } | |
| }, | |
| }, | |
| ]; | |