@estjs/template 0.0.16-beta.1 → 0.0.16-beta.3

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.
@@ -1,5 +1,5 @@
1
- import { getActiveScope, runWithScope, onCleanup, __objRest, createScope, disposeScope, __async } from './chunk-3E4EK64L.dev.esm.js';
2
- import { normalizeClassName, isObject, warn, isSpecialBooleanAttr, isBooleanAttr, includeBooleanAttr, isSymbol, isString, isArray, camelCase, capitalize, isBrowser, error, isPromise, isFunction, isOn, isNull, isUndefined, isNumber, isBoolean, coerceArray, isHTMLElement, isPrimitive, isFalsy } from '@estjs/shared';
1
+ import { getActiveScope, runWithScope, onCleanup, __objRest, createScope, disposeScope, __async } from './chunk-JT6RSDKI.dev.esm.js';
2
+ import { normalizeClassName, isObject, warn, isSpecialBooleanAttr, isBooleanAttr, includeBooleanAttr, isSymbol, isString, isArray, camelCase, capitalize, isBrowser, error, isPromise, isFunction, isOn, coerceArray } from '@estjs/shared';
3
3
  import { effect, shallowReactive, isSignal, isComputed, signal } from '@estjs/signals';
4
4
 
5
5
  // src/constants.ts
@@ -59,7 +59,7 @@ function patchAttr(el, key, prev, next2) {
59
59
  const elementIsSVG = (el == null ? void 0 : el.namespaceURI) === SVG_NAMESPACE;
60
60
  const isXlink = elementIsSVG && key.startsWith("xlink:");
61
61
  const isXmlns = elementIsSVG && key.startsWith("xmlns:");
62
- const isBoolean2 = isSpecialBooleanAttr(key) || isBooleanAttr(key);
62
+ const isBoolean = isSpecialBooleanAttr(key) || isBooleanAttr(key);
63
63
  if (prev === next2) {
64
64
  return;
65
65
  }
@@ -84,7 +84,7 @@ function patchAttr(el, key, prev, next2) {
84
84
  }
85
85
  return;
86
86
  }
