import { DeesElement, property, css, type CSSResult, cssManager, } from '@design.estate/dees-element'; import * as domtools from '@design.estate/dees-domtools'; /** * Base class for all dees-input components * Provides unified margin system and layout mode support */ export abstract class DeesInputBase extends DeesElement { /** * Layout mode for the input component * - vertical: Traditional form layout (label on top) * - horizontal: Inline layout (label position configurable) * - auto: Detect from parent context */ @property({ type: String }) public layoutMode: 'vertical' | 'horizontal' | 'auto' = 'auto'; /** * Position of the label relative to the input */ @property({ type: String }) public labelPosition: 'top' | 'left' | 'right' | 'none' = 'top'; /** * Common properties for all inputs */ @property({ type: String }) public key: string; @property({ type: String }) public label: string; @property({ type: Boolean }) public required: boolean = false; @property({ type: Boolean }) public disabled: boolean = false; @property({ type: String }) public description: string; /** * Common styles for all input components */ public static get baseStyles(): CSSResult[] { return [ css` /* CSS Variables for consistent spacing */ :host { --dees-input-spacing-unit: 8px; --dees-input-vertical-gap: calc(var(--dees-input-spacing-unit) * 2); /* 16px */ --dees-input-horizontal-gap: calc(var(--dees-input-spacing-unit) * 2); /* 16px */ --dees-input-label-gap: var(--dees-input-spacing-unit); /* 8px */ } /* Default vertical stacking mode (for forms) */ :host { display: block; margin: 0; margin-bottom: var(--dees-input-vertical-gap); } /* Last child in container should have no bottom margin */ :host(:last-child) { margin-bottom: 0; } /* Horizontal layout mode - activated by attribute */ :host([layout-mode="horizontal"]) { display: inline-block; margin: 0; margin-right: var(--dees-input-horizontal-gap); margin-bottom: 0; } :host([layout-mode="horizontal"]:last-child) { margin-right: 0; } /* Auto mode - inherit from parent dees-form if present */ /* Label position variations */ :host([label-position="left"]) .input-wrapper { display: grid; grid-template-columns: auto 1fr; gap: var(--dees-input-label-gap); align-items: center; } :host([label-position="right"]) .input-wrapper { display: grid; grid-template-columns: 1fr auto; gap: var(--dees-input-label-gap); align-items: center; } :host([label-position="top"]) .input-wrapper { display: block; } :host([label-position="none"]) dees-label { display: none; } `, ]; } /** * Subject for value changes that all inputs should implement */ public changeSubject = new domtools.plugins.smartrx.rxjs.Subject(); /** * Called when the element is connected to the DOM * Sets up layout mode detection */ async connectedCallback() { await super.connectedCallback(); this.detectLayoutMode(); } /** * Detects the appropriate layout mode based on parent context */ private detectLayoutMode() { if (this.layoutMode !== 'auto') { this.setAttribute('layout-mode', this.layoutMode); return; } // Check if parent is a form with horizontal layout const parentForm = this.closest('dees-form'); if (parentForm && parentForm.hasAttribute('horizontal-layout')) { this.setAttribute('layout-mode', 'horizontal'); } else { this.setAttribute('layout-mode', 'vertical'); } } /** * Updates the layout mode attribute when property changes */ updated(changedProperties: Map) { super.updated(changedProperties); if (changedProperties.has('layoutMode')) { this.detectLayoutMode(); } if (changedProperties.has('labelPosition')) { this.setAttribute('label-position', this.labelPosition); } } /** * Standard method for freezing input (disabling) */ public async freeze() { this.disabled = true; } /** * Standard method for unfreezing input (enabling) */ public async unfreeze() { this.disabled = false; } /** * Abstract method that child classes must implement to get their value */ public abstract getValue(): any; /** * Abstract method that child classes must implement to set their value */ public abstract setValue(value: any): void; }