Skip to content

Elements

PreffX converts JSX markup directly into DOM elements. This allows you to configure detailed reactivity for attributes, properties, and event listeners using signals.

Implementation features:

  1. Reactivity: Uses a signal system (@preact/signals-core) to track changes in parameters
  2. Lifecycle management: Automatically removes event handlers and subscriptions when the element is removed
  3. Property name conversion: Converts camelCase to kebab-case for attributes
  4. Namespace support: Works with HTML, SVG, and MathML elements

Element Parameters

Parameters starting with $ set DOM element properties directly. If a signal is passed as the value, the property will be synchronized with that signal:

tsx
// static property
<div
  $innerHTML='<p>Content</p>'
></div>

// dynamic property
const textContent = signal('Text');
<div
  $textContent={textContent}
></div>

Parameters starting with on are handled as event listeners. You can pass either a simple handler function or an object with modifiers. If a signal is passed as the value, the handler will be synchronized with that signal:

tsx
// static event listener
<div
  onClick={() => console.log('clicked')}
></div>

// static event listener with modifiers
<div
  onClick={{
    handler: () => console.log('Click'),
    // prevent default
    prevent: true,
    // stop propagation
    stop: true,    
    // listener would be automatically removed when invoked
    once: true,
    // listener will never call preventDefault()
    passive: true,
    // events of this type will be dispatched to the
    // registered listener before being dispatched to any EventTarget
    // beneath it in the DOM tree
    capture: true
  }}
></div>

// dynamic event listener
const clickListener = signal(() => console.log('Click'));
<div
  onClick={clickListener}
></div>

The remaining parameters are processed as attributes:

tsx
// static attributes
<div
  id='my-id'
  data-value='123'
  style='color:red;font-size:16px;'
  class='active'
>
</div>

<div
  style={{
    color: 'red',
    fontSize: '16px'
  }}
  class={{
    active: true,
    passive: false
  }}
>
</div>

// dynamic attributes
const classNames = signal(['active', 'base']);
<div
  class={classNames}
></div>

Element Reference

The $ref parameter allows you to get a reference to the DOM element:

tsx
// you can use callback
let elementRef;
<div
  $ref={(el) => { elementRef = el; }}
></div>
// or signal
const signalRef = signal();
<div
  $ref={signalRef}
></div>

Namespace

This is usually not required, but you can explicitly specify the namespace for an element using the $ns parameter:

tsx
<svg>
  <a $ns='svg'></a>
</svg>

Released under the Apache-2.0 License.