wrec 0.22.5 → 0.22.7

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
@@ -110,6 +110,23 @@ Here are the steps:
110
110
  MyCounter.define('my-counter');
111
111
  ```
112
112
 
113
+ Property definitions can also constrain string values to an allowed set:
114
+
115
+ ```js
116
+ class TrafficLight extends Wrec {
117
+ static properties = {
118
+ color: {
119
+ type: String,
120
+ values: ['red', 'yellow', 'green'],
121
+ value: 'red'
122
+ }
123
+ };
124
+ }
125
+ ```
126
+
127
+ With that configuration, the `color` attribute and property can only be set
128
+ to one of those strings.
129
+
113
130
  1. Create the file `index.html` containing the following.
114
131
 
115
132
  ```html
@@ -134,6 +151,7 @@ Here are the steps:
134
151
 
135
152
  Server-side rendering (SSR) is supported.
136
153
  This requires importing from "wrec/ssr" instead of "wrec".
154
+ "wrec/ssr" should only be imported by server code.
137
155
  That bundle is much larger because it bundles the node-html-parser package.
138
156
  However, the size increase is not likely an issue
139
157
  because it is used on the server-side rather than downloaded to web browsers.
@@ -225,3 +243,5 @@ to share state across multiple wrec components.
225
243
  state.name; // to see current value of "name" property
226
244
  state.name = 'Earth'; // to modify "name" property
