elements-kit 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/attributes.d.mts +1 -1
  2. package/dist/await.d.mts +1 -1
  3. package/dist/{children-CYLVeDZc.d.mts → children-C2OkLfJM.d.mts} +3 -3
  4. package/dist/{custom-elements-CdpilMDu.d.mts → custom-elements-C7oiqw-y.d.mts} +1 -1
  5. package/dist/custom-elements.d.mts +1 -1
  6. package/dist/{element-FFqOLWQu.mjs → element-Bwxltm6M.mjs} +1 -1
  7. package/dist/for.d.mts +1 -1
  8. package/dist/for.mjs +1 -1
  9. package/dist/{fragment-i-S0RyT4.mjs → fragment-DbiYZ5rL.mjs} +1 -1
  10. package/dist/hot-D_9wcFZ3.mjs +56 -0
  11. package/dist/hydrate/index.mjs +1 -1
  12. package/dist/{hydrate-DZ_o7akg.mjs → hydrate-3id6HROs.mjs} +2 -2
  13. package/dist/integrations/astro-client.mjs +14 -4
  14. package/dist/integrations/astro-server.mjs +2 -2
  15. package/dist/integrations/astro-slots.mjs +2 -2
  16. package/dist/integrations/astro.d.mts +5 -0
  17. package/dist/integrations/astro.mjs +9 -1
  18. package/dist/integrations/hmr-runtime.d.mts +25 -0
  19. package/dist/integrations/hmr-runtime.mjs +42 -0
  20. package/dist/integrations/hmr-slot.d.mts +24 -0
  21. package/dist/integrations/hmr-slot.mjs +24 -0
  22. package/dist/integrations/react.d.mts +1 -1
  23. package/dist/integrations/vite.d.mts +46 -0
  24. package/dist/integrations/vite.mjs +110 -0
  25. package/dist/jsx-runtime/dev.d.mts +13 -0
  26. package/dist/jsx-runtime/dev.mjs +4 -0
  27. package/dist/jsx-runtime/index.d.mts +2 -2
  28. package/dist/jsx-runtime/index.mjs +2 -2
  29. package/dist/server/index.mjs +1 -1
  30. package/dist/{server-C5Ka5iG2.mjs → server-3O_3GbAe.mjs} +2 -2
  31. package/dist/signals/index.d.mts +1 -1
  32. package/dist/ui/otp-input/index.d.mts +2 -2
  33. package/dist/utilities/active-element.d.mts +1 -1
  34. package/dist/utilities/async.d.mts +1 -1
  35. package/dist/utilities/debounced.d.mts +1 -1
  36. package/dist/utilities/element-rect.d.mts +1 -1
  37. package/dist/utilities/element-scroll.d.mts +1 -1
  38. package/dist/utilities/environment.d.mts +1 -1
  39. package/dist/utilities/event-driven.d.mts +1 -1
  40. package/dist/utilities/event-listener.d.mts +1 -1
  41. package/dist/utilities/focus-within.d.mts +1 -1
  42. package/dist/utilities/hover.d.mts +1 -1
  43. package/dist/utilities/interval.d.mts +1 -1
  44. package/dist/utilities/location.d.mts +1 -1
  45. package/dist/utilities/media-devices.d.mts +1 -1
  46. package/dist/utilities/media-player.d.mts +1 -1
  47. package/dist/utilities/media-query.d.mts +1 -1
  48. package/dist/utilities/network.d.mts +1 -1
  49. package/dist/utilities/orientation.d.mts +1 -1
  50. package/dist/utilities/previous.d.mts +1 -1
  51. package/dist/utilities/promise.d.mts +1 -1
  52. package/dist/utilities/routing.d.mts +1 -1
  53. package/dist/utilities/search-params.d.mts +1 -1
  54. package/dist/utilities/storage.d.mts +1 -1
  55. package/dist/utilities/throttled.d.mts +1 -1
  56. package/dist/utilities/timeout.d.mts +1 -1
  57. package/dist/utilities/window-focus.d.mts +1 -1
  58. package/dist/utilities/window-size.d.mts +1 -1
  59. package/package.json +4 -4
  60. /package/dist/{attributes-DILeh3-s.d.mts → attributes-3r7Diua4.d.mts} +0 -0
  61. /package/dist/{environment-Fg46vL6e.d.mts → environment-c2ftMYT0.d.mts} +0 -0
  62. /package/dist/{index-CzKKJCCK.d.mts → index-B1FHAd5T.d.mts} +0 -0
  63. /package/dist/{polyfill-C-CxgMqq.d.mts → polyfill-BVNd6ogU.d.mts} +0 -0
@@ -1,2 +1,2 @@
1
- import { a as Attributes, c as observedAttributes, i as AttributeTarget, n as AttrChangeHandler, o as attributes, r as AttributeDecorated, s as dispatchAttrChange, t as ATTRIBUTES } from "./attributes-DILeh3-s.mjs";
1
+ import { a as Attributes, c as observedAttributes, i as AttributeTarget, n as AttrChangeHandler, o as attributes, r as AttributeDecorated, s as dispatchAttrChange, t as ATTRIBUTES } from "./attributes-3r7Diua4.mjs";
2
2
  export { ATTRIBUTES, AttrChangeHandler, AttributeDecorated, AttributeTarget, Attributes, attributes, dispatchAttrChange, observedAttributes };
