microtags 0.0.5 → 0.0.9

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.
package/README.md CHANGED
@@ -13,7 +13,7 @@ Web component helper with reactive props, automatic cleanup, and no
13
13
  [Shadow DOM](https://gomakethings.com/the-shadow-dom-is-an-antipattern/).
14
14
  Reactive via [alien-signals](https://github.com/stackblitz/alien-signals).
15
15
 
16
- **Size**: 3.41 kB with all dependencies, minified and brotlied
16
+ **Size: <!-- size -->3.47 KB<!-- /size -->** with all dependencies, minified and brotlied
17
17
 
18
18
  Inspired by [nanotags](https://nanotags.psdcoder.dev/). Reactive props use
19
19
  **alien-signals** instead of nanostores atoms.
@@ -40,14 +40,25 @@ Inspired by [nanotags](https://nanotags.psdcoder.dev/). Reactive props use
40
40
  * [`withContexts`](#withcontexts)
41
41
  * [`setup` and `ctx`](#setup-and-ctx)
42
42
  + [peek and untracked](#peek-and-untracked)
43
+ * [Typed Events](#typed-events)
43
44
  - [Templates](#templates)
44
45
  - [Subpath Exports](#subpath-exports)
45
46
  * [`microtags/context`](#microtagscontext)
46
47
  * [`microtags/render`](#microtagsrender)
47
48
  + [`renderList`](#renderlist)
48
49
  + [`render`](#render)
49
- + [Templates](#templates-1)
50
- - [Divergence from nanotags](#divergence-from-nanotags)
50
+ * [`microtags/util`](#microtagsutil)
51
+ + [Coercion](#coercion)
52
+ + [`runCleanups`](#runcleanups)
53
+ + [`toAttributes`](#toattributes)
54
+ - [Divergence from `nanotags`](#divergence-from-nanotags)
55
+ * [Reactivity primitive](#reactivity-primitive)
56
+ * [Effects + Subscriptions](#effects--subscriptions)
57
+ * [Refs: `r.all` instead of `r.many`](#refs-rall-instead-of-rmany)
58
+ * [Context API](#context-api)
59
+ * [Props](#props-1)
60
+ * [Not ported](#not-ported)
61
+ * [Additions / New Features](#additions--new-features)
51
62
 
52
63
  <!-- tocstop -->
53
64
 
@@ -321,7 +332,6 @@ Declare reactive attributes via `withProps`. Each prop becomes:
321
332
  | `p.boolean()` | `"true"` / `""` &rarr; `true`, `"false"` &rarr; `false` | `false` |
322
333
  | `p.oneOf(opts)` | Picklist enum, throws on invalid | throws |
323
334
 
324
-
325
335
  #### `withProps`
326
336
 
327
337
  ```ts
@@ -335,6 +345,41 @@ Declare reactive attributes via `withProps`. Each prop becomes:
335
345
  }))
336
346
  ```
337
347
 
348
+ ##### `p.json`
349
+
350
+ `p.json<T>()` -- a prop whose attribute value is parsed with
351
+ `JSON.parse`. The type parameter `T` annotates the parsed result; it is a
352
+ type only, so the value is not validated at runtime. The resulting signal is
353
+ typed `T | undefined`.
354
+
355
+ ```ts
356
+ .withProps(p => ({
357
+ user: p.json<{ id:number; name:string }>(),
358
+ }))
359
+ ```
360
+
361
+ ```html
362
+ <my-el user='{"id":1,"name":"Alice"}'></my-el>
363
+ ```
364
+
365
+ Like the string/number/boolean validators it is attribute-backed and
366
+ observed, so editing the attribute re-parses and pushes the new value to
367
+ `ctx.props.user`. It falls back to `undefined` in two cases: when the
368
+ attribute is absent, and when the value is not valid JSON. Parse errors are
369
+ swallowed rather than thrown.
370
+
371
+ ```ts
372
+ // check for `undefined` case
373
+ ctx.effect(() => {
374
+ const user = ctx.props.user()
375
+ if (!user) return
376
+ ctx.refs.name.textContent = user.name
377
+ })
378
+ ```
379
+
380
+ For input you want validated rather than only parsed, pass a Standard Schema
381
+ to [`p.schema`](#withprops) instead.
382
+
338
383
  Inside `setup()`, every prop is a callable signal:
339
384
 
340
385
  ```ts
@@ -342,6 +387,7 @@ ctx.props.count() // read
342
387
  ctx.props.count(42) // write
343
388
  ```
344
389
 
390
+ ---
345
391
 
346
392
  ### Refs
347
393
 
@@ -500,6 +546,11 @@ define('themed-card')
500
546
  // Add an event listener; auto-removed on disconnect.
501
547
  ctx.on(el, 'click', handler)
502
548
 
549
+ // Dispatch an event from the host. Pass a name (with optional
550
+ // detail/options) for a bubbling CustomEvent, or a pre-built
551
+ // Event. Returns dispatchEvent's result.
552
+ ctx.emit('change', { value: 42 })
553
+
503
554
  // Read a signal without creating a subscription.
504
555
  const snap = ctx.peek(ctx.props.count)
505
556
 
@@ -527,6 +578,37 @@ ctx.effect(() => {
527
578
  })
528
579
  ```
529
580
 
581
+ ### Typed Events
582
+
583
+ `TypedEvent<Target, Detail>` is a type-only helper that narrows
584
+ `CustomEvent` to a specific `target` and `detail`. Combine it with
585
+ `HTMLElementEventMap` augmentation for app-wide type-safe events that
586
+ flow through `ctx.emit` and `ctx.on`:
587
+
588
+ ```ts
589
+ import type { TypedEvent } from 'microtags'
590
+
591
+ type TabsChangedEvent = TypedEvent<
592
+ InstanceType<typeof XTabs>,
593
+ { index:number }
594
+ >
595
+
596
+ declare global {
597
+ interface HTMLElementEventMap {
598
+ 'tabs:changed':TabsChangedEvent
599
+ }
600
+ }
601
+
602
+ // Emitting from setup:
603
+ ctx.emit('tabs:changed', { index: 2 })
604
+
605
+ // Listening, fully typed:
606
+ ctx.on(tabsEl, 'tabs:changed', ev => {
607
+ ev.target // the XTabs instance
608
+ ev.detail // { index:number }
609
+ })
610
+ ```
611
+
530
612
  ## Templates
531
613
 
532
614
  [`render` and `renderList`](#microtagsrender) both take a `<template>`
@@ -626,7 +708,8 @@ define('theme-provider')
626
708
  const theme = signal('light')
627
709
 
628
710
  // Share with descendants; remove the entry on disconnect.
629
- ctx.onCleanup(provide(ctx.host, ThemeToken, theme()))
711
+ const cleanUp = provide(ctx.host, ThemeToken, theme())
712
+ ctx.onCleanup(cleanup)
630
713
 
631
714
  // Re-provide on change. provide() updates the existing signal,
632
715
  // so consumers that read this value re-run.
@@ -780,13 +863,87 @@ For a runnable version, see `example/render-demo.ts`. It keeps an editable
780
863
  re-renders on a timer and reorders on demand to show that focus, caret, and
781
864
  typed text survive: keyed nodes are reused and at most moved, never rebuilt.
782
865
 
783
- #### Templates
866
+ ---
867
+
868
+ ### `microtags/util`
869
+
870
+ Helpers for reading raw attribute strings and running cleanup
871
+ functions. `withProps` uses these internally to coerce attribute values.
872
+ They are exported for when you need to read an attribute outside of the
873
+ prop layer.
874
+
875
+ ```ts
876
+ import {
877
+ coerceNumber,
878
+ coerceString,
879
+ coerceBoolean,
880
+ coerceJson,
881
+ runCleanups,
882
+ } from 'microtags/util'
883
+ ```
884
+
885
+ #### Coercion
886
+
887
+ Each coercion helper takes the raw `getAttribute` result -- a `string` or
888
+ `null` -- and returns a typed value. None of them throw.
889
+
890
+ ```ts
891
+ function coerceNumber (raw:string | null):number
892
+ function coerceString (raw:string | null):string
893
+ function coerceBoolean (raw:string | null):boolean
894
+ function coerceJson<T = unknown> (raw:string | null):T | undefined
895
+ ```
896
+
897
+ - `coerceNumber` -- `Number(raw)`, or `NaN` when the attribute is absent
898
+ or cannot be parsed.
899
+ - `coerceString` -- the value as-is; a missing attribute (`null`) becomes
900
+ the empty string `''`.
901
+ - `coerceBoolean` -- presence-based, matching the HTML boolean-attribute
902
+ convention: absent (`null`) is `false`, present is `true`, including the
903
+ empty string from `disabled=""`.
904
+ - `coerceJson` -- `JSON.parse(raw)`, or `undefined` when the attribute is
905
+ absent or not valid JSON. Pass a type parameter to annotate the result.
906
+
907
+ #### `runCleanups`
908
+
909
+ Runs every function in the array, even if some throw. After all have run
910
+ it re-throws the first error encountered, so one failing teardown cannot
911
+ skip the rest. A `Cleanup` is a no-argument teardown function, `() => void`.
912
+
913
+ ```ts
914
+ function runCleanups (fns:Cleanup[]):void
915
+ ```
784
916
 
917
+ #### `toAttributes`
785
918
 
919
+ Transform an object into an HTML attributes string. The object should be
920
+ like `{ attributeName: value }`. Handles boolean values by adding a string, eg
921
+ `{ disabled: true }` = `<button disabled>`. Arrays are converted to a list in
922
+ quotes, eg `{ class: ['abc', 'def'] }` = `<div class="abc def">`
923
+
924
+ ```ts
925
+ type Attrs = Record<
926
+ string,
927
+ undefined|null|string|number|boolean|(string|number)[]
928
+ >
929
+
930
+ /**
931
+ * Transform an object into an HTML attributes string. The object should be
932
+ * like `{ attributeName: value }`.
933
+ *
934
+ * @param {Attrs} attrs An object for the attributes.
935
+ * @returns {string} A string suitable for use as HTML attributes.
936
+ */
937
+ function toAttributes (attrs:Attrs):string
938
+ ```
786
939
 
787
940
  ---
788
941
 
789
- ## Divergence from nanotags
942
+ ## Divergence from `nanotags`
943
+
944
+ ### Reactivity primitive
945
+
946
+ `nanotags` uses `nanostores` atoms; `microtags` uses `alien-signals`.
790
947
 
791
948
  | nanotags (nanostores) | microtags (alien-signals) |
792
949
  |---|---|
@@ -795,5 +952,78 @@ typed text survive: keyed nodes are reused and at most moved, never rebuilt.
795
952
  | `$count.set(1)` | `count(1)` |
796
953
  | `ctx.props.$count` (store) | `ctx.props.count` (callable signal) |
797
954
 
798
- Props declared with `withProps` are native alien-signals callable signals.
799
- There is no `$` prefix convention; all prop names are plain identifiers.
955
+ Props declared with `withProps` are signals. There is no `$` prefix convention;
956
+ all prop names are plain identifiers.
957
+
958
+ ### Effects + Subscriptions
959
+
960
+ In `nanotags`, `ctx.effect` takes the store(s) to watch
961
+ explicitly and hands the value to the callback:
962
+
963
+ ```ts
964
+ // nanotags
965
+ ctx.effect(ctx.props.$count, count => {
966
+ ctx.refs.display.textContent = String(count)
967
+ })
968
+ ```
969
+
970
+ In `microtags`, `ctx.effect` takes a zero-argument function and tracks whichever
971
+ signals are read inside it (the `alien-signals` model):
972
+
973
+ ```ts
974
+ // microtags
975
+ ctx.effect(() => {
976
+ ctx.refs.display.textContent = String(ctx.props.count())
977
+ })
978
+ ```
979
+
980
+ The read operation in `ctx.effect` subscribes to the signal, and runs on
981
+ any signal change. A read inside an effect that you do *not* want to track has
982
+ to go through [`peek` or `untracked`](#peek-and-untracked).
983
+ In nanotags `.get()` never subscribes, so there is no equivalent.
984
+
985
+ ### Refs: `r.all` instead of `r.many`
986
+
987
+ The multi-element ref is `r.all()` in `microtags` and `r.many()` in `nanotags`.
988
+ The empty-match behavior also differs: `r.all()` returns an empty array when
989
+ nothing matches, whereas nanotags' `r.many()` throws. `r.one()` throws on a
990
+ missing element in both.
991
+
992
+
993
+ ### Context API
994
+
995
+ The context API is shaped differently. See
996
+ [`microtags/context`](#microtagscontext).
997
+
998
+ | nanotags | microtags |
999
+ |---|---|
1000
+ | `createContext<T>('name')` | `createContext<T>()`, no name |
1001
+ | `token.provide(ctx, value)` | `provide(ctx.host, token, value)`, standalone, returns a cleanup |
1002
+ | `withContexts({ theme: token })` | `withContexts(() => ({ theme: token }))`, a function |
1003
+ | `token.consume(ctx, cb)` | `ctx.consume(token)`, returns value-or-`undefined` |
1004
+
1005
+ ### Props
1006
+
1007
+ | nanotags | microtags |
1008
+ |---|---|
1009
+ | `p.json(schema, default)`, hydrated from a `<script type="application/json">` tag, not an attribute | `p.json<T>()`, type-only, parsed from the observed attribute |
1010
+ | custom schema passed directly as the prop def | wrap it in `p.schema(validator)` |
1011
+ | property-only via `{ schema, attribute: false }` | `p.prop(initial)` |
1012
+ | nullable fallback `p.string(null)` | no null-fallback argument; a failed `p.schema` falls back to `undefined` |
1013
+
1014
+ ### Not ported
1015
+
1016
+ These nanotags APIs have no microtags equivalent:
1017
+
1018
+ - `ctx.getElement` / `ctx.getElements` -- declare refs with `withRefs`, or
1019
+ call `ctx.host.querySelector` directly.
1020
+ - The `setup` mixin return value -- `setup` returns `void`; it does not
1021
+ assign members back onto the element.
1022
+ - The `define(name, setupFn)` two-argument shorthand -- always use the
1023
+ builder chain ending in `.setup()`.
1024
+
1025
+ ### Additions / New Features
1026
+
1027
+ * Serverside-compatible API -- see [serverside example](#serverside-example) --
1028
+ we expose `.TAG` and `.refs` on your component, which can be imported in a
1029
+ server environment.
@@ -40,12 +40,28 @@ function runCleanups(fns) {
40
40
  if (caught) throw firstError;
41
41
  }
42
42
  __name(runCleanups, "runCleanups");
43
+ function toAttributes(attrs) {
44
+ return Object.keys(attrs).reduce((acc, k) => {
45
+ const value = attrs[k];
46
+ if (!value) return acc;
47
+ if (typeof value === "boolean") {
48
+ if (value) return (acc + ` ${k}`).trim();
49
+ return acc;
50
+ }
51
+ if (Array.isArray(value)) {
52
+ return acc + ` ${k}="${value.join(" ")}"`;
53
+ }
54
+ return (acc + ` ${k}="${value}"`).trim();
55
+ }, "");
56
+ }
57
+ __name(toAttributes, "toAttributes");
43
58
 
44
59
  export {
45
60
  coerceNumber,
46
61
  coerceString,
47
62
  coerceBoolean,
48
63
  coerceJson,
49
- runCleanups
64
+ runCleanups,
65
+ toAttributes
50
66
  };
51
- //# sourceMappingURL=chunk-E7ZGOHL3.js.map
67
+ //# sourceMappingURL=chunk-P4QHFKTJ.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/util.ts"],
4
+ "sourcesContent": ["/**\n * Coerce a raw attribute string to a number.\n * Returns NaN if the value cannot be parsed.\n */\nexport function coerceNumber (raw:string | null):number {\n return raw === null ? NaN : Number(raw)\n}\n\n/**\n * Coerce a raw attribute string to a string.\n * Converts null to empty string.\n */\nexport function coerceString (raw:string | null):string {\n return raw ?? ''\n}\n\n/**\n * Coerce a raw attribute string to a boolean.\n * Absence (null) is false; presence of any value (including '') is true.\n */\nexport function coerceBoolean (raw:string | null):boolean {\n return raw !== null\n}\n\n/**\n * Coerce a raw attribute string to a parsed JSON value.\n * Returns undefined if the value is null or cannot be parsed.\n */\nexport function coerceJson<T = unknown> (raw:string | null):T | undefined {\n if (raw === null) return undefined\n try {\n return JSON.parse(raw) as T\n } catch {\n return undefined\n }\n}\n\n/**\n * Run every cleanup in the list, ensuring all run even if some throw.\n * After all have run, re-throws the first error encountered.\n */\nexport function runCleanups (fns:(() => void)[]):void {\n let firstError:unknown\n let caught = false\n for (const fn of fns) {\n try {\n fn()\n } catch (err) {\n if (!caught) {\n firstError = err\n caught = true\n }\n }\n }\n if (caught) throw firstError\n}\n\nexport type Attrs = Record<string, undefined|null|string|number|boolean|(string|number)[]>\n\n/**\n * Transform an object into an HTML attributes string. The object should be\n * like `{ attributeName: value }`.\n *\n * @param {Attrs} attrs An object for the attributes.\n * @returns {string} A string suitable for use as HTML attributes.\n */\nexport function toAttributes (attrs:Attrs):string {\n return Object.keys(attrs).reduce((acc, k) => {\n const value = attrs[k]\n if (!value) return acc\n\n if (typeof value === 'boolean') {\n if (value) return (acc + ` ${k}`).trim()\n return acc\n }\n\n if (Array.isArray(value)) {\n return (acc + ` ${k}=\"${value.join(' ')}\"`)\n }\n\n return (acc + ` ${k}=\"${value}\"`).trim()\n }, '')\n}\n"],
5
+ "mappings": ";;;;;AAIO,SAAS,aAAc,KAA0B;AACpD,SAAO,QAAQ,OAAO,MAAM,OAAO,GAAG;AAC1C;AAFgB;AAQT,SAAS,aAAc,KAA0B;AACpD,SAAO,OAAO;AAClB;AAFgB;AAQT,SAAS,cAAe,KAA2B;AACtD,SAAO,QAAQ;AACnB;AAFgB;AAQT,SAAS,WAAyB,KAAiC;AACtE,MAAI,QAAQ,KAAM,QAAO;AACzB,MAAI;AACA,WAAO,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAPgB;AAaT,SAAS,YAAa,KAAyB;AAClD,MAAI;AACJ,MAAI,SAAS;AACb,aAAW,MAAM,KAAK;AAClB,QAAI;AACA,SAAG;AAAA,IACP,SAAS,KAAK;AACV,UAAI,CAAC,QAAQ;AACT,qBAAa;AACb,iBAAS;AAAA,MACb;AAAA,IACJ;AAAA,EACJ;AACA,MAAI,OAAQ,OAAM;AACtB;AAdgB;AAyBT,SAAS,aAAc,OAAoB;AAC9C,SAAO,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,KAAK,MAAM;AACzC,UAAM,QAAQ,MAAM,CAAC;AACrB,QAAI,CAAC,MAAO,QAAO;AAEnB,QAAI,OAAO,UAAU,WAAW;AAC5B,UAAI,MAAO,SAAQ,MAAM,IAAI,CAAC,IAAI,KAAK;AACvC,aAAO;AAAA,IACX;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACtB,aAAQ,MAAM,IAAI,CAAC,KAAK,MAAM,KAAK,GAAG,CAAC;AAAA,IAC3C;AAEA,YAAQ,MAAM,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK;AAAA,EAC3C,GAAG,EAAE;AACT;AAhBgB;",
6
+ "names": []
7
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGR,YAAY,EAEZ,OAAO,EACP,YAAY,EACZ,MAAM,EACT,MAAM,YAAY,CAAA;AAEnB;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAY3D,yCAAyC;AACzC,MAAM,WAAW,aAAa,CAAC,KAAK,SAAS,YAAY,GAAG,YAAY;IACpE,kDAAkD;IAClD,KAAK,EAAC,KAAK,CAAA;IACX,qDAAqD;IACrD,iBAAiB,EAAC,MAAM,EAAE,CAAA;IAC1B,qCAAqC;IACrC,IAAI,CAAC,EAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,EAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;IAC/C,sDAAsD;IACtD,KAAK,EAAC,CAAC,GAAG,EAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,CAAA;CACpD;AAiCD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,SAAS,YAAY,GAAG,YAAY,EAC7D,MAAM,EAAC,aAAa,CAAC,KAAK,CAAC,GAC7B,OAAO,WAAW,CAuHnB"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGR,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,MAAM,EACT,MAAM,YAAY,CAAA;AAEnB;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAY3D,yCAAyC;AACzC,MAAM,WAAW,aAAa,CAAC,KAAK,SAAS,YAAY,GAAG,YAAY;IACpE,kDAAkD;IAClD,KAAK,EAAC,KAAK,CAAA;IACX,qDAAqD;IACrD,iBAAiB,EAAC,MAAM,EAAE,CAAA;IAC1B,qCAAqC;IACrC,IAAI,CAAC,EAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,EAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;IAC/C,sDAAsD;IACtD,KAAK,EAAC,CAAC,GAAG,EAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,CAAA;CACpD;AAiCD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,SAAS,YAAY,GAAG,YAAY,EAC7D,MAAM,EAAC,aAAa,CAAC,KAAK,CAAC,GAC7B,OAAO,WAAW,CAuHnB"}
package/dist/index.cjs CHANGED
@@ -132,6 +132,14 @@ function makeSetupContext(host, props, refs, contexts, cleanups) {
132
132
  );
133
133
  });
134
134
  },
135
+ emit(nameOrEvent, detail, options) {
136
+ const event = nameOrEvent instanceof Event ? nameOrEvent : new CustomEvent(nameOrEvent, {
137
+ bubbles: true,
138
+ ...options,
139
+ detail
140
+ });
141
+ return host.dispatchEvent(event);
142
+ },
135
143
  effect(fn) {
136
144
  const dispose = (0, import_alien_signals.effect)(fn);
137
145
  cleanups.push(dispose);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/reactivity.ts", "../src/util.ts", "../src/context.ts", "../src/setup-context.ts", "../src/factory.ts", "../src/builders.ts"],
4
- "sourcesContent": ["export { peek, untracked } from './reactivity.js'\nexport { define } from './builders.js'\n", "import {\n signal,\n effect,\n effectScope,\n setActiveSub,\n} from 'alien-signals'\nimport type { Signal } from './types.js'\n\n// Re-export alien-signals primitives under stable names for internal use.\nexport { signal, effect, effectScope }\n\n/**\n * Run fn without tracking any signals it reads.\n * Suspends the current subscriber via setActiveSub(undefined),\n * restoring it in a finally block so nested effects are unaffected.\n */\nexport function untracked<T> (fn:() => T):T {\n const prev = setActiveSub(undefined)\n try {\n return fn()\n } finally {\n setActiveSub(prev)\n }\n}\n\n/**\n * Read a signal's current value without subscribing.\n * Equivalent to untracked(() => sig()).\n */\nexport function peek<T> (sig:Signal<T>):T {\n return untracked(() => sig())\n}\n", "import type { Cleanup } from './types.js'\n\n/**\n * Coerce a raw attribute string to a number.\n * Returns NaN if the value cannot be parsed.\n */\nexport function coerceNumber (raw:string | null):number {\n return raw === null ? NaN : Number(raw)\n}\n\n/**\n * Coerce a raw attribute string to a string.\n * Converts null to empty string.\n */\nexport function coerceString (raw:string | null):string {\n return raw ?? ''\n}\n\n/**\n * Coerce a raw attribute string to a boolean.\n * Absence (null) is false; presence of any value (including '') is true.\n */\nexport function coerceBoolean (raw:string | null):boolean {\n return raw !== null\n}\n\n/**\n * Coerce a raw attribute string to a parsed JSON value.\n * Returns undefined if the value is null or cannot be parsed.\n */\nexport function coerceJson<T = unknown> (raw:string | null):T | undefined {\n if (raw === null) return undefined\n try {\n return JSON.parse(raw) as T\n } catch {\n return undefined\n }\n}\n\n/**\n * Run every cleanup in the list, ensuring all run even if some throw.\n * After all have run, re-throws the first error encountered.\n */\nexport function runCleanups (fns:Cleanup[]):void {\n let firstError:unknown\n let caught = false\n for (const fn of fns) {\n try {\n fn()\n } catch (err) {\n if (!caught) {\n firstError = err\n caught = true\n }\n }\n }\n if (caught) throw firstError\n}\n", "import { signal } from './reactivity.js'\nimport type { ContextToken, Signal } from './types.js'\n\n// Provider storage: element -> (contextId -> Signal)\nconst providerStorage = new WeakMap<Element, Map<symbol, Signal<unknown>>>()\n\n// Pending consumers waiting for a context by id\nconst pendingCallbacks = new Map<symbol, Set<() => void>>()\n\n/**\n * Create a new context token.\n * Each token uniquely identifies a type of shared context.\n */\nexport function createContext<T> ():ContextToken<T> {\n return { id: Symbol('microtag-context') }\n}\n\n/**\n * Provide a context value from an element to its descendants.\n * Returns a cleanup function that removes the provided value.\n */\nexport function provide<T> (\n element:Element,\n token:ContextToken<T>,\n value:T\n):() => void {\n let map = providerStorage.get(element)\n if (!map) {\n map = new Map()\n providerStorage.set(element, map)\n }\n\n const existing = map.get(token.id) as Signal<T> | undefined\n if (existing) {\n existing(value)\n } else {\n const sig = signal(value) as unknown as Signal<T>\n map.set(token.id, sig as Signal<unknown>)\n }\n\n notifyPending(token.id)\n\n return () => {\n const m = providerStorage.get(element)\n if (m) {\n m.delete(token.id)\n if (m.size === 0) providerStorage.delete(element)\n }\n }\n}\n\n/**\n * Walk up the DOM from element to find the nearest provider signal.\n * Returns the signal (not the value) so callers can subscribe to changes.\n */\nexport function resolveContextSignal<T> (\n element:Element,\n token:ContextToken<T>\n):Signal<T> | undefined {\n let current:Element | null = element.parentElement\n while (current) {\n const map = providerStorage.get(current)\n if (map && map.has(token.id)) {\n return map.get(token.id) as Signal<T>\n }\n current = current.parentElement\n }\n return undefined\n}\n\n/**\n * Register a callback to run when the given context becomes available.\n * Returns a cleanup function to unregister.\n */\nexport function onContextAvailable (\n id:symbol,\n callback:() => void\n):() => void {\n let set = pendingCallbacks.get(id)\n if (!set) {\n set = new Set()\n pendingCallbacks.set(id, set)\n }\n set.add(callback)\n return () => { pendingCallbacks.get(id)?.delete(callback) }\n}\n\nfunction notifyPending (id:symbol):void {\n const set = pendingCallbacks.get(id)\n if (set) {\n for (const cb of set) cb()\n }\n}\n", "import { effect, peek } from './reactivity.js'\nimport { resolveContextSignal } from './context.js'\nimport type {\n SetupContext,\n Cleanup,\n Signal,\n PropsSignals,\n PropDef,\n ContextToken,\n} from './types.js'\n\n/**\n * Build the ctx object passed to a component's setup() callback.\n * The cleanups array is mutated in place so factory.ts can drain it\n * on disconnect without copying.\n */\nexport function makeSetupContext<\n Props extends Record<string, PropDef> = Record<string, PropDef>,\n> (\n host:HTMLElement,\n props:PropsSignals<Props>,\n refs:Record<string, Element | Element[]>,\n contexts:Record<string, unknown>,\n cleanups:Cleanup[]\n):SetupContext<Props, any, any> {\n return {\n host,\n props,\n refs,\n contexts,\n\n peek,\n\n on (target, type, handler, options?) {\n target.addEventListener(\n type as string,\n handler as EventListener,\n options\n )\n cleanups.push(() => {\n target.removeEventListener(\n type as string,\n handler as EventListener,\n options\n )\n })\n },\n\n effect (fn) {\n const dispose = effect(fn)\n cleanups.push(dispose)\n },\n\n bind (source, control, opts) {\n const input = control instanceof HTMLInputElement ?\n control :\n undefined\n let prop = 'value'\n let autoEvent = 'change'\n if (input?.type === 'checkbox') {\n prop = 'checked'\n } else if (input?.type === 'number' ||\n input?.type === 'range') {\n prop = 'valueAsNumber'\n autoEvent = 'input'\n } else if (input || control instanceof HTMLTextAreaElement) {\n autoEvent = 'input'\n }\n\n const boundProp = opts?.prop ?? prop\n const event = opts ? opts.event : autoEvent\n const el = control as unknown as Record<string, unknown>\n\n if (event) {\n const handler = () => {\n const writable = source as Signal<unknown>\n writable(el[boundProp])\n }\n control.addEventListener(event, handler)\n cleanups.push(() => {\n control.removeEventListener(event, handler)\n })\n }\n\n const dispose = effect(() => {\n el[boundProp] = source()\n })\n cleanups.push(dispose)\n },\n\n onCleanup (fn) {\n cleanups.push(fn)\n },\n\n consume<T> (token:ContextToken<T>):T | undefined {\n const sig = resolveContextSignal(host, token)\n return sig ? sig() : undefined\n },\n }\n}\n", "import { signal } from './reactivity.js'\nimport { runCleanups } from './util.js'\nimport { makeSetupContext } from './setup-context.js'\nimport {\n resolveContextSignal,\n onContextAvailable,\n} from './context.js'\nimport type {\n PropsSignals,\n Signal,\n SetupContext,\n Cleanup,\n Coercer,\n ContextToken,\n RefDef,\n} from './types.js'\n\n/**\n * Map of prop name to coercer function.\n * The factory accepts coercers exclusively; Standard Schema support is\n * layered on top in the withProps builder (US-005).\n */\nexport type FactoryProps = Record<string, Coercer<unknown>>\n\n/**\n * The class to extend for custom elements. In the browser this is the\n * real HTMLElement; in Node (e.g. reading `.TAG` for SSR) it falls back\n * to an empty stub so the class can be defined without a DOM. The stub\n * is never instantiated or registered outside the browser.\n */\nconst HTMLElementBase = typeof HTMLElement !== 'undefined' ?\n HTMLElement :\n (class {} as unknown as typeof HTMLElement)\n\n/** Configuration passed to factory(). */\nexport interface FactoryConfig<Props extends FactoryProps = FactoryProps> {\n /** Coercer for each observed attribute / prop. */\n props:Props\n /** Attribute names to pass to observedAttributes. */\n observedAttrNames:string[]\n /** Ref definitions keyed by name. */\n refs?:Record<string, RefDef>\n /** Context tokens keyed by name. */\n contexts?:Record<string, ContextToken<unknown>>\n /** Setup callback receiving the component context. */\n setup:(ctx:SetupContext<Props, any, any>) => void\n}\n\n/**\n * Collect resolved DOM refs from within a host element.\n * Throws if any single-ref element is missing.\n */\nfunction collectRefs (\n host:HTMLElement,\n defs:Record<string, RefDef>\n):Record<string, Element | Element[]> {\n const result:Record<string, Element | Element[]> = {}\n const missing:string[] = []\n for (const [key, def] of Object.entries(defs)) {\n const sel = def.selector ?? `[data-ref=\"${key}\"]`\n if (def._microtag === 'ref:all') {\n result[key] = Array.from(host.querySelectorAll(sel))\n } else {\n const el = host.querySelector(sel)\n if (!el) {\n missing.push(key)\n } else {\n result[key] = el\n }\n }\n }\n if (missing.length > 0) {\n throw new Error(\n `${host.tagName}: missing refs: ${missing.join(', ')}`\n )\n }\n return result\n}\n\n/**\n * Create an HTMLElement subclass with the microtags lifecycle.\n * The returned class has no Shadow DOM, tracks its own prop signals,\n * and runs setup() on connect / cleanups on disconnect.\n */\nexport function factory<Props extends FactoryProps = FactoryProps> (\n config:FactoryConfig<Props>\n):typeof HTMLElement {\n const {\n props: propDefs,\n observedAttrNames,\n setup,\n refs: refDefs = {},\n contexts: ctxDefs = {},\n } = config\n\n class MicrotagElement extends HTMLElementBase {\n static get observedAttributes () { return observedAttrNames }\n\n _props:Record<string, Signal<unknown>> = {}\n _cleanups:Cleanup[] = []\n\n constructor () {\n super()\n for (const [name, coercer] of Object.entries(propDefs)) {\n this._props[name] = signal(coercer(null))\n }\n }\n\n connectedCallback () {\n // Start a fresh cleanup scope for each connection cycle.\n this._cleanups = []\n\n // Hydrate prop signals from attributes; preserve any\n // programmatically-set value when the attribute is absent.\n for (const [name, coercer] of Object.entries(propDefs)) {\n const attrVal = this.getAttribute(name)\n if (attrVal !== null) {\n (this._props[name] as Signal<unknown>)(coercer(attrVal))\n }\n }\n\n const cleanups = this._cleanups\n const props = this._props as PropsSignals<Props>\n\n // Reactive Proxy: reading a key inside a ctx.effect creates\n // a subscription to the provider's alien-signals signal.\n const contexts = new Proxy({} as Record<string, unknown>, {\n get: (_target, key) => {\n if (typeof key !== 'string') return undefined\n const token = ctxDefs[key]\n if (!token) return undefined\n const sig = resolveContextSignal(this, token)\n return sig ? sig() : undefined\n },\n has: (_target, key) => {\n if (typeof key !== 'string') return false\n return key in ctxDefs\n },\n })\n\n let setupRan = false\n // Tracks pending-context cancel functions so they are\n // removed from the global registry when setup runs or\n // when the element disconnects.\n const cancelCallbacks:(() => void)[] = []\n\n const tryRunSetup = ():void => {\n if (setupRan) return\n for (const token of Object.values(ctxDefs)) {\n if (!resolveContextSignal(this, token)) return\n }\n setupRan = true\n for (const cancel of cancelCallbacks) cancel()\n cancelCallbacks.length = 0\n\n const refs = collectRefs(this, refDefs)\n const ctx = makeSetupContext(\n this, props, refs, contexts, cleanups\n )\n setup(ctx)\n }\n\n // Deferred variant: skip if element was disconnected before\n // the context became available.\n const tryRunSetupIfConnected = ():void => {\n if (!this.isConnected) return\n tryRunSetup()\n }\n\n // Register pending listeners for any missing contexts.\n for (const token of Object.values(ctxDefs)) {\n if (!resolveContextSignal(this, token)) {\n const cancel = onContextAvailable(\n token.id, tryRunSetupIfConnected\n )\n cancelCallbacks.push(cancel)\n // Also cancel on disconnect so we don't leak.\n cleanups.push(cancel)\n }\n }\n\n tryRunSetup()\n }\n\n attributeChangedCallback (\n name:string,\n _old:string | null,\n next:string | null\n ) {\n const coercer = propDefs[name]\n if (coercer !== undefined && this._props[name] !== undefined) {\n (this._props[name] as Signal<unknown>)(coercer(next))\n }\n }\n\n disconnectedCallback () {\n // Snapshot and clear BEFORE running so re-entrant calls are safe\n // and the array is always empty after this returns (or throws).\n const fns = this._cleanups\n this._cleanups = []\n runCleanups(fns)\n }\n }\n\n return MicrotagElement\n}\n", "import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type {\n PropDef,\n PropertyOnlyProp,\n SetupContext,\n Coercer,\n RefDef,\n SingleRefDef,\n MultipleRefDef,\n RefsMap,\n ContextToken,\n ContextsMap,\n} from './types.js'\nimport {\n coerceNumber,\n coerceString,\n coerceBoolean,\n coerceJson,\n} from './util.js'\nimport { factory } from './factory.js'\n\nfunction isPropOnly (def:unknown):def is PropertyOnlyProp<unknown> {\n return (\n typeof def === 'object' &&\n def !== null &&\n '_microtag' in def &&\n (def as { _microtag: unknown })._microtag === 'prop'\n )\n}\n\nfunction isStandardSchema (def:unknown):def is StandardSchemaV1 {\n return (\n typeof def === 'object' &&\n def !== null &&\n '~standard' in def\n )\n}\n\nfunction normalizePropDef (\n name:string,\n def:PropDef<unknown>\n):Coercer<unknown> {\n if (isPropOnly(def)) {\n return (_raw:string | null) => def.initial\n }\n if (isStandardSchema(def)) {\n const schema = def as StandardSchemaV1\n return (raw:string | null):unknown => {\n const result = schema['~standard'].validate(raw)\n if (result instanceof Promise) {\n throw new TypeError(\n `withProps: async schemas are not supported (prop \"${name}\")`\n )\n }\n if (result.issues) return undefined\n return result.value\n }\n }\n return def as Coercer<unknown>\n}\n\n/** The DSL object passed to the withProps callback. */\nexport type PropDSL = {\n number():Coercer<number>\n string():Coercer<string>\n boolean():Coercer<boolean>\n json<T>():Coercer<T | undefined>\n schema<T>(validator:StandardSchemaV1<unknown, T>):StandardSchemaV1<unknown, T>\n prop<T>(initial:T):PropertyOnlyProp<T>\n}\n\nexport const propDSL:PropDSL = {\n number: () => coerceNumber,\n string: () => coerceString,\n boolean: () => coerceBoolean,\n json: <T>() => coerceJson as Coercer<T | undefined>,\n schema: <T>(v:StandardSchemaV1<unknown, T>) => v,\n prop: <T>(initial:T):PropertyOnlyProp<T> => (\n { _microtag: 'prop', initial }\n ),\n}\n\n/**\n * DSL object passed to the withRefs callback.\n * Call `r.one()` for a single element or `r.all()` for multiple. Pass a\n * CSS selector to query by it, or omit it to match `[data-ref=\"<key>\"]`.\n *\n * Element typing:\n * - `r.one()` defaults to `HTMLElement`.\n * - `r.one<T>()` sets the type and keeps the `[data-ref]` selector.\n * - `r.one('button')` infers the type from the tag AND queries by that\n * tag, exactly like `document.querySelector('button')`.\n */\nexport type RefsDSL = {\n one<K extends keyof HTMLElementTagNameMap>(\n selector:K\n ):SingleRefDef<HTMLElementTagNameMap[K]>\n one<T extends HTMLElement = HTMLElement>(selector?:string):SingleRefDef<T>\n\n all<K extends keyof HTMLElementTagNameMap>(\n selector:K\n ):MultipleRefDef<HTMLElementTagNameMap[K]>\n all<T extends HTMLElement = HTMLElement>(selector?:string):MultipleRefDef<T>\n}\n\nexport const refsDSL:RefsDSL = {\n one: ((selector?:string):SingleRefDef => (\n { _microtag: 'ref:one', selector }\n )) as RefsDSL['one'],\n all: ((selector?:string):MultipleRefDef => (\n { _microtag: 'ref:all', selector }\n )) as RefsDSL['all'],\n}\n\n/**\n * DSL object passed to the withContexts callback.\n * Currently a no-op placeholder; the user references imported\n * context tokens directly in the returned record.\n */\nexport type ContextDSL = Record<never, never>\nconst contextDSL:ContextDSL = {}\n\n/**\n * Maps each declared ref key to its own name as a string literal. Exposed\n * as the static `refs` on a registered element so server-rendered templates\n * can fill in `data-ref` values without hardcoding the names, e.g.\n * `data-ref=\"${myCounter.refs.dec}\"`.\n */\nexport type RefNames<RefDefs extends Record<string, RefDef>> = {\n readonly [K in keyof RefDefs]:K & string\n}\n\n/**\n * A registered custom element class that also exposes, as static members,\n * the tag name it was registered under (`TAG`) and the names of its\n * declared refs (`refs`).\n */\nexport type MicrotagElementClass<\n RefDefs extends Record<string, RefDef> = Record<never, never>\n> = typeof HTMLElement & {\n /** The custom element tag name, e.g. 'my-counter'. */\n readonly TAG:string\n /**\n * The declared ref names, each mapping to its own `data-ref` string.\n * Lets server-rendered markup reference refs by key instead of a magic\n * string: `myCounter.refs.dec`.\n */\n readonly refs:RefNames<RefDefs>\n}\n\n/**\n * Fluent builder that accumulates props/refs/contexts config\n * before registering a custom element via `.setup()`.\n */\nexport class ComponentBuilder<\n Props extends Record<string, PropDef> = Record<never, never>,\n RefDefs extends Record<string, RefDef> = Record<never, never>,\n CtxDefs extends Record<string, ContextToken<unknown>> =\n Record<never, never>,\n> {\n private readonly _coercers:Record<string, Coercer<unknown>>\n private readonly _observed:string[]\n private readonly _refDefs:Record<string, RefDef>\n private readonly _ctxDefs:Record<string, ContextToken<unknown>>\n\n constructor (\n readonly tagName:string,\n coercers:Record<string, Coercer<unknown>> = {},\n observed:string[] = [],\n refDefs:Record<string, RefDef> = {},\n ctxDefs:Record<string, ContextToken<unknown>> = {}\n ) {\n this._coercers = coercers\n this._observed = observed\n this._refDefs = refDefs\n this._ctxDefs = ctxDefs\n }\n\n /**\n * The custom element tag name, e.g. 'my-counter'. Available at every\n * point in the fluent chain since each builder method returns a new\n * builder carrying the same tag name.\n */\n get TAG ():string {\n return this.tagName\n }\n\n withProps<P extends Record<string, PropDef>> (\n fn:(p:PropDSL) => P\n ):ComponentBuilder<P, RefDefs, CtxDefs> {\n const defs = fn(propDSL)\n const coercers:Record<string, Coercer<unknown>> = {}\n const observed:string[] = []\n\n for (const [name, def] of Object.entries(defs)) {\n coercers[name] = normalizePropDef(name, def as PropDef<unknown>)\n if (!isPropOnly(def)) {\n observed.push(name)\n }\n }\n\n return new ComponentBuilder<P, RefDefs, CtxDefs>(\n this.tagName, coercers, observed, this._refDefs, this._ctxDefs\n )\n }\n\n withRefs<R extends Record<string, RefDef>> (\n fn:(r:RefsDSL) => R\n ):ComponentBuilder<Props, R, CtxDefs> {\n const defs = fn(refsDSL)\n return new ComponentBuilder<Props, R, CtxDefs>(\n this.tagName,\n this._coercers,\n this._observed,\n defs,\n this._ctxDefs\n )\n }\n\n withContexts<C extends Record<string, ContextToken<unknown>>> (\n fn:(c:ContextDSL) => C\n ):ComponentBuilder<Props, RefDefs, C> {\n const defs = fn(contextDSL)\n return new ComponentBuilder<Props, RefDefs, C>(\n this.tagName,\n this._coercers,\n this._observed,\n this._refDefs,\n defs\n )\n }\n\n setup (\n fn:(ctx:SetupContext<\n Props,\n RefsMap<RefDefs>,\n ContextsMap<CtxDefs>\n >) => void\n ):MicrotagElementClass<RefDefs> {\n const El = factory({\n props: this._coercers,\n observedAttrNames: this._observed,\n refs: this._refDefs,\n contexts: this._ctxDefs,\n setup: fn as any,\n })\n Object.defineProperty(El, 'TAG', {\n value: this.tagName,\n enumerable: true,\n })\n\n // Expose each ref key as its own `data-ref` name so server-rendered\n // markup can reference refs by key instead of a hardcoded string.\n const refNames:Record<string, string> = {}\n for (const key of Object.keys(this._refDefs)) {\n refNames[key] = key\n }\n Object.defineProperty(El, 'refs', {\n value: Object.freeze(refNames),\n enumerable: true,\n })\n\n if (typeof customElements !== 'undefined') {\n customElements.define(this.tagName, El)\n }\n return El as MicrotagElementClass<RefDefs>\n }\n}\n\n/** Create a new component builder for the given tag name. */\nexport function define (tagName:string):ComponentBuilder {\n return new ComponentBuilder(tagName)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export { peek, untracked } from './reactivity.js'\nexport { define } from './builders.js'\nexport type { TypedEvent } from './types.js'\n", "import {\n signal,\n effect,\n effectScope,\n setActiveSub,\n} from 'alien-signals'\nimport type { Signal } from './types.js'\n\n// Re-export alien-signals primitives under stable names for internal use.\nexport { signal, effect, effectScope }\n\n/**\n * Run fn without tracking any signals it reads.\n * Suspends the current subscriber via setActiveSub(undefined),\n * restoring it in a finally block so nested effects are unaffected.\n */\nexport function untracked<T> (fn:() => T):T {\n const prev = setActiveSub(undefined)\n try {\n return fn()\n } finally {\n setActiveSub(prev)\n }\n}\n\n/**\n * Read a signal's current value without subscribing.\n * Equivalent to untracked(() => sig()).\n */\nexport function peek<T> (sig:Signal<T>):T {\n return untracked(() => sig())\n}\n", "/**\n * Coerce a raw attribute string to a number.\n * Returns NaN if the value cannot be parsed.\n */\nexport function coerceNumber (raw:string | null):number {\n return raw === null ? NaN : Number(raw)\n}\n\n/**\n * Coerce a raw attribute string to a string.\n * Converts null to empty string.\n */\nexport function coerceString (raw:string | null):string {\n return raw ?? ''\n}\n\n/**\n * Coerce a raw attribute string to a boolean.\n * Absence (null) is false; presence of any value (including '') is true.\n */\nexport function coerceBoolean (raw:string | null):boolean {\n return raw !== null\n}\n\n/**\n * Coerce a raw attribute string to a parsed JSON value.\n * Returns undefined if the value is null or cannot be parsed.\n */\nexport function coerceJson<T = unknown> (raw:string | null):T | undefined {\n if (raw === null) return undefined\n try {\n return JSON.parse(raw) as T\n } catch {\n return undefined\n }\n}\n\n/**\n * Run every cleanup in the list, ensuring all run even if some throw.\n * After all have run, re-throws the first error encountered.\n */\nexport function runCleanups (fns:(() => void)[]):void {\n let firstError:unknown\n let caught = false\n for (const fn of fns) {\n try {\n fn()\n } catch (err) {\n if (!caught) {\n firstError = err\n caught = true\n }\n }\n }\n if (caught) throw firstError\n}\n\nexport type Attrs = Record<string, undefined|null|string|number|boolean|(string|number)[]>\n\n/**\n * Transform an object into an HTML attributes string. The object should be\n * like `{ attributeName: value }`.\n *\n * @param {Attrs} attrs An object for the attributes.\n * @returns {string} A string suitable for use as HTML attributes.\n */\nexport function toAttributes (attrs:Attrs):string {\n return Object.keys(attrs).reduce((acc, k) => {\n const value = attrs[k]\n if (!value) return acc\n\n if (typeof value === 'boolean') {\n if (value) return (acc + ` ${k}`).trim()\n return acc\n }\n\n if (Array.isArray(value)) {\n return (acc + ` ${k}=\"${value.join(' ')}\"`)\n }\n\n return (acc + ` ${k}=\"${value}\"`).trim()\n }, '')\n}\n", "import { signal } from './reactivity.js'\nimport type { ContextToken, Signal } from './types.js'\n\n// Provider storage: element -> (contextId -> Signal)\nconst providerStorage = new WeakMap<Element, Map<symbol, Signal<unknown>>>()\n\n// Pending consumers waiting for a context by id\nconst pendingCallbacks = new Map<symbol, Set<() => void>>()\n\n/**\n * Create a new context token.\n * Each token uniquely identifies a type of shared context.\n */\nexport function createContext<T> ():ContextToken<T> {\n return { id: Symbol('microtag-context') }\n}\n\n/**\n * Provide a context value from an element to its descendants.\n * Returns a cleanup function that removes the provided value.\n */\nexport function provide<T> (\n element:Element,\n token:ContextToken<T>,\n value:T\n):() => void {\n let map = providerStorage.get(element)\n if (!map) {\n map = new Map()\n providerStorage.set(element, map)\n }\n\n const existing = map.get(token.id) as Signal<T> | undefined\n if (existing) {\n existing(value)\n } else {\n const sig = signal(value) as unknown as Signal<T>\n map.set(token.id, sig as Signal<unknown>)\n }\n\n notifyPending(token.id)\n\n return () => {\n const m = providerStorage.get(element)\n if (m) {\n m.delete(token.id)\n if (m.size === 0) providerStorage.delete(element)\n }\n }\n}\n\n/**\n * Walk up the DOM from element to find the nearest provider signal.\n * Returns the signal (not the value) so callers can subscribe to changes.\n */\nexport function resolveContextSignal<T> (\n element:Element,\n token:ContextToken<T>\n):Signal<T> | undefined {\n let current:Element | null = element.parentElement\n while (current) {\n const map = providerStorage.get(current)\n if (map && map.has(token.id)) {\n return map.get(token.id) as Signal<T>\n }\n current = current.parentElement\n }\n return undefined\n}\n\n/**\n * Register a callback to run when the given context becomes available.\n * Returns a cleanup function to unregister.\n */\nexport function onContextAvailable (\n id:symbol,\n callback:() => void\n):() => void {\n let set = pendingCallbacks.get(id)\n if (!set) {\n set = new Set()\n pendingCallbacks.set(id, set)\n }\n set.add(callback)\n return () => { pendingCallbacks.get(id)?.delete(callback) }\n}\n\nfunction notifyPending (id:symbol):void {\n const set = pendingCallbacks.get(id)\n if (set) {\n for (const cb of set) cb()\n }\n}\n", "import { effect, peek } from './reactivity.js'\nimport { resolveContextSignal } from './context.js'\nimport type {\n SetupContext,\n Signal,\n PropsSignals,\n PropDef,\n ContextToken,\n} from './types.js'\n\n/**\n * Build the ctx object passed to a component's setup() callback.\n * The cleanups array is mutated in place so factory.ts can drain it\n * on disconnect without copying.\n */\nexport function makeSetupContext<\n Props extends Record<string, PropDef> = Record<string, PropDef>,\n> (\n host:HTMLElement,\n props:PropsSignals<Props>,\n refs:Record<string, Element | Element[]>,\n contexts:Record<string, unknown>,\n cleanups:(() => void)[]\n):SetupContext<Props, any, any> {\n return {\n host,\n props,\n refs,\n contexts,\n\n peek,\n\n on (target, type, handler, options?) {\n target.addEventListener(\n type as string,\n handler as EventListener,\n options\n )\n cleanups.push(() => {\n target.removeEventListener(\n type as string,\n handler as EventListener,\n options\n )\n })\n },\n\n emit (\n nameOrEvent:Event | string,\n detail?:unknown,\n options?:Omit<CustomEventInit, 'detail'>\n ):boolean {\n const event = nameOrEvent instanceof Event ?\n nameOrEvent :\n new CustomEvent(nameOrEvent, {\n bubbles: true,\n ...options,\n detail,\n })\n return host.dispatchEvent(event)\n },\n\n effect (fn) {\n const dispose = effect(fn)\n cleanups.push(dispose)\n },\n\n bind (source, control, opts) {\n const input = control instanceof HTMLInputElement ?\n control :\n undefined\n let prop = 'value'\n let autoEvent = 'change'\n if (input?.type === 'checkbox') {\n prop = 'checked'\n } else if (input?.type === 'number' ||\n input?.type === 'range') {\n prop = 'valueAsNumber'\n autoEvent = 'input'\n } else if (input || control instanceof HTMLTextAreaElement) {\n autoEvent = 'input'\n }\n\n const boundProp = opts?.prop ?? prop\n const event = opts ? opts.event : autoEvent\n const el = control as unknown as Record<string, unknown>\n\n if (event) {\n const handler = () => {\n const writable = source as Signal<unknown>\n writable(el[boundProp])\n }\n control.addEventListener(event, handler)\n cleanups.push(() => {\n control.removeEventListener(event, handler)\n })\n }\n\n const dispose = effect(() => {\n el[boundProp] = source()\n })\n cleanups.push(dispose)\n },\n\n onCleanup (fn) {\n cleanups.push(fn)\n },\n\n consume<T> (token:ContextToken<T>):T | undefined {\n const sig = resolveContextSignal(host, token)\n return sig ? sig() : undefined\n },\n }\n}\n", "import { signal } from './reactivity.js'\nimport { runCleanups } from './util.js'\nimport { makeSetupContext } from './setup-context.js'\nimport {\n resolveContextSignal,\n onContextAvailable,\n} from './context.js'\nimport type {\n PropsSignals,\n Signal,\n SetupContext,\n Coercer,\n ContextToken,\n RefDef,\n} from './types.js'\n\n/**\n * Map of prop name to coercer function.\n * The factory accepts coercers exclusively; Standard Schema support is\n * layered on top in the withProps builder (US-005).\n */\nexport type FactoryProps = Record<string, Coercer<unknown>>\n\n/**\n * The class to extend for custom elements. In the browser this is the\n * real HTMLElement; in Node (e.g. reading `.TAG` for SSR) it falls back\n * to an empty stub so the class can be defined without a DOM. The stub\n * is never instantiated or registered outside the browser.\n */\nconst HTMLElementBase = typeof HTMLElement !== 'undefined' ?\n HTMLElement :\n (class {} as unknown as typeof HTMLElement)\n\n/** Configuration passed to factory(). */\nexport interface FactoryConfig<Props extends FactoryProps = FactoryProps> {\n /** Coercer for each observed attribute / prop. */\n props:Props\n /** Attribute names to pass to observedAttributes. */\n observedAttrNames:string[]\n /** Ref definitions keyed by name. */\n refs?:Record<string, RefDef>\n /** Context tokens keyed by name. */\n contexts?:Record<string, ContextToken<unknown>>\n /** Setup callback receiving the component context. */\n setup:(ctx:SetupContext<Props, any, any>) => void\n}\n\n/**\n * Collect resolved DOM refs from within a host element.\n * Throws if any single-ref element is missing.\n */\nfunction collectRefs (\n host:HTMLElement,\n defs:Record<string, RefDef>\n):Record<string, Element | Element[]> {\n const result:Record<string, Element | Element[]> = {}\n const missing:string[] = []\n for (const [key, def] of Object.entries(defs)) {\n const sel = def.selector ?? `[data-ref=\"${key}\"]`\n if (def._microtag === 'ref:all') {\n result[key] = Array.from(host.querySelectorAll(sel))\n } else {\n const el = host.querySelector(sel)\n if (!el) {\n missing.push(key)\n } else {\n result[key] = el\n }\n }\n }\n if (missing.length > 0) {\n throw new Error(\n `${host.tagName}: missing refs: ${missing.join(', ')}`\n )\n }\n return result\n}\n\n/**\n * Create an HTMLElement subclass with the microtags lifecycle.\n * The returned class has no Shadow DOM, tracks its own prop signals,\n * and runs setup() on connect / cleanups on disconnect.\n */\nexport function factory<Props extends FactoryProps = FactoryProps> (\n config:FactoryConfig<Props>\n):typeof HTMLElement {\n const {\n props: propDefs,\n observedAttrNames,\n setup,\n refs: refDefs = {},\n contexts: ctxDefs = {},\n } = config\n\n class MicrotagElement extends HTMLElementBase {\n static get observedAttributes () { return observedAttrNames }\n\n _props:Record<string, Signal<unknown>> = {}\n _cleanups:(() => void)[] = []\n\n constructor () {\n super()\n for (const [name, coercer] of Object.entries(propDefs)) {\n this._props[name] = signal(coercer(null))\n }\n }\n\n connectedCallback () {\n // Start a fresh cleanup scope for each connection cycle.\n this._cleanups = []\n\n // Hydrate prop signals from attributes; preserve any\n // programmatically-set value when the attribute is absent.\n for (const [name, coercer] of Object.entries(propDefs)) {\n const attrVal = this.getAttribute(name)\n if (attrVal !== null) {\n (this._props[name] as Signal<unknown>)(coercer(attrVal))\n }\n }\n\n const cleanups = this._cleanups\n const props = this._props as PropsSignals<Props>\n\n // Reactive Proxy: reading a key inside a ctx.effect creates\n // a subscription to the provider's alien-signals signal.\n const contexts = new Proxy({} as Record<string, unknown>, {\n get: (_target, key) => {\n if (typeof key !== 'string') return undefined\n const token = ctxDefs[key]\n if (!token) return undefined\n const sig = resolveContextSignal(this, token)\n return sig ? sig() : undefined\n },\n has: (_target, key) => {\n if (typeof key !== 'string') return false\n return key in ctxDefs\n },\n })\n\n let setupRan = false\n // Tracks pending-context cancel functions so they are\n // removed from the global registry when setup runs or\n // when the element disconnects.\n const cancelCallbacks:(() => void)[] = []\n\n const tryRunSetup = ():void => {\n if (setupRan) return\n for (const token of Object.values(ctxDefs)) {\n if (!resolveContextSignal(this, token)) return\n }\n setupRan = true\n for (const cancel of cancelCallbacks) cancel()\n cancelCallbacks.length = 0\n\n const refs = collectRefs(this, refDefs)\n const ctx = makeSetupContext(\n this, props, refs, contexts, cleanups\n )\n setup(ctx)\n }\n\n // Deferred variant: skip if element was disconnected before\n // the context became available.\n const tryRunSetupIfConnected = ():void => {\n if (!this.isConnected) return\n tryRunSetup()\n }\n\n // Register pending listeners for any missing contexts.\n for (const token of Object.values(ctxDefs)) {\n if (!resolveContextSignal(this, token)) {\n const cancel = onContextAvailable(\n token.id, tryRunSetupIfConnected\n )\n cancelCallbacks.push(cancel)\n // Also cancel on disconnect so we don't leak.\n cleanups.push(cancel)\n }\n }\n\n tryRunSetup()\n }\n\n attributeChangedCallback (\n name:string,\n _old:string | null,\n next:string | null\n ) {\n const coercer = propDefs[name]\n if (coercer !== undefined && this._props[name] !== undefined) {\n (this._props[name] as Signal<unknown>)(coercer(next))\n }\n }\n\n disconnectedCallback () {\n // Snapshot and clear BEFORE running so re-entrant calls are safe\n // and the array is always empty after this returns (or throws).\n const fns = this._cleanups\n this._cleanups = []\n runCleanups(fns)\n }\n }\n\n return MicrotagElement\n}\n", "import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type {\n PropDef,\n PropertyOnlyProp,\n SetupContext,\n Coercer,\n RefDef,\n SingleRefDef,\n MultipleRefDef,\n RefsMap,\n ContextToken,\n ContextsMap,\n} from './types.js'\nimport {\n coerceNumber,\n coerceString,\n coerceBoolean,\n coerceJson,\n} from './util.js'\nimport { factory } from './factory.js'\n\nfunction isPropOnly (def:unknown):def is PropertyOnlyProp<unknown> {\n return (\n typeof def === 'object' &&\n def !== null &&\n '_microtag' in def &&\n (def as { _microtag: unknown })._microtag === 'prop'\n )\n}\n\nfunction isStandardSchema (def:unknown):def is StandardSchemaV1 {\n return (\n typeof def === 'object' &&\n def !== null &&\n '~standard' in def\n )\n}\n\nfunction normalizePropDef (\n name:string,\n def:PropDef<unknown>\n):Coercer<unknown> {\n if (isPropOnly(def)) {\n return (_raw:string | null) => def.initial\n }\n if (isStandardSchema(def)) {\n const schema = def as StandardSchemaV1\n return (raw:string | null):unknown => {\n const result = schema['~standard'].validate(raw)\n if (result instanceof Promise) {\n throw new TypeError(\n `withProps: async schemas are not supported (prop \"${name}\")`\n )\n }\n if (result.issues) return undefined\n return result.value\n }\n }\n return def as Coercer<unknown>\n}\n\n/** The DSL object passed to the withProps callback. */\nexport type PropDSL = {\n number():Coercer<number>\n string():Coercer<string>\n boolean():Coercer<boolean>\n json<T>():Coercer<T | undefined>\n schema<T>(validator:StandardSchemaV1<unknown, T>):StandardSchemaV1<unknown, T>\n prop<T>(initial:T):PropertyOnlyProp<T>\n}\n\nexport const propDSL:PropDSL = {\n number: () => coerceNumber,\n string: () => coerceString,\n boolean: () => coerceBoolean,\n json: <T>() => coerceJson as Coercer<T | undefined>,\n schema: <T>(v:StandardSchemaV1<unknown, T>) => v,\n prop: <T>(initial:T):PropertyOnlyProp<T> => (\n { _microtag: 'prop', initial }\n ),\n}\n\n/**\n * DSL object passed to the withRefs callback.\n * Call `r.one()` for a single element or `r.all()` for multiple. Pass a\n * CSS selector to query by it, or omit it to match `[data-ref=\"<key>\"]`.\n *\n * Element typing:\n * - `r.one()` defaults to `HTMLElement`.\n * - `r.one<T>()` sets the type and keeps the `[data-ref]` selector.\n * - `r.one('button')` infers the type from the tag AND queries by that\n * tag, exactly like `document.querySelector('button')`.\n */\nexport type RefsDSL = {\n one<K extends keyof HTMLElementTagNameMap>(\n selector:K\n ):SingleRefDef<HTMLElementTagNameMap[K]>\n one<T extends HTMLElement = HTMLElement>(selector?:string):SingleRefDef<T>\n\n all<K extends keyof HTMLElementTagNameMap>(\n selector:K\n ):MultipleRefDef<HTMLElementTagNameMap[K]>\n all<T extends HTMLElement = HTMLElement>(selector?:string):MultipleRefDef<T>\n}\n\nexport const refsDSL:RefsDSL = {\n one: ((selector?:string):SingleRefDef => (\n { _microtag: 'ref:one', selector }\n )) as RefsDSL['one'],\n all: ((selector?:string):MultipleRefDef => (\n { _microtag: 'ref:all', selector }\n )) as RefsDSL['all'],\n}\n\n/**\n * DSL object passed to the withContexts callback.\n * Currently a no-op placeholder; the user references imported\n * context tokens directly in the returned record.\n */\nexport type ContextDSL = Record<never, never>\nconst contextDSL:ContextDSL = {}\n\n/**\n * Maps each declared ref key to its own name as a string literal. Exposed\n * as the static `refs` on a registered element so server-rendered templates\n * can fill in `data-ref` values without hardcoding the names, e.g.\n * `data-ref=\"${myCounter.refs.dec}\"`.\n */\nexport type RefNames<RefDefs extends Record<string, RefDef>> = {\n readonly [K in keyof RefDefs]:K & string\n}\n\n/**\n * A registered custom element class that also exposes, as static members,\n * the tag name it was registered under (`TAG`) and the names of its\n * declared refs (`refs`).\n */\nexport type MicrotagElementClass<\n RefDefs extends Record<string, RefDef> = Record<never, never>\n> = typeof HTMLElement & {\n /** The custom element tag name, e.g. 'my-counter'. */\n readonly TAG:string\n /**\n * The declared ref names, each mapping to its own `data-ref` string.\n * Lets server-rendered markup reference refs by key instead of a magic\n * string: `myCounter.refs.dec`.\n */\n readonly refs:RefNames<RefDefs>\n}\n\n/**\n * Fluent builder that accumulates props/refs/contexts config\n * before registering a custom element via `.setup()`.\n */\nexport class ComponentBuilder<\n Props extends Record<string, PropDef> = Record<never, never>,\n RefDefs extends Record<string, RefDef> = Record<never, never>,\n CtxDefs extends Record<string, ContextToken<unknown>> =\n Record<never, never>,\n> {\n private readonly _coercers:Record<string, Coercer<unknown>>\n private readonly _observed:string[]\n private readonly _refDefs:Record<string, RefDef>\n private readonly _ctxDefs:Record<string, ContextToken<unknown>>\n\n constructor (\n readonly tagName:string,\n coercers:Record<string, Coercer<unknown>> = {},\n observed:string[] = [],\n refDefs:Record<string, RefDef> = {},\n ctxDefs:Record<string, ContextToken<unknown>> = {}\n ) {\n this._coercers = coercers\n this._observed = observed\n this._refDefs = refDefs\n this._ctxDefs = ctxDefs\n }\n\n /**\n * The custom element tag name, e.g. 'my-counter'. Available at every\n * point in the fluent chain since each builder method returns a new\n * builder carrying the same tag name.\n */\n get TAG ():string {\n return this.tagName\n }\n\n withProps<P extends Record<string, PropDef>> (\n fn:(p:PropDSL) => P\n ):ComponentBuilder<P, RefDefs, CtxDefs> {\n const defs = fn(propDSL)\n const coercers:Record<string, Coercer<unknown>> = {}\n const observed:string[] = []\n\n for (const [name, def] of Object.entries(defs)) {\n coercers[name] = normalizePropDef(name, def as PropDef<unknown>)\n if (!isPropOnly(def)) {\n observed.push(name)\n }\n }\n\n return new ComponentBuilder<P, RefDefs, CtxDefs>(\n this.tagName, coercers, observed, this._refDefs, this._ctxDefs\n )\n }\n\n withRefs<R extends Record<string, RefDef>> (\n fn:(r:RefsDSL) => R\n ):ComponentBuilder<Props, R, CtxDefs> {\n const defs = fn(refsDSL)\n return new ComponentBuilder<Props, R, CtxDefs>(\n this.tagName,\n this._coercers,\n this._observed,\n defs,\n this._ctxDefs\n )\n }\n\n withContexts<C extends Record<string, ContextToken<unknown>>> (\n fn:(c:ContextDSL) => C\n ):ComponentBuilder<Props, RefDefs, C> {\n const defs = fn(contextDSL)\n return new ComponentBuilder<Props, RefDefs, C>(\n this.tagName,\n this._coercers,\n this._observed,\n this._refDefs,\n defs\n )\n }\n\n setup (\n fn:(ctx:SetupContext<\n Props,\n RefsMap<RefDefs>,\n ContextsMap<CtxDefs>\n >) => void\n ):MicrotagElementClass<RefDefs> {\n const El = factory({\n props: this._coercers,\n observedAttrNames: this._observed,\n refs: this._refDefs,\n contexts: this._ctxDefs,\n setup: fn as any,\n })\n Object.defineProperty(El, 'TAG', {\n value: this.tagName,\n enumerable: true,\n })\n\n // Expose each ref key as its own `data-ref` name so server-rendered\n // markup can reference refs by key instead of a hardcoded string.\n const refNames:Record<string, string> = {}\n for (const key of Object.keys(this._refDefs)) {\n refNames[key] = key\n }\n Object.defineProperty(El, 'refs', {\n value: Object.freeze(refNames),\n enumerable: true,\n })\n\n if (typeof customElements !== 'undefined') {\n customElements.define(this.tagName, El)\n }\n return El as MicrotagElementClass<RefDefs>\n }\n}\n\n/** Create a new component builder for the given tag name. */\nexport function define (tagName:string):ComponentBuilder {\n return new ComponentBuilder(tagName)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { peek, untracked } from './reactivity.js';
2
2
  export { define } from './builders.js';
3
+ export type { TypedEvent } from './types.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  coerceNumber,
13
13
  coerceString,
14
14
  runCleanups
15
- } from "./chunk-E7ZGOHL3.js";
15
+ } from "./chunk-P4QHFKTJ.js";
16
16
  import {
17
17
  __name
18
18
  } from "./chunk-7QVYU63E.js";
@@ -39,6 +39,14 @@ function makeSetupContext(host, props, refs, contexts, cleanups) {
39
39
  );
40
40
  });
41
41
  },
42
+ emit(nameOrEvent, detail, options) {
43
+ const event = nameOrEvent instanceof Event ? nameOrEvent : new CustomEvent(nameOrEvent, {
44
+ bubbles: true,
45
+ ...options,
46
+ detail
47
+ });
48
+ return host.dispatchEvent(event);
49
+ },
42
50
  effect(fn) {
43
51
  const dispose = effect(fn);
44
52
  cleanups.push(dispose);