@expressive/dom 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as untrack, c as enter, d as claim$1, f as release, h as transition, i as track, l as owner, m as settle$1, n as latest, o as call, p as schedule, r as same, s as dispose, u as afterFlush } from "./chunk-hot-vusv_ouU.js";
2
- import { a as createElement, i as childrenOf, n as PORTAL, o as isVNode, r as Portal, s as vnode, t as Fragment } from "./chunk-vnode-wpCWQ_Zg.js";
2
+ import { a as authoring, c as isVNode, i as authorOf, l as vnode, n as PORTAL, o as childrenOf, r as Portal, s as createElement, t as Fragment } from "./chunk-vnode-BN2KOsCV.js";
3
3
  import "./jsx-runtime.js";
4
4
  import { Component, Context, Model, has, map, unbind } from "@expressive/mvc";
5
5
  import { watch } from "@expressive/mvc/observable";
@@ -12,7 +12,7 @@ let probe;
12
12
  * Does the CSSOM accept a bare number for this property? Probed once with a
13
13
  * canonical value; the answer is a property of CSS, not of the value.
14
14
  */
15
- function bare(property) {
15
+ function bare$1(property) {
16
16
  let known = unitless.get(property);
17
17
  if (known === void 0) {
18
18
  probe ||= document.createElement("div").style;
@@ -24,30 +24,14 @@ function bare(property) {
24
24
  }
25
25
  function sized(property, value) {
26
26
  if (Array.isArray(value)) return value.map((entry) => sized(property, entry));
27
- return typeof value == "number" && value !== 0 && !bare(property) ? `${value}px` : value;
27
+ return typeof value == "number" && value !== 0 && !bare$1(property) ? `${value}px` : value;
28
28
  }
29
29
  /**
30
30
  * Web macro pack. Register with `macro(css)` to opt into pixel units for
31
- * numbers and the axis shorthands CSS itself does not provide.
31
+ * numbers and the `size` shorthand.
32
32
  */
33
33
  const css = {
34
34
  "*": (value, key) => ({ [key]: sized(key, value) }),
35
- mx: (value) => ({
36
- marginLeft: value,
37
- marginRight: value
38
- }),
39
- my: (value) => ({
40
- marginTop: value,
41
- marginBottom: value
42
- }),
43
- px: (value) => ({
44
- paddingLeft: value,
45
- paddingRight: value
46
- }),
47
- py: (value) => ({
48
- paddingTop: value,
49
- paddingBottom: value
50
- }),
51
35
  size: (value) => Array.isArray(value) ? {
52
36
  width: value[0],
53
37
  height: value[1]
@@ -57,6 +41,23 @@ const css = {
57
41
  }
58
42
  };
59
43
 
44
+ //#endregion
45
+ //#region src/style/units.ts
46
+ function unit(suffix) {
47
+ return (...values) => values.map((value) => value + suffix).join(" ");
48
+ }
49
+ const rem = unit("rem");
50
+ const em = unit("em");
51
+ const px = unit("px");
52
+
53
+ //#endregion
54
+ //#region src/style/media.ts
55
+ function media(query) {
56
+ return `@media ${Object.entries(query).map(([key, value]) => {
57
+ return `(${key.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`)}: ${typeof value == "number" ? `${value}px` : value})`;
58
+ }).join(" and ")}`;
59
+ }
60
+
60
61
  //#endregion
61
62
  //#region src/style/protocol.ts
62
63
  const SUBCOMPONENT = /^_[A-Z]/;
@@ -111,6 +112,9 @@ function appearanceToken(value) {
111
112
  //#endregion
112
113
  //#region src/style/appearance.ts
113
114
  const bases = /* @__PURE__ */ new WeakMap();
115
+ const groups$1 = /* @__PURE__ */ new WeakMap();
116
+ const ownGroups = /* @__PURE__ */ new WeakMap();
117
+ const ancestors = /* @__PURE__ */ new Map();
114
118
  const chains = /* @__PURE__ */ new WeakMap();
115
119
  const contexts = /* @__PURE__ */ new WeakMap();
116
120
  const rootScopes = /* @__PURE__ */ new WeakMap();
@@ -126,6 +130,8 @@ function createStyleScope(parent, value, label, defines) {
126
130
  const own = [];
127
131
  const source = {};
128
132
  const base = {};
133
+ const scopeLabel = label || parent?.label || "style";
134
+ const root = { name: scopeLabel };
129
135
  for (const key of Object.keys(value)) {
130
136
  const entry = value[key];
131
137
  if (key[0] == "$") throw new Error(`Reserved key "${key}" in style map.`);
@@ -133,36 +139,46 @@ function createStyleScope(parent, value, label, defines) {
133
139
  if (key[0] == "_") {
134
140
  if (!isObject(entry)) throw new Error(`Rule "${key}" must be an object. Macros are defined by macro().`);
135
141
  const name = key.slice(1);
136
- own.push(name);
137
- source[name] = entry;
142
+ if (!own.includes(name)) own.push(name);
143
+ source[name] = merge(source[name], entry);
144
+ } else if (isCondition(key) && isObject(entry)) {
145
+ const rest = {};
146
+ for (const inner of Object.keys(entry)) if (inner[0] == "_") {
147
+ const name = inner.slice(1);
148
+ if (!own.includes(name)) own.push(name);
149
+ for (const when of split(key)) source[name] = merge(source[name], { [hoist(root, when)]: entry[inner] });
150
+ } else rest[inner] = entry[inner];
151
+ base[key] = merge(base[key], rest);
138
152
  } else if (defines && typeof entry == "function") {
139
153
  own.push(key);
140
154
  source[key] = entry;
141
155
  } else base[key] = entry;
142
156
  }
143
157
  const names = parent ? [...parent.names, ...own.filter((name) => !parent.names.includes(name))] : own;
158
+ const before = parent && parent !== parent.globals ? parent.local : [];
159
+ const local = defines ? [] : [...before, ...own.filter((name) => !before.includes(name))];
144
160
  const rules = Object.create(parent?.rules || null);
145
161
  const labels = Object.create(parent?.labels || null);
146
- const scopeLabel = label || parent?.label || "style";
147
162
  for (const name of own) {
148
163
  const rule = source[name];
149
164
  const inherited = parent?.rules[name];
150
- rules[name] = isObject(inherited) && isObject(rule) ? {
151
- ...inherited,
152
- ...rule
153
- } : rule;
165
+ rules[name] = isObject(inherited) && isObject(rule) && (defines || inherited !== parent.globals?.rules[name]) ? mergeRule(inherited, rule) : rule;
154
166
  labels[name] = scopeLabel;
155
167
  }
156
168
  const scope = {
157
169
  children: /* @__PURE__ */ new WeakMap(),
158
170
  expansions: /* @__PURE__ */ new Map(),
171
+ globals: parent?.globals,
159
172
  label: scopeLabel,
160
173
  labels,
174
+ local,
161
175
  names,
162
176
  own: base,
163
177
  routes: /* @__PURE__ */ new Map(),
164
178
  rules
165
179
  };
180
+ if (defines) scope.globals = scope;
181
+ if (root.group) ownGroups.set(scope, root.group);
166
182
  cache.set(value, scope);
167
183
  return scope;
168
184
  }
@@ -182,23 +198,26 @@ function createContext(scope) {
182
198
  function extendContext(parent, maps, label, defines) {
183
199
  let scope = parent?.scope;
184
200
  const base = { ...scope && bases.get(scope) };
201
+ const anchors = new Set(scope && groups$1.get(scope));
185
202
  for (const map of maps) {
186
203
  scope = createStyleScope(scope, map, label, defines);
187
- Object.assign(base, scope.own);
204
+ Object.assign(base, mergeRule(base, scope.own));
205
+ const own = ownGroups.get(scope);
206
+ if (own) anchors.add(own);
188
207
  }
189
208
  if (Object.keys(base).length) bases.set(scope, base);
209
+ if (anchors.size) groups$1.set(scope, [...anchors]);
190
210
  return createContext(scope);
191
211
  }
192
212
  function baseToken(scope) {
193
213
  const base = bases.get(scope);
194
- if (!base) return void 0;
195
- const expansion = expand(scope, base, /* @__PURE__ */ new Map());
214
+ const anchors = groups$1.get(scope);
215
+ if (!base && !anchors) return void 0;
216
+ const frame = { name: scope.label };
217
+ const expansion = expand(scope, base, /* @__PURE__ */ new Map(), frame);
218
+ const blocks = [...toBlocks(expansion, frame, shared(scope) - .5), ...anchors || []];
196
219
  const appearance = {};
197
- if (Object.keys(expansion.declarations).length) appearance.blocks = [{
198
- declarations: expansion.declarations,
199
- name: scope.label,
200
- ordinal: -1
201
- }];
220
+ if (blocks.length) appearance.blocks = blocks;
202
221
  if (expansion.classes.length) appearance.classes = expansion.classes;
203
222
  return createAppearanceToken(appearance);
204
223
  }
@@ -263,8 +282,8 @@ function resolveAppearance(scope, props, tag) {
263
282
  const parts = [];
264
283
  const names = route.tag ? [route.tag] : [];
265
284
  for (const name of route.flags) if (props[`_${name}`]) names.push(name);
266
- for (const name of names) parts.push(expandRule(route.scope, name));
267
- const blocks = parts.flatMap((part) => part.block ? [part.block] : []);
285
+ for (const name of names) expandShadowed(route.scope, name, parts);
286
+ const blocks = parts.flatMap((part) => part.blocks);
268
287
  const classes = parts.flatMap((part) => part.classes);
269
288
  let child = route.scope;
270
289
  for (const part of parts) for (const nested of part.nested) child = createStyleScope(child, nested, tag ? `${route.scope.label}_${tag}` : route.scope.label);
@@ -278,37 +297,83 @@ function resolveAppearance(scope, props, tag) {
278
297
  function expandRule(scope, name) {
279
298
  let expansion = scope.expansions.get(name);
280
299
  if (!expansion) {
281
- expansion = expand(scope, scope.rules[name], /* @__PURE__ */ new Map());
282
- if (Object.keys(expansion.declarations).length) expansion.block = {
283
- declarations: expansion.declarations,
284
- name: `${scope.labels[name]}_${name}`,
285
- ordinal: scope.names.indexOf(name)
286
- };
300
+ const frame = { name: `${scope.labels[name]}_${name}` };
301
+ expansion = expand(scope, scope.rules[name], /* @__PURE__ */ new Map(), frame);
302
+ expansion.blocks = toBlocks(expansion, frame, ordinal(scope, name));
287
303
  scope.expansions.set(name, expansion);
288
304
  }
289
305
  return expansion;
290
306
  }
307
+ function toBlocks({ declarations, variants }, { group, name }, ordinal) {
308
+ const blocks = [];
309
+ if (Object.keys(declarations).length) blocks.push({
310
+ declarations,
311
+ name,
312
+ ordinal
313
+ });
314
+ for (const { declarations, when } of variants) blocks.push({
315
+ declarations,
316
+ name,
317
+ ordinal: ordinal + .5 - .25 / when.length,
318
+ when: when.map((condition) => ancestors.get(condition) || condition)
319
+ });
320
+ if (group) blocks.push(group);
321
+ return blocks;
322
+ }
323
+ function hoist(frame, condition) {
324
+ if (condition[0] != ":") return condition;
325
+ if (condition.includes("::")) throw new Error(`Rules cannot nest inside pseudo-element "${condition}".`);
326
+ frame.group ||= {
327
+ declarations: {},
328
+ group: true,
329
+ name: frame.name,
330
+ ordinal: 0
331
+ };
332
+ const key = `\0${ancestors.size}`;
333
+ ancestors.set(key, {
334
+ on: frame.group,
335
+ state: condition
336
+ });
337
+ return key;
338
+ }
339
+ function shared(scope) {
340
+ return scope.globals ? scope.globals.names.length : 0;
341
+ }
342
+ function ordinal(scope, name) {
343
+ return scope.rules[name] === scope.globals?.rules[name] ? scope.names.indexOf(name) : shared(scope) + scope.local.indexOf(name);
344
+ }
345
+ function expandShadowed(scope, name, parts) {
346
+ const { globals } = scope;
347
+ if (globals && isObject(globals.rules[name]) && globals.rules[name] !== scope.rules[name]) parts.push(expandRule(globals, name));
348
+ parts.push(expandRule(scope, name));
349
+ }
291
350
  function handlers(scope, name) {
292
351
  let known = chains.get(scope);
293
352
  if (!known) chains.set(scope, known = /* @__PURE__ */ new Map());
294
353
  let chain = known.get(name);
295
354
  if (!chain) {
296
- chain = [];
297
- for (const key of [name, "*"]) for (let rules = scope.rules; rules; rules = Object.getPrototypeOf(rules)) {
298
- const own = Object.getOwnPropertyDescriptor(rules, key);
299
- if (own && typeof own.value == "function") chain.push(own.value);
355
+ chain = Object.assign([], { named: 0 });
356
+ for (const key of [name, "*"]) {
357
+ for (let rules = scope.rules; rules; rules = Object.getPrototypeOf(rules)) {
358
+ const own = Object.getOwnPropertyDescriptor(rules, key);
359
+ if (own && typeof own.value == "function") chain.push(own.value);
360
+ }
361
+ if (key == name) chain.named = chain.length;
300
362
  }
301
363
  known.set(name, chain);
302
364
  }
303
365
  return chain;
304
366
  }
305
- function expand(scope, value, depths) {
367
+ function expand(scope, value, depths, frame) {
306
368
  const output = {
369
+ blocks: [],
307
370
  classes: [],
308
371
  declarations: {},
309
- nested: []
372
+ nested: [],
373
+ variants: []
310
374
  };
311
375
  const nested = {};
376
+ const conditions = [];
312
377
  function walk(value, depths) {
313
378
  if (!value) return;
314
379
  if (typeof value == "string") {
@@ -321,25 +386,78 @@ function expand(scope, value, depths) {
321
386
  }
322
387
  for (const [name, entry] of Object.entries(value)) {
323
388
  if (name[0] == "_") {
324
- if (isObject(entry)) nested[name] = entry;
389
+ if (isObject(entry)) nested[name] = merge(nested[name], entry);
390
+ continue;
391
+ }
392
+ if (isCondition(name)) {
393
+ if (isObject(entry)) conditions.push([name, entry]);
394
+ else if (isPresent(entry)) throw new Error(`Condition "${name}" must be an object.`);
325
395
  continue;
326
396
  }
327
397
  const chain = handlers(scope, name);
328
398
  const depth = depths.get(name) || 0;
399
+ if (depth && depth >= chain.named && entry === true) throw new Error(`Macro "${name}" returned itself.`);
329
400
  if (depth < chain.length) {
330
401
  if (isPresent(entry)) walk(chain[depth](entry === true ? void 0 : entry, name), new Map(depths).set(name, depth + 1));
331
402
  } else output.declarations[name] = terminal(name, entry);
332
403
  }
333
404
  }
334
405
  walk(value, depths);
406
+ for (const [key, body] of conditions) for (const when of split(key)) {
407
+ const inner = expand(scope, body, depths, frame);
408
+ if (inner.classes.length) throw new Error(`Classes are not supported inside "${when}".`);
409
+ for (const map of inner.nested) {
410
+ const key = hoist(frame, when);
411
+ for (const rule of Object.keys(map)) nested[rule] = merge(nested[rule], { [key]: map[rule] });
412
+ }
413
+ if (Object.keys(inner.declarations).length) output.variants.push({
414
+ declarations: inner.declarations,
415
+ when: [when]
416
+ });
417
+ for (const variant of inner.variants) output.variants.push({
418
+ declarations: variant.declarations,
419
+ when: [when, ...variant.when]
420
+ });
421
+ }
335
422
  if (Object.keys(nested).length) output.nested.push(nested);
336
423
  return output;
337
424
  }
338
425
  function terminal(name, value) {
339
426
  if (Array.isArray(value)) return value.join(" ");
340
- if (typeof value == "function" || isObject(value)) throw new Error(`No macro handles "${name}".`);
427
+ if (value === true || typeof value == "function" || isObject(value)) throw new Error(`No macro handles "${name}".`);
341
428
  return typeof value == "number" ? String(value) : value;
342
429
  }
430
+ function isCondition(key) {
431
+ return key[0] == ":" || key[0] == "@" || key[0] == "\0";
432
+ }
433
+ function split(key) {
434
+ if (key[0] != ":") return [key];
435
+ const parts = [];
436
+ let depth = 0;
437
+ let start = 0;
438
+ for (let index = 0; index < key.length; index++) {
439
+ const char = key[index];
440
+ if (char == "(") depth++;
441
+ else if (char == ")") depth--;
442
+ else if (char == "," && !depth) {
443
+ parts.push(key.slice(start, index).trim());
444
+ start = index + 1;
445
+ }
446
+ }
447
+ parts.push(key.slice(start).trim());
448
+ return parts;
449
+ }
450
+ function merge(left, right) {
451
+ return isObject(left) ? mergeRule(left, right) : right;
452
+ }
453
+ function mergeRule(left, right) {
454
+ const output = {
455
+ ...left,
456
+ ...right
457
+ };
458
+ for (const key of Object.keys(right)) if (isCondition(key) && isObject(left[key]) && isObject(right[key])) output[key] = mergeRule(left[key], right[key]);
459
+ return output;
460
+ }
343
461
  function isPresent(value) {
344
462
  return value !== false && value !== null && value !== void 0;
345
463
  }
@@ -369,8 +487,9 @@ function applyDeclarations(style, declarations, previous = {}) {
369
487
  //#endregion
370
488
  //#region src/style/stylesheet.ts
371
489
  const sheets = /* @__PURE__ */ new WeakMap();
372
- function style(type, rules) {
373
- style$1(type, rules);
490
+ let groups = 0;
491
+ function style(type, ...maps) {
492
+ for (const rules of maps) if (rules) style$1(type, rules);
374
493
  registerEmitter(emit);
375
494
  return type;
376
495
  }
@@ -393,21 +512,40 @@ function emit(block, depth, document) {
393
512
  };
394
513
  sheets.set(document, sheet);
395
514
  }
515
+ if (block.group) depth = 0;
396
516
  let byDepth = sheet.emitted.get(block);
397
517
  if (!byDepth) sheet.emitted.set(block, byDepth = /* @__PURE__ */ new Map());
398
518
  const cached = byDepth.get(depth);
399
519
  if (cached) return cached;
400
- const css = serialize(document, block.declarations);
401
- const base = (depth ? `${block.name}-d${depth}` : block.name).replace(/[^\w-]/g, "_");
520
+ const when = block.when || [];
521
+ const at = when.filter((condition) => typeof condition == "string" && condition[0] == "@");
522
+ const pseudo = when.filter((condition) => typeof condition == "string" && condition[0] == ":").join("");
523
+ const split = pseudo.indexOf("::");
524
+ const states = split < 0 ? pseudo : pseudo.slice(0, split);
525
+ const element = split < 0 ? "" : pseudo.slice(split);
526
+ const selector = `${when.map((condition) => typeof condition == "string" ? "" : `:where(.${emit(condition.on, 0, document)}${condition.state}) `).join("")}.%${states ? `:where(${states})` : ""}${element}`;
527
+ const css = block.group ? `\0${groups++}` : serialize(document, block.declarations);
528
+ const key = [
529
+ ...at,
530
+ selector,
531
+ css
532
+ ].join("\0");
533
+ const base = [
534
+ depth ? `${block.name}-d${depth}` : block.name,
535
+ ...when.map((condition) => typeof condition == "string" ? condition : condition.on.name + condition.state),
536
+ ...block.group ? ["group"] : []
537
+ ].join("-").replace(/[^\w-]+/g, "_").replace(/_*(-)_*|_+$/g, "$1");
402
538
  let name = base;
403
- for (let index = 2; sheet.names.has(name) && sheet.names.get(name) !== css; index++) name = `${base}-${index}`;
539
+ for (let index = 2; sheet.names.has(name) && sheet.names.get(name) !== key; index++) name = `${base}-${index}`;
404
540
  if (!sheet.names.has(name)) {
405
- const { positions } = sheet;
406
- let at = positions.findIndex(([d, o]) => d > depth || d == depth && o > block.ordinal);
407
- if (at < 0) at = positions.length;
408
- sheet.names.set(name, css);
409
- positions.splice(at, 0, [depth, block.ordinal]);
410
- sheet.element.sheet.insertRule(`.${name}{${css}}`, at);
541
+ sheet.names.set(name, key);
542
+ if (!block.group) {
543
+ const { positions } = sheet;
544
+ let index = positions.findIndex(([d, o]) => d > depth || d == depth && o > block.ordinal);
545
+ if (index < 0) index = positions.length;
546
+ positions.splice(index, 0, [depth, block.ordinal]);
547
+ sheet.element.sheet.insertRule(at.reduceRight((rule, condition) => `${condition}{${rule}}`, `${selector.replace("%", name)}{${css}}`), index);
548
+ }
411
549
  }
412
550
  byDepth.set(depth, name);
413
551
  return name;
@@ -511,63 +649,6 @@ function removeRange(start, end) {
511
649
  }
512
650
  }
513
651
 
514
- //#endregion
515
- //#region src/render/collection.ts
516
- function mountCollection(value, parent, before, context, boundary, appearance) {
517
- const fiber = range("collection", parent, before, context);
518
- fiber.source = value;
519
- fiber.value = value;
520
- fiber.boundary = boundary;
521
- fiber.appearance = appearance;
522
- fiber.scope = makeScope(context, (passive) => runCollection(fiber, passive));
523
- let first = true;
524
- fiber.release = watch(value, (current) => {
525
- fiber.value = current;
526
- if (!first && fiber.scope?.active) schedule(fiber.scope);
527
- first = false;
528
- }, void 0, transition);
529
- return complete(fiber, () => {
530
- runCollection(fiber, passiveRender);
531
- });
532
- }
533
- function runCollection(fiber, passive) {
534
- attempt(fiber, passive, () => {
535
- return fiber.value.render();
536
- });
537
- }
538
- function patchCollection(fiber, appearance) {
539
- if (fiber.appearance === appearance) return;
540
- fiber.appearance = appearance;
541
- runCollection(fiber, passiveRender);
542
- }
543
- function isCollection(value) {
544
- return value instanceof has.List || value instanceof has.Pool || value instanceof map.Managed;
545
- }
546
-
547
- //#endregion
548
- //#region src/node/loader.ts
549
- const LOADS = /* @__PURE__ */ new WeakMap();
550
- function resolve(type, props, run) {
551
- const load = LOADS.get(type);
552
- if (load?.resolved) return vnode(load.resolved, props);
553
- if (load?.failed) {
554
- LOADS.delete(type);
555
- throw load.failed.error;
556
- }
557
- if (load) throw load.pending;
558
- const output = run();
559
- if (!output || typeof output.then != "function") return output;
560
- const next = {};
561
- LOADS.set(type, next);
562
- throw next.pending = output.then((module) => {
563
- const component = typeof module == "function" ? module : module?.default;
564
- if (typeof component == "function") next.resolved = component;
565
- else next.failed = { error: /* @__PURE__ */ new Error("Loader resolved no component.") };
566
- }, (error) => {
567
- next.failed = { error };
568
- });
569
- }
570
-
571
652
  //#endregion
572
653
  //#region src/style/claim.ts
573
654
  const tickets = /* @__PURE__ */ new WeakMap();
@@ -579,15 +660,21 @@ function componentProps(type, props, appearance) {
579
660
  props
580
661
  };
581
662
  const value = context.resolve(props);
582
- const entries = appearance.entries;
663
+ const { author, entries } = appearance;
583
664
  if (!value) return {
584
- appearance: { entries },
665
+ appearance: {
666
+ author,
667
+ entries,
668
+ lexical: context
669
+ },
585
670
  props
586
671
  };
587
672
  return {
588
673
  appearance: {
674
+ author,
589
675
  context: value.context,
590
- entries
676
+ entries,
677
+ lexical: value.context || context
591
678
  },
592
679
  props: {
593
680
  ...props,
@@ -595,6 +682,9 @@ function componentProps(type, props, appearance) {
595
682
  }
596
683
  };
597
684
  }
685
+ function placed(appearance) {
686
+ return appearance && { entries: appearance.entries };
687
+ }
598
688
  function door(value) {
599
689
  const collected = {
600
690
  classes: [],
@@ -684,11 +774,69 @@ function appendClasses(classes, value) {
684
774
  if (typeof value == "string") classes.push(...value.split(/\s+/).filter(Boolean));
685
775
  }
686
776
 
777
+ //#endregion
778
+ //#region src/render/collection.ts
779
+ function mountCollection(value, parent, before, context, boundary, appearance) {
780
+ const fiber = range("collection", parent, before, context);
781
+ fiber.source = value;
782
+ fiber.value = value;
783
+ fiber.boundary = boundary;
784
+ fiber.appearance = appearance;
785
+ fiber.scope = makeScope(context, (passive) => runCollection(fiber, passive));
786
+ let first = true;
787
+ fiber.release = watch(value, (current) => {
788
+ fiber.value = current;
789
+ if (!first && fiber.scope?.active) schedule(fiber.scope);
790
+ first = false;
791
+ }, void 0, transition);
792
+ return complete(fiber, () => {
793
+ runCollection(fiber, passiveRender);
794
+ });
795
+ }
796
+ function runCollection(fiber, passive) {
797
+ attempt(fiber, passive, () => {
798
+ return fiber.value.render();
799
+ });
800
+ }
801
+ function patchCollection(fiber, appearance) {
802
+ if (fiber.appearance === appearance) return;
803
+ fiber.appearance = appearance;
804
+ runCollection(fiber, passiveRender);
805
+ }
806
+ function isCollection(value) {
807
+ return value instanceof has.List || value instanceof has.Pool || value instanceof map.Managed;
808
+ }
809
+
810
+ //#endregion
811
+ //#region src/node/loader.ts
812
+ const LOADS = /* @__PURE__ */ new WeakMap();
813
+ function resolve(type, props, run) {
814
+ const load = LOADS.get(type);
815
+ if (load?.resolved) return vnode(load.resolved, props);
816
+ if (load?.failed) {
817
+ LOADS.delete(type);
818
+ throw load.failed.error;
819
+ }
820
+ if (load) throw load.pending;
821
+ const output = run();
822
+ if (!output || typeof output.then != "function") return output;
823
+ const next = {};
824
+ LOADS.set(type, next);
825
+ throw next.pending = output.then((module) => {
826
+ const component = typeof module == "function" ? module : module?.default;
827
+ if (typeof component == "function") next.resolved = component;
828
+ else next.failed = { error: /* @__PURE__ */ new Error("Loader resolved no component.") };
829
+ }, (error) => {
830
+ next.failed = { error };
831
+ });
832
+ }
833
+
687
834
  //#endregion
688
835
  //#region src/render/style.ts
689
836
  let rendering;
690
837
  let touched = false;
691
838
  const observed = /* @__PURE__ */ new WeakMap();
839
+ const bare = /* @__PURE__ */ new WeakMap();
692
840
  function observe(props) {
693
841
  if (!("style" in props)) return props;
694
842
  let output = observed.get(props);
@@ -717,7 +865,7 @@ function consume(fiber, render) {
717
865
  rendering = fiber.props;
718
866
  touched = false;
719
867
  try {
720
- const output = render();
868
+ const output = authoring(fiber, render);
721
869
  fiber.consumed = touched;
722
870
  return output;
723
871
  } finally {
@@ -743,10 +891,27 @@ function renderedAppearance(fiber) {
743
891
  hops: 0,
744
892
  style
745
893
  });
746
- return entries.length || context ? {
894
+ if (entries.length || context) return {
895
+ author: fiber,
747
896
  context,
748
897
  entries
749
- } : void 0;
898
+ };
899
+ let empty = bare.get(fiber);
900
+ if (!empty) bare.set(fiber, empty = {
901
+ author: fiber,
902
+ entries
903
+ });
904
+ return empty;
905
+ }
906
+ function authored(value, appearance) {
907
+ const author = authorOf(value);
908
+ if (!author || !appearance || author === appearance.author) return appearance;
909
+ for (let fiber = appearance.author; fiber; fiber = fiber.appearance?.author) if (fiber.appearance?.author === author) return {
910
+ author,
911
+ context: fiber.appearance.lexical,
912
+ entries: appearance.entries
913
+ };
914
+ return appearance;
750
915
  }
751
916
 
752
917
  //#endregion
@@ -815,7 +980,8 @@ function patchProps(fiber, next, appearance) {
815
980
  fiber.claimed = claimed;
816
981
  fiber.props = next;
817
982
  fiber.appearance = appearance;
818
- if (!raw) reconcileChildren(fiber, element, null, next.children, fiber.context, fiber.boundary, claimed.context ? {
983
+ if (!raw) reconcileChildren(fiber, element, null, next.children, fiber.context, fiber.boundary, claimed.context || appearance?.author ? {
984
+ author: appearance?.author,
819
985
  context: claimed.context,
820
986
  entries: []
821
987
  } : void 0);
@@ -984,7 +1150,7 @@ function reconcileChildren(owner, parent, before, value, context, boundary, appe
984
1150
  let child = key !== null && key !== void 0 ? keyed.get(key) : old[index]?.key == null ? old[index] : void 0;
985
1151
  if (child && used.has(child)) child = void 0;
986
1152
  if (child) used.add(child);
987
- const fiber = patch(child, value, parent, before, context, boundary, appearance);
1153
+ const fiber = patch(child, value, parent, before, context, boundary, authored(value, appearance));
988
1154
  if (fiber !== child) used.delete(child);
989
1155
  next.push(fiber);
990
1156
  }
@@ -1197,13 +1363,20 @@ function mountFunction(value, parent, before, context, boundary, appearance) {
1197
1363
  run(fiber, passiveRender);
1198
1364
  });
1199
1365
  }
1366
+ const PLACED = /* @__PURE__ */ new WeakMap();
1367
+ Component.on({ setup(self) {
1368
+ return PLACED.get(self);
1369
+ } });
1200
1370
  function mountOwnedComponent(value, parent, before, context, boundary, appearance) {
1201
1371
  const resolved = componentProps(value.type, value.props, appearance);
1202
1372
  const Type = value.type;
1203
1373
  const props = observe(resolved.props);
1204
- return mountComponent(new Type(props), parent, before, context, boundary, resolved.appearance, true, value.key, props);
1374
+ const instance = new Type(props);
1375
+ let place;
1376
+ PLACED.set(instance, new Promise((resolve) => place = resolve));
1377
+ return mountComponent(instance, parent, before, context, boundary, resolved.appearance, true, value.key, props, place);
1205
1378
  }
1206
- function mountComponent(instance, parent, before, context, inherited, appearance, owned = false, key, props = instance.props) {
1379
+ function mountComponent(instance, parent, before, context, inherited, appearance, owned = false, key, props = instance.props, place) {
1207
1380
  const fiber = range("component", parent, before, context);
1208
1381
  const childContext = context.push(instance);
1209
1382
  const element = owned ? props : {};
@@ -1246,7 +1419,7 @@ function mountComponent(instance, parent, before, context, inherited, appearance
1246
1419
  run(fiber, passiveRender);
1247
1420
  });
1248
1421
  } finally {
1249
- if (owned && !fiber.dead) inserted(fiber, () => fiber.cleanup = instance.mount?.());
1422
+ if (owned && !fiber.dead) inserted(fiber, place);
1250
1423
  }
1251
1424
  return fiber;
1252
1425
  }
@@ -1278,7 +1451,7 @@ function patchFunction(fiber, value, appearance) {
1278
1451
  }
1279
1452
  function patchComponent(fiber, value, appearance) {
1280
1453
  const resolved = isVNode(value) ? componentProps(value.type, value.props, appearance) : {
1281
- appearance,
1454
+ appearance: placed(appearance),
1282
1455
  props: fiber.props
1283
1456
  };
1284
1457
  fiber.appearance = resolved.appearance;
@@ -1297,7 +1470,6 @@ function rerun(fiber, run) {
1297
1470
  settle$1(fiber.scope);
1298
1471
  }
1299
1472
  function unmountComponent(fiber) {
1300
- if (typeof fiber.cleanup == "function") fiber.cleanup();
1301
1473
  fiber.childContext?.pop();
1302
1474
  if (fiber.owned && !fiber.instance.get(null)) fiber.instance.set(null);
1303
1475
  }
@@ -1329,7 +1501,7 @@ function mount(value, parent, before, context, boundary, appearance) {
1329
1501
  children: []
1330
1502
  };
1331
1503
  }
1332
- if (renderable(value)) return mountComponent(value, parent, before, context, boundary, appearance);
1504
+ if (renderable(value)) return mountComponent(value, parent, before, context, boundary, placed(appearance));
1333
1505
  if (value instanceof Model) notRenderable(value.constructor);
1334
1506
  if (isCollection(value)) return mountCollection(value, parent, before, context, boundary, appearance);
1335
1507
  if (!isVNode(value)) throw new TypeError(`Cannot render ${String(value)}.`);
@@ -1458,5 +1630,5 @@ function attempt(fiber, passive, render) {
1458
1630
  }
1459
1631
 
1460
1632
  //#endregion
1461
- export { Fragment, Portal, createElement, css, macro, render, style };
1633
+ export { Fragment, Portal, createElement, css, em, macro, media, px, rem, render, style };
1462
1634
  //# sourceMappingURL=index.js.map