87
- if (isBoolean2) {
87
+ if (isBoolean) {
88
88
  if (includeBooleanAttr(next2)) {
89
89
  el.setAttribute(key, "");
90
90
  } else {
@@ -528,22 +528,30 @@ function insertNode(parent, child2, before) {
528
528
  }
529
529
  }
530
530
  function normalizeNode(node) {
531
- if (isHTMLElement(node)) {
532
- return node;
533
- }
534
- if (isPrimitive(node)) {
535
- return document.createTextNode(isFalsy(node) ? "" : String(node));
531
+ if (node instanceof Node) return node;
532
+ if (isComponent(node)) return node;
533
+ const t = typeof node;
534
+ if (node == null || t === "string" || t === "number" || t === "boolean" || t === "symbol") {
535
+ return document.createTextNode(node === false || node == null ? "" : String(node));
536
+ }
537
+ if (isObject(node)) {
538
+ warn(
539
+ "Rendering a plain object as a node is not recommended. The object will be converted to its string representation.",
540
+ node
541
+ );
536
542
  }
537
- return node;
543
+ return document.createTextNode(String(node));
538
544
  }
539
545
  function insert(parent, nodeFactory, before) {
540
546
  if (!parent) return;
541
- const ownerScope = getActiveScope();
547
+ const parentScope = getActiveScope();
542
548
  let renderedNodes = [];
543
549
  let isFirstRun = true;
544
550
  const resolveNodes = (raw) => {
545
551
  if (raw instanceof Node) return [raw];
546
- if (isNull(raw) || isUndefined(raw) || isString(raw) || isNumber(raw) || isBoolean(raw)) {
552
+ if (isComponent(raw)) return [raw];
553
+ const t = typeof raw;
554
+ if (raw == null || t === "string" || t === "number" || t === "boolean") {
547
555
  return [normalizeNode(raw)];
548
556
  }
549
557
  return coerceArray(raw).map((item) => isFunction(item) ? item() : item).flatMap((i) => i).map(normalizeNode);
@@ -560,8 +568,8 @@ function insert(parent, nodeFactory, before) {
560
568
  renderedNodes = reconcileArrays(parent, renderedNodes, nodes, before);
561
569
  isFirstRun = false;
562
570
  };
563
- if (ownerScope && !ownerScope.isDestroyed) {
564
- runWithScope(ownerScope, executeUpdate);
571
+ if (parentScope && !parentScope.isDestroyed) {
572
+ runWithScope(parentScope, executeUpdate);
565
573
  } else {
566
574
  executeUpdate();
567
575
  }
@@ -762,7 +770,9 @@ var Component = class {
762
770
  if (isFunction(result)) {
763
771
  result = result(this.reactiveProps);
764
772
  }
765
- if (isSignal(result) || isComputed(result)) {
773
+ if (isSignal(result)) {
774
+ result = result.value;
775
+ } else if (isComputed(result)) {
766
776
  result = result.value;
767
777
  }
768
778
  return (_a3 = insert(parentNode, result, beforeNode)) != null ? _a3 : [];
@@ -863,11 +873,12 @@ var Component = class {
863
873
  return () => value(null);
864
874
  }
865
875
  if (isSignal(value)) {
866
- const previousValue = value.value;
867
- value.value = root;
876
+ const ref = value;
877
+ const previousValue = ref.value;
878
+ ref.value = root;
868
879
  return () => {
869
- if (value.value === root) {
870
- value.value = previousValue;
880
+ if (ref.value === root) {
881
+ ref.value = previousValue;
871
882
  }
872
883
  };
873
884
  }
@@ -1082,154 +1093,144 @@ function addEventListener(element, event, handler, options) {
1082
1093
  }
1083
1094
 
1084
1095
  // src/binding.ts
1085
- var INPUT_CHECKBOX_CHECKED = {
1096
+ function writeValue(el, v) {
1097
+ const target = el;
1098
+ const next2 = v == null ? "" : String(v);
1099
+ if (target.value !== next2) target.value = next2;
1100
+ }
1101
+ var CHECKBOX = {
1086
1102
  event: "change",
1087
- forceChangeEvent: true,
1088
- read: (n) => n.checked,
1089
- write: (n, v) => {
1090
- const el = n;
1103
+ forceChange: true,
1104
+ read: (el) => el.checked,
1105
+ write(el, v) {
1106
+ const e = el;
1091
1107
  const next2 = Boolean(v);
1092
- if (el.checked !== next2) el.checked = next2;
1108
+ if (e.checked !== next2) e.checked = next2;
1093
1109
  }
1094
1110
  };
1095
- var INPUT_RADIO_CHECKED = {
1111
+ var RADIO = {
1096
1112
  event: "change",
1097
- forceChangeEvent: true,
1098
- read: (n) => {
1099
- const el = n;
1100
- return el.checked ? el.value : "";
1113
+ forceChange: true,
1114
+ read(el) {
1115
+ const e = el;
1116
+ return e.checked ? e.value : "";
1101
1117
  },
1102
- write: (n, v) => {
1103
- const el = n;
1104
- const next2 = String(v) === el.value;
1105
- if (el.checked !== next2) el.checked = next2;
1118
+ write(el, v) {
1119
+ const e = el;
1120
+ const next2 = String(v) === e.value;
1121
+ if (e.checked !== next2) e.checked = next2;
1106
1122
  }
1107
1123
  };
1108
- var INPUT_FILE_FILES = {
1124
+ var FILE = {
1109
1125
  event: "change",
1110
- forceChangeEvent: true,
1111
- read: (n) => n.files,
1112
- // Browsers do not allow programmatic writes to <input type="file">.
1113
- write: () => {
1126
+ forceChange: true,
1127
+ read: (el) => el.files,
1128
+ write() {
1114
1129
  }
1130
+ // browsers forbid programmatic writes to file inputs
1115
1131
  };
1116
- var INPUT_VALUE = {
1132
+ var TEXT = {
1117
1133
  event: "input",
1118
- needsComposition: true,
1119
- read: (n) => n.value,
1120
- write: (n, v) => {
1121
- const el = n;
1122
- const next2 = v == null ? "" : String(v);
1123
- if (el.value !== next2) el.value = next2;
1124
- }
1134
+ ime: true,
1135
+ read: (el) => el.value,
1136
+ write: writeValue
1125
1137
  };
1126
- var SELECT_VALUE = {
1138
+ var TEXTAREA = {
1139
+ event: "input",
1140
+ ime: true,
1141
+ read: (el) => el.value,
1142
+ write: writeValue
1143
+ };
1144
+ var SELECT = {
1127
1145
  event: "change",
1128
- forceChangeEvent: true,
1129
- read: (n) => {
1130
- const s = n;
1146
+ forceChange: true,
1147
+ read(el) {
1148
+ const s = el;
1131
1149
  return s.multiple ? Array.from(s.selectedOptions, (o) => o.value) : s.value;
1132
1150
  },
1133
- write: (n, v) => {
1134
- const s = n;
1151
+ write(el, v) {
1152
+ const s = el;
1135
1153
  if (s.multiple) {
1136
- const set = new Set((Array.isArray(v) ? v : []).map(String));
1137
- for (const opt of Array.from(s.options)) opt.selected = set.has(opt.value);
1154
+ const selected = new Set((Array.isArray(v) ? v : []).map(String));
1155
+ for (const opt of Array.from(s.options)) opt.selected = selected.has(opt.value);
1138
1156
  } else {
1139
- const next2 = v == null ? "" : String(v);
1140
- if (s.value !== next2) s.value = next2;
1157
+ writeValue(el, v);
1141
1158
  }
1142
1159
  }
1143
1160
  };
1144
- var TEXTAREA_VALUE = {
1145
- event: "input",
1146
- needsComposition: true,
1147
- read: (n) => n.value,
1148
- write: (n, v) => {
1149
- const el = n;
1150
- const next2 = v == null ? "" : String(v);
1151
- if (el.value !== next2) el.value = next2;
1161
+ function resolve(node, prop) {
1162
+ switch (node.nodeName) {
1163
+ case "INPUT":
1164
+ if (prop === "checked") return node.type === "radio" ? RADIO : CHECKBOX;
1165
+ if (prop === "files") return FILE;
1166
+ return TEXT;
1167
+ case "SELECT":
1168
+ return SELECT;
1169
+ case "TEXTAREA":
1170
+ return TEXTAREA;
1171
+ default:
1172
+ return {
1173
+ event: "input",
1174
+ read: (el) => el[prop],
1175
+ write(el, v) {
1176
+ el[prop] = v;
1177
+ }
1178
+ };
1152
1179
  }
1153
- };
1154
- function resolveStrategy(node, prop) {
1155
- const tag = node.nodeName;
1156
- if (tag === "INPUT") {
1157
- const type = node.type;
1158
- if (prop === "checked") {
1159
- return type === "radio" ? INPUT_RADIO_CHECKED : INPUT_CHECKBOX_CHECKED;
1160
- }
1161
- if (prop === "files") return INPUT_FILE_FILES;
1162
- return INPUT_VALUE;
1163
- }
1164
- if (tag === "SELECT") return SELECT_VALUE;
1165
- if (tag === "TEXTAREA") return TEXTAREA_VALUE;
1166
- return {
1167
- event: "input",
1168
- read: (n) => n[prop],
1169
- write: (n, v) => {
1170
- n[prop] = v;
1171
- }
1172
- };
1173
1180
  }
1174
- function castValue(val, trim, number) {
1175
- if (!isString(val)) return val;
1176
- if (trim) val = val.trim();
1177
- if (number && val !== "") {
1178
- const parsed = Number(val);
1179
- if (!Number.isNaN(parsed)) return parsed;
1181
+ function applyModifiers(v, trim, toNum) {
1182
+ if (!isString(v)) return v;
1183
+ let s = v;
1184
+ if (trim) s = s.trim();
1185
+ if (toNum && s !== "") {
1186
+ const n = Number(s);
1187
+ if (!Number.isNaN(n)) return n;
1180
1188
  }
1181
- return val;
1189
+ return s;
1182
1190
  }
1183
- function isFocused(node) {
1184
- const root = node.getRootNode();
1185
- return (root instanceof Document || root instanceof ShadowRoot) && root.activeElement === node;
1191
+ function isFocused(el) {
1192
+ const root = el.getRootNode();
1193
+ return (root instanceof Document || root instanceof ShadowRoot) && root.activeElement === el;
1186
1194
  }
1187
1195
  function bindElement(node, prop, getter, setter, modifiers = {}) {
1188
1196
  if (!node) return;
1189
- const strategy = resolveStrategy(node, prop);
1190
- const { trim, number, lazy } = modifiers;
1191
- const isFiles = prop === "files";
1192
- const readModel = () => isFunction(getter) ? getter() : getter;
1193
- const transform = (v) => isFiles ? v : castValue(v, trim, number);
1194
- const eventName = lazy || strategy.forceChangeEvent ? "change" : strategy.event;
1197
+ const { event, read, write, forceChange, ime } = resolve(node, prop);
1198
+ const trim = modifiers.trim === true;
1199
+ const toNum = modifiers.number === true;
1200
+ const lazy = modifiers.lazy === true;
1201
+ const shouldCast = (trim || toNum) && prop !== "files";
1202
+ const getModel = isFunction(getter) ? getter : () => getter;
1203
+ const cast = shouldCast ? (v) => applyModifiers(v, trim, toNum) : (v) => v;
1195
1204
  let composing = false;
1196
- const syncFromDom = () => {
1205
+ const eventName = lazy || forceChange ? "change" : event;
1206
+ const syncToModel = () => {
1197
1207
  if (composing) return;
1198
- const raw = strategy.read(node);
1208
+ const raw = read(node);
1199
1209
  if (raw === void 0) return;
1200
- if (isFiles) {
1201
- setter(raw);
1202
- return;
1203
- }
1204
- const next2 = transform(raw);
1205
- if (!Object.is(readModel(), next2)) {
1206
- setter(next2);
1207
- }
1210
+ const next2 = cast(raw);
1211
+ if (!Object.is(getModel(), next2)) setter(next2);
1208
1212
  };
1209
- addEventListener(node, eventName, syncFromDom);
1210
- if (!lazy && !isFiles && (trim || number) && eventName !== "change") {
1211
- addEventListener(node, "change", () => {
1212
- strategy.write(node, transform(strategy.read(node)));
1213
- });
1213
+ addEventListener(node, eventName, syncToModel);
1214
+ if (!lazy && shouldCast && eventName !== "change") {
1215
+ addEventListener(node, "change", () => write(node, cast(read(node))));
1214
1216
  }
1215
- if (strategy.needsComposition && !lazy) {
1217
+ if (ime && !lazy) {
1216
1218
  addEventListener(node, "compositionstart", () => {
1217
1219
  composing = true;
1218
1220
  });
1219
1221
  addEventListener(node, "compositionend", () => {
1220
1222
  if (!composing) return;
1221
1223
  composing = false;
1222
- syncFromDom();
1224
+ syncToModel();
1223
1225
  });
1224
1226
  }
1225
1227
  const runner = effect(() => {
1226
- const value = readModel();
1227
- if (strategy.needsComposition && !lazy && isFocused(node)) {
1228
+ const value = getModel();
1229
+ if (ime && !lazy && isFocused(node)) {
1228
1230
  if (composing) return;
1229
- const current = transform(strategy.read(node));
1230
- if (Object.is(current, value)) return;
1231
+ if (Object.is(cast(read(node)), value)) return;
1231
1232
  }
1232
- strategy.write(node, value);
1233
+ write(node, value);
1233
1234
  });
1234
1235
  if (getActiveScope()) {
1235
1236
  onCleanup(() => runner.stop());
@@ -1303,10 +1304,10 @@ function Portal(props) {
1303
1304
  placeholder[PORTAL_COMPONENT] = true;
1304
1305
  const { children } = props;
1305
1306
  if (children == null) return placeholder;
1306
- const ownerScope = getActiveScope();
1307
+ const parentScope = getActiveScope();
1307
1308
  let innerScope = null;
1308
1309
  const mountAt = (parent, before) => {
1309
- innerScope = createScope(ownerScope);
1310
+ innerScope = createScope(parentScope);
1310
1311
  runWithScope(innerScope, () => {
1311
1312
  insert(parent, () => children, before);
1312
1313
  });