# @domql/element

> Takes object and creates DOMQL element.

Latest version **3.8.9** (published 2026-03-29) · CC-BY-NC-4.0 license · 0 weekly downloads

## Install

```sh
npm install @domql/element
pnpm add @domql/element
yarn add @domql/element
bun add @domql/element
```

## Health

**Score 50/100 (C)** — status: active.

Positive: esm support; no vulnerabilities.

Warnings: low downloads; no types.

## Facts

| | |
|---|---|
| Version | 3.8.9 |
| Published | 2026-03-29 |
| First published | 2021-12-02 |
| Weekly downloads | 0 |
| License | CC-BY-NC-4.0 |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Dependencies | 4 |
| Unpacked size | 543.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | nikoloza |

## Links

- npm: https://www.npmjs.com/package/@domql/element
- npm.io page: https://npm.io/package/@domql/element

## Dependencies (4)

- [@domql/state](https://npm.io/package/@domql/state.md) ^3.8.9
- [@domql/utils](https://npm.io/package/@domql/utils.md) ^3.8.9
- [@domql/report](https://npm.io/package/@domql/report.md) ^3.8.9
- [attrs-in-props](https://npm.io/package/attrs-in-props.md) ^3.8.9

## Recent versions

- 3.8.9 (latest) — 2026-03-29
- 3.8.8 — 2026-03-29
- 3.8.7 — 2026-03-28
- 3.8.6 — 2026-03-24
- 3.8.1 — 2026-03-24
- 3.8.0 — 2026-03-17
- 3.7.6 — 2026-03-16
- 3.7.5 — 2026-03-15
- 3.7.4 — 2026-03-14
- 3.7.3 — 2026-03-14
- 3.7.0 — 2026-03-13
- 3.6.8 — 2026-03-13
- 3.6.7 — 2026-03-13
- 3.6.6 — 2026-03-12
- 3.6.4 — 2026-03-11
- … 541 more at https://npm.io/package/@domql/element/versions

## README

# DOMQL Element
Takes object and creates DOMQL element.

[![npm version](https://badge.fury.io/js/%40domql%2Felement.svg)](https://badge.fury.io/js/%40domql%2Felement)

### Example:
```javascript
import DOM from 'domql'

const Poster = {
  extends: [Link, Img],
  boxSize: [100, 200],
  borderRadius: 12,
  padding: 16,
  background: '#fff'
}

DOM.create(Poster, document.body)
```

### html mixin

The `html` mixin sets raw HTML content on an element. It supports both direct assignment and props:

```javascript
// Direct assignment (el.html)
const MyComponent = {
  html: '<strong>Hello</strong>'
}

// Via props (el.props.html) — works as an alias
const MyComponent = {
  props: { html: '<strong>Hello</strong>' }
}
```

`el.html` takes priority when both are set. `props.html` is used as a fallback when `el.html` is not defined.

## REGISTRY (`mixins/registry.js`)

The `REGISTRY` object defines which keys are recognized as framework properties (rather than child elements). Any key **not** in REGISTRY and starting with an uppercase letter is treated as a child element.

**Every framework-level key must be listed here.** If a key like `childExtend` is missing from REGISTRY, it gets interpreted as a child element name, causing silent rendering failures (e.g., cart components not rendering in Archy).

Current framework keys that must remain in REGISTRY:

```
extends, children, content,
childExtend (deprecated), childExtends,
childExtendRecursive (deprecated), childExtendsRecursive,
props, if, define,
__name, __ref, __hash, __text, key, tag, query, parent, node,
variables, on, component, context
```

Plus mixin handlers: `attr`, `style`, `text`, `html`, `data`, `classlist`, `state`, `scope`, `deps`.

## Scope and globalScope

During `create()`, `createScope(element, parent)` establishes a prototype chain:

```
el.scope → parent.scope → ... → root.scope → context.globalScope
```

- Elements without a `scope` property inherit their parent's scope (same reference)
- Elements with `scope: { ... }` get their own scope with parent's scope as prototype
- `context.globalScope` is auto-initialized as `{}` and sits at the chain's root

This enables serialized functions to access module-scoped values (constants, helpers) via `el.scope.X` without closures or imports — the values are placed in `globalScope` by the serialization pipeline and are accessible through prototype lookup.

> **v3 note:** `childExtend` (singular) is deprecated v2 syntax — use `childExtends` (plural) in new code. The singular forms remain in REGISTRY for backwards compatibility with older projects. If a key is missing from REGISTRY, it gets interpreted as a child element name, causing silent rendering failures.

## set.js — Content Setting

### Fragment forwarding

When `set()` receives content with `tag: 'fragment'`, the fragment itself doesn't create a DOM node — its children are inserted directly. This means:

1. **childExtends forwarding** — The parent's `childExtends` must be forwarded to the fragment's params so that fragment children inherit the correct extends:
   ```javascript
   if (tag === 'fragment') {
     const elementChildExtends = element.childExtends || element.childExtend
     if (!childExtends && elementChildExtends) {
       params.childExtends = elementChildExtends
     }
   }
   ```
   (Also checks deprecated `childExtend` for backwards compatibility with v2 projects.)

2. **childProps forwarding** — Similarly, `childProps` from the parent must be explicitly passed through the fragment to its children.

3. **ignoreChildProps** — When forwarding `childProps` through a fragment, set `props.ignoreChildProps = true` on the fragment itself to prevent the fragment from inheriting the parent's `childProps` via `inheritParentProps`. The `childProps` are already forwarded explicitly for the fragment's children.

### Infinite loop guard

`set()` includes a re-entrancy guard via `ref.__settingContent`. Without this, define handlers (like `$router`) that call `el.set()` can trigger infinite recursion when content-setting triggers another content-set cycle.

```javascript
if (ref.__settingContent) return element
ref.__settingContent = true
try {
  return _setInner(params, options, element)
} finally {
  ref.__settingContent = false
}
```

---
_Source: https://npm.io/package/@domql/element · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
