Source: ds-page.js

/**
 * @file ds-page.js
 * @summary A custom Web Component that provides a consistent wrapper around application content.
 * @description
 * The `ds-page` component handles page-level layout and margins, providing a consistent
 * foundation for application pages. It uses CSS custom properties for customization
 * and ensures proper viewport handling.
 *
 * @element ds-page
 * @extends HTMLElement
 *
 * @slot - Renders the main page content inside the page container.
 *
 * @example
 * <!-- Basic page wrapper -->
 * <ds-page>
 *   <h1>Welcome to My App</h1>
 *   <p>This content is wrapped in a consistent page layout.</p>
 * </ds-page>
 *
 * @example
 * <!-- Page with nested layout components -->
 * <ds-page>
 *   <ds-row justify-content="space-between" align-items="center">
 *     <ds-col>
 *       <h1>Page Title</h1>
 *     </ds-col>
 *     <ds-col>
 *       <ds-button>Action</ds-button>
 *     </ds-col>
 *   </ds-row>
 *   <ds-row>
 *     <ds-col>
 *       <p>Main content area</p>
 *     </ds-col>
 *   </ds-row>
 * </ds-page>
 */
class DsPage extends HTMLElement {
    constructor() {
        super();
        
        // Attach shadow root with open mode for experimentation
        const shadowRoot = this.attachShadow({ mode: 'open' });
        
        // Define the template with internal markup and styles
        const template = document.createElement('template');
        template.innerHTML = `
            <style>
                @import url('/src/design_system/styles.css');
                
                :host {
                    display: block; /* Custom elements are inline by default */
                    width: 100%;
                    min-height: 100vh; /* Ensures it takes full viewport height */
                    box-sizing: border-box; /* Include padding/border in element's total width/height */
                }
                
                .page-container {
                    display: flex; /* Makes the main element a flex container for its children */
                    flex-direction: column; /* Stacks children vertically by default */
                    width: 100%;
                    padding: var(--ds-spacing-page-padding, 20px); /* Default padding, can be overridden by CSS variable */
                    margin: 0 auto; /* Center content if width is limited */
                    max-width: var(--ds-page-max-width, 1200px); /* Optional max-width for content */
                }
            </style>
            <main class="page-container">
                <slot></slot>
            </main>
        `;
        
        // Append the template's content to the shadow root
        shadowRoot.appendChild(template.content.cloneNode(true));
        
        // Store reference to the internal container
        this.pageContainer = shadowRoot.querySelector('.page-container');
    }
    
    /**
     * Defines which attributes the component observes for changes.
     * @returns {Array<string>} An array of attribute names to observe.
     */
    static get observedAttributes() {
        return []; // No specific attributes to observe
    }
    
    /**
     * Called when the element is connected to the DOM.
     * Applies any initial setup if needed.
     */
    connectedCallback() {
        // No specific initialization needed for ds-page
        // It's designed to be a simple wrapper
    }
}

// Register the custom element
customElements.define('ds-page', DsPage);