227
245
  ```
246
+
247
+ `traffic-light.html` demonstrates a property with an enumerated value.
@@ -1,3 +1,5 @@
1
+ declare type AnyClass = new (...args: any[]) => any;
2
+
1
3
  declare type ChangeListener = {
2
4
  changed: (statePath: string, componentProperty: string, newValue: unknown, oldValue: unknown, state: WrecState) => void;
3
5
  };
@@ -15,6 +17,15 @@ declare const HTMLElementBase: {
15
17
 
16
18
  declare type LooseObject = Record<string, unknown>;
17
19
 
20
+ declare type PropertyConfig = {
21
+ computed?: string;
22
+ dispatch?: boolean;
23
+ required?: boolean;
24
+ type: AnyClass;
25
+ value?: any;
26
+ values?: string[];
27
+ };
28
+
18
29
  declare type StringToAny = Record<string, any>;
19
30
 
20
31
  declare type StringToString = Record<string, string>;
@@ -28,7 +39,7 @@ export declare abstract class Wrec extends HTMLElementBase implements ChangeList
28
39
  private static elementName;
29
40
  static formAssociated: boolean;
30
41
  static html: string;
31
- static properties: StringToAny;
42
+ static properties: Record<string, PropertyConfig>;
32
43
  private static propToComputedMap;
33
44
  private static propToExprsMap;
34
45
  private static template;
package/dist/wrec.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ declare type AnyClass = new (...args: any[]) => any;
2
+
1
3
  export declare type ChangeListener = {
2
4
  changed: (statePath: string, componentProperty: string, newValue: unknown, oldValue: unknown, state: WrecState) => void;
3
5
  };
@@ -15,6 +17,15 @@ declare const HTMLElementBase: {
15
17
 
16
18
  declare type LooseObject = Record<string, unknown>;
17
19
 
20
+ declare type PropertyConfig = {
21
+ computed?: string;
22
+ dispatch?: boolean;
23
+ required?: boolean;
24
+ type: AnyClass;
25
+ value?: any;
26
+ values?: string[];
27
+ };
28
+
18
29
  declare type StringToAny = Record<string, any>;
19
30
 
20
31
  declare type StringToString = Record<string, string>;
@@ -28,7 +39,7 @@ export declare abstract class Wrec extends HTMLElementBase implements ChangeList
28
39
  private static elementName;
29
40
  static formAssociated: boolean;
30
41
  static html: string;
31
- static properties: StringToAny;
42
+ static properties: Record<string, PropertyConfig>;
32
43
  private static propToComputedMap;
33
44
  private static propToExprsMap;
34
45
  private static template;
package/dist/wrec.es.js CHANGED
@@ -1,37 +1,37 @@
1
- var V = (n) => {
2
- throw TypeError(n);
1
+ var B = (r) => {
2
+ throw TypeError(r);
3
3
  };
4
- var O = (n, t, e) => t.has(n) || V("Cannot " + e);
5
- var p = (n, t, e) => (O(n, t, "read from private field"), e ? e.call(n) : t.get(n)), b = (n, t, e) => t.has(n) ? V("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(n) : t.set(n, e), w = (n, t, e, s) => (O(n, t, "write to private field"), s ? s.call(n, e) : t.set(n, e), e), B = (n, t, e) => (O(n, t, "access private method"), e);
4
+ var N = (r, t, e) => t.has(r) || B("Cannot " + e);
5
+ var u = (r, t, e) => (N(r, t, "read from private field"), e ? e.call(r) : t.get(r)), b = (r, t, e) => t.has(r) ? B("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(r) : t.set(r, e), w = (r, t, e, s) => (N(r, t, "write to private field"), s ? s.call(r, e) : t.set(r, e), e), V = (r, t, e) => (N(r, t, "access private method"), e);
6
6
  import W from "xss";
7
- function K(n, t, e = "") {
7
+ function U(r, t, e = "") {
8
8
  const s = /* @__PURE__ */ new WeakMap(), o = {
9
9
  // Intercept property reads.
10
10
  // This creates nested proxies lazily.
11
- get(i, r) {
12
- const c = Reflect.get(i, r);
11
+ get(i, n) {
12
+ const c = Reflect.get(i, n);
13
13
  if (c === null || typeof c != "object") return c;
14
14
  const a = s.get(c);
15
15
  if (a) return a;
16
- const h = e ? `${e}.${r}` : r, f = K(c, t, h);
17
- return s.set(c, f), f;
16
+ const f = e ? `${e}.${n}` : n, l = U(c, t, f);
17
+ return s.set(c, l), l;
18
18
  },
19
19
  // Intercept property writes.
20
- set(i, r, c) {
21
- const a = Reflect.get(i, r);
20
+ set(i, n, c) {
21
+ const a = Reflect.get(i, n);
22
22
  if (a !== c) {
23
- Reflect.set(i, r, c);
24
- const h = e ? `${e}.${r}` : r;
25
- t(h, a, c);
23
+ Reflect.set(i, n, c);
24
+ const f = e ? `${e}.${n}` : n;
25
+ t(f, a, c);
26
26
  }
27
27
  return !0;
28
28
  }
29
29
  };
30
- return new Proxy(n, o);
30
+ return new Proxy(r, o);
31
31
  }
32
- function Z(n) {
32
+ function Z(r) {
33
33
  const t = {};
34
- for (const [e, s] of Object.entries(n)) {
34
+ for (const [e, s] of Object.entries(r)) {
35
35
  const o = typeof s == "object" && s !== null;
36
36
  t[e] = o ? Z(s) : s;
37
37
  }
@@ -40,11 +40,11 @@ function Z(n) {
40
40
  const P = typeof window < "u" && typeof window.document < "u";
41
41
  let z = class extends Error {
42
42
  };
43
- var y, N, d, v, C, g, $, U;
43
+ var y, $, d, v, C, g, O, Y;
44
44
  const T = class T {
45
45
  constructor(t, e, s) {
46
- b(this, $);
47
- b(this, N, /* @__PURE__ */ Symbol("objectId"));
46
+ b(this, O);
47
+ b(this, $, /* @__PURE__ */ Symbol("objectId"));
48
48
  // This cannot be replaced by a WeakMap<ChangeListener, Set<string>>
49
49
  // because there is no way to iterate over the keys of a WeakMap.
50
50
  b(this, d, []);
@@ -52,16 +52,16 @@ const T = class T {
52
52
  b(this, C);
53
53
  b(this, g);
54
54
  if (!t) throw new z("name cannot be empty");
55
- if (p(T, y).has(t))
55
+ if (u(T, y).has(t))
56
56
  throw new z(`WrecState with name "${t}" already exists`);
57
- if (w(this, v, t), w(this, C, e), w(this, g, K({}, B(this, $, U).bind(this))), e && P) {
57
+ if (w(this, v, t), w(this, C, e), w(this, g, U({}, V(this, O, Y).bind(this))), e && P) {
58
58
  const o = sessionStorage.getItem("wrec-state-" + t), i = o ? JSON.parse(o) : void 0;
59
59
  i && (s = i);
60
60
  }
61
61
  if (s)
62
62
  for (const [o, i] of Object.entries(s))
63
63
  this.addProperty(o, i);
64
- p(T, y).set(t, this);
64
+ u(T, y).set(t, this);
65
65
  }
66
66
  // This static method is useful for accessing a specific WrecState object
67
67
  // from the DevTools console. For example:
@@ -74,22 +74,22 @@ const T = class T {
74
74
  // state.color = 'blue';
75
75
  // state.team.leader.name = 'Mark';
76
76
  static get(t) {
77
- return p(this, y).get(t);
77
+ return u(this, y).get(t);
78
78
  }
79
79
  /**
80
80
  * @param listener - object that has a "changed" method
81
81
  * @param map - map from state property paths to component properties
82
82
  */
83
83
  addListener(t, e = {}) {
84
- const s = p(this, d).find(
84
+ const s = u(this, d).find(
85
85
  (o) => o.listenerRef.deref() === t
86
86
  );
87
87
  if (s) {
88
88
  const { propertyMap: o } = s;
89
- for (const [i, r] of Object.entries(e))
90
- o[i] = r;
89
+ for (const [i, n] of Object.entries(e))
90
+ o[i] = n;
91
91
  } else
92
- p(this, d).push({
92
+ u(this, d).push({
93
93
  listenerRef: new WeakRef(t),
94
94
  propertyMap: e
95
95
  });
@@ -98,38 +98,38 @@ const T = class T {
98
98
  Object.defineProperty(this, t, {
99
99
  enumerable: !0,
100
100
  get() {
101
- return p(this, g)[t];
101
+ return u(this, g)[t];
102
102
  },
103
103
  set(s) {
104
- p(this, g)[t] = s;
104
+ u(this, g)[t] = s;
105
105
  }
106
- }), p(this, g)[t] = e;
106
+ }), u(this, g)[t] = e;
107
107
  }
108
108
  get id() {
109
- return p(this, N);
109
+ return u(this, $);
110
110
  }
111
111
  // This is useful for debugging from the DevTools console.
112
112
  // For example: state.log()
113
113
  log() {
114
- console.log("WrecState:", p(this, v));
115
- for (const [t, e] of Object.entries(p(this, g)))
114
+ console.log("WrecState:", u(this, v));
115
+ for (const [t, e] of Object.entries(u(this, g)))
116
116
  console.log(` ${t} = ${JSON.stringify(e)}`);
117
117
  }
118
118
  removeListener(t) {
119
- w(this, d, p(this, d).filter((e) => e.listenerRef.deref() !== t));
119
+ w(this, d, u(this, d).filter((e) => e.listenerRef.deref() !== t));
120
120
  }
121
121
  };
122
- y = new WeakMap(), N = new WeakMap(), d = new WeakMap(), v = new WeakMap(), C = new WeakMap(), g = new WeakMap(), $ = new WeakSet(), U = function(t, e, s) {
122
+ y = new WeakMap(), $ = new WeakMap(), d = new WeakMap(), v = new WeakMap(), C = new WeakMap(), g = new WeakMap(), O = new WeakSet(), Y = function(t, e, s) {
123
123
  const o = /* @__PURE__ */ new Set();
124
- for (const i of p(this, d)) {
125
- const r = i.listenerRef.deref();
126
- if (!r)
124
+ for (const i of u(this, d)) {
125
+ const n = i.listenerRef.deref();
126
+ if (!n)
127
127
  o.add(i);
128
- else if (P && r instanceof HTMLElement && !r.isConnected)
128
+ else if (P && n instanceof HTMLElement && !n.isConnected)
129
129
  o.add(i);
130
130
  else {
131
131
  const { propertyMap: c } = i, a = Object.keys(c);
132
- (a.length === 0 || a.includes(t)) && r.changed(
132
+ (a.length === 0 || a.includes(t)) && n.changed(
133
133
  t,
134
134
  c[t],
135
135
  s,
@@ -138,43 +138,43 @@ y = new WeakMap(), N = new WeakMap(), d = new WeakMap(), v = new WeakMap(), C =
138
138
  );
139
139
  }
140
140
  }
141
- w(this, d, p(this, d).filter(
141
+ w(this, d, u(this, d).filter(
142
142
  (i) => !o.has(i)
143
143
  ));
144
144
  }, b(T, y, /* @__PURE__ */ new Map()), P && window.addEventListener("beforeunload", () => {
145
- for (const [t, e] of p(T, y).entries())
146
- if (p(e, C)) {
145
+ for (const [t, e] of u(T, y).entries())
146
+ if (u(e, C)) {
147
147
  const s = Z(e);
148
148
  sessionStorage.setItem("wrec-state-" + t, JSON.stringify(s));
149
149
  }
150
150
  });
151
- let _ = T;
152
- P && process.env.NODE_ENV === "development" && (window.WrecState = _);
153
- function q(n, t) {
154
- let e = n;
151
+ let F = T;
152
+ P && process.env.NODE_ENV === "development" && (window.WrecState = F);
153
+ function q(r, t) {
154
+ let e = r;
155
155
  for (const s of t.split("."))
156
156
  e = e[s];
157
157
  return e;
158
158
  }
159
- function st(n, t, e) {
159
+ function ot(r, t, e) {
160
160
  const s = t.split("."), o = s.length - 1;
161
- let i = n;
162
- s.forEach((r, c) => {
163
- c === o ? i[r] = e : i = i[r];
161
+ let i = r;
162
+ s.forEach((n, c) => {
163
+ c === o ? i[n] = e : i = i[n];
164
164
  });
165
165
  }
166
- const ot = /* @__PURE__ */ new Set(["input", "label", "option", "th"]), J = "__WREC", X = "__";
167
- function it(n) {
166
+ const it = /* @__PURE__ */ new Set(["input", "label", "option", "th"]), J = "__WREC", X = "__";
167
+ function nt(r) {
168
168
  const t = {
169
169
  allowCommentTag: !0,
170
170
  onTag: (o, i) => {
171
- if (ot.has(o)) return i;
171
+ if (it.has(o)) return i;
172
172
  },
173
- onTagAttr(o, i, r) {
173
+ onTagAttr(o, i, n) {
174
174
  if (i.startsWith("on")) return "";
175
175
  },
176
- safeAttrValue(o, i, r) {
177
- return i === "class" || o === "a" && i === "href" && !r.startsWith("javascript") || o === "img" && i === "src" ? r : "";
176
+ safeAttrValue(o, i, n) {
177
+ return i === "class" || o === "a" && i === "href" && !n.startsWith("javascript") || o === "img" && i === "src" ? n : "";
178
178
  },
179
179
  stripIgnoreTagBody: ["script", "style", "iframe"],
180
180
  whiteList: {
@@ -183,32 +183,32 @@ function it(n) {
183
183
  span: ["class"]
184
184
  }
185
185
  }, e = [];
186
- n = n.replace(/<!--[\s\S]*?-->/g, (o) => {
186
+ r = r.replace(/<!--[\s\S]*?-->/g, (o) => {
187
187
  let i = "";
188
188
  do
189
189
  i = J + e.length + X;
190
- while (n.includes(i));
190
+ while (r.includes(i));
191
191
  return e.push(o), i;
192
192
  });
193
- let s = W(n, t);
193
+ let s = W(r, t);
194
194
  return e.forEach((o, i) => {
195
- const r = new RegExp(
195
+ const n = new RegExp(
196
196
  `${J}${i}${X}`,
197
197
  "g"
198
198
  );
199
- s = s.replace(r, o);
199
+ s = s.replace(n, o);
200
200
  }), s;
201
201
  }
202
- const nt = /* @__PURE__ */ new Set([
202
+ const rt = /* @__PURE__ */ new Set([
203
203
  "class",
204
204
  "disabled",
205
205
  "hidden",
206
206
  "id",
207
207
  "tabindex",
208
208
  "title"
209
- ]), rt = globalThis.HTMLElement ?? class {
210
- }, F = globalThis.customElements ?? {
211
- get: (n) => {
209
+ ]), ct = globalThis.HTMLElement ?? class {
210
+ }, _ = globalThis.customElements ?? {
211
+ get: (r) => {
212
212
  },
213
213
  getName: () => "",
214
214
  define: () => {
@@ -221,96 +221,96 @@ const nt = /* @__PURE__ */ new Set([
221
221
  };
222
222
  class E extends Error {
223
223
  }
224
- const ct = /([a-zA-Z-]+)\s*:\s*([^;}]+)/g, Y = "a-zA-Z_$", at = Y + "0-9", S = `[${Y}][${at}]*`, ft = /<!--\s*(.*?)\s*-->/, ht = /<(\w+)(?:\s[^>]*)?>((?:[^<]|<(?!\w))*?)<\/\1>/g, L = new RegExp(`^this\\.${S}$`), j = new RegExp(`this\\.${S}(\\.${S})*`, "g"), G = new RegExp(`this\\.${S}(\\.${S})*`), lt = 5;
225
- function pt(n) {
226
- return n instanceof HTMLButtonElement || n instanceof HTMLFieldSetElement || n instanceof HTMLInputElement || n instanceof HTMLSelectElement || n instanceof HTMLTextAreaElement || n instanceof u;
224
+ const at = /([a-zA-Z-]+)\s*:\s*([^;}]+)/g, G = "a-zA-Z_$", ft = G + "0-9", A = `[${G}][${ft}]*`, lt = /<!--\s*(.*?)\s*-->/, ht = /<(\w+)(?:\s[^>]*)?>((?:[^<]|<(?!\w))*?)<\/\1>/g, L = new RegExp(`^this\\.${A}$`), j = new RegExp(`this\\.${A}(\\.${A})*`, "g"), Q = new RegExp(`this\\.${A}(\\.${A})*`), ut = 5;
225
+ function pt(r) {
226
+ return r instanceof HTMLButtonElement || r instanceof HTMLFieldSetElement || r instanceof HTMLInputElement || r instanceof HTMLSelectElement || r instanceof HTMLTextAreaElement || r instanceof p;
227
227
  }
228
- function wt(n, t, e) {
229
- const s = document.createElement(n);
228
+ function Et(r, t, e) {
229
+ const s = document.createElement(r);
230
230
  if (t)
231
231
  for (const [o, i] of Object.entries(t))
232
232
  s.setAttribute(o, i);
233
233
  return e && (s.innerHTML = e), s;
234
234
  }
235
- const ut = (n) => n === String ? "" : n === Number ? 0 : n === Boolean ? !1 : n === Array ? [] : n === Object ? {} : void 0;
236
- function R(n) {
235
+ const K = (r) => Array.isArray(r.values) && r.values.length > 0 ? r.values[0] : dt(r.type), dt = (r) => r === String ? "" : r === Number ? 0 : r === Boolean ? !1 : r === Array ? [] : r === Object ? {} : void 0;
236
+ function R(r) {
237
237
  const t = [];
238
- let e = n.firstElementChild;
238
+ let e = r.firstElementChild;
239
239
  for (; e; )
240
240
  t.push(e), e.shadowRoot && t.push(...R(e.shadowRoot)), e.firstElementChild && t.push(...R(e)), e = e.nextElementSibling;
241
241
  return t;
242
242
  }
243
- const M = (n) => n.substring(lt).split(".")[0];
244
- function Q(n, t) {
245
- let e = n[0];
243
+ const M = (r) => r.substring(ut).split(".")[0];
244
+ function tt(r, t) {
245
+ let e = r[0];
246
246
  return t.forEach((s, o) => {
247
- e += s + n[o + 1];
247
+ e += s + r[o + 1];
248
248
  }), e;
249
249
  }
250
- function I(n) {
251
- const t = typeof n;
250
+ function I(r) {
251
+ const t = typeof r;
252
252
  return t === "string" || t === "number" || t === "boolean";
253
253
  }
254
- function A(n) {
255
- return n.localName === "textarea";
254
+ function S(r) {
255
+ return r.localName === "textarea";
256
256
  }
257
- function D(n) {
258
- const { localName: t } = n;
257
+ function D(r) {
258
+ const { localName: t } = r;
259
259
  return t === "input" || t === "select";
260
260
  }
261
- const dt = (n) => n.replace(/<!--[\s\S]*?-->/g, "");
262
- function tt(n, t, e, s) {
263
- return n.slice(0, t) + s + n.slice(t + e);
261
+ const mt = (r) => r.replace(/<!--[\s\S]*?-->/g, "");
262
+ function et(r, t, e, s) {
263
+ return r.slice(0, t) + s + r.slice(t + e);
264
264
  }
265
- function H(n) {
266
- const t = Number(n);
267
- if (isNaN(t)) throw new E(`can't convert "${n}" to a number`);
265
+ function H(r) {
266
+ const t = Number(r);
267
+ if (isNaN(t)) throw new E(`can't convert "${r}" to a number`);
268
268
  return t;
269
269
  }