package/dist/await.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { s as Props, t as Children } from "./children-CYLVeDZc.mjs";
1
+ import { s as Props, t as Children } from "./children-C2OkLfJM.mjs";
2
2
 
3
3
  //#region src/await.d.ts
4
4
  /** @internal Metadata stamped on an Await region getter (see claim walk). */
@@ -1,6 +1,6 @@
1
- import { n as AttrChangeHandler, t as ATTRIBUTES } from "./attributes-DILeh3-s.mjs";
2
- import { i as PropertiesOf, n as CustomElementRegistry, r as EventsOf } from "./custom-elements-CdpilMDu.mjs";
3
- import { r as MaybeReactive } from "./index-CzKKJCCK.mjs";
1
+ import { n as AttrChangeHandler, t as ATTRIBUTES } from "./attributes-3r7Diua4.mjs";
2
+ import { i as PropertiesOf, n as CustomElementRegistry, r as EventsOf } from "./custom-elements-C7oiqw-y.mjs";
3
+ import { r as MaybeReactive } from "./index-B1FHAd5T.mjs";
4
4
  import * as CSS from "csstype";
5
5
  import { JSX } from "dom-expressions/src/jsx";
6
6
 
@@ -1,4 +1,4 @@
1
- import { t as ATTRIBUTES } from "./attributes-DILeh3-s.mjs";
1
+ import { t as ATTRIBUTES } from "./attributes-3r7Diua4.mjs";
2
2
 
3
3
  //#region src/custom-elements.d.ts
4
4
  type RegisteredElementInstances = { [K in keyof ElementsKit.CustomElementRegistry]: ElementsKit.CustomElementRegistry[K] extends (abstract new (...args: any[]) => infer I) ? I : never };
@@ -1,2 +1,2 @@
1
- import { a as PublicPropKeys, i as PropertiesOf, n as CustomElementRegistry, o as defineElement, r as EventsOf, t as AttributesOf } from "./custom-elements-CdpilMDu.mjs";
1
+ import { a as PublicPropKeys, i as PropertiesOf, n as CustomElementRegistry, o as defineElement, r as EventsOf, t as AttributesOf } from "./custom-elements-C7oiqw-y.mjs";
2
2
  export { AttributesOf, CustomElementRegistry, EventsOf, PropertiesOf, PublicPropKeys, defineElement };
@@ -619,4 +619,4 @@ function renderNode(node) {
619
619
  return renderNode(node.render());
620
620
  }
621
621
  //#endregion
622
- export { mountChild as a, BooleanAttributes as c, applyProps as i, ChildProperties as l, disposeElement as n, resolveChild as o, setRenderer as r, AttrAliases as s, createElement as t, Properties as u };
622
+ export { applyProps as a, AttrAliases as c, Properties as d, setRenderer as i, BooleanAttributes as l, disposeElement as n, mountChild as o, getRenderer as r, resolveChild as s, createElement as t, ChildProperties as u };
package/dist/for.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { o as MaybeReactiveProps } from "./children-CYLVeDZc.mjs";
1
+ import { o as MaybeReactiveProps } from "./children-C2OkLfJM.mjs";
2
2
 
3
3
  //#region src/for.d.ts
4
4
  type KeyFn<T> = (item: T, index: number) => string | number;
package/dist/for.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { C as untracked, S as trigger, _ as onCleanup, d as effectScope, u as effect, x as signal } from "./lib-DYypKhxk.mjs";
2
2
  import "./signals/index.mjs";
3
- import { n as disposeElement } from "./element-FFqOLWQu.mjs";
3
+ import { n as disposeElement } from "./element-Bwxltm6M.mjs";
4
4
  //#region src/for.ts
