Skip to content

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 07 Nov 15:35
7b3247d

Summary

Nativele 0.7.0 checks more of the contract between HTML and TypeScript: a data-on-* handler's parameter is checked against the event it is bound to, a form's elements and a list item's el are typed from the template. Lint, ts-dom check, codegen and the oxlint plugin now read how templates, classes and define() calls relate from one index that follows imports, barrels and namespaces, so they agree with each other on any file layout and stay current in the editor and the Vite dev server. The accessibility rules judge an element by its composed content, including what child components render into it, and say so with unchecked-content when they cannot. This release has breaking changes; see below.

Changes

Types and checks

  • A data-on-* handler may declare its event as its first parameter (onPick(e: EmitEvent<Picker, "pick">), onKey(e: KeyboardEvent)); define() checks it against the event the element declares for that name (the child's emits, the element's on<event> property, then HTMLElementEventMap), and ts-dom check reports a mismatch as handler-event-type at the attribute. this.on() checks an annotated parameter the same way.
  • A data-ref on a <form> types elements with the controls inside it by name and id; a misspelled name is a tsc error.
  • A list item's el is typed by the item's root tag: the item component's class for a component list, the element type for plain items.
  • New errors and warnings: each-in-svg (data-each inside <svg> or <math>), unchecked-custom-elements (custom elements lint has no single definition of, listed once per run with the cause and fix of each), and the a11y warning unchecked-content.
  • ts-dom lint and ts-dom check take --ignore=<rule-id> (repeatable) to leave out warnings.

Lint and tooling

  • One component index follows templates and classes through re-exports, barrels and namespaces and finds a class whose define() is in another file, so such components are in ts-dom-tags.ts, have typed refs, and get their props, events and template checked.
  • ts-dom check points missing-binding, missing-handler and handler-event-type at the template of the class the error is about, for every missing name, and keeps independent errors inside a broken class.
  • role-tabindex and click-semantics no longer overlap; click-semantics, control-name and heading-empty read what child components render, slots filled, so <div data-on-click><button> and a button whose name comes from a child component pass.
  • custom-event-on-native uses lib.dom's event names and reports only an event a component emits without bubbles: true.
  • The oxlint language server and the Vite plugin follow file changes across files (a child template, a new define(), a package.json) instead of keeping what they read first; the Vite plugin's a11y gives the same results as ts-dom lint --a11y.
  • Faster on large projects: each template is parsed once per run, a define() save regenerates only the templates that use the changed tags, and ts-dom gen --watch parses only the saved template.

Fixes

  • A data-on-* inside a data-if block of a list item now fires.
  • ts-dom lint and ts-dom gen report a missing folder as dir-not-found instead of crashing.
  • Templates imported from any folder, imported without .js, or used by a generic component class are found and checked.

Documentation and Skills

  • New Official Skill nativele-web-awesome; nativele-svelte, nativele-angular, nativele-zod, nativele-tanstack-query and nativele-tailwind are Official.
  • Every library rule is stated once in docs/ and linked from llms.txt; new recipes for request cancellation, config-driven tables, form-associated components and switching the language; AGENTS.md is a guide for agents that use the library.

Breaking Changes

  • Schema["events"] maps each handler to the [tag, event] pairs it is bound to instead of being a union of handler names. Migration: only a schema written by hand for template<...>() changes; use events: Record<never, never> for a template without handlers.
  • A handler whose first parameter does not accept the bound event (KeyboardEvent on a click, InputEvent on a change) is a tsc error (wrongHandlerParameters). Migration: declare the event type the error names, or type the parameter Event and narrow it in the body.
  • A list item's el is no longer Element, so a cast such as ctx.el as HTMLInputElement on an <li> item fails. Migration: remove the cast, or cast to the element the template has at the root.
  • The lint rule missing-handler is removed from ts-dom lint and the oxlint plugin (ts-dom/missing-handler); tsc reports a missing handler at define(), and ts-dom check reports it at the template under the same id. Migration: drop ts-dom/missing-handler from the linter config, and run ts-dom check or tsc where only ts-dom lint ran.
  • emits named focusin, focusout, compositionstart, compositionupdate, compositionend, touchstart, touchmove, touchend or touchcancel throws [native-event-name] in every browser (tsc already reported it). Migration: rename the event, for example with a prefix.
  • A custom event emitted with bubbles: true is handled in the bubble phase, so a stopPropagation() between its target and the handler now stops it. Migration: where the handler must still receive it, do not stop its propagation below that handler.