270
- function et(n, t, e) {
270
+ function st(r, t, e) {
271
271
  const [s, o] = t.split(":");
272
272
  if (I(e))
273
273
  if (typeof e == "boolean") {
274
- e ? n.setAttribute(s, s) : n.removeAttribute(s);
275
- const i = u.getPropName(s);
276
- n[i] = e;
274
+ e ? r.setAttribute(s, s) : r.removeAttribute(s);
275
+ const i = p.getPropName(s);
276
+ r[i] = e;
277
277
  } else {
278
- const i = n.getAttribute(t), r = String(e);
279
- i !== r && (n.setAttribute(s, r), s === "value" && D(n) && (n.value = r));
278
+ const i = r.getAttribute(t), n = String(e);
279
+ i !== n && (r.setAttribute(s, n), s === "value" && D(r) && (r.value = n));
280
280
  }
281
281
  else {
282
- const i = u.getPropName(t);
283
- n[i] = e;
282
+ const i = p.getPropName(t);
283
+ r[i] = e;
284
284
  }
285
285
  }
286
- function k(n, t, e) {
286
+ function k(r, t, e) {
287
287
  const [s, o] = t.split(":");
288
- n instanceof CSSStyleRule ? n.style.setProperty(s, e) : (et(n, s, e), s === "value" && D(n) && (n.value = e));
288
+ r instanceof CSSStyleRule ? r.style.setProperty(s, e) : (st(r, s, e), s === "value" && D(r) && (r.value = e));
289
289
  }
290
- async function mt(n) {
290
+ async function bt(r) {
291
291
  const t = /* @__PURE__ */ new Set();
292
- for (const s of R(n.content)) {
292
+ for (const s of R(r.content)) {
293
293
  const { localName: o } = s;
294
294
  o.includes("-") && t.add(o);
295
295
  }
296
296
  function e(s) {
297
297
  return new Promise((o, i) => {
298
298
  setTimeout(() => {
299
- const r = `custom element <${s}> not defined`;
300
- i(new Error(r));
299
+ const n = `custom element <${s}> not defined`;
300
+ i(new Error(n));
301
301
  }, 1e3);
302
302
  });
303
303
  }
304
304
  return Promise.all(
305
305
  [...t].map(
306
306
  async (s) => Promise.race([
307
- F.whenDefined(s),
307
+ _.whenDefined(s),
308
308
  e(s)
309
309
  ])
310
310
  )
311
311
  );
312
312
  }
313
- class u extends rt {
313
+ class p extends ct {
314
314
  // There is one instance of `attrToPropMap`, `properties`, `propToAttrMap`,
315
315
  // `propToComputedMap`, and `propToExprsMap` per Wrec subclass,
316
316
  // not one for only the Wrec class.
@@ -352,21 +352,24 @@ class u extends rt {
352
352
  static propToExprsMap;
353
353
  static template = null;
354
354
  // This is true while the batchSet method is running.
355
- #f = !1;
355
+ #h = !1;
356
+ // This holds the names of computed properties
357
+ // that are currently being updated.
358
+ #u = /* @__PURE__ */ new Set();
356
359
  #t = this.constructor;
357
360
  // This is a map from expressions to references to them
358
361
  // which can be found in element text content,
359
362
  // attribute values, and CSS property values.
360
363
  // Each component instance needs its own map.
361
- #o = /* @__PURE__ */ new Map();
362
- #h = {};
364
+ #s = /* @__PURE__ */ new Map();
365
+ #p = {};
363
366
  #i;
364
367
  // For components that set `formAssociated` to true,
365
368
  // this stores in the initial value of each property
366
369
  // in the formAssociatedCallback method
367
370
  // so they can be restored in the formResetCallback method.
368
- #l = {};
369
- #p = null;
371
+ #d = {};
372
+ #m = null;
370
373
  // This is a map from properties in this web component
371
374
  // to corresponding properties in a parent web component.
372
375
  // This must be an instance property because
@@ -374,15 +377,15 @@ class u extends rt {
374
377
  // to the properties of different parent components.
375
378
  // This is used to update a parent property
376
379
  // when the corresponding child property value changes.
377
- #u = /* @__PURE__ */ new Map();
380
+ #b = /* @__PURE__ */ new Map();
378
381
  // This is a map from component properties to state bindings.
379
382
  // It must be instance-specific because each component instance
380
383
  // can bind the same property to a different WrecState/path.
381
- #m = /* @__PURE__ */ new Map();
384
+ #r = /* @__PURE__ */ new Map();
382
385
  static define(t) {
383
- if (this.elementName = t, F.get(t))
386
+ if (this.elementName = t, _.get(t))
384
387
  throw new E(`custom element ${t} is already defined`);
385
- F.define(t, this);
388
+ _.define(t, this);
386
389
  }
387
390
  constructor() {
388
391
  super(), this.attachShadow({ mode: "open" });
@@ -390,53 +393,53 @@ class u extends rt {
390
393
  this.#n("attrToPropMap") || (t.attrToPropMap = /* @__PURE__ */ new Map()), this.#n("properties") || (t.properties = {}), this.#n("propToAttrMap") || (t.propToAttrMap = /* @__PURE__ */ new Map()), this.#n("propToComputedMap") || (t.propToComputedMap = /* @__PURE__ */ new Map()), this.#n("propToExprsMap") || (t.propToExprsMap = /* @__PURE__ */ new Map());
391
394
  }
392
395
  attributeChangedCallback(t, e, s) {
393
- t === "disabled" && this.#g();
394
- const o = u.getPropName(t);
395
- if (this.#r(o)) {
396
- const i = this.#S(o, String(s));
396
+ t === "disabled" && this.#w();
397
+ const o = p.getPropName(t);
398
+ if (this.#c(o)) {
399
+ const i = this.#x(o, s);
397
400
  this[o] = i;
398
- const r = this.#h[o];
399
- r && this.setFormValue(r, String(i)), this.propertyChangedCallback(o, e, s);
401
+ const n = this.#p[o];
402
+ n && this.setFormValue(n, String(i)), this.propertyChangedCallback(o, e, s);
400
403
  }
401
404
  }
402
405
  // This applies multiple property changes and only updates
403
406
  // the affected parts of the DOM after all of them are made.
404
407
  batchSet(t) {
405
- this.#f = !0;
408
+ this.#h = !0;
406
409
  const e = this.#t.propToExprsMap, s = /* @__PURE__ */ new Set();
407
410
  for (const [c, a] of Object.entries(t)) {
408
411
  this[c] = a;
409
- const h = e.get(c) ?? [];
410
- for (const f of h)
411
- s.add(f);
412
+ const f = e.get(c) ?? [];
413
+ for (const l of f)
414
+ s.add(l);
412
415
  }
413
- const o = this.#t.propToComputedMap, i = /* @__PURE__ */ new Set(), r = {};
416
+ const o = this.#t.propToComputedMap, i = /* @__PURE__ */ new Set(), n = {};
414
417
  for (const c of Object.keys(t)) {
415
418
  const a = o.get(c) || [];
416
- for (const [h, f] of a)
417
- i.add(h), r[h] = f;
419
+ for (const [f, l] of a)
420
+ i.add(f), n[f] = l;
418
421
  }
419
422
  for (const c of i) {
420
- const a = r[c];
421
- this[c] = this.#s(a);
422
- const h = e.get(c) ?? [];
423
- for (const f of h)
424
- s.add(f);
423
+ const a = n[c];
424
+ this.#a(c, this.#o(a));
425
+ const f = e.get(c) ?? [];
426
+ for (const l of f)
427
+ s.add(l);
425
428
  }
426
429
  for (; ; ) {
427
430
  let c = !1;
428
431
  for (const a of i) {
429
- const h = r[a], f = this.#s(h), l = this[a];
430
- JSON.stringify(f) !== JSON.stringify(l) && (this[a] = f, c = !0);
432
+ const f = n[a], l = this.#o(f), h = this[a];
433
+ JSON.stringify(l) !== JSON.stringify(h) && (this.#a(a, l), c = !0);
431
434
  }
432
435
  if (!c) break;
433
436
  }
434
- this.#y([...s]), this.#f = !1;
437
+ this.#E([...s]), this.#h = !1;
435
438
  }
436
- async #x() {
439
+ async #$() {
437
440
  const t = this.#t;
438
441
  let { template: e } = t;
439
- e || (e = t.template = document.createElement("template"), e.innerHTML = t.buildHTML()), await mt(e), this.shadowRoot.replaceChildren(e.content.cloneNode(!0));
442
+ e || (e = t.template = document.createElement("template"), e.innerHTML = t.buildHTML()), await bt(e), this.shadowRoot.replaceChildren(e.content.cloneNode(!0));
440
443
  }
441
444
  static buildHTML() {
442
445
  let t = `<style>
@@ -451,59 +454,65 @@ class u extends rt {
451
454
  this[e] = s;
452
455
  }
453
456
  connectedCallback() {
454
- this.#_(), this.#R(), this.#x().then(() => {
455
- this.hasAttribute("disabled") && this.#g(), this.#C(this.shadowRoot), this.#w(this.shadowRoot), this.#P();
457
+ this.#D(), this.#N(), this.#$().then(() => {
458
+ this.hasAttribute("disabled") && this.#w(), this.#R(this.shadowRoot), this.#M(this.shadowRoot), this.#O();
456
459
  });
457
460
  }
458
- #P() {
461
+ #O() {
459
462
  const t = this.#t, { properties: e } = t;
460
463
  for (const [s, { computed: o }] of Object.entries(e))
461
- o && (this[s] = this.#s(o));
464
+ o && this.#a(s, this.#o(o));
462
465
  }
463
- #R() {
466
+ #N() {
464
467
  const t = this.#t, { observedAttributes: e, properties: s } = t;
465
468
  for (const [o, i] of Object.entries(s))
466
- i.computed || this.#b(o, i, e);
469
+ i.computed || this.#y(o, i, e);
467
470
  for (const [o, i] of Object.entries(s))
468
- i.computed && this.#b(o, i, e);
471
+ i.computed && this.#y(o, i, e);
469
472
  }
470
- #b(t, e, s) {
473
+ #y(t, e, s) {
471
474
  if (t === "class" || t === "style")
472
475
  throw new E(`"${t}" is a reserved property`);
473
- const o = u.getAttrName(t), i = this.hasAttribute(o);
476
+ const o = p.getAttrName(t), i = this.hasAttribute(o);
474
477
  e.required && !i && this.#e(this, o, "is a required attribute");
475
- let r = e.value;
476
- this.hasOwnProperty(t) && (r = this[t], delete this[t]);
477
- const { type: c } = e, a = c === Boolean ? r || i : s.includes(o) && i ? this.#A(t, o) : r || ut(c), h = "#" + t;
478
- this[h] = a, e.computed && this.#L(t, e), Object.defineProperty(this, t, {
478
+ let n = e.value;
479
+ this.hasOwnProperty(t) && (n = this[t], delete this[t]);
480
+ const { type: c } = e, a = c === Boolean ? n || i : s.includes(o) && i ? this.#C(t, o) : n ?? K(e), f = "#" + t;
481
+ this[f] = a, e.computed && this.#k(t, e), Object.defineProperty(this, t, {
479
482
  enumerable: !0,
480
483
  get() {
481
- return this[h];
484
+ return this[f];
482
485
  },
483
- set(f) {
484
- c === Number && typeof f == "string" && (f = H(f));
485
- const l = this[h];
486
- if (f === l) return;
487
- this.#I(t, c, f), this[h] = f;
488
- const m = this.#m.get(t);
489
- m && st(m.state, m.stateProp, f), this.#j(t, c, f, o), this.#f || (this.#H(t), this.#M(t)), this.#k(t, f);
490
- const x = this.#h[t];
491
- x && this.setFormValue(x, String(f)), this.propertyChangedCallback(t, l, f), e.dispatch && this.dispatch("change", {
486
+ set(l) {
487
+ e.computed && !this.#u.has(t) && this.#e(
488
+ null,
489
+ t,
490
+ "is a computed property and cannot be set directly"
491
+ ), c === Number && typeof l == "string" && (l = H(l));
492
+ const h = this[f];
493
+ if (l === h) return;
494
+ this.#V(t, c, l), this[f] = l;
495
+ const m = this.#r.get(t);
496
+ m && ot(m.state, m.stateProp, l), this.#F(t, c, l, o), this.#h || (this.#_(t), this.#v(t)), this.#I(t, l);
497
+ const x = this.#p[t];
498
+ x && this.setFormValue(x, String(l)), this.propertyChangedCallback(t, h, l), e.dispatch && this.dispatch("change", {
492
499
  tagName: this.localName,
493
500
  property: t,
494
- oldValue: l,
495
- value: f
501
+ oldValue: h,
502
+ value: l
496
503
  });
497
504
  }
498
505
  });
499
506
  }
500
- #g() {
507
+ #w() {
501
508
  const t = this.hasAttribute("disabled"), e = R(this.shadowRoot);
502
509
  for (const s of e)
503
510
  pt(s) && (s.disabled = t);
504
511
  }
505
512
  disconnectedCallback() {
506
- this.#o.clear(), this.#l.clear(), this.#u.clear();
513
+ for (const { state: t } of this.#r.values())
514
+ t.removeListener(this);
515
+ this.#s.clear(), this.#d.clear(), this.#b.clear(), this.#r.clear();
507
516
  }
508
517
  dispatch(t, e) {
509
518
  this.dispatchEvent(
@@ -519,60 +528,70 @@ class u extends rt {
519
528
  displayIfSet(t, e = "block") {
520
529
  return `display: ${t ? e : "none"}`;
521
530
  }
522
- #N(t) {
523
- const e = t instanceof u;
531
+ #L(t) {
532
+ const e = t instanceof p;
524
533
  for (const s of t.getAttributeNames()) {
525
- const o = t.getAttribute(s), i = this.#T(t, o);
534
+ const o = t.getAttribute(s), i = this.#A(t, o);
526
535
  if (i) {
527
- const r = this[i];
528
- r === void 0 && this.#a(t, s, i);
536
+ const n = this[i];
537
+ n === void 0 && this.#l(t, s, i);
529
538
  let [c, a] = s.split(":");
530
- const h = u.getPropName(c);
531
- t[h] = r, c === "value" && (a ? (t["on" + a] === void 0 && this.#e(t, s, "refers to an unsupported event name"), t.setAttribute(c, this[i])) : a = "change"), e && t.#u.set(
532
- u.getPropName(c),
539
+ const f = p.getPropName(c), l = this.#T(i);
540
+ e && t.#T(f) || (t[f] = n), c === "value" && (a ? (t["on" + a] === void 0 && this.#e(t, s, "refers to an unsupported event name"), t.setAttribute(c, this[i])) : a = "change"), e && !l && t.#b.set(
541
+ p.getPropName(c),
533
542
  i
534
543
  );
535
544
  }
536
- this.#c(o, t, s);
545
+ this.#f(o, t, s);
537
546
  }
538
547
  }
539
- #y(t) {
548
+ #E(t) {
540
549
  for (const e of t) {
541
- const s = this.#s(e), o = this.#o.get(e) ?? [];
542
- for (const i of o)
543
- if (i instanceof HTMLElement)
544
- this.#v(i, s);
545
- else if (!(i instanceof CSSStyleRule)) {
546
- const { element: r, attrName: c } = i;
547
- r instanceof CSSStyleRule ? r.style.setProperty(c, s) : k(r, c, s);
550
+ const s = this.#o(e), o = this.#s.get(e) ?? [], i = /* @__PURE__ */ new Set();
551
+ for (const n of o) {
552
+ const c = n instanceof HTMLElement || n instanceof CSSStyleRule ? n : n.element;
553
+ if (c instanceof HTMLElement && !c.isConnected) {
554
+ i.add(n);
555
+ continue;
548
556
  }
557
+ if (n instanceof HTMLElement)
558
+ this.#P(n, s);
559
+ else if (!(n instanceof CSSStyleRule)) {
560
+ const { element: a, attrName: f } = n;
561
+ a instanceof CSSStyleRule ? a.style.setProperty(f, s) : k(a, f, s);
562
+ }
563
+ }
564
+ if (i.size > 0) {
565
+ const n = o.filter((c) => !i.has(c));
566
+ n.length === 0 ? this.#s.delete(e) : this.#s.set(e, n);
567
+ }
549
568
  }
550
569
  }
551
- #s(t) {
570
+ #o(t) {
552
571
  const { context: e } = this.#t;
553
572
  return new Function(
554
573
  "context",
555
574
  `const {${Object.keys(e).join(",")}} = context; return ${t};`
556
575
  ).call(this, e);
557
576
  }
558
- #$(t) {
577
+ #j(t) {
559
578
  const { localName: e } = t;
560
579
  if (e === "style") {
561
580
  const { sheet: s } = t, o = s?.cssRules ?? [], i = Array.from(o);
562
- for (const r of i)
563
- if (r.constructor === CSSStyleRule) {
564
- const c = Array.from(r.style);
581
+ for (const n of i)
582
+ if (n.constructor === CSSStyleRule) {
583
+ const c = Array.from(n.style);
565
584
  for (const a of c)
566
585
  if (a.startsWith("--")) {
567
- const h = r.style.getPropertyValue(a);
568
- this.#c(h, r, a);
586
+ const f = n.style.getPropertyValue(a);
587
+ this.#f(f, n, a);
569
588
  }
570
589
  }
571
590
  } else {
572
591
  let s = "";
573
- if (A(t)) {
574
- this.#c(t.textContent, t);
575
- const o = t.textContent?.match(ft);
592
+ if (S(t)) {
593
+ this.#f(t.textContent, t);
594
+ const o = t.textContent?.match(lt);
576
595
  o && (s = o[1]);
577
596
  } else {
578
597
  const o = Array.from(t.childNodes).find(
@@ -581,8 +600,8 @@ class u extends rt {
581
600
  o && (s = o.textContent?.trim() ?? "");
582
601
  }
583
602
  if (s) {
584
- const o = this.#T(t, s);
585
- o && A(t) ? t.textContent = this[o] : this.#c(s, t);
603
+ const o = this.#A(t, s);
604
+ o && S(t) ? t.textContent = this[o] : this.#f(s, t);
586
605
  }
587
606
  }
588
607
  }
@@ -593,30 +612,30 @@ class u extends rt {
593
612
  formAssociatedCallback() {
594
613
  let t = this.getAttribute("form-assoc");
595
614
  if (!t) {
596
- const r = this.getAttribute("name");
597
- if (r)
598
- if (this.#r("value"))
599
- t = `value:${r}`;
615
+ const n = this.getAttribute("name");
616
+ if (n)
617
+ if (this.#c("value"))
618
+ t = `value:${n}`;
600
619
  else
601
620
  return;
602
621
  else
603
622
  return;
604
623
  }
605
624
  const e = {}, s = t.split(",");
606
- for (const r of s) {
607
- const [c, a] = r.split(":");
625
+ for (const n of s) {
626
+ const [c, a] = n.split(":");
608
627
  e[c.trim()] = a.trim();
609
628
  }
610
- this.#h = e, this.#i = new FormData(), this.#p = this.attachInternals(), this.#p.setFormValue(this.#i);
611
- const o = Object.keys(this.#t.properties), i = this.#l;
612
- for (const r of o)
613
- i[r] = this[r];
629
+ this.#p = e, this.#i = new FormData(), this.#m = this.attachInternals(), this.#m.setFormValue(this.#i);
630
+ const o = Object.keys(this.#t.properties), i = this.#d;
631
+ for (const n of o)
632
+ i[n] = this[n];
614
633
  }
615
634
  formResetCallback() {
616
- const t = this.#l;
635
+ const t = this.#d;
617
636
  for (const e of Object.keys(t)) {
618
637
  let s = t[e];
619
- L.test(s) && (s = this.#s(s)), this[e] = s;
638
+ L.test(s) && (s = this.#o(s)), this[e] = s;
620
639
  }
621
640
  }
622
641
  static getAttrName(t) {
@@ -627,35 +646,38 @@ class u extends rt {
627
646
  let e = this.attrToPropMap.get(t);
628
647
  return e || (e = t.replace(/-([a-z])/g, (s, o) => o.toUpperCase()), this.attrToPropMap.set(t, e)), e;
629
648
  }
630
- #O(t, e, s) {
649
+ #H(t, e, s) {
631
650
  if (s.length !== 1) return;
632
651
  const [o] = s;
633
652
  if (!L.test(o)) return;
634
- const i = D(t) || A(t);
635
- let [r, c] = (e ?? "").split(":");
636
- if (!(i && r === "value" || A(t))) return;
653
+ const i = D(t) || S(t);
654
+ let [n, c] = (e ?? "").split(":");
655
+ if (!(i && n === "value" || S(t))) return;
637
656
  c ? t["on" + c] === void 0 && this.#e(t, e, "refers to an unsupported event name") : c = "change";
638
- const h = M(o);
639
- t.addEventListener(c, (f) => {
640
- const { target: l } = f;
641
- if (!l) return;
642
- const m = l.value, { type: x } = this.#t.properties[h];
643
- this[h] = x === Number ? H(m) : m, this.#M(h);
657
+ const f = M(o);
658
+ t.addEventListener(c, (l) => {
659
+ const { target: h } = l;
660
+ if (!h) return;
661
+ const m = h.value, { type: x } = this.#t.properties[f];
662
+ this[f] = x === Number ? H(m) : m, this.#v(f);
644
663
  });
645
664
  }
646
665
  #n(t) {
647
666
  return Object.hasOwn(this.#t, t);
648
667
  }
649
- #r(t) {
668
+ #c(t) {
650
669
  return !!this.#t.properties[t];
651
670
  }
652
- #w(t) {
671
+ #T(t) {
672
+ return !!this.#t.properties[t]?.computed;
673
+ }
674
+ #M(t) {
653
675
  const e = Array.from(t.querySelectorAll("*"));
654
676
  for (const s of e)
655
- this.#N(s), s.firstElementChild || this.#$(s);
677
+ this.#L(s), s.firstElementChild || this.#j(s);
656
678
  }
657
679
  // formAssociated is only needed when the component is inside a form.
658
- #E() {
680
+ #S() {
659
681
  if (this.#t.formAssociated || this.closest("form") === null) return;
660
682
  const t = this.#t.name;
661
683
  this.#e(
@@ -666,42 +688,50 @@ class u extends rt {
666
688
  }
667
689
  static get observedAttributes() {
668
690
  const t = Object.keys(this.properties || {}).map(
669
- (e) => u.getAttrName(e)
691
+ (e) => p.getAttrName(e)
670
692
  );
671
693
  return t.includes("disabled") || t.push("disabled"), t;
672
694
  }
673
695
  // Subclasses can override this to add functionality.
674
696
  propertyChangedCallback(t, e, s) {
675
697
  }
676
- #T(t, e) {
698
+ #A(t, e) {
677
699
  if (!e || !L.test(e)) return;
678
700
  const s = M(e);
679
- return this[s] === void 0 && this.#a(t, "", s), s;
701
+ return this[s] === void 0 && this.#l(t, "", s), s;
680
702
  }
681
- #M(t) {
703
+ #v(t) {
682
704
  const e = this.#t.propToExprsMap.get(t) || [];
683
- this.#y(e);
705
+ this.#E(e);
684
706
  }
685
- #L(t, e) {
707
+ #k(t, e) {
686
708
  const { computed: s, uses: o } = e, i = this.#t.propToComputedMap;
687
- function r(a, h) {
688
- let f = i.get(a);
689
- f || (f = [], i.set(a, f)), f.push([t, h]);
709
+ function n(a, f) {
710
+ let l = i.get(a);
711
+ l || (l = [], i.set(a, l)), l.push([t, f]);
690
712
  }
691
713
  const c = s.match(j) || [];
692
714
  for (const a of c) {
693
- const h = M(a);
694
- this[h] === void 0 && this.#a(null, t, h), typeof this[h] != "function" && r(h, s);
715
+ const f = M(a);
716
+ this[f] === void 0 && this.#l(null, t, f), typeof this[f] != "function" && n(f, s);
695
717
  }
696
718
  if (o)
697
719
  for (const a of o.split(","))
698
- r(a.trim(), s);
720
+ n(a.trim(), s);
721
+ }
722
+ #a(t, e) {
723
+ this.#u.add(t);
724
+ try {
725
+ this[t] = e;
726
+ } finally {
727
+ this.#u.delete(t);
728
+ }
699
729
  }
700
730
  // WARNING: Do not place untrusted JavaScript expressions
701
731
  // in attribute values or the text content of elements!
702
- #c(t, e, s = void 0) {
732
+ #f(t, e, s = void 0) {
703
733
  if (!t) return;
704
- const o = this.#d(e, s, t);
734
+ const o = this.#g(e, s, t);
705
735
  if (!o) {
706
736
  const a = t.replaceAll("this..", "this.");
707
737
  s ? k(e, s, a) : "textContent" in e && (e.textContent = a);
@@ -709,24 +739,24 @@ class u extends rt {
709
739
  }
710
740
  const i = this.#t;
711
741
  o.forEach((a) => {
712
- const h = M(a);
713
- if (typeof this[h] == "function") return;
714
- const f = i.propToExprsMap;
715
- let l = f.get(h);
716
- l || (l = [], f.set(h, l)), l.includes(t) || l.push(t);
742
+ const f = M(a);
743
+ if (typeof this[f] == "function") return;
744
+ const l = i.propToExprsMap;
745
+ let h = l.get(f);
746
+ h || (h = [], l.set(f, h)), h.includes(t) || h.push(t);
717
747
  });
718
- for (const [a, h] of this.#o.entries())
719
- for (const f of h) {
720
- const l = f instanceof HTMLElement || f instanceof CSSStyleRule ? f : f.element;
721
- l instanceof CSSStyleRule || l.isConnected || this.#o.set(
748
+ for (const [a, f] of this.#s.entries())
749
+ for (const l of f) {
750
+ const h = l instanceof HTMLElement || l instanceof CSSStyleRule ? l : l.element;
751
+ h instanceof CSSStyleRule || h.isConnected || this.#s.set(
722
752
  a,
723
- h.filter((m) => m !== f)
753
+ f.filter((m) => m !== l)
724
754
  );
725
755
  }
726
- let r = this.#o.get(t);
727
- r || (r = [], this.#o.set(t, r)), r.push(s ? { element: e, attrName: s } : e), e instanceof HTMLElement && this.#O(e, s, o);
728
- const c = this.#s(t);
729
- s ? k(e, s, c) : this.#v(e, c);
756
+ let n = this.#s.get(t);
757
+ n || (n = [], this.#s.set(t, n)), n.push(s ? { element: e, attrName: s } : e), e instanceof HTMLElement && this.#H(e, s, o);
758
+ const c = this.#o(t);
759
+ s ? k(e, s, c) : this.#P(e, c);
730
760
  }
731
761
  // This follows the best practice
732
762
  // "Do not override author-set, global attributes."
@@ -734,7 +764,7 @@ class u extends rt {
734
764
  this.hasAttribute(t) || this.setAttribute(t, e);
735
765
  }
736
766
  setFormValue(t, e) {
737
- !this.#i || !I(e) || (this.#i.set(t, e), this.#p?.setFormValue(this.#i));
767
+ !this.#i || !I(e) || (this.#i.set(t, e), this.#m?.setFormValue(this.#i));
738
768
  }
739
769
  static ssr(t = {}) {
740
770
  throw new E('Import Wrec from "wrec/ssr" to use the ssr method.');
@@ -745,44 +775,52 @@ class u extends rt {
745
775
  `component ${this.#t.elementName}` + (t ? `, element "${o}"` : "") + (e ? `, attribute "${e}"` : "") + ` ${s}`
746
776
  );
747
777
  }
748
- #a(t, e, s) {
778
+ #l(t, e, s) {
749
779
  this.#e(t, e, `refers to missing property "${s}"`);
750
780
  }
751
- #A(t, e) {
752
- return this.#S(t, this.getAttribute(e));
781
+ #C(t, e) {
782
+ return this.#x(t, this.getAttribute(e));
753
783
  }
754
- #S(t, e) {
784
+ #x(t, e) {
755
785
  if (e?.match(j)) return e;
756
- const s = this.#t, { type: o } = s.properties[t];
757
- if (o || this.#e(null, t, "does not specify its type"), o === String) return e;
758
- if (o === Number) return H(e);
759
- if (o === Boolean) {
786
+ const o = this.#t.properties[t], { type: i, values: n } = o;
787
+ if (i || this.#e(null, t, "does not specify its type"), e === null)
788
+ return i === Boolean ? !1 : K(o);
789
+ if (i === String) {
790
+ if (n && !n.includes(e)) {
791
+ const c = n.map((a) => `"${a}"`).join(", ");
792
+ this.#e(null, t, `must be one of ${c}`);
793
+ }
794
+ return e;
795
+ }
796
+ if (i === Number) return H(e);
797
+ if (i === Boolean) {
760
798
  if (e === "true") return !0;
761
799
  if (e === "false" || e === "null") return !1;
762
- const i = u.getAttrName(t);
763
- return e && e !== i && this.#e(
800
+ const c = p.getAttrName(t);
801
+ return e && e !== c && this.#e(
764
802
  null,
765
803
  t,
766
804
  "is a Boolean attribute, so its value must match attribute name or be missing"
767
- ), e === "" || e === i;
805
+ ), e === "" || e === c;
768
806
  }
769
807
  }
770
808
  // Updates the matching attribute for a property.
771
809
  // VS Code thinks this is never called, but it is called by #defineProp.
772
- #j(t, e, s, o) {
810
+ #F(t, e, s, o) {
773
811
  if (I(s)) {
774
- const i = e === Boolean ? this.hasAttribute(o) : this.#A(t, o);
775
- s !== i && et(this, o || t, s);
812
+ const i = e === Boolean ? this.hasAttribute(o) : this.#C(t, o);
813
+ s !== i && st(this, o || t, s);
776
814
  }
777
815
  }
778
816
  // Updates all computed properties that reference this property.
779
817
  // VS Code thinks this is never called, but it is called by #defineProp.
780
- #H(t) {
818
+ #_(t) {
781
819
  const s = this.#t.propToComputedMap.get(t) || [];
782
820
  for (const [o, i] of s)
783
- this[o] = this.#s(i);
821
+ this.#a(o, this.#o(i));
784
822
  }
785
- #v(t, e) {
823
+ #P(t, e) {
786
824
  if (e === void 0) return;
787
825
  const s = t instanceof HTMLElement;
788
826
  Array.isArray(e) && (e = e.join(""));
@@ -793,24 +831,24 @@ class u extends rt {
793
831
  " computed content is not a string or number"
794
832
  );
795
833
  const i = String(e);
796
- if (t instanceof HTMLElement && A(t))
834
+ if (t instanceof HTMLElement && S(t))
797
835
  t.value = i;
798
836
  else if (s && o === "string" && i.trim().startsWith("<")) {
799
- const r = it(i);
800
- t.innerHTML = r, this.#C(t), this.#w(t);
837
+ const n = nt(i);
838
+ t.innerHTML = n, this.#R(t), this.#M(t);
801
839
  } else s && (t.textContent = i);
802
840
  }
803
841
  // Update corresponding parent web component property if bound to one.
804
842
  // VS Code thinks this is never called, but it is called by #defineProp.
805
- #k(t, e) {
806
- const s = this.#u.get(t);
843
+ #I(t, e) {
844
+ const s = this.#b.get(t);
807
845
  if (!s) return;
808
846
  const o = this.getRootNode();
809
847
  if (!(o instanceof ShadowRoot)) return;
810
848
  const { host: i } = o;
811
849
  if (!i) return;
812
- const r = i;
813
- r[s] = e;
850
+ const n = i;
851
+ n[s] = e;
814
852
  }
815
853
  /**
816
854
  * @param state - WrecState object
@@ -823,43 +861,43 @@ class u extends rt {
823
861
  for (const s of Object.keys(t))
824
862
  e[s] = s;
825
863
  }
826
- this.#F(t, e);
864
+ this.#B(t, e);
827
865
  for (const [s, o] of Object.entries(e))
828
- if (this.#r(o)) {
866
+ if (this.#c(o)) {
829
867
  const i = q(t, s);
830
- i !== void 0 && (this[o] = i), this.#m.set(o, { state: t, stateProp: s });
868
+ i !== void 0 && (this[o] = i), this.#r.set(o, { state: t, stateProp: s });
831
869
  }
832
870
  t.addListener(this, e);
833
871
  }
834
- #_() {
872
+ #D() {
835
873
  const t = new Set(Object.keys(this.#t.properties));
836
874
  for (const e of this.getAttributeNames())
837
- if (!nt.has(e) && !e.startsWith("on")) {
875
+ if (!rt.has(e) && !e.startsWith("on")) {
838
876
  if (e === "form-assoc") {
839
- this.#E();
877
+ this.#S();
840
878
  continue;
841
879
  }
842
- if (!t.has(u.getPropName(e))) {
880
+ if (!t.has(p.getPropName(e))) {
843
881
  if (e === "name") {
844
- this.#E();
882
+ this.#S();
845
883
  continue;
846
884
  }
847
885
  this.#e(null, e, "is not a supported attribute");
848
886
  }
849
887
  }
850
888
  }
851
- #d(t, e, s) {
889
+ #g(t, e, s) {
852
890
  const o = s.match(j);
853
891
  if (o)
854
892
  return o.forEach((i) => {
855
- const r = M(i);
856
- this[r] === void 0 && this.#a(t, e, r);
893
+ const n = M(i);
894
+ this[n] === void 0 && this.#l(t, e, n);
857
895
  }), o;
858
896
  }
859
- #F(t, e) {
897
+ #B(t, e) {
860
898
  for (const [s, o] of Object.entries(e)) {
861
899
  let i = q(t, s);
862
- i === void 0 && this.#e(this, void 0, `invalid state path "${s}"`), i = this[o], this.#r(o) || this.#e(
900
+ i === void 0 && this.#e(this, void 0, `invalid state path "${s}"`), i = this[o], this.#c(o) || this.#e(
863
901
  null,
864
902
  o,
865
903
  "refers to missing property in useState map"
@@ -868,36 +906,41 @@ class u extends rt {
868
906
  }
869
907
  // When type is an array, this can't validate the type of the array elements.
870
908
  // This is called by #defineProp.
871
- #I(t, e, s) {
909
+ #V(t, e, s) {
910
+ const { values: o } = this.#t.properties[t];
911
+ if (o) {
912
+ let n;
913
+ e !== String ? n = "declares allowed values, but its type is not String" : typeof s != "string" ? n = `value is a ${typeof s}, but type is String` : o.includes(s) || (n = `must be one of ${o.map((a) => `"${a}"`).join(", ")}`), n && this.#e(null, t, n);
914
+ }
872
915
  if (s instanceof e) return;
873
- let o = typeof s;
874
- if (o === "object") {
875
- const { constructor: i } = s;
876
- o = i.name, i !== e && this.#e(
916
+ let i = typeof s;
917
+ if (i === "object") {
918
+ const { constructor: n } = s;
919
+ i = n.name, n !== e && this.#e(
877
920
  null,
878
921
  t,
879
- `was set to a ${o}, but must be a ${e.name}`
922
+ `was set to a ${i}, but must be a ${e.name}`
880
923
  );
881
924
  }
882
- o !== e.name.toLowerCase() && this.#e(
925
+ i !== e.name.toLowerCase() && this.#e(
883
926
  null,
884
927
  t,
885
- `was set to a ${o}, but must be a ${e.name}`
928
+ `was set to a ${i}, but must be a ${e.name}`
886
929
  );
887
930
  }
888
- #C(t) {
931
+ #R(t) {
889
932
  const e = Array.from(t.querySelectorAll("*"));
890
933
  for (const s of e) {
891
934
  const o = [];
892
935
  for (const i of Array.from(s.attributes)) {
893
- const r = i.name;
894
- if (r.startsWith("on")) {
895
- let c = r.slice(2);
936
+ const n = i.name;
937
+ if (n.startsWith("on")) {
938
+ let c = n.slice(2);
896
939
  c = c[0].toLowerCase() + c.slice(1).toLowerCase();
897
940
  const a = i.value;
898
- this.#d(s, r, a);
899
- let h;
900
- typeof this[a] == "function" ? h = (f) => this[a](f) : (this.#d(s, r, a), h = () => this.#s(a)), s.addEventListener(c, h), o.push(r);
941
+ this.#g(s, n, a);
942
+ let f;
943
+ typeof this[a] == "function" ? f = (l) => this[a](l) : (this.#g(s, n, a), f = () => this.#o(a)), s.addEventListener(c, f), o.push(n);
901
944
  }
902
945
  }
903
946
  for (const i of o)
@@ -905,40 +948,40 @@ class u extends rt {
905
948
  }
906
949
  }
907
950
  }
908
- function Et(n, ...t) {
909
- let e = Q(n, t);
951
+ function Tt(r, ...t) {
952
+ let e = tt(r, t);
910
953
  for (; ; ) {
911
- const s = ct.exec(e);
954
+ const s = at.exec(e);
912
955
  if (!s) break;
913
956
  const o = s[2];
914
- if (G.test(o)) {
957
+ if (Q.test(o)) {
915
958
  const i = s[1];
916
959
  if (!i.startsWith("--")) {
917
- const r = `--${i}: ${o};
960
+ const n = `--${i}: ${o};
918
961
  ${i}: var(--${i})`;
919
- e = tt(e, s.index, s[0].length, r);
962
+ e = et(e, s.index, s[0].length, n);
920
963
  }
921
964
  }
922
965
  }
923
966
  return e;
924
967
  }
925
- function Tt(n, ...t) {
926
- let e = Q(n, t);
968
+ function Mt(r, ...t) {
969
+ let e = tt(r, t);
927
970
  for (; ; ) {
928
971
  const s = ht.exec(e);
929
972
  if (!s || s[1] === "style") break;
930
- const o = dt(s[2]);
931
- if (G.test(o)) {
932
- const i = `<!-- ${o.trim()} -->`, r = s.index + s[0].indexOf(">") + 1;
933
- e = tt(e, r, o.length, i);
973
+ const o = mt(s[2]);
974
+ if (Q.test(o)) {
975
+ const i = `<!-- ${o.trim()} -->`, n = s.index + s[0].indexOf(">") + 1;
976
+ e = et(e, n, o.length, i);
934
977
  }
935
978
  }
936
979
  return e;
937
980
  }
938
981
  export {
939
- u as Wrec,
940
- _ as WrecState,
941
- wt as createElement,
942
- Et as css,
943
- Tt as html
982
+ p as Wrec,
983
+ F as WrecState,
984
+ Et as createElement,
985
+ Tt as css,
986
+ Mt as html
944
987
  };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "wrec",
3
3
  "description": "a small library that greatly simplifies building web components",
4
4
  "author": "R. Mark Volkmann",
5
- "version": "0.22.5",
5
+ "version": "0.22.7",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",