RealBlocks / client /src /blocks /web /index.ts
incognitolm
asdl;f
d081604
Raw
History Blame Contribute Delete
62.5 kB
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()';
}
},
},
];