5
5
  /**
6
6
  * Keyed list renderer. See {@link ForProps} for prop details.
@@ -1,6 +1,6 @@
1
1
  import { _ as onCleanup, u as effect } from "./lib-DYypKhxk.mjs";
2
2
  import "./signals/index.mjs";
3
- import { a as mountChild } from "./element-FFqOLWQu.mjs";
3
+ import { o as mountChild } from "./element-Bwxltm6M.mjs";
4
4
  import { Slot } from "./slot.mjs";
5
5
  //#region src/jsx-runtime/fragment.ts
6
6
  /**
@@ -0,0 +1,56 @@
1
+ import { _ as onCleanup, u as effect, x as signal } from "./lib-DYypKhxk.mjs";
2
+ import "./signals/index.mjs";
3
+ import { r as getRenderer, t as createElement } from "./element-Bwxltm6M.mjs";
4
+ import { Slot } from "./slot.mjs";
5
+ import { HMR_CELLS_SLOT } from "./integrations/hmr-slot.mjs";
6
+ //#region src/jsx-runtime/hot.ts
7
+ const store = globalThis;
8
+ const cells = store[HMR_CELLS_SLOT] ??= /* @__PURE__ */ new WeakMap();
9
+ function cellFor(type) {
10
+ let cell = cells.get(type);
11
+ if (cell === void 0) {
12
+ cell = signal(type);
13
+ cells.set(type, cell);
14
+ }
15
+ return cell;
16
+ }
17
+ /**
18
+ * `createElement` with a hot-swappable component boundary. Intrinsic elements
19
+ * and non-DOM renderers fall straight through.
20
+ */
21
+ function createHotElement(type, allProps = {}) {
22
+ if (typeof type !== "function" || getRenderer()) return createElement(type, allProps);
23
+ const cell = cellFor(type);
24
+ const slot = new Slot();
25
+ effect(() => {
26
+ const node = createElement(cell(), allProps);
27
+ const dispose = node?.[Symbol.dispose];
28
+ if (node) slot.set(node);
29
+ else slot.set();
30
+ if (dispose) onCleanup(dispose);
31
+ });
32
+ onCleanup(() => slot.clear());
33
+ return slot.get();
34
+ }
35
+ /**
36
+ * Re-point the cells of every component the changed module exports. Returns
37
+ * whether any cell belonged to this module, which tells the caller whether the
38
+ * update was handled or has to fall back to a reload.
39
+ */
40
+ function updateCells(prev, next) {
41
+ let updated = false;
42
+ for (const key of Object.keys(prev)) {
43
+ const Prev = prev[key];
44
+ const Next = next[key];
45
+ if (typeof Prev !== "function" || typeof Next !== "function") continue;
46
+ const cell = cells.get(Prev);
47
+ if (cell === void 0) continue;
48
+ updated = true;
49
+ if (Next === Prev) continue;
50
+ cells.set(Next, cell);
51
+ cell(Next);
52
+ }
53
+ return updated;
54
+ }
55
+ //#endregion
56
+ export { updateCells as n, createHotElement as t };
@@ -1,2 +1,2 @@
1
- import { t as hydrate } from "../hydrate-DZ_o7akg.mjs";
1
+ import { t as hydrate } from "../hydrate-3id6HROs.mjs";
2
2
  export { hydrate };
