### Async Setup with setup() - JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/setup-async.html This example demonstrates initializing data asynchronously using the setup() method in a hyperElement. The setup method uses setTimeout to simulate an async operation, calling onNext with the loaded data. The render method then displays the data, initially showing 'loading...' and updating to 'loaded!' once the async operation completes. ```javascript class extends hyperElement { setup(onNext) { setTimeout(onNext(() => "loaded!"), 10) } render(Html, data = "loading...") { Html`Status: ${data}` } } ``` -------------------------------- ### Counter Component with Setup using Functional API (JavaScript) Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Provides a practical example of the functional API for hyper-element, demonstrating a counter component. It utilizes the `setup` function to initialize state and define an `increment` method, and the `render` function to display the count and a button to trigger the increment action. ```javascript hyperElement('my-counter', { setup: (ctx, onNext) => { const store = { count: 0 }; const render = onNext(() => store); ctx.increment = () => { store.count++; render(); }; }, handleClick: (ctx, event) => ctx.increment(), render: (Html, ctx, store) => Html` `, }); ``` -------------------------------- ### Setup Data Sources with setup() in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md The `setup` function is used to wire up external data sources using the `attachStore` argument. It allows binding data sources to your renderer and handling cleanup. ```javascript setup(attachStore) { // the getMouseValues function will be called before each render and passed to render const onStoreChange = attachStore(getMouseValues); // call onStoreChange on every mouse event onMouseMove(onStoreChange); // cleanup logic return () => console.warn('On remove, do component cleanup here'); } ``` ```javascript setup(attachStore) { setInterval(attachStore(), 1000); // re-render every second } ``` ```javascript setup(attachStore) { attachStore({ max_levels: 3 }); // passed to every render } ``` -------------------------------- ### Create a Timer Element with Setup and Render Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/functional-api.html Demonstrates creating a custom element 'func-timer' that displays a continuously updating count. The setup function initializes a timer using setInterval, and the render function displays the current count. The teardown function clears the interval when the element is removed. ```javascript hyperElement('func-timer', { setup: (ctx, onNext) => { let count = 0; const render = onNext(() => ({ count })); const interval = setInterval(() => { count++; render(); }, 100); return () => clearInterval(interval); }, render: (Html, ctx, store) => Html`Timer: ${store?.count || 0}`, }); const elem5 = document.createElement('func-timer'); document.getElementById('output-5').appendChild(elem5); setTimeout(() => { const section = document.querySelector( '[data-test="setup-teardown"]' ); const text = elem5.textContent; if (text.includes('Timer:') && parseInt(text.split(':')[1]) >= 2) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } elem5.remove(); }, 350); ``` -------------------------------- ### Verify Setup Cleanup Functionality Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/functional-api.html Tests the teardown mechanism of the `setup` function in HyperElement. A 'func-cleanup-test' element is created, and its `setup` function returns a cleanup function that sets a global flag `window.cleanupTestCalled`. This flag is checked after the element is removed to confirm the cleanup function was executed. ```javascript window.cleanupTestCalled = false; hyperElement('func-cleanup-test', { setup: (ctx, onNext) => { onNext(); return () => { window.cleanupTestCalled = true; }; }, render: (Html, ctx) => Html`Cleanup Test`, }); const elem9 = document.createElement('func-cleanup-test'); document.getElementById('output-9').appendChild(elem9); requestAnimationFrame(() => { elem9.remove(); requestAnimationFrame(() => { const section = document.querySelector( '[data-test="setup-cleanup-verify"]' ); if (window.cleanupTestCalled === true) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }); }); ``` -------------------------------- ### Define and Test Async Setup Element - JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/setup-async.html This code defines a custom element 'setup-element' using the hyperElement base class and demonstrates its asynchronous setup. It then includes a test to verify that the element's content updates to 'loaded!' after the asynchronous operation, marking the test result as 'pass' or 'fail'. ```javascript customElements.define( 'setup-element', class extends hyperElement { setup(onNext) { setTimeout( onNext(() => 'loaded!'), 10 ); } render(Html, data = 'loading...') { Html`Status: ${data}`; } } ); setTimeout(() => { const section = document.querySelector('\\[data-test="setup-element"\\]'); const elem = document.querySelector('setup-element'); if (elem && elem.textContent.includes('loaded!')) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }, 100); ``` -------------------------------- ### Install Pre-commit Hooks Manually Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Installs the project's pre-commit hooks manually if they were not installed automatically during the initial setup. This ensures code quality checks are performed before each commit. ```bash npm run hooks:install ``` -------------------------------- ### Functional API with Setup and Render in HyperElement Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/ssr-hydration.html Demonstrates the basic usage of the functional API in HyperElement. It includes a setup function for initializing state, a render function for defining the component's HTML structure, and a click handler to update the state and re-render the component. This example is written in JavaScript. ```javascript setTimeout(() => { hyperElement('ssr-func-counter', { setup: (ctx, onNext) => { ctx.count = 0; return onNext(() => ({ count: ctx.count })); }, handleClick: (ctx) => { ctx.count++; ctx.element.render(); }, render: (Html, ctx, store) => Html``, }); setTimeout(() => { const elem = document.querySelector('ssr-func-counter'); const section = document.querySelector( '\\[data-test="ssr-functional-api"\\]' ); if (elem.textContent.includes('Count: 2')) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }, 100); }, 250); ``` -------------------------------- ### Install Project Dependencies with npm Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Installs all necessary project dependencies, including development tools and pre-commit hooks, using npm. This command should be run after cloning the repository. ```bash npm install ``` -------------------------------- ### Test setup() before render() in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/lifecycle-sequence.html Verifies that the setup() method is executed before the initial render() call. It checks the order of calls and the value set in setup(). ```javascript (function () { const section = document.querySelector( '[data-test="setup-before-render"]' ); const callOrder = []; customElements.define( 'setup-order-elem', class extends hyperElement { setup(onNext) { callOrder.push('setup'); this.value = 'from-setup'; onNext(); } render(Html) { callOrder.push('render'); Html`
${this.value}
` } } ); const elem = document.createElement('setup-order-elem'); document.getElementById('setup-order-output').appendChild(elem); requestAnimationFrame(() => { const result = document.getElementById('setup-order-result'); if ( callOrder[0] === 'setup' && callOrder[1] === 'render' && result?.textContent === 'from-setup' ) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }); })(); ``` -------------------------------- ### Connect a Data Source with Cleanup in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/lifecycle/README.md Demonstrates how to connect a data source using `attachStore` and handle cleanup logic by returning a function from `setup`. This is useful for managing resources like WebSocket connections. ```javascript setup(attachStore) { // getMouseValues function called before each render const onStoreChange = attachStore(getMouseValues); // call onStoreChange on every mouse event onMouseMove(onStoreChange); // cleanup logic return () => console.warn('On remove, do component cleanup here'); } ``` ```javascript setup(attachStore) { let newSocketValue; const onStoreChange = attachStore(() => newSocketValue); const ws = new WebSocket('ws://127.0.0.1/data'); ws.onmessage = ({ data }) => { newSocketValue = JSON.parse(data); onStoreChange(); }; // Return way to unsubscribe return ws.close.bind(ws); } ``` -------------------------------- ### Resource Cleanup in setup() Lifecycle Hook in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Shows how to properly manage resources that require cleanup within the `setup()` lifecycle hook of a HyperElement component. It emphasizes returning a cleanup function to prevent memory leaks. ```javascript setup(attachStore) { const interval = setInterval(attachStore(), 1000); return () => clearInterval(interval); // Cleanup on removal } ``` -------------------------------- ### Install hyper-element using npm Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md This command installs the hyper-element library using npm. It's a prerequisite for using the library in your project. ```bash npm install hyper-element ``` -------------------------------- ### Custom Element with Setup and Teardown Lifecycle - JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/functional-api.html Defines a custom element 'func-timer' that utilizes setup and teardown lifecycle methods for managing state and side effects. The setup function initializes an interval timer and returns a teardown function to clear it. Dependencies include hyperElement. Input is an object with setup and render properties. Output is a registered custom element. ```javascript hyperElement('func-timer', { setup: (ctx, onNext) => { let count = 0; const render = onNext(() => ({ count })); const interval = setInterval(() => { count++; render(); }, 100); return () => clearInterval(interval); }, render: (Html, ctx, store) => Html`Timer: ${store?.count || 0}` }); // Example usage (not fully provided in original text, but implied): // const timerElem = document.createElement('func-timer'); // document.getElementById('output-5').appendChild(timerElem); ``` -------------------------------- ### Run Local Server with Serve Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/README.md Starts a local HTTP server using 'npx serve .' to serve the project files. This is useful for accessing the HTML demo files directly in a browser. ```bash npx serve . ``` -------------------------------- ### JavaScript: Setup Cleanup Function on DOM Removal Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Demonstrates how to return a cleanup function from the `setup` method in HyperElement. This function is automatically executed when the element is removed from the DOM, allowing for resource management like closing WebSocket connections. ```javascript setup(attachStore) { let newSocketValue; const onStoreChange = attachStore(() => newSocketValue); const ws = new WebSocket('ws://127.0.0.1/data'); ws.onmessage = ({ data }) => { newSocketValue = JSON.parse(data); onStoreChange(); }; // Return cleanup function return ws.close.bind(ws); } ``` -------------------------------- ### Basic Template Syntax Example Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/template/README.md Demonstrates the basic syntax for template compilation in hyper-element, including simple variable interpolation, 'each' loops, and 'if/unless' conditionals. ```html
{name}
{+each items}
  • {name}
  • {-each} {+if show}

    Visible

    {else}

    Hidden

    {-if} {+unless hidden}

    Shown

    {-unless} ``` -------------------------------- ### Setup with Undefined Store - JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/coverage-edge-cases.html Tests the `onNext` function when called without a store argument, ensuring it handles an undefined store path gracefully. It verifies that the element renders correctly after a short delay. ```javascript customElements.define( 'no-store-elem', class extends hyperElement { setup(attachStore) { // Call attachStore with no arguments - triggers undefined store path const trigger = attachStore(); setTimeout(() => trigger(), 10); } render(Html) { Html`No store render`; } } ); const elem = document.createElement('no-store-elem'); document.getElementById('no-store-output').appendChild(elem); setTimeout(() => { const section = document.querySelector('কালের[data-test="setup-no-store"]'); if (elem && elem.textContent.includes('No store render')) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }, 100); ``` -------------------------------- ### Integrate Signals with hyper-element Lifecycle Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Shows a practical example of using signals within a hyper-element component. It sets up a reactive counter, triggers re-renders on signal changes, and exposes methods to update the signal. ```javascript import hyperElement, { signal, effect } from 'hyper-element'; hyperElement('counter-app', { setup: (ctx, onNext) => { const count = signal(0); // Trigger re-render when count changes const stopEffect = effect(() => { onNext(() => ({ count: count.value }))(); }); // Expose increment method ctx.increment = () => count.value++; // Cleanup effect on disconnect return stopEffect; }, handleClick: (ctx) => ctx.increment(), render: (Html, ctx, store) => Html` `, }); ``` -------------------------------- ### MobX Integration with HyperElement Source: https://context7.com/codemeasandwich/hyper-element/llms.txt Connect HyperElement components to MobX observables for reactive state management. The `setup` method uses `autorun` to re-render the component whenever observable state changes. State updates can be made directly within event handlers. ```javascript // MobX integration import { observable, autorun } from 'mobx'; const state = observable({ count: 0 }); hyperElement('mobx-counter', { setup: (ctx, onNext) => { // MobX autorun triggers on observable changes const dispose = autorun(onNext(state)); return dispose; }, render: (Html, ctx, store) => Html`
    ${store?.count ?? 0}
    ` }); ``` -------------------------------- ### Redux Integration with HyperElement Source: https://context7.com/codemeasandwich/hyper-element/llms.txt Integrate HyperElement with Redux to manage application state. The `setup` lifecycle method subscribes to the Redux store, and updates to the store automatically trigger component re-renders. Actions can be dispatched directly from event handlers. ```javascript // Redux integration import { createStore } from 'redux'; const store = createStore((state = { count: 0 }, action) => { switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } }); hyperElement('redux-counter', { setup: (ctx, onNext) => { // Connect store updates to render const unsubscribe = store.subscribe( onNext(store.getState) ); return unsubscribe; }, render: (Html, ctx, state) => Html`
    ${state?.count ?? 0}
    ` }); ``` -------------------------------- ### Signals in HyperElement Component (JavaScript) Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/signals.html Shows how to integrate `signal` within a custom `hyperElement` component. It defines a 'signal-counter' element with a reactive counter that updates the UI. The example demonstrates component setup, rendering, and updating signal values, triggering UI changes. ```javascript (function () { const section = document.querySelector('\\[data-test="signal-component"\\]'); customElements.define( 'signal-counter', class extends hyperElement { setup(attachStore) { this.count = signal(0); this.trigger = attachStore(); } render(Html) { Html`
    ${this.count.value}
    `; } increment() { this.count.value++; this.trigger(); } } ); const elem = document.createElement('signal-counter'); document.getElementById('signal-component-output').appendChild(elem); setTimeout(() => { const valueSpan = document.getElementById('signal-counter-value'); const btn = document.getElementById('signal-counter-btn'); const initial = valueSpan?.textContent; // Click button btn?.click(); setTimeout(() => { const after = valueSpan?.textContent; const pass = initial === '0' && after === '1'; section.dataset.testResult = pass ? 'pass' : 'fail'; }, 50); }, 100); })(); ``` -------------------------------- ### Set Initial Values for Store in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/lifecycle/README.md Illustrates how to provide initial values to the store that will be passed to every render cycle. ```javascript setup(attachStore) { attachStore({ max_levels: 3 }); // passed to every render } ``` -------------------------------- ### Create a Click Counter Element with Methods and Events Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/functional-api.html Illustrates the creation of a 'func-clicker' element that counts button clicks. It defines a `handleClick` method and uses it as an event listener for a button within the render function. The setup function manages the click count and provides an `increment` function. ```javascript hyperElement('func-clicker', { setup: (ctx, onNext) => { const store = { clicks: 0 }; const render = onNext(() => store); ctx.increment = () => { store.clicks++; render(); }; }, handleClick: (ctx, event) => ctx.increment(), render: (Html, ctx, store) => Html``, }); const elem6 = document.createElement('func-clicker'); document.getElementById('output-6').appendChild(elem6); setTimeout(() => { const btn = elem6.querySelector('button'); btn.click(); btn.click(); setTimeout(() => { const section = document.querySelector( '[data-test="methods-events"]' ); if (btn.textContent.includes('Clicks: 2')) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }, 50); }, 50); ``` -------------------------------- ### Multiple Subscriptions for Real-time and Periodic Updates in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/lifecycle/README.md Demonstrates setting up multiple subscriptions to a store for both real-time feedback and periodic updates, ensuring the component stays synchronized with data changes. ```javascript setup(attachStore) { const onStoreChange = attachStore(user); mobx.autorun(onStoreChange); // update when changed (real-time feedback) setInterval(onStoreChange, 1000); // update every second (update "the time is now ...") } ``` -------------------------------- ### JavaScript Signals Usage Example Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/signals/README.md Demonstrates how to import and use signal, computed, and effect primitives. It shows creating a signal, reading and writing its value, creating a computed value based on the signal, and setting up an effect that logs changes. Includes cleanup for the effect. ```javascript import { signal, computed, effect } from './signals/index.js'; // Create a signal const count = signal(0); // Read value console.log(count.value); // 0 // Write value (triggers updates) count.value = 1; // Derived value const doubled = computed(() => count.value * 2); // Side effect const cleanup = effect(() => { console.log('Count changed:', count.value); }); // Cleanup when done cleanup(); ``` -------------------------------- ### Use withOptions shorthand for rendering Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/styled.html Demonstrates the shorthand usage of `withOptions` for creating styled elements. This method simplifies the process of applying styles and rendering content, especially when only a render function is needed. ```javascript const themed12 = withOptions({ colors: { info: '#17a2b8' } }); themed12('styled-shorthand', (Html) => Html`Shorthand Works`); const elem12 = document.createElement('styled-shorthand'); document.getElementById('output-12').appendChild(elem12); requestAnimationFrame(() => { const section = document.querySelector( '[data-test="withoptions-shorthand"]' ); const span = elem12.querySelector('span'); const renderedCorrectly = span && span.textContent === 'Shorthand Works'; if (renderedCorrectly) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; console.log('withOptions shorthand test failed:', { renderedCorrectly, spanContent: span?.textContent }); } }); ``` -------------------------------- ### Define Custom Element with Setup and Render - JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/lifecycle-sequence.html Defines a custom HTML element 'element-ref-elem' that captures its tag name in the setup phase and renders it in the render phase. It then appends this element to the DOM and verifies its rendered tag name. ```javascript (function () { const section = document.querySelector('\\[data-test="element-ref"\\]'); customElements.define( 'element-ref-elem', class extends hyperElement { setup(onNext) { this.tagName = this.element.tagName.toLowerCase(); onNext(); } render(Html) { Html\`
    tag: ${this.tagName}
    \`; } } ); const elem = document.createElement('element-ref-elem'); document.getElementById('element-ref-output').appendChild(elem); requestAnimationFrame(() => { const result = document.getElementById('element-ref-result'); if (result?.textContent === 'tag: element-ref-elem') { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }); })(); ``` -------------------------------- ### Import and Use Rendering Utilities Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/render/README.md Shows how to import `html`, `bind`, and `wire` from the rendering module and use them for creating template 'holes', binding them to DOM elements, and creating keyed templates for efficient list rendering. ```javascript import { html, bind, wire } from './render/index.js'; // Create a hole const greeting = html`

    Hello ${name}

    `; // Bind to an element const render = bind(element); render`
    ${content}
    `; // Keyed templates const item = wire(obj, ':id')`
  • ${obj.name}
  • `; ``` -------------------------------- ### Conventional Commit Message (Bash) Source: https://github.com/codemeasandwich/hyper-element/blob/master/CONTRIBUTING.md This command commits staged changes using the Conventional Commits format, starting with 'feat:' to indicate a new feature. ```bash git commit -m "feat: add new feature" ``` -------------------------------- ### Define and Render Inline Template (HTML) Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/templates.html An example of an inline HTML template using the `` tag with a {variable} placeholder. This demonstrates the markup structure for a template that will be processed by hyper-element. ```html Hello {name}! ``` -------------------------------- ### Conventional Commit Message with Breaking Change (Bash) Source: https://github.com/codemeasandwich/hyper-element/blob/master/CONTRIBUTING.md This command commits staged changes using the Conventional Commits format, indicating a breaking change with '!' after the type, for example, 'feat!:'. ```bash git commit -m "feat!: remove deprecated API" ``` -------------------------------- ### Test teardown() called on disconnect in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/lifecycle-sequence.html Confirms that the teardown function returned by setup() is called when the custom element is removed from the DOM. It uses a flag to track if teardown was executed. ```javascript (function () { const section = document.querySelector( '[data-test="teardown-disconnect"]' ); let teardownCalled = false; customElements.define( 'teardown-elem', class extends hyperElement { setup(onNext) { onNext(); return () => { teardownCalled = true; }; } render(Html) { Html`
    teardown test
    ` } } ); const container = document.getElementById('teardown-output'); const elem = document.createElement('teardown-elem'); container.appendChild(elem); requestAnimationFrame(() => { // Remove element container.removeChild(elem); requestAnimationFrame(() => { if (teardownCalled) { section.dataset.testResult = 'pass'; container.innerHTML = '
    Teardown was called
    '; } else { section.dataset.testResult = 'fail'; container.innerHTML = '
    Teardown NOT called
    '; } }); }); })(); ``` -------------------------------- ### Running SSR Integration Tests Source: https://github.com/codemeasandwich/hyper-element/blob/master/todo/ssr-string-rendering.md Provides the command to build the SSR bundles and then run the integration tests. This ensures that the server-side rendering functionality works as expected across various scenarios. ```bash npm run build && node test/ssr.test.mjs ``` -------------------------------- ### Iterating Over Arrays with {+each} Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/template/README.md Explains how to use the '{+each}' block syntax to iterate over arrays within hyper-element templates. The 'list-elem' example renders an unordered list from an array of items. ```html ``` ```javascript customElements.define( 'list-elem', class extends hyperElement { render(Html) { Html`${Html.template({ items: [{ name: 'Ann' }, { name: 'Bob' }] })}`; } } ); ``` -------------------------------- ### Using HyperElement Signals with Components Source: https://context7.com/codemeasandwich/hyper-element/llms.txt Shows how to integrate hyper-element's signals API into custom components for reactive state management. It demonstrates creating signals within the `setup` function, connecting them to rendering via `onNext`, and exposing methods to modify state. ```javascript import hyperElement, { signal, effect } from 'hyper-element'; hyperElement('reactive-counter', { setup: (ctx, onNext) => { // Create signal-based state const count = signal(0); const step = signal(1); // Connect signal to component rendering const stopEffect = effect(() => { // Reading .value creates subscription onNext(() => ({ count: count.value, step: step.value }))(); }); // Expose methods to modify state ctx.increment = () => count.value += step.peek(); ctx.decrement = () => count.value -= step.peek(); ctx.setStep = (n) => step.value = n; // Cleanup effect on disconnect return stopEffect; }, render: (Html, ctx, store) => Html`
    ${store?.count ?? 0}
    ` }); ``` -------------------------------- ### Run Tests (Bash) Source: https://github.com/codemeasandwich/hyper-element/blob/master/CONTRIBUTING.md This command executes the test suite for the project using npm. It is expected that all tests pass with 100% code coverage. ```bash npm test ``` -------------------------------- ### Negated Conditional Rendering with {+unless} Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/template/README.md Demonstrates the use of the '{+unless}' block syntax for displaying content when a condition is falsy. The 'warning-elem' example shows a message when the 'valid' property is false. ```html {+unless valid}Invalid input!{-unless} ``` ```javascript customElements.define( 'warning-elem', class extends hyperElement { render(Html) { Html`${Html.template({ valid: false })}`; } } ); ``` -------------------------------- ### Create a Timer Component with Teardown in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Demonstrates how to create a custom timer element using HyperElement. It utilizes the `setup` function for initializing an interval and returning a cleanup function to clear the interval when the element is torn down. The `render` function displays the elapsed time. ```javascript hyperElement('my-timer', { setup: (ctx, onNext) => { let seconds = 0; const render = onNext(() => ({ seconds })); const interval = setInterval(() => { seconds++; render(); }, 1000); // Return cleanup function return () => clearInterval(interval); }, render: (Html, ctx, store) => Html`Elapsed: ${store?.seconds || 0}s`, }); ``` -------------------------------- ### Teardown Function Execution with disconnectedCallback Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/coverage-edge-cases.html Verifies that the teardown function returned by setup() is executed when an element is removed, confirming proper lifecycle management. This ensures that any subscriptions or event listeners are cleaned up. ```javascript (function () { const section = document.querySelector( '[data-test="disconnected-callback"]' ); let teardownCalled = false; customElements.define( 'disconnect-elem', class extends hyperElement { setup(onNext) { // Return teardown function return onNext(() => { teardownCalled = true; }); } render(Html) { Html`
    Connected
    `; } } ); const container = document.getElementById('disconnect-output'); container.innerHTML = ''; const elem = container.querySelector('disconnect-elem'); setTimeout(() => { // Remove element to trigger disconnectedCallback elem.remove(); // Check if teardown was called setTimeout(() => { section.dataset.testResult = teardownCalled ? 'pass' : 'fail'; }, 50); }, 100); })(); ``` -------------------------------- ### Disconnected Callback Teardown Test - JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/coverage-edge-cases.html Tests that the teardown function returned from `setup` is correctly called when a hyperElement is removed from the DOM. It uses a flag to track if the teardown function was executed. ```javascript let teardownCalled = false; customElements.define( 'teardown-elem', class extends hyperElement { setup(attachStore) { attachStore({ count: 0 }); // Return teardown function return () => { teardownCalled = true; }; } render(Html, store) { Html`Count: ${store ? store.count : 0}`; } } ); const container = document.getElementById('disconnected-output'); const elem6 = document.createElement('teardown-elem'); container.appendChild(elem6); setTimeout(() => { // Remove element to trigger disconnectedCallback container.removeChild(elem6); setTimeout(() => { const section = document.querySelector('কালের[data-test="disconnected"]'); if (teardownCalled) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }, 50); }, 50); ``` -------------------------------- ### Clone HyperElement Repository using Git Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Provides the command to clone the HyperElement repository from GitHub. This is the first step in setting up the development environment. ```bash git clone https://github.com/codemeasandwich/hyper-element.git cd hyper-element ``` -------------------------------- ### JavaScript Hyper-Element Integration Example Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/signals/README.md Illustrates integrating Signals as class properties within a hyper-element component. It shows how to define signals and computed properties, and use them within the render method to display reactive data and handle user interactions like button clicks. ```javascript class Counter extends hyperElement { count = signal(0); doubled = computed(() => this.count.value * 2); render(Html) { Html` ${this.count.value} `; } } ``` -------------------------------- ### Conditional Rendering with {+if} Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/template/README.md Illustrates how to use the '{+if}' block syntax for conditional rendering within hyper-element templates. The example shows a 'status-elem' that displays 'Online' or 'Offline' based on the 'active' property. ```html {+if active}Online{else}Offline{-if} ``` ```javascript customElements.define( 'status-elem', class extends hyperElement { render(Html) { Html`${Html.template({ active: true })}`; } } ); ``` -------------------------------- ### Re-render on innerHTML Change with hyper-element Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/content-mutations.html This example shows a custom element extending hyperElement. When its innerHTML is modified externally, the element re-renders, reflecting the updated wrappedContent. This is useful for dynamic content updates. ```javascript class extends hyperElement { render(Html) { Html`Content is: ${this.wrappedContent}` } } // Later: element.innerHTML = "CHANGED" // Re-renders with new content ``` ```javascript initial customElements.define( 'change-content', class extends hyperElement { render(Html) { Html`Content is: ${this.wrappedContent}`; } } ); // Change content after initial render setTimeout(() => { document.querySelector('change-content').innerHTML = 'CHANGED'; }, 50); // Check after mutation setTimeout(() => { const section = document.querySelector( '`[data-test="change-content"]`' ); const elem = document.querySelector('change-content'); if (elem && elem.textContent.includes('CHANGED')) { section.dataset.testResult = 'pass'; } else { section.dataset.testResult = 'fail'; } }, 150); ``` -------------------------------- ### Special Variables in {+each} Loops Source: https://github.com/codemeasandwich/hyper-element/blob/master/src/template/README.md Details the special variables available within '{+each}' loops in hyper-element templates: '{...}' for the current item and '{@}' for the current loop index. The 'nums-elem' example shows how to use both. ```html {+each numbers}{@}: {number}, {-each} ``` ```javascript customElements.define( 'nums-elem', class extends hyperElement { render(Html) { Html`${Html.template({ numbers: ['a', 'b', 'c'] })}`; } } ); ``` -------------------------------- ### Create and Manage a Reactive Signal Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Demonstrates the creation of a reactive signal using `signal()`, reading its value, updating it, peeking at the value without tracking, and subscribing to its changes. ```javascript const count = signal(0); // Read value (tracks dependencies in effects/computed) console.log(count.value); // 0 // Write value (notifies subscribers) count.value = 1; // Read without tracking count.peek(); // 1 // Subscribe to changes const unsubscribe = count.subscribe(() => { console.log('Count changed:', count.peek()); }); ``` -------------------------------- ### Render Inline Template with Variables (JavaScript) Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/templates.html Defines an inline HTML template with {variable} placeholders and renders it using Html.template() with provided data. This example shows how to create a reusable template structure that can be populated dynamically. ```javascript class extends hyperElement { render(Html) { Html`${Html.template({ name: "World" })}` } } ``` -------------------------------- ### Swap First and Last Items with HyperElement Wire Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/keyed-templates.html This example tests the dual swap path optimization in HyperElement's diff algorithm by swapping the first and last items in a list. It initializes a list, renders it, then modifies the order of items and triggers an update, verifying the correct reordering of DOM elements. This specifically targets the `a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]` condition. ```javascript (function () { const section = document.querySelector('\\[data-test="wire-swap-ends"\\]'); const itemA = { id: 'a', text: 'First' }; const itemB = { id: 'b', text: 'Middle' }; const itemC = { id: 'c', text: 'Last' }; customElements.define( 'wire-swap-ends-elem', class extends hyperElement { setup(attachStore) { this.element._items = [itemA, itemB, itemC]; this.element._trigger = attachStore(); } render(Html) { Html``; } } ); const elem = document.createElement('wire-swap-ends-elem'); document.getElementById('wire-swap-ends-output').appendChild(elem); setTimeout(() => { const list = document.getElementById('wire-swap-ends-list'); const initialOrder = Array.from(list?.querySelectorAll('li') || []).map(li => li.dataset.id); // Swap first and last: [C, B, A] - triggers the a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1] branch elem._items = [itemC, itemB, itemA]; elem._trigger(); setTimeout(() => { const newOrder = Array.from(list?.querySelectorAll('li') || []).map(li => li.dataset.id); const pass = initialOrder.join(',') === 'a,b,c' && newOrder.join(',') === 'c,b,a'; section.dataset.testResult = pass ? 'pass' : 'fail'; }, 100); }, 100); })(); ``` -------------------------------- ### Define Custom Element with HyperElement (HTML, JavaScript) Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Demonstrates how to define a custom HTML element 'my-elem' using the hyperElement library. It includes the necessary HTML structure, script inclusion, and the JavaScript code for defining the custom element's behavior, specifically rendering a 'hello world' message based on an attribute. ```html ``` -------------------------------- ### Direct Usage of Html.wire() for Wired Templates in JavaScript Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/coverage-edge-cases.html Tests the direct usage of Html.wire() for creating wired templates in JavaScript. This example demonstrates how to generate a list of elements using Html.wire() with mapped data. ```javascript (function () { const section = document.querySelector( '[data-test="html-wire-direct"]' ); customElements.define( 'html-wire-direct-elem', class extends hyperElement { render(Html) { const items = [ { id: 1, name: 'A' }, { id: 2, name: 'B' }, ]; const wired = items.map( (item) => Html.wire(item)`
  • ${item.name}
  • ` ); Html``; } } ); const elem = document.createElement('html-wire-direct-elem'); document.getElementById('html-wire-direct-output').appendChild(elem); setTimeout(() => { const result = document.getElementById('html-wire-direct-result'); const lis = result?.querySelectorAll('li') || []; const pass = lis.length === 2 && lis[0].textContent === 'A' && lis[1].textContent === 'B'; section.dataset.testResult = pass ? 'pass' : 'fail'; }, 100); })(); ``` -------------------------------- ### Run Source Code Tests Source: https://github.com/codemeasandwich/hyper-element/blob/master/README.md Executes the first phase of the testing workflow, focusing on source code coverage. It loads source files directly via ES modules and collects V8 coverage, requiring 100% coverage on all metrics. ```bash npm run test:src ``` -------------------------------- ### Remove Data-* Attribute Source: https://github.com/codemeasandwich/hyper-element/blob/master/kitchensink/coverage-edge-cases.html Tests that removing a `data-*` attribute from a custom element correctly deletes the corresponding property from the `dataset`. The example sets a `data-removable` attribute, then removes it, and verifies that the attribute is no longer present. ```javascript (function () { const section = document.querySelector( '[data-test="remove-data-attr"]' ); customElements.define( 'remove-data-elem', class extends hyperElement { render(Html) { const hasKey = this.dataset && 'removable' in this.dataset; Html`Has removable: ${hasKey}`; } } ); const elem = document.createElement('remove-data-elem'); document.getElementById('remove-data-attr-output').appendChild(elem); // Wait for element to connect, then set and remove attribute setTimeout(() => { elem.setAttribute('data-removable', 'exists'); setTimeout(() => { // Remove data attribute - triggers attributeChangedCallback with newVal=null elem.removeAttribute('data-removable'); setTimeout(() => { // Check using native dataset since our wrapper may have cleaned up const keyRemoved = elem.getAttribute('data-removable') === null; section.dataset.testResult = keyRemoved ? 'pass' : 'fail'; }, 100); }, 100); }, 100); })(); ```