regor 1.3.4 → 1.3.6

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.
@@ -110,8 +110,8 @@ var Regor = (() => {
110
110
  // src/cleanup/unbind.ts
111
111
  var unbind = (node) => {
112
112
  const stack = [node];
113
- while (stack.length > 0) {
114
- const currentNode = stack.pop();
113
+ for (let i = 0; i < stack.length; ++i) {
114
+ const currentNode = stack[i];
115
115
  unbindSingle(currentNode);
116
116
  for (let child = currentNode.lastChild; child != null; child = child.previousSibling) {
117
117
  stack.push(child);
@@ -247,30 +247,105 @@ var Regor = (() => {
247
247
  // src/app/ComponentHead.ts
248
248
  var ComponentHead = class {
249
249
  constructor(props, element, ctx, start, end) {
250
+ /**
251
+ * Values provided by parent for this component instance.
252
+ *
253
+ * Sources:
254
+ * - declared props via `props: ['foo']` + attribute binding (`:foo="..."`)
255
+ * - object binding via `:context="{ ... }"`
256
+ */
250
257
  __publicField(this, "props");
258
+ /**
259
+ * Comment node that marks the beginning of this mounted component block.
260
+ * Advanced use only.
261
+ */
251
262
  __publicField(this, "start");
263
+ /**
264
+ * Comment node that marks the end of this mounted component block.
265
+ * Advanced use only.
266
+ */
252
267
  __publicField(this, "end");
268
+ /**
269
+ * Captured context chain used by this component instance.
270
+ * Used internally for lifecycle/unmount behavior.
271
+ */
253
272
  __publicField(this, "ctx");
254
- /** Automatically assigns properties defined in the :props binding to the component context when enabled. If disabled, props should be manually assigned using head.props.
255
- * Default: true */
273
+ /**
274
+ * Controls whether Regor should automatically apply incoming `head.props`
275
+ * values to the component context after `context(head)` returns.
276
+ *
277
+ * Think of it as "auto wire parent inputs into my component fields".
278
+ *
279
+ * - `true` (default):
280
+ * - If a key exists in `head.props` but does not exist on the object
281
+ * returned by `context(head)`, Regor adds that key to component context.
282
+ * - Existing ref fields can receive incoming values automatically.
283
+ * - Ref-to-ref inputs can be entangled when `head.entangle` is enabled.
284
+ * - `false`:
285
+ * - Regor does not auto-apply props.
286
+ * - You fully control mapping manually inside `context(head)`.
287
+ *
288
+ * Use `false` when you need strict custom mapping/validation/transforms
289
+ * before any value touches component state.
290
+ *
291
+ * "Missing key" is always checked against the returned component context object.
292
+ *
293
+ * Example (auto add):
294
+ * ```ts
295
+ * // Parent passes: :context="{ badge: 'pro' }"
296
+ * context(head) {
297
+ * // Returned context has no "badge" key:
298
+ * return { name: ref('Ada') }
299
+ * }
300
+ * // Resulting component context becomes:
301
+ * // { name: ref('Ada'), badge: 'pro' }
302
+ * ```
303
+ *
304
+ * Example:
305
+ * ```ts
306
+ * context(head) {
307
+ * head.autoProps = false
308
+ * const title = ref((head.props.title as string) ?? 'Untitled')
309
+ * return { title }
310
+ * }
311
+ * ```
312
+ */
256
313
  __publicField(this, "autoProps", true);
257
- /** When both autoProps and entangle are enabled,
258
- * the refs defined in the component context (without using head.props)
259
- * become entangled with the head.props refs. (parent[ref] `<==>` component[ref])
260
- * This means that changes to parent[ref] reflect in component[ref], and vice versa.
261
- * Disable this flag to isolate refs created within the component context.
262
- * Default: true */
314
+ /**
315
+ * Enables two-way ref linking between incoming props and component context
316
+ * when `autoProps` is also enabled.
317
+ *
318
+ * - `true` (default): parent and component refs stay synchronized.
319
+ * - `false`: component keeps local ref isolation.
320
+ */
263
321
  __publicField(this, "entangle", true);
264
- /** enables slot context switch to the parent
265
- * Default: false */
322
+ /**
323
+ * Enables slot context switch behavior for advanced slot scenarios.
324
+ * Default: `false`.
325
+ */
266
326
  __publicField(this, "enableSwitch", false);
267
- /** A callback invoked after auto props get assigned to the component context. */
327
+ /**
328
+ * Optional hook called after automatic prop assignment completes.
329
+ * Useful when post-assignment normalization is needed.
330
+ */
268
331
  __publicField(this, "onAutoPropsAssigned");
269
332
  /**
270
333
  * @internal
271
334
  */
272
335
  __publicField(this, "__element");
273
- /** use arrow syntax to be called without using head.emit.bind(head) in Binder.ts. */
336
+ /**
337
+ * Emits a custom DOM event from the component host element.
338
+ *
339
+ * Example:
340
+ * ```ts
341
+ * head.emit('saved', { id: 42 })
342
+ * ```
343
+ *
344
+ * Parent markup can listen via regular event binding:
345
+ * ```html
346
+ * <MyComp @saved="onSaved"></MyComp>
347
+ * ```
348
+ */
274
349
  __publicField(this, "emit", (event, args) => {
275
350
  this.__element.dispatchEvent(
276
351
  new CustomEvent(event, { detail: args })
@@ -282,6 +357,10 @@ var Regor = (() => {
282
357
  this.start = start;
283
358
  this.end = end;
284
359
  }
360
+ /**
361
+ * Unmounts this component instance by removing nodes between `start` and `end`
362
+ * and calling unmount lifecycle handlers for captured contexts.
363
+ */
285
364
  unmount() {
286
365
  let next = this.start.nextSibling;
287
366
  const end = this.end;
@@ -383,6 +462,8 @@ var Regor = (() => {
383
462
  };
384
463
 
385
464
  // src/bind/IfBinder.ts
465
+ var noopStopObserving = () => {
466
+ };
386
467
  var mount = (nodes, binder, parent, end) => {
387
468
  const childNodes = [];
388
469
  for (const x of nodes) {
@@ -507,18 +588,14 @@ var Regor = (() => {
507
588
  const parseResult = this.__binder.__parser.__parse(expression);
508
589
  const value = parseResult.value;
509
590
  const remainingElses = this.__collectElses(nextElement, refresh);
510
- const stopObserverList = [];
591
+ let stopObserver = noopStopObserving;
511
592
  const unbinder = () => {
512
593
  parseResult.stop();
513
- for (const stopObserver of stopObserverList) {
514
- stopObserver();
515
- }
516
- stopObserverList.length = 0;
594
+ stopObserver();
595
+ stopObserver = noopStopObserving;
517
596
  };
518
597
  addUnbinder(commentBegin, unbinder);
519
- const stopObserving = parseResult.subscribe ? parseResult.subscribe(refresh) : () => {
520
- };
521
- stopObserverList.push(stopObserving);
598
+ stopObserver = parseResult.subscribe(refresh);
522
599
  return [
523
600
  {
524
601
  mount: () => {
@@ -529,8 +606,9 @@ var Regor = (() => {
529
606
  },
530
607
  isTrue: () => !!value()[0],
531
608
  isMounted: false
532
- }
533
- ].concat(remainingElses);
609
+ },
610
+ ...remainingElses
611
+ ];
534
612
  }
535
613
  }
536
614
  __bindToExpression(el, expression) {
@@ -576,29 +654,31 @@ var Regor = (() => {
576
654
  });
577
655
  };
578
656
  const collectedElses = this.__collectElses(nextElement, refresh);
579
- const stopObserverList = [];
657
+ let stopObserver = noopStopObserving;
580
658
  const unbinder = () => {
581
659
  parseResult.stop();
582
- for (const stopObserver of stopObserverList) {
583
- stopObserver();
584
- }
585
- stopObserverList.length = 0;
660
+ stopObserver();
661
+ stopObserver = noopStopObserving;
586
662
  };
587
663
  addUnbinder(commentBegin, unbinder);
588
664
  refresh();
589
- const stopObserving = parseResult.subscribe ? parseResult.subscribe(refresh) : () => {
590
- };
591
- stopObserverList.push(stopObserving);
665
+ stopObserver = parseResult.subscribe(refresh);
592
666
  }
593
667
  };
594
668
 
595
669
  // src/common/common.ts
596
670
  var getNodes = (el) => {
597
- const childNodes = isTemplate(el) ? el.content.childNodes : [el];
598
- return Array.from(childNodes).filter((x) => {
599
- const tagName = x == null ? void 0 : x.tagName;
600
- return tagName !== "SCRIPT" && tagName !== "STYLE";
601
- });
671
+ const source = isTemplate(el) ? el.content.childNodes : [el];
672
+ const result = [];
673
+ for (let i = 0; i < source.length; ++i) {
674
+ const node = source[i];
675
+ if (node.nodeType === 1) {
676
+ const tagName = node == null ? void 0 : node.tagName;
677
+ if (tagName === "SCRIPT" || tagName === "STYLE") continue;
678
+ }
679
+ result.push(node);
680
+ }
681
+ return result;
602
682
  };
603
683
  var bindChildNodes = (binder, childNodes) => {
604
684
  for (let i = 0; i < childNodes.length; ++i) {
@@ -696,7 +776,9 @@ var Regor = (() => {
696
776
  });
697
777
 
698
778
  // src/directives/teleport.ts
699
- var teleportDirective = {};
779
+ var teleportDirective = {
780
+ mount: () => void 0
781
+ };
700
782
 
701
783
  // src/composition/callMounted.ts
702
784
  var callMounted = (context) => {
@@ -731,12 +813,6 @@ var Regor = (() => {
731
813
  return scopeSymbol2 in value;
732
814
  };
733
815
 
734
- // src/composition/onUnmounted.ts
735
- var onUnmounted = (onUnmounted2, noThrow) => {
736
- var _a;
737
- (_a = peekScope(noThrow)) == null ? void 0 : _a.onUnmounted.push(onUnmounted2);
738
- };
739
-
740
816
  // src/reactivity/refSymbols.ts
741
817
  var refSymbol = Symbol("ref");
742
818
  var srefSymbol = Symbol("sref");
@@ -747,6 +823,35 @@ var Regor = (() => {
747
823
  return value != null && value[srefSymbol] === 1;
748
824
  };
749
825
 
826
+ // src/directives/context.ts
827
+ var contextDirective = {
828
+ collectRefObj: true,
829
+ mount: ({ parseResult }) => ({
830
+ update: ({ values }) => {
831
+ const ctx = parseResult.context;
832
+ const obj = values[0];
833
+ if (!isObject(obj)) return;
834
+ for (const item of Object.entries(obj)) {
835
+ const key = item[0];
836
+ const nextValue = item[1];
837
+ const ctxKey = ctx[key];
838
+ if (ctxKey === nextValue) continue;
839
+ if (isRef(ctxKey)) {
840
+ ctxKey(nextValue);
841
+ } else {
842
+ ctx[key] = nextValue;
843
+ }
844
+ }
845
+ }
846
+ })
847
+ };
848
+
849
+ // src/composition/onUnmounted.ts
850
+ var onUnmounted = (onUnmounted2, noThrow) => {
851
+ var _a;
852
+ (_a = peekScope(noThrow)) == null ? void 0 : _a.onUnmounted.push(onUnmounted2);
853
+ };
854
+
750
855
  // src/observer/observe.ts
751
856
  var observe = (source, observer, init, trackUnmount = true) => {
752
857
  if (!isRef(source))
@@ -763,65 +868,6 @@ var Regor = (() => {
763
868
  return stop;
764
869
  };
765
870
 
766
- // src/directives/props.ts
767
- var propsDirective = {
768
- collectRefObj: true,
769
- onBind: (_, parseResult) => {
770
- const stopObserving = observe(
771
- parseResult.value,
772
- () => {
773
- const value = parseResult.value();
774
- const ctx = parseResult.context;
775
- const obj = value[0];
776
- if (!isObject(obj)) {
777
- return;
778
- }
779
- for (const item of Object.entries(obj)) {
780
- const key = item[0];
781
- const value2 = item[1];
782
- const ctxKey = ctx[key];
783
- if (ctxKey === value2) continue;
784
- if (isRef(ctxKey)) {
785
- ctxKey(value2);
786
- } else {
787
- ctx[key] = value2;
788
- }
789
- }
790
- },
791
- true
792
- );
793
- return stopObserving;
794
- }
795
- };
796
-
797
- // src/directives/props-once.ts
798
- var propsOnceDirective = {
799
- collectRefObj: true,
800
- once: true,
801
- onBind: (_, parseResult) => {
802
- const value = parseResult.value();
803
- const ctx = parseResult.context;
804
- const obj = value[0];
805
- if (!isObject(obj)) {
806
- return () => {
807
- };
808
- }
809
- for (const item of Object.entries(obj)) {
810
- const key = item[0];
811
- const value2 = item[1];
812
- const ctxKey = ctx[key];
813
- if (ctxKey === value2) continue;
814
- if (isRef(ctxKey)) {
815
- ctxKey(value2);
816
- } else {
817
- ctx[key] = value2;
818
- }
819
- }
820
- return () => {
821
- };
822
- }
823
- };
824
-
825
871
  // src/reactivity/entangle.ts
826
872
  var entangle = (r1, r2) => {
827
873
  if (r1 === r2) return () => {
@@ -1149,8 +1195,8 @@ var Regor = (() => {
1149
1195
  };
1150
1196
  var singlePropDirective = {
1151
1197
  collectRefObj: true,
1152
- onBind: (_, parseResult, _expr, option, _dynamicOption, _flags) => {
1153
- if (!option) return noop;
1198
+ mount: ({ parseResult, option }) => {
1199
+ if (typeof option !== "string" || !option) return noop;
1154
1200
  const key = camelize(option);
1155
1201
  let currentSource;
1156
1202
  let bridge;
@@ -1171,44 +1217,44 @@ var Regor = (() => {
1171
1217
  stopEntangle = entangle(source, target);
1172
1218
  currentSource = source;
1173
1219
  };
1174
- const stopObserving = observe(
1175
- parseResult.value,
1176
- () => {
1177
- var _a;
1178
- const value = (_a = parseResult.refs[0]) != null ? _a : parseResult.value()[0];
1179
- const ctx = parseResult.context;
1180
- const ctxKey = ctx[key];
1181
- if (!isRef(value)) {
1182
- if (bridge && ctxKey === bridge) {
1183
- bridge(value);
1184
- return;
1185
- }
1186
- resetSync();
1187
- if (isRef(ctxKey)) {
1188
- ctxKey(value);
1189
- return;
1190
- }
1191
- ctx[key] = value;
1220
+ const apply = () => {
1221
+ var _a;
1222
+ const value = (_a = parseResult.refs[0]) != null ? _a : parseResult.value()[0];
1223
+ const ctx = parseResult.context;
1224
+ const ctxKey = ctx[key];
1225
+ if (!isRef(value)) {
1226
+ if (bridge && ctxKey === bridge) {
1227
+ bridge(value);
1192
1228
  return;
1193
1229
  }
1194
- if (isModelBridge(value)) {
1195
- if (ctxKey === value) return;
1196
- if (isRef(ctxKey)) {
1197
- syncRefs(value, ctxKey);
1198
- } else {
1199
- ctx[key] = value;
1200
- }
1230
+ resetSync();
1231
+ if (isRef(ctxKey)) {
1232
+ ctxKey(value);
1201
1233
  return;
1202
1234
  }
1203
- if (!bridge) bridge = createModelBridge(value);
1204
- ctx[key] = bridge;
1205
- syncRefs(value, bridge);
1235
+ ctx[key] = value;
1236
+ return;
1237
+ }
1238
+ if (isModelBridge(value)) {
1239
+ if (ctxKey === value) return;
1240
+ if (isRef(ctxKey)) {
1241
+ syncRefs(value, ctxKey);
1242
+ } else {
1243
+ ctx[key] = value;
1244
+ }
1245
+ return;
1246
+ }
1247
+ if (!bridge) bridge = createModelBridge(value);
1248
+ ctx[key] = bridge;
1249
+ syncRefs(value, bridge);
1250
+ };
1251
+ return {
1252
+ update: () => {
1253
+ apply();
1206
1254
  },
1207
- true
1208
- );
1209
- return () => {
1210
- stopEntangle();
1211
- stopObserving();
1255
+ unmount: () => {
1256
+ stopEntangle();
1257
+ }
1212
1258
  };
1213
1259
  }
1214
1260
  };
@@ -1229,7 +1275,10 @@ var Regor = (() => {
1229
1275
  __getRegisteredComponentSelector(registeredComponents) {
1230
1276
  if (this.__registeredComponentSize !== registeredComponents.size) {
1231
1277
  const names = [...registeredComponents.keys()];
1232
- this.__registeredComponentSelector = names.concat(names.map(hyphenate)).join(",");
1278
+ this.__registeredComponentSelector = [
1279
+ ...names,
1280
+ ...names.map(hyphenate)
1281
+ ].join(",");
1233
1282
  this.__registeredComponentSize = registeredComponents.size;
1234
1283
  }
1235
1284
  return this.__registeredComponentSelector;
@@ -1284,18 +1333,19 @@ var Regor = (() => {
1284
1333
  const endOfComponent = new Comment(" end component: " + component.tagName);
1285
1334
  componentParent.insertBefore(startOfComponent, component);
1286
1335
  component.remove();
1287
- const propsName = binder.__config.__builtInNames.props;
1288
- const propsOnceName = binder.__config.__builtInNames.propsOnce;
1336
+ const contextName = binder.__config.__builtInNames.context;
1337
+ const contextAliasName = binder.__config.__builtInNames.contextAlias;
1289
1338
  const bindName = binder.__config.__builtInNames.bind;
1290
1339
  const getProps = (component2, capturedContext2) => {
1291
1340
  const props = {};
1292
- const hasProps = component2.hasAttribute(propsName);
1293
- const hasPropsOnce = component2.hasAttribute(propsOnceName);
1341
+ const hasContext = component2.hasAttribute(contextName);
1294
1342
  parser.__scoped(capturedContext2, () => {
1295
1343
  parser.__push(props);
1296
- if (hasProps) binder.__bind(propsDirective, component2, propsName);
1297
- if (hasPropsOnce)
1298
- binder.__bind(propsOnceDirective, component2, propsOnceName);
1344
+ if (hasContext) {
1345
+ binder.__bind(contextDirective, component2, contextName);
1346
+ } else if (component2.hasAttribute(contextAliasName)) {
1347
+ binder.__bind(contextDirective, component2, contextAliasName);
1348
+ }
1299
1349
  let definedProps = registeredComponent.props;
1300
1350
  if (!definedProps || definedProps.length === 0) return;
1301
1351
  definedProps = definedProps.map(camelize);
@@ -1305,7 +1355,10 @@ var Regor = (() => {
1305
1355
  definedProp
1306
1356
  ])
1307
1357
  );
1308
- for (const name of definedProps.concat(definedProps.map(hyphenate))) {
1358
+ for (const name of [
1359
+ ...definedProps,
1360
+ ...definedProps.map(hyphenate)
1361
+ ]) {
1309
1362
  const value = component2.getAttribute(name);
1310
1363
  if (value === null) continue;
1311
1364
  props[camelize(name)] = value;
@@ -1352,8 +1405,20 @@ var Regor = (() => {
1352
1405
  if (key in componentCtx2) {
1353
1406
  const compValue = componentCtx2[key];
1354
1407
  if (compValue === propsValue) continue;
1355
- if (head2.entangle && isRef(compValue) && isRef(propsValue)) {
1356
- addUnbinder(startOfComponent, entangle(propsValue, compValue));
1408
+ if (isRef(compValue)) {
1409
+ if (isRef(propsValue)) {
1410
+ if (head2.entangle) {
1411
+ addUnbinder(
1412
+ startOfComponent,
1413
+ entangle(propsValue, compValue)
1414
+ );
1415
+ } else {
1416
+ compValue(propsValue());
1417
+ }
1418
+ } else {
1419
+ compValue(propsValue);
1420
+ }
1421
+ continue;
1357
1422
  }
1358
1423
  } else componentCtx2[key] = propsValue;
1359
1424
  }
@@ -1464,7 +1529,8 @@ var Regor = (() => {
1464
1529
  const inheritor = inheritorChildNodes[0];
1465
1530
  if (!inheritor) return;
1466
1531
  for (const attrName of component.getAttributeNames()) {
1467
- if (attrName === propsName || attrName === propsOnceName) continue;
1532
+ if (attrName === contextName || attrName === contextAliasName)
1533
+ continue;
1468
1534
  const value = component.getAttribute(attrName);
1469
1535
  if (attrName === "class") {
1470
1536
  inheritor.classList.add(...value.split(" "));
@@ -1587,18 +1653,17 @@ var Regor = (() => {
1587
1653
  }
1588
1654
  };
1589
1655
  const processNode = (node) => {
1590
- var _a, _b;
1656
+ var _a;
1591
1657
  const attrs = node.attributes;
1592
1658
  if (!attrs || attrs.length === 0) return;
1593
- const attrsAny = attrs;
1594
1659
  for (let i = 0; i < attrs.length; ++i) {
1595
- const name = (_b = (_a = attrsAny[i]) != null ? _a : attrs.item(i)) == null ? void 0 : _b.name;
1660
+ const name = (_a = attrs.item(i)) == null ? void 0 : _a.name;
1596
1661
  if (!name) continue;
1597
1662
  appendDirective(node, name);
1598
1663
  }
1599
1664
  };
1600
1665
  processNode(element);
1601
- if (!isRecursive) return map;
1666
+ if (!isRecursive || !element.firstElementChild) return map;
1602
1667
  const nodes = element.querySelectorAll("*");
1603
1668
  for (const node of nodes) {
1604
1669
  processNode(node);
@@ -1608,6 +1673,8 @@ var Regor = (() => {
1608
1673
  };
1609
1674
 
1610
1675
  // src/bind/DynamicBinder.ts
1676
+ var noopStopObserving2 = () => {
1677
+ };
1611
1678
  var mount2 = (nodes, parent) => {
1612
1679
  for (const x of nodes) {
1613
1680
  const node = x.cloneNode(true);
@@ -1723,19 +1790,15 @@ var Regor = (() => {
1723
1790
  mounted.name = name;
1724
1791
  });
1725
1792
  };
1726
- const stopObserverList = [];
1793
+ let stopObserver = noopStopObserving2;
1727
1794
  const unbinder = () => {
1728
1795
  parseResult.stop();
1729
- for (const stopObserver of stopObserverList) {
1730
- stopObserver();
1731
- }
1732
- stopObserverList.length = 0;
1796
+ stopObserver();
1797
+ stopObserver = noopStopObserving2;
1733
1798
  };
1734
1799
  addUnbinder(commentBegin, unbinder);
1735
1800
  refresh();
1736
- const stopObserving = parseResult.subscribe ? parseResult.subscribe(refresh) : () => {
1737
- };
1738
- stopObserverList.push(stopObserving);
1801
+ stopObserver = parseResult.subscribe(refresh);
1739
1802
  }
1740
1803
  };
1741
1804
 
@@ -1745,6 +1808,274 @@ var Regor = (() => {
1745
1808
  return anyValue != null && anyValue[srefSymbol] === 1 ? anyValue() : anyValue;
1746
1809
  };
1747
1810
 
1811
+ // src/directives/html.ts
1812
+ var updateHtml = (el, values) => {
1813
+ const [value, replacer] = values;
1814
+ if (isFunction(replacer)) replacer(el, value);
1815
+ else el.innerHTML = value == null ? void 0 : value.toString();
1816
+ };
1817
+ var htmlDirective = {
1818
+ mount: () => ({
1819
+ update: ({ el, values }) => {
1820
+ updateHtml(el, values);
1821
+ }
1822
+ })
1823
+ };
1824
+
1825
+ // src/bind/ForBinderFastPath.ts
1826
+ var ForBinderFastPath = class _ForBinderFastPath {
1827
+ constructor(bindings) {
1828
+ __publicField(this, "__bindings");
1829
+ this.__bindings = bindings;
1830
+ }
1831
+ static __create(binder, nodes) {
1832
+ var _a, _b;
1833
+ const parser = binder.__parser;
1834
+ const config = binder.__config;
1835
+ const builtInNames = config.__builtInNames;
1836
+ const blockedBuiltIns = /* @__PURE__ */ new Set([
1837
+ builtInNames.for,
1838
+ builtInNames.if,
1839
+ builtInNames.else,
1840
+ builtInNames.elseif,
1841
+ builtInNames.pre
1842
+ ]);
1843
+ const directiveMap = config.__directiveMap;
1844
+ const contextComponents = parser.__getComponents();
1845
+ if (Object.keys(contextComponents).length > 0 || config.__componentsUpperCase.size > 0) {
1846
+ return void 0;
1847
+ }
1848
+ const collector = binder.__directiveCollector;
1849
+ const bindings = [];
1850
+ let nodeIndex = 0;
1851
+ const stack = [];
1852
+ for (let i = nodes.length - 1; i >= 0; --i) {
1853
+ stack.push(nodes[i]);
1854
+ }
1855
+ while (stack.length > 0) {
1856
+ const node = stack.pop();
1857
+ if (node.nodeType === Node.ELEMENT_NODE) {
1858
+ const el = node;
1859
+ if (el.tagName === "TEMPLATE") return void 0;
1860
+ if (el.tagName.includes("-")) return void 0;
1861
+ const tagNameUpper = camelize(el.tagName).toUpperCase();
1862
+ if (config.__componentsUpperCase.has(tagNameUpper) || contextComponents[tagNameUpper]) {
1863
+ return void 0;
1864
+ }
1865
+ const attrs = el.attributes;
1866
+ for (let i = 0; i < attrs.length; ++i) {
1867
+ const attrName = (_a = attrs.item(i)) == null ? void 0 : _a.name;
1868
+ if (!attrName) continue;
1869
+ if (blockedBuiltIns.has(attrName)) return void 0;
1870
+ const { terms, flags } = collector.__parseName(attrName);
1871
+ const [name, option] = terms;
1872
+ const directive = (_b = directiveMap[attrName]) != null ? _b : directiveMap[name];
1873
+ if (!directive) continue;
1874
+ if (directive === htmlDirective) return void 0;
1875
+ bindings.push({
1876
+ nodeIndex,
1877
+ attrName,
1878
+ directive,
1879
+ option,
1880
+ flags
1881
+ });
1882
+ }
1883
+ ++nodeIndex;
1884
+ }
1885
+ const children = node.childNodes;
1886
+ for (let i = children.length - 1; i >= 0; --i) {
1887
+ stack.push(children[i]);
1888
+ }
1889
+ }
1890
+ if (bindings.length === 0) return void 0;
1891
+ return new _ForBinderFastPath(bindings);
1892
+ }
1893
+ __bind(binder, nodes) {
1894
+ const elements = [];
1895
+ const stack = [];
1896
+ for (let i = nodes.length - 1; i >= 0; --i) {
1897
+ stack.push(nodes[i]);
1898
+ }
1899
+ while (stack.length > 0) {
1900
+ const node = stack.pop();
1901
+ if (node.nodeType === Node.ELEMENT_NODE) {
1902
+ elements.push(node);
1903
+ }
1904
+ const children = node.childNodes;
1905
+ for (let i = children.length - 1; i >= 0; --i) {
1906
+ stack.push(children[i]);
1907
+ }
1908
+ }
1909
+ for (let i = 0; i < this.__bindings.length; ++i) {
1910
+ const binding = this.__bindings[i];
1911
+ const el = elements[binding.nodeIndex];
1912
+ if (!el) continue;
1913
+ binder.__bind(
1914
+ binding.directive,
1915
+ el,
1916
+ binding.attrName,
1917
+ false,
1918
+ binding.option,
1919
+ binding.flags
1920
+ );
1921
+ }
1922
+ }
1923
+ };
1924
+
1925
+ // src/bind/ForBinderKeyedDiff.ts
1926
+ var moveMountItemBefore = (item, anchor) => {
1927
+ const parent = anchor.parentNode;
1928
+ if (!parent) return;
1929
+ for (let i = 0; i < item.items.length; ++i) {
1930
+ parent.insertBefore(item.items[i], anchor);
1931
+ }
1932
+ };
1933
+ var getSequence = (arr) => {
1934
+ var _a;
1935
+ const len = arr.length;
1936
+ const p = arr.slice();
1937
+ const result = [];
1938
+ let u;
1939
+ let v;
1940
+ let c;
1941
+ for (let i = 0; i < len; ++i) {
1942
+ const value = arr[i];
1943
+ if (value === 0) continue;
1944
+ const j = result[result.length - 1];
1945
+ if (j === void 0 || arr[j] < value) {
1946
+ p[i] = j != null ? j : -1;
1947
+ result.push(i);
1948
+ continue;
1949
+ }
1950
+ u = 0;
1951
+ v = result.length - 1;
1952
+ while (u < v) {
1953
+ c = u + v >> 1;
1954
+ if (arr[result[c]] < value) u = c + 1;
1955
+ else v = c;
1956
+ }
1957
+ if (value < arr[result[u]]) {
1958
+ if (u > 0) p[i] = result[u - 1];
1959
+ result[u] = i;
1960
+ }
1961
+ }
1962
+ u = result.length;
1963
+ v = (_a = result[u - 1]) != null ? _a : -1;
1964
+ while (u-- > 0) {
1965
+ result[u] = v;
1966
+ v = p[v];
1967
+ }
1968
+ return result;
1969
+ };
1970
+ var ForBinderKeyedDiff = class {
1971
+ /**
1972
+ * Applies keyed patch and returns the next ordered mount list.
1973
+ * Returns `undefined` when keyed mode is not safe for this update.
1974
+ */
1975
+ static __patch(options) {
1976
+ const {
1977
+ oldItems,
1978
+ newValues,
1979
+ getKey,
1980
+ isSameValue,
1981
+ mountNewValue,
1982
+ removeMountItem,
1983
+ endAnchor
1984
+ } = options;
1985
+ const oldLen = oldItems.length;
1986
+ const newLen = newValues.length;
1987
+ const newKeys = new Array(newLen);
1988
+ const keySeen = /* @__PURE__ */ new Set();
1989
+ for (let i2 = 0; i2 < newLen; ++i2) {
1990
+ const key = getKey(newValues[i2]);
1991
+ if (key === void 0 || keySeen.has(key)) return void 0;
1992
+ keySeen.add(key);
1993
+ newKeys[i2] = key;
1994
+ }
1995
+ const newMountItems = new Array(newLen);
1996
+ let i = 0;
1997
+ let e1 = oldLen - 1;
1998
+ let e2 = newLen - 1;
1999
+ while (i <= e1 && i <= e2) {
2000
+ const oldItem = oldItems[i];
2001
+ if (getKey(oldItem.value) !== newKeys[i]) break;
2002
+ if (!isSameValue(oldItem.value, newValues[i])) break;
2003
+ oldItem.value = newValues[i];
2004
+ newMountItems[i] = oldItem;
2005
+ ++i;
2006
+ }
2007
+ while (i <= e1 && i <= e2) {
2008
+ const oldItem = oldItems[e1];
2009
+ if (getKey(oldItem.value) !== newKeys[e2]) break;
2010
+ if (!isSameValue(oldItem.value, newValues[e2])) break;
2011
+ oldItem.value = newValues[e2];
2012
+ newMountItems[e2] = oldItem;
2013
+ --e1;
2014
+ --e2;
2015
+ }
2016
+ if (i > e1) {
2017
+ for (let k = e2; k >= i; --k) {
2018
+ const anchor = k + 1 < newLen ? newMountItems[k + 1].items[0] : endAnchor;
2019
+ newMountItems[k] = mountNewValue(k, newValues[k], anchor);
2020
+ }
2021
+ return newMountItems;
2022
+ }
2023
+ if (i > e2) {
2024
+ for (let k = i; k <= e1; ++k) removeMountItem(oldItems[k]);
2025
+ return newMountItems;
2026
+ }
2027
+ const s1 = i;
2028
+ const s2 = i;
2029
+ const toBePatched = e2 - s2 + 1;
2030
+ const newIndexToOldIndexMap = new Array(toBePatched).fill(0);
2031
+ const keyToNewIndexMap = /* @__PURE__ */ new Map();
2032
+ for (let k = s2; k <= e2; ++k) {
2033
+ keyToNewIndexMap.set(newKeys[k], k);
2034
+ }
2035
+ let moved = false;
2036
+ let maxNewIndexSoFar = 0;
2037
+ for (let k = s1; k <= e1; ++k) {
2038
+ const oldItem = oldItems[k];
2039
+ const newIndex = keyToNewIndexMap.get(getKey(oldItem.value));
2040
+ if (newIndex === void 0) {
2041
+ removeMountItem(oldItem);
2042
+ continue;
2043
+ }
2044
+ if (!isSameValue(oldItem.value, newValues[newIndex])) {
2045
+ removeMountItem(oldItem);
2046
+ continue;
2047
+ }
2048
+ oldItem.value = newValues[newIndex];
2049
+ newMountItems[newIndex] = oldItem;
2050
+ newIndexToOldIndexMap[newIndex - s2] = k + 1;
2051
+ if (newIndex >= maxNewIndexSoFar) maxNewIndexSoFar = newIndex;
2052
+ else moved = true;
2053
+ }
2054
+ const increasingNewIndexSequence = moved ? getSequence(newIndexToOldIndexMap) : [];
2055
+ let seqIdx = increasingNewIndexSequence.length - 1;
2056
+ for (let k = toBePatched - 1; k >= 0; --k) {
2057
+ const newIndex = s2 + k;
2058
+ const anchor = newIndex + 1 < newLen ? newMountItems[newIndex + 1].items[0] : endAnchor;
2059
+ if (newIndexToOldIndexMap[k] === 0) {
2060
+ newMountItems[newIndex] = mountNewValue(
2061
+ newIndex,
2062
+ newValues[newIndex],
2063
+ anchor
2064
+ );
2065
+ continue;
2066
+ }
2067
+ const item = newMountItems[newIndex];
2068
+ if (!moved) continue;
2069
+ if (seqIdx >= 0 && increasingNewIndexSequence[seqIdx] === k) {
2070
+ --seqIdx;
2071
+ } else if (item) {
2072
+ moveMountItemBefore(item, anchor);
2073
+ }
2074
+ }
2075
+ return newMountItems;
2076
+ }
2077
+ };
2078
+
1748
2079
  // src/bind/MountList.ts
1749
2080
  var MountList = class {
1750
2081
  constructor(getKey) {
@@ -1826,6 +2157,8 @@ var Regor = (() => {
1826
2157
  // src/bind/ForBinder.ts
1827
2158
  var forMarker = Symbol("r-for");
1828
2159
  var noIndexRef = (_) => -1;
2160
+ var noopStopObserving3 = () => {
2161
+ };
1829
2162
  var _ForBinder = class _ForBinder {
1830
2163
  constructor(binder) {
1831
2164
  __publicField(this, "__binder");
@@ -1896,6 +2229,7 @@ var Regor = (() => {
1896
2229
  el.removeAttribute(nameKey);
1897
2230
  el.removeAttribute(nameKeyBind);
1898
2231
  const nodes = getNodes(el);
2232
+ const fastPath = ForBinderFastPath.__create(this.__binder, nodes);
1899
2233
  const parent = el.parentNode;
1900
2234
  if (!parent) return;
1901
2235
  const title = `${this.__for} => ${forPath}`;
@@ -1915,6 +2249,7 @@ var Regor = (() => {
1915
2249
  const rowContexts = singleCapturedContext ? [void 0, capturedContext[0]] : void 0;
1916
2250
  const getKey = this.__createKeyGetter(keyExpression);
1917
2251
  const areEqual = (a, b) => getKey(a) === getKey(b);
2252
+ const isSameValue = (a, b) => a === b;
1918
2253
  const mountNewValue = (i2, newValue, nextSibling) => {
1919
2254
  const result = config.createContext(newValue, i2);
1920
2255
  const mountItem = MountList.__createItem(result.index, newValue);
@@ -1928,7 +2263,8 @@ var Regor = (() => {
1928
2263
  insertParent.insertBefore(node, nextSibling);
1929
2264
  childNodes.push(node);
1930
2265
  }
1931
- bindChildNodes(binder, childNodes);
2266
+ if (fastPath) fastPath.__bind(binder, childNodes);
2267
+ else bindChildNodes(binder, childNodes);
1932
2268
  start = start.nextSibling;
1933
2269
  while (start !== nextSibling) {
1934
2270
  mountItem.items.push(start);
@@ -1980,16 +2316,51 @@ var Regor = (() => {
1980
2316
  mountList.__removeAllAfter(0);
1981
2317
  return;
1982
2318
  }
2319
+ const iterableValues = [];
2320
+ for (const value2 of this.__getIterable(newValues[0])) {
2321
+ iterableValues.push(value2);
2322
+ }
2323
+ const patched = ForBinderKeyedDiff.__patch({
2324
+ oldItems: mountList.__list,
2325
+ newValues: iterableValues,
2326
+ getKey,
2327
+ isSameValue,
2328
+ mountNewValue: (index, value2, nextSibling) => mountNewValue(index, value2, nextSibling),
2329
+ removeMountItem: (item) => {
2330
+ for (let k = 0; k < item.items.length; ++k) {
2331
+ removeNode(item.items[k]);
2332
+ }
2333
+ },
2334
+ endAnchor: commentEnd
2335
+ });
2336
+ if (patched) {
2337
+ mountList.__list = patched;
2338
+ mountList.__valueMap.clear();
2339
+ for (let k = 0; k < patched.length; ++k) {
2340
+ const item = patched[k];
2341
+ item.order = k;
2342
+ item.index(k);
2343
+ const key = getKey(item.value);
2344
+ if (key !== void 0) {
2345
+ mountList.__valueMap.set(key, item);
2346
+ }
2347
+ }
2348
+ return;
2349
+ }
1983
2350
  let i2 = 0;
1984
2351
  let firstRemovalOrInsertionIndex = Number.MAX_SAFE_INTEGER;
1985
2352
  const initialLength = len;
1986
2353
  const forGrowThreshold = this.__binder.__config.forGrowThreshold;
1987
2354
  const shouldGrowList = () => mountList.__length < initialLength + forGrowThreshold;
1988
- for (const newValue of this.__getIterable(newValues[0])) {
2355
+ for (const newValue of iterableValues) {
1989
2356
  const modify = () => {
1990
2357
  if (i2 < len) {
1991
2358
  const mountItem = mountList.__get(i2++);
1992
- if (areEqual(mountItem.value, newValue)) return;
2359
+ if (areEqual(mountItem.value, newValue)) {
2360
+ if (isSameValue(mountItem.value, newValue)) return;
2361
+ replace(i2 - 1, newValue);
2362
+ return;
2363
+ }
1993
2364
  const newValueMountPosition = mountList.__lookupValueOrderIfMounted(
1994
2365
  getKey(newValue)
1995
2366
  );
@@ -2039,24 +2410,21 @@ var Regor = (() => {
2039
2410
  mountList.__removeAllAfter(j);
2040
2411
  updateIndexes(firstRemovalOrInsertionIndex);
2041
2412
  };
2042
- const observeTailChanges = () => {
2043
- stopObserving = parseResult.subscribe ? parseResult.subscribe(updateDom) : () => {
2044
- };
2045
- };
2046
2413
  const unbinder = () => {
2047
2414
  parseResult.stop();
2048
2415
  stopObserving();
2416
+ stopObserving = noopStopObserving3;
2049
2417
  };
2050
2418
  const parseResult = parser.__parse(config.list);
2051
2419
  const value = parseResult.value;
2052
- let stopObserving;
2420
+ let stopObserving = noopStopObserving3;
2053
2421
  let i = 0;
2054
2422
  const mountList = new MountList(getKey);
2055
2423
  for (const item of this.__getIterable(value()[0])) {
2056
2424
  mountList.__push(mountNewValue(i++, item, commentEnd));
2057
2425
  }
2058
2426
  addUnbinder(commentBegin, unbinder);
2059
- observeTailChanges();
2427
+ stopObserving = parseResult.subscribe(updateDom);
2060
2428
  }
2061
2429
  __parseForPath(forPath) {
2062
2430
  var _a, _b;
@@ -2240,105 +2608,111 @@ var Regor = (() => {
2240
2608
  return true;
2241
2609
  }
2242
2610
  __bindToExpression(config, el, valueExpression, option, flags) {
2243
- var _a;
2244
2611
  if (el.nodeType !== Node.ELEMENT_NODE || valueExpression == null) return;
2245
2612
  if (this.__handleTeleport(config, el, valueExpression)) return;
2246
- const result = this.__parser.__parse(
2613
+ const dynamicOption = this.__parseDynamicOption(option, config.once);
2614
+ const result = this.__parseExpression(config, valueExpression);
2615
+ const stops = this.__createBindStops(result, dynamicOption);
2616
+ addUnbinder(el, stops.stop);
2617
+ const payload = this.__createDirectivePayload(
2618
+ el,
2619
+ valueExpression,
2620
+ result,
2621
+ dynamicOption,
2622
+ option,
2623
+ flags
2624
+ );
2625
+ const mountedUpdate = this.__mountDirective(config, payload, stops);
2626
+ if (!mountedUpdate) return;
2627
+ const emitChange = this.__createEmitter(
2628
+ payload,
2629
+ result,
2630
+ dynamicOption,
2631
+ option,
2632
+ mountedUpdate
2633
+ );
2634
+ emitChange();
2635
+ if (!config.once) {
2636
+ stops.result = result.subscribe(emitChange);
2637
+ if (dynamicOption) {
2638
+ stops.dynamic = dynamicOption.subscribe(emitChange);
2639
+ }
2640
+ }
2641
+ }
2642
+ __parseDynamicOption(option, once) {
2643
+ const dynamicOptionExpression = isOptionDynamic(option, this.__dynamic);
2644
+ if (!dynamicOptionExpression) return void 0;
2645
+ return this.__parser.__parse(
2646
+ camelize(dynamicOptionExpression),
2647
+ void 0,
2648
+ void 0,
2649
+ void 0,
2650
+ once
2651
+ );
2652
+ }
2653
+ __parseExpression(config, valueExpression) {
2654
+ return this.__parser.__parse(
2247
2655
  valueExpression,
2248
2656
  config.isLazy,
2249
2657
  config.isLazyKey,
2250
2658
  config.collectRefObj,
2251
2659
  config.once
2252
2660
  );
2253
- const stopObserverList = [];
2254
- const hasOnChange = !!config.onChange;
2255
- const unbinder = () => {
2256
- result.stop();
2257
- dynamicOption == null ? void 0 : dynamicOption.stop();
2258
- for (let i = 0; i < stopObserverList.length; ++i) {
2259
- stopObserverList[i]();
2661
+ }
2662
+ __createBindStops(result, dynamicOption) {
2663
+ const stops = {
2664
+ stop: () => {
2665
+ var _a, _b, _c;
2666
+ result.stop();
2667
+ dynamicOption == null ? void 0 : dynamicOption.stop();
2668
+ (_a = stops.result) == null ? void 0 : _a.call(stops);
2669
+ (_b = stops.dynamic) == null ? void 0 : _b.call(stops);
2670
+ (_c = stops.mounted) == null ? void 0 : _c.call(stops);
2671
+ stops.result = void 0;
2672
+ stops.dynamic = void 0;
2673
+ stops.mounted = void 0;
2260
2674
  }
2261
- stopObserverList.length = 0;
2262
2675
  };
2263
- addUnbinder(el, unbinder);
2264
- const dynamicOptionExpression = isOptionDynamic(option, this.__dynamic);
2265
- let dynamicOption;
2266
- if (dynamicOptionExpression) {
2267
- dynamicOption = this.__parser.__parse(
2268
- camelize(dynamicOptionExpression),
2269
- void 0,
2270
- void 0,
2271
- void 0,
2272
- config.once
2273
- );
2676
+ return stops;
2677
+ }
2678
+ __createDirectivePayload(el, expr, result, dynamicOption, option, flags) {
2679
+ return {
2680
+ el,
2681
+ expr,
2682
+ values: result.value(),
2683
+ previousValues: void 0,
2684
+ option: dynamicOption ? dynamicOption.value()[0] : option,
2685
+ previousOption: void 0,
2686
+ flags,
2687
+ parseResult: result,
2688
+ dynamicOption
2689
+ };
2690
+ }
2691
+ __mountDirective(config, payload, stops) {
2692
+ const mounted = config.mount(payload);
2693
+ if (typeof mounted === "function") {
2694
+ stops.mounted = mounted;
2695
+ return void 0;
2274
2696
  }
2275
- const dynamicOpt = dynamicOption;
2276
- const hasDynamicOption = dynamicOpt != null;
2277
- let previousValues = result.value();
2278
- let previousOption = hasDynamicOption ? dynamicOption.value()[0] : option;
2279
- if (!config.once && hasOnChange) {
2280
- const stopObserving = result.subscribe ? result.subscribe(() => {
2281
- var _a2;
2282
- const preValues = previousValues;
2283
- const preOption = previousOption;
2284
- const nextValues = result.value();
2285
- const nextOption = hasDynamicOption ? dynamicOpt.value()[0] : option;
2286
- previousValues = nextValues;
2287
- previousOption = nextOption;
2288
- (_a2 = config.onChange) == null ? void 0 : _a2.call(
2289
- config,
2290
- el,
2291
- nextValues,
2292
- preValues,
2293
- nextOption,
2294
- preOption,
2295
- flags
2296
- );
2297
- }) : () => {
2298
- };
2299
- stopObserverList.push(stopObserving);
2300
- if (dynamicOpt) {
2301
- const stopObserving2 = dynamicOpt.subscribe ? dynamicOpt.subscribe(() => {
2302
- var _a2;
2303
- const preOption = previousOption;
2304
- const nextValues = result.value();
2305
- const nextOption = dynamicOpt.value()[0];
2306
- previousValues = nextValues;
2307
- previousOption = nextOption;
2308
- (_a2 = config.onChange) == null ? void 0 : _a2.call(
2309
- config,
2310
- el,
2311
- nextValues,
2312
- preOption,
2313
- nextOption,
2314
- preOption,
2315
- flags
2316
- );
2317
- }) : () => {
2318
- };
2319
- stopObserverList.push(stopObserving2);
2320
- }
2697
+ if (mounted == null ? void 0 : mounted.unmount) {
2698
+ stops.mounted = mounted.unmount;
2321
2699
  }
2322
- if (config.onBind)
2323
- stopObserverList.push(
2324
- config.onBind(
2325
- el,
2326
- result,
2327
- valueExpression,
2328
- option,
2329
- dynamicOption,
2330
- flags
2331
- )
2332
- );
2333
- (_a = config.onChange) == null ? void 0 : _a.call(
2334
- config,
2335
- el,
2336
- previousValues,
2337
- void 0,
2338
- previousOption,
2339
- void 0,
2340
- flags
2341
- );
2700
+ return mounted == null ? void 0 : mounted.update;
2701
+ }
2702
+ __createEmitter(payload, result, dynamicOption, option, mountedUpdate) {
2703
+ let previousValues;
2704
+ let previousOption;
2705
+ return () => {
2706
+ const nextValues = result.value();
2707
+ const nextOption = dynamicOption ? dynamicOption.value()[0] : option;
2708
+ payload.values = nextValues;
2709
+ payload.previousValues = previousValues;
2710
+ payload.option = nextOption;
2711
+ payload.previousOption = previousOption;
2712
+ previousValues = nextValues;
2713
+ previousOption = nextOption;
2714
+ mountedUpdate(payload);
2715
+ };
2342
2716
  }
2343
2717
  };
2344
2718
 
@@ -2375,39 +2749,51 @@ var Regor = (() => {
2375
2749
  function includeBooleanAttr(value) {
2376
2750
  return !!value || value === "";
2377
2751
  }
2378
- var attrDirective = {
2379
- onChange: (el, values, previousValues, option, previousOption, flags) => {
2380
- var _a;
2381
- if (option) {
2382
- if (flags && flags.includes("camel")) option = camelize(option);
2383
- patchAttribute(el, option, values[0], previousOption);
2384
- return;
2385
- }
2386
- const len = values.length;
2387
- for (let i = 0; i < len; ++i) {
2388
- const next = values[i];
2389
- if (isArray(next)) {
2390
- const previousKey = (_a = previousValues == null ? void 0 : previousValues[i]) == null ? void 0 : _a[0];
2391
- const key = next[0];
2392
- const value = next[1];
2393
- patchAttribute(el, key, value, previousKey);
2394
- } else if (isObject(next)) {
2395
- for (const item of Object.entries(next)) {
2396
- const key = item[0];
2397
- const value = item[1];
2398
- const p = previousValues == null ? void 0 : previousValues[i];
2399
- const previousKey = p && key in p ? key : void 0;
2400
- patchAttribute(el, key, value, previousKey);
2401
- }
2402
- } else {
2403
- const previousKey = previousValues == null ? void 0 : previousValues[i];
2404
- const key = values[i++];
2405
- const value = values[i];
2752
+ var updateAttr = (el, values, previousValues, option, previousOption, flags) => {
2753
+ var _a;
2754
+ if (option) {
2755
+ if (flags && flags.includes("camel")) option = camelize(option);
2756
+ patchAttribute(el, option, values[0], previousOption);
2757
+ return;
2758
+ }
2759
+ const len = values.length;
2760
+ for (let i = 0; i < len; ++i) {
2761
+ const next = values[i];
2762
+ if (isArray(next)) {
2763
+ const previousKey = (_a = previousValues == null ? void 0 : previousValues[i]) == null ? void 0 : _a[0];
2764
+ const key = next[0];
2765
+ const value = next[1];
2766
+ patchAttribute(el, key, value, previousKey);
2767
+ } else if (isObject(next)) {
2768
+ for (const item of Object.entries(next)) {
2769
+ const key = item[0];
2770
+ const value = item[1];
2771
+ const p = previousValues == null ? void 0 : previousValues[i];
2772
+ const previousKey = p && key in p ? key : void 0;
2406
2773
  patchAttribute(el, key, value, previousKey);
2407
2774
  }
2775
+ } else {
2776
+ const previousKey = previousValues == null ? void 0 : previousValues[i];
2777
+ const key = values[i++];
2778
+ const value = values[i];
2779
+ patchAttribute(el, key, value, previousKey);
2408
2780
  }
2409
2781
  }
2410
2782
  };
2783
+ var attrDirective = {
2784
+ mount: () => ({
2785
+ update: ({ el, values, previousValues, option, previousOption, flags }) => {
2786
+ updateAttr(
2787
+ el,
2788
+ values,
2789
+ previousValues,
2790
+ option,
2791
+ previousOption,
2792
+ flags
2793
+ );
2794
+ }
2795
+ })
2796
+ };
2411
2797
  var patchAttribute = (el, key, value, previousKey) => {
2412
2798
  if (previousKey && previousKey !== key) {
2413
2799
  el.removeAttribute(previousKey);
@@ -2441,23 +2827,28 @@ var Regor = (() => {
2441
2827
  };
2442
2828
 
2443
2829
  // src/directives/class.ts
2444
- var classDirective = {
2445
- onChange: (el, values, previousValues) => {
2446
- const len = values.length;
2447
- for (let i = 0; i < len; ++i) {
2448
- const next = values[i];
2449
- const previous = previousValues == null ? void 0 : previousValues[i];
2450
- if (isArray(next)) {
2451
- const len2 = next.length;
2452
- for (let j = 0; j < len2; ++j) {
2453
- patchClass(el, next[j], previous == null ? void 0 : previous[j]);
2454
- }
2455
- } else {
2456
- patchClass(el, next, previous);
2830
+ var updateClass = (el, values, previousValues) => {
2831
+ const len = values.length;
2832
+ for (let i = 0; i < len; ++i) {
2833
+ const next = values[i];
2834
+ const previous = previousValues == null ? void 0 : previousValues[i];
2835
+ if (isArray(next)) {
2836
+ const len2 = next.length;
2837
+ for (let j = 0; j < len2; ++j) {
2838
+ patchClass(el, next[j], previous == null ? void 0 : previous[j]);
2457
2839
  }
2840
+ } else {
2841
+ patchClass(el, next, previous);
2458
2842
  }
2459
2843
  }
2460
2844
  };
2845
+ var classDirective = {
2846
+ mount: () => ({
2847
+ update: ({ el, values, previousValues }) => {
2848
+ updateClass(el, values, previousValues);
2849
+ }
2850
+ })
2851
+ };
2461
2852
  var patchClass = (el, next, prev) => {
2462
2853
  const classList = el.classList;
2463
2854
  const isClassString = isString(next);
@@ -2485,15 +2876,6 @@ var Regor = (() => {
2485
2876
  }
2486
2877
  };
2487
2878
 
2488
- // src/directives/html.ts
2489
- var htmlDirective = {
2490
- onChange: (el, values) => {
2491
- const [value, replacer] = values;
2492
- if (isFunction(replacer)) replacer(el, value);
2493
- else el.innerHTML = value == null ? void 0 : value.toString();
2494
- }
2495
- };
2496
-
2497
2879
  // src/common/looseEqual.ts
2498
2880
  function looseCompareArrays(a, b) {
2499
2881
  if (a.length !== b.length) return false;
@@ -2566,12 +2948,12 @@ var Regor = (() => {
2566
2948
 
2567
2949
  // src/directives/model.ts
2568
2950
  var modelDirective = {
2569
- onChange: (el, values) => {
2570
- updateDomElementValue(el, values[0]);
2571
- },
2572
- onBind: (el, parseResult, _expr, _option, _dynamicOption, flags) => {
2573
- return attachDOMChangeListener(el, parseResult, flags);
2574
- }
2951
+ mount: ({ el, parseResult, flags }) => ({
2952
+ update: ({ values }) => {
2953
+ updateDomElementValue(el, values[0]);
2954
+ },
2955
+ unmount: attachDOMChangeListener(el, parseResult, flags)
2956
+ })
2575
2957
  };
2576
2958
  var updateDomElementValue = (el, value) => {
2577
2959
  const isAnInput = isInput(el);
@@ -2877,66 +3259,75 @@ var Regor = (() => {
2877
3259
  }
2878
3260
  return result;
2879
3261
  };
3262
+ var bindOn = (el, parseResult, option, dynamicOption, flags) => {
3263
+ var _a, _b;
3264
+ if (dynamicOption) {
3265
+ const values2 = parseResult.value();
3266
+ const option2 = unref(dynamicOption.value()[0]);
3267
+ if (!isString(option2)) return () => {
3268
+ };
3269
+ return attachEventListener(
3270
+ el,
3271
+ camelize(option2),
3272
+ () => parseResult.value()[0],
3273
+ (_a = flags == null ? void 0 : flags.join(",")) != null ? _a : values2[1]
3274
+ );
3275
+ } else if (option) {
3276
+ const values2 = parseResult.value();
3277
+ return attachEventListener(
3278
+ el,
3279
+ camelize(option),
3280
+ () => parseResult.value()[0],
3281
+ (_b = flags == null ? void 0 : flags.join(",")) != null ? _b : values2[1]
3282
+ );
3283
+ }
3284
+ const unbinders = [];
3285
+ const unbinder = () => {
3286
+ unbinders.forEach((x) => x());
3287
+ };
3288
+ const values = parseResult.value();
3289
+ const len = values.length;
3290
+ for (let i = 0; i < len; ++i) {
3291
+ let next = values[i];
3292
+ if (isFunction(next)) next = next();
3293
+ if (isObject(next)) {
3294
+ for (const item of Object.entries(next)) {
3295
+ const eventType = item[0];
3296
+ const method = () => {
3297
+ let obj = parseResult.value()[i];
3298
+ if (isFunction(obj)) obj = obj();
3299
+ obj = obj[eventType];
3300
+ if (isFunction(obj)) obj = obj();
3301
+ return obj;
3302
+ };
3303
+ const flags2 = next[eventType + "_flags"];
3304
+ unbinders.push(attachEventListener(el, eventType, method, flags2));
3305
+ }
3306
+ } else {
3307
+ warning(2 /* BindingRequiresObjectExpressions */, "r-on", el);
3308
+ }
3309
+ }
3310
+ return unbinder;
3311
+ };
2880
3312
  var onDirective = {
2881
3313
  isLazy: (i, d) => d === -1 && i % 2 === 0,
2882
3314
  isLazyKey: (key, d) => d === 0 && !key.endsWith("_flags"),
2883
3315
  once: false,
2884
3316
  collectRefObj: true,
2885
- onBind: (el, parseResult, _expr, option, dynamicOption, flags) => {
2886
- var _a, _b;
2887
- if (dynamicOption) {
2888
- const values2 = parseResult.value();
2889
- const option2 = unref(dynamicOption.value()[0]);
2890
- if (!isString(option2)) return () => {
2891
- };
2892
- return attachEventListener(
2893
- el,
2894
- camelize(option2),
2895
- () => parseResult.value()[0],
2896
- (_a = flags == null ? void 0 : flags.join(",")) != null ? _a : values2[1]
2897
- );
2898
- } else if (option) {
2899
- const values2 = parseResult.value();
2900
- return attachEventListener(
2901
- el,
2902
- camelize(option),
2903
- () => parseResult.value()[0],
2904
- (_b = flags == null ? void 0 : flags.join(",")) != null ? _b : values2[1]
2905
- );
2906
- }
2907
- const unbinders = [];
2908
- const unbinder = () => {
2909
- unbinders.forEach((x) => x());
2910
- };
2911
- const values = parseResult.value();
2912
- const len = values.length;
2913
- for (let i = 0; i < len; ++i) {
2914
- let next = values[i];
2915
- if (isFunction(next)) next = next();
2916
- if (isObject(next)) {
2917
- for (const item of Object.entries(next)) {
2918
- const eventType = item[0];
2919
- const method = () => {
2920
- let obj = parseResult.value()[i];
2921
- if (isFunction(obj)) obj = obj();
2922
- obj = obj[eventType];
2923
- if (isFunction(obj)) obj = obj();
2924
- return obj;
2925
- };
2926
- const flags2 = next[eventType + "_flags"];
2927
- unbinders.push(attachEventListener(el, eventType, method, flags2));
2928
- }
2929
- } else {
2930
- warning(2 /* BindingRequiresObjectExpressions */, "r-on", el);
2931
- }
2932
- }
2933
- return unbinder;
3317
+ mount: ({ el, parseResult, option, dynamicOption, flags }) => {
3318
+ return bindOn(
3319
+ el,
3320
+ parseResult,
3321
+ option,
3322
+ dynamicOption,
3323
+ flags
3324
+ );
2934
3325
  }
2935
3326
  };
2936
3327
  var getShouldExecuteEvent = (eventType, flags) => {
2937
3328
  if (eventType.startsWith("keydown") || eventType.startsWith("keyup") || eventType.startsWith("keypress")) {
2938
3329
  flags != null ? flags : flags = "";
2939
- const parts = eventType.split(".").concat(flags.split(","));
3330
+ const parts = [...eventType.split("."), ...flags.split(",")];
2940
3331
  eventType = parts[0];
2941
3332
  const keyType = parts[1];
2942
3333
  const isCtrl = parts.includes("ctrl");
@@ -3009,34 +3400,39 @@ var Regor = (() => {
3009
3400
  };
3010
3401
 
3011
3402
  // src/directives/prop.ts
3012
- var propDirective = {
3013
- onChange: (el, values, _previousValues, option, _previousOption, flags) => {
3014
- if (option) {
3015
- if (flags && flags.includes("camel")) option = camelize(option);
3016
- patchProp(el, option, values[0]);
3017
- return;
3018
- }
3019
- const len = values.length;
3020
- for (let i = 0; i < len; ++i) {
3021
- const next = values[i];
3022
- if (isArray(next)) {
3023
- const key = next[0];
3024
- const value = next[1];
3025
- patchProp(el, key, value);
3026
- } else if (isObject(next)) {
3027
- for (const item of Object.entries(next)) {
3028
- const key = item[0];
3029
- const value = item[1];
3030
- patchProp(el, key, value);
3031
- }
3032
- } else {
3033
- const key = values[i++];
3034
- const value = values[i];
3403
+ var updatePropBinding = (el, values, option, flags) => {
3404
+ if (option) {
3405
+ if (flags && flags.includes("camel")) option = camelize(option);
3406
+ patchProp(el, option, values[0]);
3407
+ return;
3408
+ }
3409
+ const len = values.length;
3410
+ for (let i = 0; i < len; ++i) {
3411
+ const next = values[i];
3412
+ if (isArray(next)) {
3413
+ const key = next[0];
3414
+ const value = next[1];
3415
+ patchProp(el, key, value);
3416
+ } else if (isObject(next)) {
3417
+ for (const item of Object.entries(next)) {
3418
+ const key = item[0];
3419
+ const value = item[1];
3035
3420
  patchProp(el, key, value);
3036
3421
  }
3422
+ } else {
3423
+ const key = values[i++];
3424
+ const value = values[i];
3425
+ patchProp(el, key, value);
3037
3426
  }
3038
3427
  }
3039
3428
  };
3429
+ var propDirective = {
3430
+ mount: () => ({
3431
+ update: ({ el, values, option, flags }) => {
3432
+ updatePropBinding(el, values, option, flags);
3433
+ }
3434
+ })
3435
+ };
3040
3436
  function includeBooleanAttr2(value) {
3041
3437
  return !!value || value === "";
3042
3438
  }
@@ -3091,7 +3487,8 @@ var Regor = (() => {
3091
3487
  // src/directives/ref.ts
3092
3488
  var refDirective = {
3093
3489
  once: true,
3094
- onBind: (el, result, expr) => {
3490
+ mount: ({ el, parseResult, expr }) => {
3491
+ const result = parseResult;
3095
3492
  const value = result.value()[0];
3096
3493
  const isAnArray = isArray(value);
3097
3494
  const sref2 = result.refs[0];
@@ -3108,37 +3505,47 @@ var Regor = (() => {
3108
3505
  };
3109
3506
 
3110
3507
  // src/directives/show.ts
3508
+ var updateShow = (el, values) => {
3509
+ const data = getBindData(el).data;
3510
+ let originalDisplay = data._ord;
3511
+ if (isUndefined(originalDisplay)) {
3512
+ originalDisplay = data._ord = el.style.display;
3513
+ }
3514
+ const isVisible = !!values[0];
3515
+ if (isVisible) el.style.display = originalDisplay;
3516
+ else el.style.display = "none";
3517
+ };
3111
3518
  var showDirective = {
3112
- onChange: (el, values) => {
3113
- const data = getBindData(el).data;
3114
- let originalDisplay = data._ord;
3115
- if (isUndefined(originalDisplay)) {
3116
- originalDisplay = data._ord = el.style.display;
3519
+ mount: () => ({
3520
+ update: ({ el, values }) => {
3521
+ updateShow(el, values);
3117
3522
  }
3118
- const isVisible = !!values[0];
3119
- if (isVisible) el.style.display = originalDisplay;
3120
- else el.style.display = "none";
3121
- }
3523
+ })
3122
3524
  };
3123
3525
 
3124
3526
  // src/directives/style.ts
3125
- var styleDirective = {
3126
- onChange: (el, values, previousValues) => {
3127
- const len = values.length;
3128
- for (let i = 0; i < len; ++i) {
3129
- const next = values[i];
3130
- const previous = previousValues == null ? void 0 : previousValues[i];
3131
- if (isArray(next)) {
3132
- const len2 = next.length;
3133
- for (let j = 0; j < len2; ++j) {
3134
- patchStyle(el, next[j], previous == null ? void 0 : previous[j]);
3135
- }
3136
- } else {
3137
- patchStyle(el, next, previous);
3527
+ var updateStyle = (el, values, previousValues) => {
3528
+ const len = values.length;
3529
+ for (let i = 0; i < len; ++i) {
3530
+ const next = values[i];
3531
+ const previous = previousValues == null ? void 0 : previousValues[i];
3532
+ if (isArray(next)) {
3533
+ const len2 = next.length;
3534
+ for (let j = 0; j < len2; ++j) {
3535
+ patchStyle(el, next[j], previous == null ? void 0 : previous[j]);
3138
3536
  }
3537
+ } else {
3538
+ patchStyle(el, next, previous);
3139
3539
  }
3140
3540
  }
3141
3541
  };
3542
+ var styleDirective = {
3543
+ mount: () => ({
3544
+ update: ({ el, values, previousValues }) => {
3545
+ updateStyle(el, values, previousValues);
3546
+ }
3547
+ })
3548
+ };
3142
3549
  var patchStyle = (el, next, prev) => {
3143
3550
  const style = el.style;
3144
3551
  const isCssString = isString(next);
@@ -3246,19 +3653,26 @@ var Regor = (() => {
3246
3653
  };
3247
3654
 
3248
3655
  // src/directives/text.ts
3656
+ var updateText = (el, values) => {
3657
+ var _a;
3658
+ const value = values[0];
3659
+ el.textContent = isSet(value) ? JSON.stringify(flatten([...value])) : isMap(value) ? JSON.stringify(flatten([...value])) : isObject(value) ? JSON.stringify(flatten(value)) : (_a = value == null ? void 0 : value.toString()) != null ? _a : "";
3660
+ };
3249
3661
  var textDirective = {
3250
- onChange: (el, values) => {
3251
- var _a;
3252
- const value = values[0];
3253
- el.textContent = isSet(value) ? JSON.stringify(flatten([...value])) : isMap(value) ? JSON.stringify(flatten([...value])) : isObject(value) ? JSON.stringify(flatten(value)) : (_a = value == null ? void 0 : value.toString()) != null ? _a : "";
3254
- }
3662
+ mount: () => ({
3663
+ update: ({ el, values }) => {
3664
+ updateText(el, values);
3665
+ }
3666
+ })
3255
3667
  };
3256
3668
 
3257
3669
  // src/directives/value.ts
3258
3670
  var valueDirective = {
3259
- onChange: (el, values) => {
3260
- patchProp(el, "value", values[0]);
3261
- }
3671
+ mount: () => ({
3672
+ update: ({ el, values }) => {
3673
+ patchProp(el, "value", values[0]);
3674
+ }
3675
+ })
3262
3676
  };
3263
3677
 
3264
3678
  // src/app/RegorConfig.ts
@@ -3347,6 +3761,7 @@ var Regor = (() => {
3347
3761
  [`${prefix}show`]: showDirective,
3348
3762
  [`${prefix}model`]: modelDirective,
3349
3763
  ":style": styleDirective,
3764
+ [`${prefix}style`]: styleDirective,
3350
3765
  [`${prefix}bind:style`]: styleDirective,
3351
3766
  ":class": classDirective,
3352
3767
  [`${prefix}bind:class`]: classDirective,
@@ -3362,8 +3777,8 @@ var Regor = (() => {
3362
3777
  pre: `${prefix}pre`,
3363
3778
  inherit: `${prefix}inherit`,
3364
3779
  text: `${prefix}text`,
3365
- props: ":props",
3366
- propsOnce: ":props-once",
3780
+ context: ":context",
3781
+ contextAlias: `${prefix}context`,
3367
3782
  bind: `${prefix}bind`,
3368
3783
  on: `${prefix}on`,
3369
3784
  keyBind: ":key",
@@ -5073,6 +5488,7 @@ var Regor = (() => {
5073
5488
 
5074
5489
  // src/parser/Parser.ts
5075
5490
  var astCache = {};
5491
+ var isComponentMap = (value) => !!value;
5076
5492
  var Parser = class {
5077
5493
  constructor(contexts, config) {
5078
5494
  __publicField(this, "__contexts");
@@ -5085,7 +5501,7 @@ var Regor = (() => {
5085
5501
  this.__contexts = [context, ...this.__contexts];
5086
5502
  }
5087
5503
  __getComponents() {
5088
- const obj = this.__contexts.map((x) => x.components).filter((x) => !!x).reverse().reduce((p, c) => {
5504
+ const obj = this.__contexts.map((x) => x.components).filter(isComponentMap).reverse().reduce((p, c) => {
5089
5505
  for (const [key, value] of Object.entries(c)) {
5090
5506
  p[key.toUpperCase()] = value;
5091
5507
  }
@@ -5096,7 +5512,7 @@ var Regor = (() => {
5096
5512
  __getComponentSelectors() {
5097
5513
  const selectors = [];
5098
5514
  const seen = /* @__PURE__ */ new Set();
5099
- const componentsList = this.__contexts.map((x) => x.components).filter((x) => !!x).reverse();
5515
+ const componentsList = this.__contexts.map((x) => x.components).filter(isComponentMap).reverse();
5100
5516
  for (const components of componentsList) {
5101
5517
  for (const key of Object.keys(components)) {
5102
5518
  if (seen.has(key)) continue;
@@ -5108,12 +5524,12 @@ var Regor = (() => {
5108
5524
  }
5109
5525
  __parse(expression, isLazy, isLazyKey, collectRefObj, once) {
5110
5526
  var _a;
5111
- const value = sref([]);
5527
+ let currentValues = [];
5112
5528
  const stopObserverList = [];
5113
5529
  const subscribers = /* @__PURE__ */ new Set();
5114
5530
  const clearObservers = () => {
5115
- for (const stopObserver of stopObserverList) {
5116
- stopObserver();
5531
+ for (let i = 0; i < stopObserverList.length; ++i) {
5532
+ stopObserverList[i]();
5117
5533
  }
5118
5534
  stopObserverList.length = 0;
5119
5535
  };
@@ -5123,13 +5539,13 @@ var Regor = (() => {
5123
5539
  };
5124
5540
  const subscribe = (observer, init) => {
5125
5541
  subscribers.add(observer);
5126
- if (init) observer(value());
5542
+ if (init) observer(currentValues);
5127
5543
  return () => {
5128
5544
  subscribers.delete(observer);
5129
5545
  };
5130
5546
  };
5131
5547
  const result = {
5132
- value,
5548
+ value: () => currentValues,
5133
5549
  stop: unbinder,
5134
5550
  subscribe,
5135
5551
  refs: [],
@@ -5150,7 +5566,7 @@ var Regor = (() => {
5150
5566
  context,
5151
5567
  collectRefObj
5152
5568
  );
5153
- if (collectRefs2) refs.push(...r.refs);
5569
+ if (collectRefs2 && r.refs.length > 0) refs.push(...r.refs);
5154
5570
  return { value: r.value, refs: r.refs, ref: r.ref };
5155
5571
  } catch (e) {
5156
5572
  warning(6 /* ErrorLog */, `evaluation error: ${expression}`, e);
@@ -5163,36 +5579,37 @@ var Regor = (() => {
5163
5579
  const contexts = this.__contexts.slice();
5164
5580
  const elements = ast.elements;
5165
5581
  const len = elements.length;
5582
+ const expressionRefs = new Array(len);
5583
+ result.refs = expressionRefs;
5166
5584
  const refresh = () => {
5167
5585
  refs.length = 0;
5168
- uniqueRefs.clear();
5169
- clearObservers();
5170
- const values = new Array(len);
5171
- const expressionRefs = new Array(len);
5586
+ if (!once) {
5587
+ uniqueRefs.clear();
5588
+ clearObservers();
5589
+ }
5590
+ const nextValues = new Array(len);
5172
5591
  for (let i = 0; i < len; ++i) {
5173
5592
  const expr = elements[i];
5174
5593
  if (isLazy == null ? void 0 : isLazy(i, -1)) {
5175
- values[i] = (e) => evaluate(expr, contexts, false, { $event: e }).value;
5594
+ nextValues[i] = (e) => evaluate(expr, contexts, false, { $event: e }).value;
5176
5595
  continue;
5177
5596
  }
5178
5597
  const evaluated = evaluate(expr, contexts, true);
5179
- values[i] = evaluated.value;
5598
+ nextValues[i] = evaluated.value;
5180
5599
  expressionRefs[i] = evaluated.ref;
5181
5600
  }
5182
5601
  if (!once) {
5183
5602
  for (const r of refs) {
5184
5603
  if (uniqueRefs.has(r)) continue;
5185
5604
  uniqueRefs.add(r);
5186
- const stopObserving = observe(r, refresh);
5187
- stopObserverList.push(stopObserving);
5605
+ stopObserverList.push(observe(r, refresh));
5188
5606
  }
5189
5607
  }
5190
- result.refs = expressionRefs;
5191
- value(values);
5608
+ currentValues = nextValues;
5192
5609
  if (subscribers.size !== 0) {
5193
5610
  for (const subscriber of subscribers) {
5194
5611
  if (!subscribers.has(subscriber)) continue;
5195
- subscriber(values);
5612
+ subscriber(currentValues);
5196
5613
  }
5197
5614
  }
5198
5615
  };