@@ -2,10 +2,10 @@ import { C as untracked, _ as onCleanup, d as effectScope, n as CLAIM, t as ASYN
2
2
  import { isReactive } from "./signals/index.mjs";
3
3
  import { isReactivePromiseLike } from "./utilities/promise.mjs";
4
4
  import { flushDeferredAsyncRuns, isAsyncLike } from "./utilities/async.mjs";
5
- import { i as applyProps, o as resolveChild, r as setRenderer, t as createElement } from "./element-FFqOLWQu.mjs";
5
+ import { a as applyProps, i as setRenderer, s as resolveChild, t as createElement } from "./element-Bwxltm6M.mjs";
6
6
  import { Slot } from "./slot.mjs";
7
7
  import { For, isForComponent } from "./for.mjs";
8
- import { n as isFragmentComponent, r as parseHtml, t as Fragment } from "./fragment-i-S0RyT4.mjs";
8
+ import { n as isFragmentComponent, r as parseHtml, t as Fragment } from "./fragment-DbiYZ5rL.mjs";
9
9
  //#region src/hydrate/claim.ts
10
10
  let hydrationContext = null;
11
11
  function setHydrationContext(ctx) {
@@ -1,7 +1,8 @@
1
- import { t as createElement } from "../element-FFqOLWQu.mjs";
1
+ import { t as createElement } from "../element-Bwxltm6M.mjs";
2
2
  import { render } from "../render.mjs";
3
- import { t as hydrate } from "../hydrate-DZ_o7akg.mjs";
3
+ import { t as hydrate } from "../hydrate-3id6HROs.mjs";
4
4
  import { withSlotProps } from "./astro-slots.mjs";
5
+ import { HMR_SLOT } from "./hmr-slot.mjs";
5
6
  //#region src/integrations/astro-client.ts
6
7
  /**
7
8
  * Astro client entrypoint: hydrate an elements-kit island.
@@ -16,8 +17,17 @@ var astro_client_default = (element) => async (Component, props, slots, { client
16
17
  if (!element.hasAttribute("ssr")) return;
17
18
  const merged = withSlotProps(props, slots);
18
19
  const app = () => createElement(Component, merged);
19
- const dispose = client === "only" ? render(element, app) : hydrate(element, app).dispose;
20
- element.addEventListener("astro:unmount", () => dispose(), { once: true });
20
+ const record = {
21
+ element,
22
+ Component,
23
+ props: merged,
24
+ dispose: client === "only" ? render(element, app) : hydrate(element, app).dispose
25
+ };
26
+ const unregister = globalThis[HMR_SLOT]?.register(record);
27
+ element.addEventListener("astro:unmount", () => {
28
+ unregister?.();
29
+ record.dispose();
30
+ }, { once: true });
21
31
  };
22
32
  //#endregion
23
33
  export { astro_client_default as default };
@@ -1,7 +1,7 @@
1
1
  import { y as setInertEffects } from "../lib-DYypKhxk.mjs";
2
- import { r as setRenderer, t as createElement } from "../element-FFqOLWQu.mjs";
2
+ import { i as setRenderer, t as createElement } from "../element-Bwxltm6M.mjs";
3
3
  import { withSlotProps } from "./astro-slots.mjs";
4
- import { i as serverJsx, n as renderToString, r as SNode } from "../server-C5Ka5iG2.mjs";
4
+ import { i as serverJsx, n as renderToString, r as SNode } from "../server-3O_3GbAe.mjs";
5
5
  //#region src/integrations/astro-server.ts
6
6
  /**
7
7
  * Decide whether `Component` is an elements-kit component. Invoked by Astro
@@ -1,5 +1,5 @@
1
- import { t as createElement } from "../element-FFqOLWQu.mjs";
2
- import { t as Fragment } from "../fragment-i-S0RyT4.mjs";
1
+ import { t as createElement } from "../element-Bwxltm6M.mjs";
2
+ import { t as Fragment } from "../fragment-DbiYZ5rL.mjs";
3
3
  //#region src/integrations/astro-slots.ts
4
4
  /**
5
5
  * @internal Map Astro's pre-rendered slot HTML (`Record<name, html>`) into
@@ -27,6 +27,11 @@ interface ElementsKitAstroIntegration {
27
27
  * <Widget client:only="elements-kit" /> // client-rendered only
28
28
  * ```
29
29
  *
30
+ * In dev it also installs an HMR plugin: editing an island component swaps it
31
+ * in place instead of reloading the page. The island re-mounts, so its state
32
+ * resets — hoist anything that must survive into a module the edit doesn't
33
+ * invalidate.
34
+ *
30
35
  * Coexists with other framework renderers (React, etc.); scope their JSX
31
36
  * transform with the framework integration's `include` option.
32
37
  *
@@ -1,3 +1,4 @@
1
+ import elementsKitHmr from "./vite.mjs";
1
2
  //#region src/integrations/astro.ts
2
3
  /**
3
4
  * Astro integration: use elements-kit components as Astro islands.
@@ -12,6 +13,11 @@
12
13
  * <Widget client:only="elements-kit" /> // client-rendered only
13
14
  * ```
14
15
  *
16
+ * In dev it also installs an HMR plugin: editing an island component swaps it
17
+ * in place instead of reloading the page. The island re-mounts, so its state
18
+ * resets — hoist anything that must survive into a module the edit doesn't
19
+ * invalidate.
20
+ *
15
21
  * Coexists with other framework renderers (React, etc.); scope their JSX
16
22
  * transform with the framework integration's `include` option.
17
23
  *
@@ -53,9 +59,11 @@ function elementsKit() {
53
59
  "elements-kit/custom-elements",
54
60
  "elements-kit/attributes",
55
61
  "elements-kit/integrations/astro-client",
62
+ "elements-kit/integrations/hmr-runtime",
56
63
  "elements-kit/utilities/*"
57
64
  ] },
58
- resolve: { dedupe: ["elements-kit"] }
65
+ resolve: { dedupe: ["elements-kit"] },
66
+ plugins: [elementsKitHmr()]
59
67
  } });
60
68
  } }
61
69
  };
@@ -0,0 +1,25 @@
1
+ //#region src/integrations/hmr-runtime.d.ts
2
+ /**
3
+ * A live island mount. `Component` and `dispose` are mutable: a hot swap
4
+ * replaces both in place, so the `astro:unmount` listener closed over this
5
+ * record still tears down whatever is currently mounted.
6
+ */
7
+ interface IslandRecord {
8
+ element: Element;
9
+ Component: unknown;
10
+ props: Record<string, unknown>;
11
+ dispose: () => void;
12
+ }
13
+ interface ElementsKitHmr {
14
+ /** Track a mount. Returns an unregister function for unmount. */
15
+ register(record: IslandRecord): () => void;
16
+ /**
17
+ * Re-mount every island whose component came from a module that just
18
+ * changed. `false` means nothing on the page matched — the caller falls
19
+ * back to `import.meta.hot.invalidate()`.
20
+ */
21
+ swap(prev: Record<string, unknown>, next: Record<string, unknown>): boolean;
22
+ }
23
+ declare const _default: ElementsKitHmr;
24
+ //#endregion
25
+ export { ElementsKitHmr, IslandRecord, _default as default };
@@ -0,0 +1,42 @@
1
+ import { t as createElement } from "../element-Bwxltm6M.mjs";
2
+ import { render } from "../render.mjs";
3
+ import { HMR_SLOT } from "./hmr-slot.mjs";
4
+ import { n as updateCells } from "../hot-D_9wcFZ3.mjs";
5
+ //#region src/integrations/hmr-runtime.ts
6
+ const slot = globalThis;
7
+ const records = /* @__PURE__ */ new Set();
8
+ function register(record) {
9
+ records.add(record);
10
+ return () => {
11
+ records.delete(record);
12
+ };
13
+ }
14
+ /**
15
+ * Islands are matched by export identity, not by module URL: the changed
16
+ * module hands over its own exports, and a record belongs to it when one of
17
+ * those exports *is* the mounted component. That keeps this independent of
18
+ * Astro's `component-url` format and handles named exports for free.
19
+ */
20
+ function swap(prev, next) {
21
+ let swapped = updateCells(prev, next);
22
+ for (const record of records) {
23
+ const key = Object.keys(prev).find((name) => prev[name] === record.Component);
24
+ if (key === void 0) continue;
25
+ const Next = next[key];
26
+ if (typeof Next !== "function") continue;
27
+ swapped = true;
28
+ if (Next === record.Component) continue;
29
+ record.dispose();
30
+ record.element.replaceChildren();
31
+ record.Component = Next;
32
+ record.dispose = render(record.element, () => createElement(Next, record.props));
33
+ }
34
+ return swapped;
35
+ }
36
+ slot[HMR_SLOT] ??= {
37
+ register,
38
+ swap
39
+ };
40
+ var hmr_runtime_default = slot[HMR_SLOT];
41
+ //#endregion
42
+ export { hmr_runtime_default as default };
@@ -0,0 +1,24 @@
1
+ //#region src/integrations/hmr-slot.d.ts
2
+ /**
3
+ * Where the dev HMR registry lives.
4
+ *
5
+ * Its own module because the three users can't share one: the client
6
+ * entrypoint needs the key but must not pull in the registry (which would drag
7
+ * `render` and the island bookkeeping into production bundles), and the Vite
8
+ * plugin runs in Node and only ever emits the name into generated source.
9
+ *
10
+ * `Symbol.for` rather than a fresh symbol: duplicate module copies (dev
11
+ * pre-bundling, mixed chunks) have to land on the same slot or a swap would
12
+ * miss islands the other copy mounted — same reasoning as the active renderer.
13
+ */
14
+ declare const HMR_SLOT_NAME = "elements-kit.hmr";
15
+ declare const HMR_SLOT: unique symbol;
16
+ /**
17
+ * Where the dev JSX runtime keeps its component cells. Separate from the
18
+ * island registry above because the two are populated by different entrypoints
19
+ * — `jsx-dev-runtime` for cells, the Astro client for islands — and either can
20
+ * load without the other.
21
+ */
22
+ declare const HMR_CELLS_SLOT: unique symbol;
23
+ //#endregion
24
+ export { HMR_CELLS_SLOT, HMR_SLOT, HMR_SLOT_NAME };
@@ -0,0 +1,24 @@
1
+ //#region src/integrations/hmr-slot.ts
2
+ /**
3
+ * Where the dev HMR registry lives.
4
+ *
5
+ * Its own module because the three users can't share one: the client
6
+ * entrypoint needs the key but must not pull in the registry (which would drag
7
+ * `render` and the island bookkeeping into production bundles), and the Vite
8
+ * plugin runs in Node and only ever emits the name into generated source.
9
+ *
10
+ * `Symbol.for` rather than a fresh symbol: duplicate module copies (dev
11
+ * pre-bundling, mixed chunks) have to land on the same slot or a swap would
12
+ * miss islands the other copy mounted — same reasoning as the active renderer.
13
+ */
14
+ const HMR_SLOT_NAME = "elements-kit.hmr";
15
+ const HMR_SLOT = Symbol.for(HMR_SLOT_NAME);
16
+ /**
17
+ * Where the dev JSX runtime keeps its component cells. Separate from the
18
+ * island registry above because the two are populated by different entrypoints
19
+ * — `jsx-dev-runtime` for cells, the Astro client for islands — and either can
20
+ * load without the other.
21
+ */
22
+ const HMR_CELLS_SLOT = Symbol.for("elements-kit.hmr-cells");
23
+ //#endregion
24
+ export { HMR_CELLS_SLOT, HMR_SLOT, HMR_SLOT_NAME };
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/integrations/react.d.ts
4
4
  /**
@@ -0,0 +1,46 @@
1
+ //#region src/integrations/vite.d.ts
2
+ interface TransformOptions {
3
+ ssr?: boolean;
4
+ }
5
+ interface TransformResult {
6
+ code: string;
7
+ map: null;
8
+ }
9
+ interface ElementsKitHmrPlugin {
10
+ name: string;
11
+ apply: "serve";
12
+ enforce: "post";
13
+ transform(code: string, id: string, options?: TransformOptions): TransformResult | undefined;
14
+ }
15
+ /**
16
+ * Vite plugin: give elements-kit component modules an HMR accept boundary, so
17
+ * editing one swaps the components it exports instead of reloading the page.
18
+ *
19
+ * The swap itself lives in `elements-kit/jsx-dev-runtime`, which renders every
20
+ * component through a signal holding its current implementation. This plugin
21
+ * only supplies the trigger — which module changed, and what it exported
22
+ * before.
23
+ *
24
+ * Dev only (`apply: "serve"`) and client only — production builds and SSR
25
+ * transforms emit nothing, so no HMR code ships.
26
+ *
27
+ * The Astro integration registers this for you; add it by hand in a plain Vite
28
+ * app. A swapped component re-runs, so its own state resets — keep anything
29
+ * that must survive in a module the edit doesn't invalidate.
30
+ *
31
+ * A module that registers a custom element at top level can't be swapped:
32
+ * re-evaluating it calls `customElements.define` twice, which throws. Give
33
+ * those their own module.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * // vite.config.ts
38
+ * import { defineConfig } from "vite";
39
+ * import elementsKit from "elements-kit/integrations/vite";
40
+ *
41
+ * export default defineConfig({ plugins: [elementsKit()] });
42
+ * ```
43
+ */
44
+ declare function elementsKitHmr(): ElementsKitHmrPlugin;
45
+ //#endregion
46
+ export { ElementsKitHmrPlugin, TransformOptions, TransformResult, elementsKitHmr as default };
@@ -0,0 +1,110 @@
1
+ import { HMR_SLOT_NAME } from "./hmr-slot.mjs";
2
+ //#region src/integrations/vite.ts
3
+ const COMPONENT_MODULE = /\.[cm]?[jt]sx(\?|$)/;
4
+ const JSX_RUNTIME_IMPORT = /["']elements-kit\/jsx-(?:dev-)?runtime["']/;
5
+ /**
6
+ * Vite plugin: give elements-kit component modules an HMR accept boundary, so
7
+ * editing one swaps the components it exports instead of reloading the page.
8
+ *
9
+ * The swap itself lives in `elements-kit/jsx-dev-runtime`, which renders every
10
+ * component through a signal holding its current implementation. This plugin
11
+ * only supplies the trigger — which module changed, and what it exported
12
+ * before.
13
+ *
14
+ * Dev only (`apply: "serve"`) and client only — production builds and SSR
15
+ * transforms emit nothing, so no HMR code ships.
16
+ *
17
+ * The Astro integration registers this for you; add it by hand in a plain Vite
18
+ * app. A swapped component re-runs, so its own state resets — keep anything
19
+ * that must survive in a module the edit doesn't invalidate.
20
+ *
21
+ * A module that registers a custom element at top level can't be swapped:
22
+ * re-evaluating it calls `customElements.define` twice, which throws. Give
23
+ * those their own module.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * // vite.config.ts
28
+ * import { defineConfig } from "vite";
29
+ * import elementsKit from "elements-kit/integrations/vite";
30
+ *
31
+ * export default defineConfig({ plugins: [elementsKit()] });
32
+ * ```
33
+ */
34
+ function elementsKitHmr() {
35
+ return {
36
+ name: "elements-kit:hmr",
37
+ apply: "serve",
38
+ enforce: "post",
39
+ transform(code, id, options) {
40
+ if (options?.ssr) return;
41
+ if (!COMPONENT_MODULE.test(id)) return;
42
+ if (id.includes("/node_modules/")) return;
43
+ if (!JSX_RUNTIME_IMPORT.test(code)) return;
44
+ const exported = collectExports(code);
45
+ if (exported.length === 0) return;
46
+ return {
47
+ code: `${code}\n${footer(exported)}`,
48
+ map: null
49
+ };
50
+ }
51
+ };
52
+ }
53
+ /**
54
+ * `swap` needs the module's *previous* exports to match against mounted
55
+ * components, so the accept callback closes over them from inside the old
56
+ * module instance.
57
+ *
58
+ * `invalidate()` is the escape hatch, and it is load-bearing: a module that
59
+ * self-accepts with no island on the page would otherwise leave its importers
60
+ * holding stale bindings. Invalidating re-propagates the update upward, back
61
+ * to the ordinary reload.
62
+ */
63
+ function footer(exported) {
64
+ return `import "elements-kit/integrations/hmr-runtime";
65
+ if (import.meta.hot) {
66
+ const __ek_prev = { ${exported.map(([name, local]) => `${JSON.stringify(name)}: ${local}`).join(", ")} };
67
+ import.meta.hot.accept((__ek_next) => {
68
+ const __ek_hmr = globalThis[Symbol.for(${JSON.stringify(HMR_SLOT_NAME)})];
69
+ if (!__ek_next || !__ek_hmr || !__ek_hmr.swap(__ek_prev, __ek_next)) {
70
+ import.meta.hot.invalidate();
71
+ }
72
+ });
73
+ }
74
+ `;
75
+ }
76
+ const IDENT = String.raw`[A-Za-z_$][\w$]*`;
77
+ const DECLARATIONS = [new RegExp(String.raw`^export\s+default\s+(?:async\s+)?(?:function\s*\*?\s+|class\s+)(${IDENT})`, "gm"), new RegExp(String.raw`^export\s+default\s+(${IDENT})\s*;`, "gm")];
78
+ const NAMED = [
79
+ new RegExp(String.raw`^export\s+(?:async\s+)?function\s*\*?\s+(${IDENT})`, "gm"),
80
+ new RegExp(String.raw`^export\s+class\s+(${IDENT})`, "gm"),
81
+ new RegExp(String.raw`^export\s+(?:const|let|var)\s+(${IDENT})`, "gm")
82
+ ];
83
+ const SPECIFIER_LIST = /^export\s*\{([^}]*)\}\s*;/gm;
84
+ /**
85
+ * Exported name → local binding, read off the post-transform ESM. The output
86
+ * is machine-generated, so the shapes are regular.
87
+ *
88
+ * An anonymous `export default () => …` has no binding to reference and is
89
+ * skipped. The module still self-accepts; `swap` finds no match and falls
90
+ * through to `invalidate()`, which is the pre-existing reload behaviour.
91
+ */
92
+ function collectExports(code) {
93
+ const found = /* @__PURE__ */ new Map();
94
+ for (const pattern of DECLARATIONS) for (const match of code.matchAll(pattern)) if (!found.has("default")) found.set("default", match[1]);
95
+ for (const pattern of NAMED) for (const match of code.matchAll(pattern)) {
96
+ const name = match[1];
97
+ if (!found.has(name)) found.set(name, name);
98
+ }
99
+ for (const match of code.matchAll(SPECIFIER_LIST)) for (const entry of match[1].split(",")) {
100
+ const parts = entry.trim().split(/\s+as\s+/);
101
+ if (parts.length === 0 || parts[0] === "") continue;
102
+ const local = parts[0].trim();
103
+ const name = (parts[1] ?? local).trim();
104
+ if (!new RegExp(`^${IDENT}$`).test(local)) continue;
105
+ if (!found.has(name)) found.set(name, local);
106
+ }
107
+ return [...found];
108
+ }
109
+ //#endregion
110
+ export { elementsKitHmr as default };
@@ -0,0 +1,13 @@
1
+ import { a as Fragment, c as PropsOf, i as JSX, l as Require, n as ComponentClass, o as MaybeReactiveProps, r as ComponentFn, s as Props, t as Children } from "../children-C2OkLfJM.mjs";
2
+ import { n as ComputedProps, r as MaybeReactive } from "../index-B1FHAd5T.mjs";
3
+
4
+ //#region src/jsx-runtime/hot.d.ts
5
+ /**
6
+ * `createElement` with a hot-swappable component boundary. Intrinsic elements
7
+ * and non-DOM renderers fall straight through.
8
+ */
9
+ declare function createHotElement(type: JSX.ElementType, allProps?: {
10
+ ref?: (el: Element) => void;
11
+ } & Record<string, unknown>): JSX.Element | null;
12
+ //#endregion
13
+ export { type Children, ComponentClass, ComponentFn, type ComputedProps, Fragment, JSX, type MaybeReactive, type MaybeReactiveProps, type Props, type PropsOf, type Require, createHotElement as h, createHotElement as jsx, createHotElement as jsxDEV, createHotElement as jsxs };
@@ -0,0 +1,4 @@
1
+ import { t as Fragment } from "../fragment-DbiYZ5rL.mjs";
2
+ import { t as createHotElement } from "../hot-D_9wcFZ3.mjs";
3
+ import "./index.mjs";
4
+ export { Fragment, createHotElement as h, createHotElement as jsx, createHotElement as jsxDEV, createHotElement as jsxs };
@@ -1,3 +1,3 @@
1
- import { a as Fragment, c as PropsOf, i as JSX, l as Require, n as ComponentClass, o as MaybeReactiveProps, r as ComponentFn, s as Props, t as Children, u as createElement } from "../children-CYLVeDZc.mjs";
2
- import { n as ComputedProps, r as MaybeReactive } from "../index-CzKKJCCK.mjs";
1
+ import { a as Fragment, c as PropsOf, i as JSX, l as Require, n as ComponentClass, o as MaybeReactiveProps, r as ComponentFn, s as Props, t as Children, u as createElement } from "../children-C2OkLfJM.mjs";
2
+ import { n as ComputedProps, r as MaybeReactive } from "../index-B1FHAd5T.mjs";
3
3
  export { type Children, ComponentClass, ComponentFn, type ComputedProps, Fragment, JSX, type MaybeReactive, type MaybeReactiveProps, type Props, type PropsOf, type Require, createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -1,3 +1,3 @@
1
- import { t as createElement } from "../element-FFqOLWQu.mjs";
2
- import { t as Fragment } from "../fragment-i-S0RyT4.mjs";
1
+ import { t as createElement } from "../element-Bwxltm6M.mjs";
2
+ import { t as Fragment } from "../fragment-DbiYZ5rL.mjs";
3
3
  export { Fragment, createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -1,2 +1,2 @@
1
- import { n as renderToString, t as renderToStream } from "../server-C5Ka5iG2.mjs";
1
+ import { n as renderToString, t as renderToStream } from "../server-3O_3GbAe.mjs";
2
2
  export { renderToStream, renderToString };
@@ -2,9 +2,9 @@ import { C as untracked, y as setInertEffects } from "./lib-DYypKhxk.mjs";
2
2
  import { isReactive } from "./signals/index.mjs";
3
3
  import { isReactivePromiseLike } from "./utilities/promise.mjs";
4
4
  import { isAsyncLike } from "./utilities/async.mjs";
5
- import { c as BooleanAttributes, l as ChildProperties, r as setRenderer, s as AttrAliases, u as Properties } from "./element-FFqOLWQu.mjs";
5
+ import { c as AttrAliases, d as Properties, i as setRenderer, l as BooleanAttributes, u as ChildProperties } from "./element-Bwxltm6M.mjs";
6
6
  import { isForComponent } from "./for.mjs";
7
- import { n as isFragmentComponent } from "./fragment-i-S0RyT4.mjs";
7
+ import { n as isFragmentComponent } from "./fragment-DbiYZ5rL.mjs";
8
8
  //#region src/server/escape.ts
9
9
  function escapeDelim(s, delim, escDelim) {
10
10
  let iDelim = s.indexOf(delim);
@@ -1,2 +1,2 @@
1
- import { C as isSignal, D as untracked, E as trigger, S as isEffectScope, T as signal, _ as computed, a as Updater, b as isComputed, c as reactive, d as COMPUTED, f as EFFECT, g as batch, h as SIGNAL, i as Signal, l as resolve, m as SEED, n as ComputedProps, o as computedProps, p as EFFECT_SCOPE, r as MaybeReactive, s as isReactive, t as Computed, u as CLAIM, v as effect, w as onCleanup, x as isEffect, y as effectScope } from "../index-CzKKJCCK.mjs";
1
+ import { C as isSignal, D as untracked, E as trigger, S as isEffectScope, T as signal, _ as computed, a as Updater, b as isComputed, c as reactive, d as COMPUTED, f as EFFECT, g as batch, h as SIGNAL, i as Signal, l as resolve, m as SEED, n as ComputedProps, o as computedProps, p as EFFECT_SCOPE, r as MaybeReactive, s as isReactive, t as Computed, u as CLAIM, v as effect, w as onCleanup, x as isEffect, y as effectScope } from "../index-B1FHAd5T.mjs";
2
2
  export { CLAIM, COMPUTED, Computed, ComputedProps, EFFECT, EFFECT_SCOPE, MaybeReactive, SEED, SIGNAL, Signal, Updater, batch, computed, computedProps, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, onCleanup, reactive, resolve, signal, trigger, untracked };
@@ -1,5 +1,5 @@
1
- import { n as AttrChangeHandler, t as ATTRIBUTES } from "../../attributes-DILeh3-s.mjs";
2
- import { t as HTMLElementBase } from "../../environment-Fg46vL6e.mjs";
1
+ import { n as AttrChangeHandler, t as ATTRIBUTES } from "../../attributes-3r7Diua4.mjs";
2
+ import { t as HTMLElementBase } from "../../environment-c2ftMYT0.mjs";
3
3
 
4
4
  //#region src/ui/otp-input/otp-input.d.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/active-element.d.ts
4
4
  declare const activeElement: Computed<Element | null>;
@@ -1,4 +1,4 @@
1
- import { m as SEED, r as MaybeReactive, u as CLAIM } from "../index-CzKKJCCK.mjs";
1
+ import { m as SEED, r as MaybeReactive, u as CLAIM } from "../index-B1FHAd5T.mjs";
2
2
  import { ComputedPromise } from "./promise.mjs";
3
3
 
4
4
  //#region src/utilities/async.d.ts
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/debounced.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/element-rect.d.ts
4
4
  type RectResult = {
@@ -1,4 +1,4 @@
1
- import { i as Signal } from "../index-CzKKJCCK.mjs";
1
+ import { i as Signal } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/element-scroll.d.ts
4
4
  type ElementScrollResult = {
@@ -1,2 +1,2 @@
1
- import { n as isBrowser, r as noopDisposable, t as HTMLElementBase } from "../environment-Fg46vL6e.mjs";
1
+ import { n as isBrowser, r as noopDisposable, t as HTMLElementBase } from "../environment-c2ftMYT0.mjs";
2
2
  export { HTMLElementBase, isBrowser, noopDisposable };
@@ -1,4 +1,4 @@
1
- import { i as Signal, t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { i as Signal, t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/event-driven.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/event-listener.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/focus-within.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/hover.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/interval.d.ts
4
4
  type IntervalResult = {
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/location.d.ts
4
4
  type LocationResult = {
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/media-devices.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { i as Signal, t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { i as Signal, t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/media-player.d.ts
4
4
  type MediaPlayerResult<T extends HTMLMediaElement> = {
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/media-query.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/network.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/orientation.d.ts
4
4
  type OrientationResult = {
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/previous.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { m as SEED, t as Computed, u as CLAIM } from "../index-CzKKJCCK.mjs";
1
+ import { m as SEED, t as Computed, u as CLAIM } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/promise.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/routing.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/search-params.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { i as Signal } from "../index-CzKKJCCK.mjs";
1
+ import { i as Signal } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/storage.d.ts
4
4
  type StorageOptions<T> = {
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/throttled.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/timeout.d.ts
4
4
  type TimeoutResult = {
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/window-focus.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../index-CzKKJCCK.mjs";
1
+ import { t as Computed } from "../index-B1FHAd5T.mjs";
2
2
 
3
3
  //#region src/utilities/window-size.d.ts
4
4
  type WindowSizeResult = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elements-kit",
3
3
  "type": "module",
4
- "version": "0.24.0",
4
+ "version": "0.25.0",
5
5
  "description": "A lightweight reactive UI library that transforms native HTMLElements into reactive components with signals. Ideal for framework-agnostic applications and web components.",
6
6
  "keywords": [
7
7
  "webcomponents",
@@ -90,9 +90,9 @@
90
90
  "types": "./dist/jsx-runtime/index.d.mts"
91
91
  },
92
92
  "./jsx-dev-runtime": {
93
- "source": "./src/jsx-runtime/index.ts",
94
- "import": "./dist/jsx-runtime/index.mjs",
95
- "types": "./dist/jsx-runtime/index.d.mts"
93
+ "source": "./src/jsx-runtime/dev.ts",
94
+ "import": "./dist/jsx-runtime/dev.mjs",
95
+ "types": "./dist/jsx-runtime/dev.d.mts"
96
96
  },
97
97
  "./integrations/*": {
98
98
  "source": "./src/integrations/*.ts",