UNPKG

@plotinus/matrix-package-calculator

Version:

Calculator components for the Matrix framework - basic arithmetic operations with UI

512 lines (472 loc) 19.9 kB
// dist/browser/component-sources.js var componentSources = { // Calculator component sources calculatorCommunication: `class CalculatorComponent extends window.Matrix.BaseCommunicationComponent { static dslTag = 'calculator'; static isMatrixComponent = true; constructor(id, eventBus) { super(id, eventBus); this.calculatorState = { display: '0', currentValue: 0, previousValue: null, pendingOperation: null, waitingForNewValue: false, history: [] }; } startExecution() { console.log(\`Calculator \${this.id} started\`); this.setState(this.calculatorState); this.emitEvent('CalculatorReady', { calculatorId: this.id }); } numberInputHandler(data) { console.log(\`Calculator \${this.id}: Number input: \${data.digit}\`); if (this.calculatorState.waitingForNewValue) { this.calculatorState.display = data.digit.toString(); this.calculatorState.currentValue = data.digit; this.calculatorState.waitingForNewValue = false; } else { if (this.calculatorState.display === '0') { this.calculatorState.display = data.digit.toString(); } else { this.calculatorState.display += data.digit.toString(); } this.calculatorState.currentValue = parseFloat(this.calculatorState.display); } this.setState(this.calculatorState); this.emitEvent('DisplayUpdated', { calculatorId: this.id, display: this.calculatorState.display, value: this.calculatorState.currentValue }); } operationHandler(data) { console.log(\`Calculator \${this.id}: Operation: \${data.operation}\`); if (this.calculatorState.pendingOperation && !this.calculatorState.waitingForNewValue) { // Complete pending operation first this.performCalculation({ id: \`calc-\${Date.now()}\`, operation: this.calculatorState.pendingOperation, operand: this.calculatorState.currentValue, timestamp: Date.now() }); } else { this.calculatorState.previousValue = this.calculatorState.currentValue; } this.calculatorState.pendingOperation = data.operation; this.calculatorState.waitingForNewValue = true; this.setState(this.calculatorState); this.emitEvent('OperationSet', { calculatorId: this.id, operation: data.operation, display: this.calculatorState.display }); } equalsHandler() { console.log(\`Calculator \${this.id}: Equals pressed\`); if (this.calculatorState.pendingOperation && this.calculatorState.previousValue !== null) { this.performCalculation({ id: \`calc-\${Date.now()}\`, operation: this.calculatorState.pendingOperation, operand: this.calculatorState.currentValue, timestamp: Date.now() }); this.calculatorState.pendingOperation = null; this.calculatorState.previousValue = null; this.calculatorState.waitingForNewValue = true; this.setState(this.calculatorState); this.emitEvent('EqualsComplete', { calculatorId: this.id, result: this.calculatorState.display }); } } clearHandler() { console.log(\`Calculator \${this.id}: Clear pressed\`); this.calculatorState = { display: '0', currentValue: 0, previousValue: null, pendingOperation: null, waitingForNewValue: false, history: [...this.calculatorState.history] }; const clearCalculation = { id: \`clear-\${Date.now()}\`, operation: 'clear', timestamp: Date.now() }; this.calculatorState.history.push(clearCalculation); this.setState(this.calculatorState); this.emitEvent('CalculatorCleared', { calculatorId: this.id, display: this.calculatorState.display }); } performCalculation(calculation) { let result = this.calculatorState.currentValue; if (this.calculatorState.previousValue !== null && calculation.operand !== undefined) { switch (calculation.operation) { case 'add': result = this.calculatorState.previousValue + calculation.operand; break; case 'subtract': result = this.calculatorState.previousValue - calculation.operand; break; case 'multiply': result = this.calculatorState.previousValue * calculation.operand; break; case 'divide': if (calculation.operand === 0) { this.calculatorState.display = 'Error'; this.emitEvent('CalculationError', { calculatorId: this.id, error: 'Division by zero', calculation }); return this.calculatorState.currentValue; } result = this.calculatorState.previousValue / calculation.operand; break; } } this.calculatorState.currentValue = result; this.calculatorState.display = result.toString(); this.calculatorState.history.push(calculation); return result; } }`, calculatorPresentation: `class CalculatorPresentationElement extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } bindTo(commComponent) { this.commComponent = commComponent; // Subscribe to state changes if (commComponent.eventBus) { const stateKey = \`cmp:\${commComponent.id}:_stateChanged\`; commComponent.eventBus.on(stateKey, () => this.render()); } this.render(); } render() { const state = this.commComponent?.state || { display: '0' }; this.shadowRoot.innerHTML = \` <style> :host { display: block; font-family: 'Courier New', monospace; } .calculator { border: 2px solid #ff6b35; padding: 16px; margin: 8px; border-radius: 12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); box-shadow: 0 8px 16px rgba(0,0,0,0.2); max-width: 300px; } .display { background: #000; color: #00ff00; font-size: 24px; text-align: right; padding: 12px; margin-bottom: 16px; border-radius: 6px; border: 2px inset #333; min-height: 40px; display: flex; align-items: center; justify-content: flex-end; } .buttons { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; } button { background: linear-gradient(145deg, #f0f0f0, #d0d0d0); border: 2px outset #ddd; padding: 16px; font-size: 18px; font-weight: bold; border-radius: 8px; cursor: pointer; transition: all 0.1s; } button:hover { background: linear-gradient(145deg, #e0e0e0, #c0c0c0); transform: translateY(-1px); } button:active { border: 2px inset #ddd; transform: translateY(0); } .operator { background: linear-gradient(145deg, #ff6b35, #f4511e); color: white; } .operator:hover { background: linear-gradient(145deg, #f4511e, #e64a19); } .equals { background: linear-gradient(145deg, #4caf50, #45a049); color: white; grid-column: span 2; } .equals:hover { background: linear-gradient(145deg, #45a049, #3d8b40); } .clear { background: linear-gradient(145deg, #f44336, #d32f2f); color: white; } .clear:hover { background: linear-gradient(145deg, #d32f2f, #c62828); } .zero { grid-column: span 2; } h3 { color: white; text-align: center; margin-top: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); } </style> <div class="calculator"> <h3>Calculator: \${this.commComponent?.id}</h3> <div class="display">\${state.display || '0'}</div> <div class="buttons"> <button class="clear" onclick="this.getRootNode().host.clearCalculator()">C</button> <button class="operator" onclick="this.getRootNode().host.inputOperation('divide')">\xF7</button> <button class="operator" onclick="this.getRootNode().host.inputOperation('multiply')">\xD7</button> <button class="operator" onclick="this.getRootNode().host.inputOperation('subtract')">\u2212</button> <button onclick="this.getRootNode().host.inputNumber(7)">7</button> <button onclick="this.getRootNode().host.inputNumber(8)">8</button> <button onclick="this.getRootNode().host.inputNumber(9)">9</button> <button class="operator" onclick="this.getRootNode().host.inputOperation('add')">+</button> <button onclick="this.getRootNode().host.inputNumber(4)">4</button> <button onclick="this.getRootNode().host.inputNumber(5)">5</button> <button onclick="this.getRootNode().host.inputNumber(6)">6</button> <button class="equals" onclick="this.getRootNode().host.calculateEquals()" style="grid-row: span 2;">=</button> <button onclick="this.getRootNode().host.inputNumber(1)">1</button> <button onclick="this.getRootNode().host.inputNumber(2)">2</button> <button onclick="this.getRootNode().host.inputNumber(3)">3</button> <button class="zero" onclick="this.getRootNode().host.inputNumber(0)">0</button> <button onclick="this.getRootNode().host.inputNumber('.')">.</button> </div> </div> \`; } inputNumber(digit) { if (typeof digit === 'string' && digit === '.') { console.log('Decimal point not yet implemented'); return; } this.commComponent?.numberInputHandler({ digit: Number(digit) }); } inputOperation(operation) { this.commComponent?.operationHandler({ operation }); } calculateEquals() { this.commComponent?.equalsHandler(); } clearCalculator() { this.commComponent?.clearHandler(); } }` }; // dist/presentation/calculator-presentation.js var CalculatorPresentationElement = class extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } bindTo(commComponent) { this.commComponent = commComponent; if (commComponent.eventBus) { const stateKey = `cmp:${commComponent.id}:_stateChanged`; commComponent.eventBus.on(stateKey, () => this.render()); } this.render(); } render() { const state = this.commComponent?.state || { display: "0" }; this.shadowRoot.innerHTML = ` <style> :host { display: block; font-family: 'Courier New', monospace; } .calculator { border: 2px solid #ff6b35; padding: 16px; margin: 8px; border-radius: 12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); box-shadow: 0 8px 16px rgba(0,0,0,0.2); max-width: 300px; } .display { background: #000; color: #00ff00; font-size: 24px; text-align: right; padding: 12px; margin-bottom: 16px; border-radius: 6px; border: 2px inset #333; min-height: 40px; display: flex; align-items: center; justify-content: flex-end; } .buttons { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; } button { background: linear-gradient(145deg, #f0f0f0, #d0d0d0); border: 2px outset #ddd; padding: 16px; font-size: 18px; font-weight: bold; border-radius: 8px; cursor: pointer; transition: all 0.1s; } button:hover { background: linear-gradient(145deg, #e0e0e0, #c0c0c0); transform: translateY(-1px); } button:active { border: 2px inset #ddd; transform: translateY(0); } .operator { background: linear-gradient(145deg, #ff6b35, #f4511e); color: white; } .operator:hover { background: linear-gradient(145deg, #f4511e, #e64a19); } .equals { background: linear-gradient(145deg, #4caf50, #45a049); color: white; grid-column: span 2; } .equals:hover { background: linear-gradient(145deg, #45a049, #3d8b40); } .clear { background: linear-gradient(145deg, #f44336, #d32f2f); color: white; } .clear:hover { background: linear-gradient(145deg, #d32f2f, #c62828); } .zero { grid-column: span 2; } h3 { color: white; text-align: center; margin-top: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); } </style> <div class="calculator"> <h3>Calculator: ${this.commComponent?.id}</h3> <div class="display">${state.display || "0"}</div> <div class="buttons"> <button class="clear" onclick="this.getRootNode().host.clearCalculator()">C</button> <button onclick="this.getRootNode().host.inputOperation('divide')">\xF7</button> <button onclick="this.getRootNode().host.inputOperation('multiply')">\xD7</button> <button onclick="this.getRootNode().host.inputOperation('subtract')">\u2212</button> <button onclick="this.getRootNode().host.inputNumber(7)">7</button> <button onclick="this.getRootNode().host.inputNumber(8)">8</button> <button onclick="this.getRootNode().host.inputNumber(9)">9</button> <button onclick="this.getRootNode().host.inputOperation('add')">+</button> <button onclick="this.getRootNode().host.inputNumber(4)">4</button> <button onclick="this.getRootNode().host.inputNumber(5)">5</button> <button onclick="this.getRootNode().host.inputNumber(6)">6</button> <button class="equals" onclick="this.getRootNode().host.calculateEquals()" style="grid-row: span 2;">=</button> <button onclick="this.getRootNode().host.inputNumber(1)">1</button> <button onclick="this.getRootNode().host.inputNumber(2)">2</button> <button onclick="this.getRootNode().host.inputNumber(3)">3</button> <button class="zero" onclick="this.getRootNode().host.inputNumber(0)">0</button> <button onclick="this.getRootNode().host.inputNumber('.')">.</button> </div> </div> `; } inputNumber(digit) { if (typeof digit === "string" && digit === ".") { console.log("Decimal point not yet implemented"); return; } this.commComponent?.numberInputHandler({ digit: Number(digit) }); } inputOperation(operation) { this.commComponent?.operationHandler({ operation }); } calculateEquals() { this.commComponent?.equalsHandler(); } clearCalculator() { this.commComponent?.clearHandler(); } }; // dist/browser-entry.js function registerCalculatorComponents(Matrix) { if (!Matrix || !Matrix.BaseCommunicationComponent) { throw new Error("Matrix framework not found"); } const components = { calculator: { name: "CalculatorComponent", source: componentSources.calculatorCommunication, tag: "calculator" } }; Object.values(components).forEach((comp) => { try { const ComponentClass = new Function( "BaseCommunicationComponent", comp.source + "\nreturn " + comp.name )(Matrix.BaseCommunicationComponent); ComponentClass.dslTag = comp.tag; ComponentClass.isMatrixComponent = true; if (!window.MatrixComponents) { window.MatrixComponents = {}; } window.MatrixComponents[comp.name] = ComponentClass; Matrix.register(ComponentClass); console.log("Registered communication component:", comp.tag); } catch (error) { console.error("Failed to register component:", comp.name, error); } }); if (!customElements.get("calculator-presentation")) { customElements.define("calculator-presentation", CalculatorPresentationElement); } console.log("All calculator components registered"); } if (typeof window !== "undefined") { window.MatrixPackageCalculator = { componentSources, CalculatorPresentationElement, registerCalculatorComponents }; } export { CalculatorPresentationElement, componentSources, registerCalculatorComponents }; //# sourceMappingURL=browser-bundle.js.map