# `Noizu.Tessera.Component`
[🔗](https://github.com/the-robot-lives/tessera/blob/v0.2.0/lib/noizu/tessera/component.ex#L1)

`use Noizu.Tessera.Component, tag: "persona-card", js: "persona_card.mjs"`

Turns a module into a tessera component:

  * the `attr` / `prop` / `event` / `slot` / `cy` DSL declares the wire
    contract (CONTRACT.md §1); everything is validated at compile time and
    raises `CompileError` with a pointed message;
  * the module gains `__tessera_spec__/0` (a `Noizu.Tessera.Spec` struct)
    and `__tessera_manifest__/0` (a plain map);
  * at compile time the generated JS contract module
    (`<snake_tag>.contract.generated.mjs`, CONTRACT.md §2) is written next
    to the component's `.mjs` — only when its content changed; the `.mjs` is
    an `@external_resource`, so touching it recompiles and regenerates;
  * when Hologram is available (`Code.ensure_loaded?(Hologram.Component)`)
    the same module becomes a Hologram component via
    `Noizu.Tessera.Hologram.Adapter` (CONTRACT.md §3/§5). Without Hologram
    the module stays spec-only (the JS contract still generates).

## DSL

    use Noizu.Tessera.Component, tag: "persona-card", js: "persona_card.mjs"

    attr :display_name, :string, required: true
    attr :disabled, :boolean, default: false
    prop :tag_list, :list, json: true, default: []
    prop :filters, :map, json: true
    event "persona-select", detail: %{persona_id: :string, click_count: :integer}
    slot "header"
    css "--persona-card-accent", default: "#6366f1"
    part "select-button"
    cy "persona-card-root"

    styles ~CSS":host { border-color: var(--tsr-persona-card-accent, #6cf); }"

Element DSL (template-bearing components): `state`, `action`, the lifecycle
hooks `should_update` / `will_update` / `first_updated` / `updated` (each
`fn state, changed -> ... end`), and `?attr={expr}` boolean attribute
bindings in the template. `attr`/`prop`/`state` accept Lit property options
`attribute: "custom-name" | false` and `reflect: true`; `:list` types emit
Lit's `Array` converter.

Naming rules (CONTRACT.md §1): attr/prop/detail names are snake_case atoms;
`attr` names reach the DOM kebab-cased, `prop` names camelCased; event
names are kebab-case strings matching `^[a-z][a-z0-9]*(-[a-z0-9]+)+$`. Each
event also gets a binding prop `on_<event>` (e.g. `on_persona_select`)
whose value is `:action` (target `page`) or `{:action, target: "layout" |
cid}`.

When Hologram is loaded, `prop` is Hologram's own `prop/2,3` macro (imported
by `use Hologram.Component`); tessera opts `json:` and `default:` ride along
and are interpreted by this module's compiler. The `attr` macro additionally
declares the Hologram prop behind the scenes, and each `event` declares its
`on_<event>` binding prop — all during module-body expansion, so Hologram's
`@__props__` accumulator is complete before Hologram's `__before_compile__`
runs (hooks run in registration order, hologram's first).

Reserved names: the generated component defines `__tessera_*__` helpers and
`template/0` — do not define them by hand.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
