/* BFA Banana Dryer — Custom HMI Blocks for GrapesJS */ function registerHMIBlocks(editor) { const bm = editor.BlockManager; const dm = editor.DomComponents; // ── Shared styles ── const cardBase = { 'display': 'flex', 'flex-direction': 'column', 'align-items': 'center', 'justify-content': 'center', 'gap': '6px', 'padding': '16px', 'border-radius': '10px', 'cursor': 'pointer', 'min-height': '120px', 'width': '48%', 'font-family': 'Segoe UI, system-ui, sans-serif', 'border': '1px solid #1e2a45', 'transition': 'background 0.15s', 'box-sizing': 'border-box' }; // ══════════════════════════════════════════ // TEMPERATURE CARD // ══════════════════════════════════════════ dm.addType('temp-card', { model: { defaults: { tagName: 'div', draggable: true, droppable: false, attributes: {'data-type': 'temp'}, traits: [ {type: 'text', name: 'label', label: 'Name', changeProp: true}, {type: 'color', name: 'temp_color', label: 'Temp Color', changeProp: true}, {type: 'number', name: 'setpoint', label: 'Setpoint (°C)', changeProp: true, min: 0, max: 200}, {type: 'text', name: 'linked_id', label: 'Linked Control ID', changeProp: true}, ], label: 'Heat Input', temp_color: '#ff4444', setpoint: 130, linked_id: '', components: [ {tagName: 'div', attributes: {'data-role': 'name'}, content: 'Heat Input', style: {'font-size': '20px', 'color': '#7a8baa'}}, {tagName: 'div', attributes: {'data-role': 'value'}, content: '-- °C', style: {'font-size': '36px', 'font-weight': '700', 'color': '#ff4444'}}, {tagName: 'div', attributes: {'data-role': 'bar'}, style: {'width': '80%', 'height': '6px', 'background': '#1a2240', 'border-radius': '3px', 'overflow': 'hidden'}, components: [{tagName: 'div', style: {'width': '50%', 'height': '100%', 'background': '#ff4444', 'border-radius': '3px'}}]}, {tagName: 'div', attributes: {'data-role': 'sp'}, content: 'SP: 130 °C', style: {'font-size': '14px', 'color': '#4a5670'}}, ], style: {...cardBase, 'background': '#131a2b'}, } } }); bm.add('temp-card', { label: '🌡 Temperature', category: 'HMI Controls', content: {type: 'temp-card'}, attributes: {class: 'gjs-fonts gjs-f-b1'} }); // ══════════════════════════════════════════ // MOTOR CARD // ══════════════════════════════════════════ dm.addType('motor-card', { model: { defaults: { tagName: 'div', draggable: true, droppable: false, attributes: {'data-type': 'motor'}, traits: [ {type: 'text', name: 'label', label: 'Name', changeProp: true}, {type: 'number', name: 'speed_sp', label: 'Speed SP (%)', changeProp: true, min: 0, max: 100, step: 5}, {type: 'color', name: 'active_color', label: 'Active Color', changeProp: true}, {type: 'color', name: 'inactive_color', label: 'Inactive Color', changeProp: true}, {type: 'select', name: 'animation', label: 'Animation', changeProp: true, options: [{value:'none'},{value:'fan'},{value:'agitator'},{value:'conveyor'},{value:'pulse'},{value:'vibrate'},{value:'glow'},{value:'blink'},{value:'flow'}]}, {type: 'text', name: 'linked_id', label: 'Linked Control ID', changeProp: true}, ], label: 'Motor', speed_sp: 50, active_color: '#00c853', inactive_color: '#ff1744', animation: 'none', linked_id: '', components: [ {tagName: 'div', style: {'display': 'flex', 'gap': '10px', 'align-items': 'center'}, components: [ {tagName: 'span', attributes: {'data-role': 'name'}, content: 'Motor', style: {'font-size': '24px', 'font-weight': '600', 'color': '#e8ecf4'}}, {tagName: 'span', attributes: {'data-role': 'speed'}, content: '50%', style: {'font-size': '24px', 'color': '#7a8baa'}}, ]}, {tagName: 'div', attributes: {'data-role': 'state'}, content: 'OFF', style: {'font-size': '36px', 'font-weight': '700', 'color': '#e8ecf4'}}, ], style: {...cardBase, 'background': '#ff1744'}, } } }); bm.add('motor-card', { label: '⚙ Motor / Speed', category: 'HMI Controls', content: {type: 'motor-card'}, }); // ══════════════════════════════════════════ // OUTPUT CARD // ══════════════════════════════════════════ dm.addType('output-card', { model: { defaults: { tagName: 'div', draggable: true, droppable: false, attributes: {'data-type': 'output'}, traits: [ {type: 'text', name: 'label', label: 'Name', changeProp: true}, {type: 'color', name: 'active_color', label: 'Active Color', changeProp: true}, {type: 'color', name: 'inactive_color', label: 'Inactive Color', changeProp: true}, {type: 'text', name: 'linked_id', label: 'Linked Control ID', changeProp: true}, ], label: 'Output', active_color: '#00c853', inactive_color: '#ff1744', linked_id: '', components: [ {tagName: 'div', attributes: {'data-role': 'name'}, content: 'Output', style: {'font-size': '20px', 'text-align': 'center', 'color': '#e8ecf4'}}, {tagName: 'div', attributes: {'data-role': 'state'}, content: 'OFF', style: {'font-size': '28px', 'font-weight': '700', 'color': '#e8ecf4'}}, ], style: {...cardBase, 'background': '#ff1744'}, } } }); bm.add('output-card', { label: '⚡ Output / Switch', category: 'HMI Controls', content: {type: 'output-card'}, }); // ══════════════════════════════════════════ // BURNER CARD // ══════════════════════════════════════════ dm.addType('burner-card', { model: { defaults: { tagName: 'div', draggable: true, droppable: false, attributes: {'data-type': 'burner'}, traits: [ {type: 'text', name: 'label', label: 'Name', changeProp: true}, {type: 'color', name: 'active_color', label: 'Active Color', changeProp: true}, {type: 'color', name: 'inactive_color', label: 'Inactive Color', changeProp: true}, ], label: 'Burner', active_color: '#ffab00', inactive_color: '#ff1744', components: [ {tagName: 'div', attributes: {'data-role': 'name'}, content: 'Burner', style: {'font-size': '24px', 'color': '#e8ecf4'}}, {tagName: 'div', attributes: {'data-role': 'state'}, content: 'OFF', style: {'font-size': '32px', 'font-weight': '700', 'color': '#e8ecf4'}}, ], style: {...cardBase, 'background': '#ff1744'}, } } }); bm.add('burner-card', { label: '🔥 Burner', category: 'HMI Controls', content: {type: 'burner-card'}, }); // ══════════════════════════════════════════ // AUTOMATION CARD // ══════════════════════════════════════════ dm.addType('automation-card', { model: { defaults: { tagName: 'div', draggable: true, droppable: false, attributes: {'data-type': 'automation'}, traits: [ {type: 'text', name: 'label', label: 'Name', changeProp: true}, {type: 'color', name: 'active_color', label: 'Active Color', changeProp: true}, {type: 'color', name: 'inactive_color', label: 'Inactive Color', changeProp: true}, ], label: 'Automation', active_color: '#00c853', inactive_color: '#ff1744', components: [ {tagName: 'div', attributes: {'data-role': 'name'}, content: 'Automation', style: {'font-size': '24px', 'font-weight': '700', 'color': '#e8ecf4'}}, {tagName: 'div', attributes: {'data-role': 'rules'}, content: 'Click to configure', style: {'font-size': '12px', 'color': '#7a8baa'}}, ], style: {...cardBase, 'background': '#ff1744', 'width': '100%'}, } } }); bm.add('automation-card', { label: '🤖 Automation', category: 'HMI Controls', content: {type: 'automation-card'}, }); // ══════════════════════════════════════════ // GAUGE (arc) // ══════════════════════════════════════════ bm.add('gauge', { label: '📊 Gauge', category: 'HMI Controls', content: `
50%
`, }); // ══════════════════════════════════════════ // LAYOUT HELPERS // ══════════════════════════════════════════ bm.add('page-container', { label: '📄 Page Container', category: 'Layout', content: `
`, }); bm.add('tab-bar', { label: '📑 Tab Bar', category: 'Layout', content: `
PAGE 1
PAGE 2
PAGE 3
`, }); bm.add('top-bar', { label: '📌 Top Bar', category: 'Layout', content: `
BFA BANANA DRYER SAE Engineering
RS485 OFFLINE
`, }); bm.add('text-label', { label: '📝 Text Label', category: 'Layout', content: `
Label Text
`, }); bm.add('divider', { label: '➖ Divider', category: 'Layout', content: `
`, }); bm.add('spacer', { label: '⬜ Spacer', category: 'Layout', content: `
`, }); }