### 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`
`;
```
--------------------------------
### 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`
';
}
});
});
})();
```
--------------------------------
### 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
{+each items}
{name}
{-each}
```
```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`
${wired}
`; } } ); 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); })();
```