sibujs 3.2.2 → 3.3.1

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.
Files changed (60) hide show
  1. package/dist/browser.cjs +217 -27
  2. package/dist/browser.js +5 -5
  3. package/dist/build.cjs +236 -105
  4. package/dist/build.js +14 -14
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-5N74TKLD.js → chunk-37BUKSLH.js} +1 -1
  7. package/dist/{chunk-BGNLPNGV.js → chunk-4UUMSLSL.js} +4 -4
  8. package/dist/{chunk-2UPRY23K.js → chunk-5VGSK6D2.js} +1 -1
  9. package/dist/{chunk-OYLPZO4N.js → chunk-6LTFHJQG.js} +4 -4
  10. package/dist/{chunk-VOCE4NNK.js → chunk-AMIKDMLP.js} +5 -5
  11. package/dist/{chunk-LMLD24FC.js → chunk-COY6PUD2.js} +7 -1
  12. package/dist/{chunk-YFDGQWDA.js → chunk-F7FXQ3QS.js} +1 -1
  13. package/dist/{chunk-V2MTG5FT.js → chunk-IKLYI3RF.js} +33 -16
  14. package/dist/{chunk-HMJFCBRR.js → chunk-L3GAGWCC.js} +10 -1
  15. package/dist/{chunk-X67UYC74.js → chunk-LU2MQXQQ.js} +14 -24
  16. package/dist/{chunk-4JCAUOLN.js → chunk-M5KBNOSJ.js} +22 -12
  17. package/dist/{chunk-FDY42FIU.js → chunk-MHBCEJQO.js} +2 -2
  18. package/dist/{chunk-RLUJL2MV.js → chunk-NHKQKKZU.js} +6 -7
  19. package/dist/{chunk-HXMS4SNP.js → chunk-R3QEDXFS.js} +2 -2
  20. package/dist/{chunk-NPIEEKPT.js → chunk-RYMOSG5B.js} +6 -6
  21. package/dist/{chunk-H6PCHJZQ.js → chunk-SLMFA3ZZ.js} +11 -3
  22. package/dist/{chunk-Z2FWAE4B.js → chunk-TEFZT5PJ.js} +84 -16
  23. package/dist/{chunk-7XDYVJLE.js → chunk-ULLTNDRA.js} +6 -6
  24. package/dist/{chunk-GOUM4JCT.js → chunk-VOVVTOEA.js} +2 -2
  25. package/dist/{chunk-FOI23UJL.js → chunk-WL7BIR6O.js} +1 -1
  26. package/dist/{chunk-JYXOEYI4.js → chunk-WW6DAGGR.js} +5 -5
  27. package/dist/{chunk-C427DVQF.js → chunk-WZG2SZOT.js} +22 -5
  28. package/dist/{chunk-NFYWLRUO.js → chunk-XH2RTYEQ.js} +3 -3
  29. package/dist/{chunk-2C4E3HBM.js → chunk-Z37APKBV.js} +5 -5
  30. package/dist/{chunk-RDRSWYNP.js → chunk-ZUVLC7TM.js} +1 -1
  31. package/dist/data.cjs +168 -24
  32. package/dist/data.js +8 -8
  33. package/dist/devtools.cjs +252 -32
  34. package/dist/devtools.js +7 -7
  35. package/dist/ecosystem.cjs +205 -64
  36. package/dist/ecosystem.js +10 -10
  37. package/dist/extras.cjs +245 -112
  38. package/dist/extras.js +24 -24
  39. package/dist/index.cjs +236 -105
  40. package/dist/index.d.cts +72 -8
  41. package/dist/index.d.ts +72 -8
  42. package/dist/index.js +14 -14
  43. package/dist/motion.cjs +336 -14
  44. package/dist/motion.js +4 -4
  45. package/dist/patterns.cjs +168 -24
  46. package/dist/patterns.js +6 -6
  47. package/dist/performance.cjs +305 -32
  48. package/dist/performance.js +8 -8
  49. package/dist/plugins.cjs +268 -69
  50. package/dist/plugins.js +12 -12
  51. package/dist/{ssr-2QDQ27EV.js → ssr-6D67RAVB.js} +3 -3
  52. package/dist/ssr.cjs +205 -63
  53. package/dist/ssr.js +11 -11
  54. package/dist/testing.cjs +415 -12
  55. package/dist/testing.js +16 -10
  56. package/dist/ui.cjs +248 -36
  57. package/dist/ui.js +9 -9
  58. package/dist/widgets.cjs +176 -26
  59. package/dist/widgets.js +8 -8
  60. package/package.json +1 -1
package/dist/plugins.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  preloadCritical,
19
19
  prerenderRoutes,
20
20
  satisfies
21
- } from "./chunk-RDRSWYNP.js";
21
+ } from "./chunk-ZUVLC7TM.js";
22
22
  import {
23
23
  isUnsafeKey
24
24
  } from "./chunk-H3SRKIYX.js";
@@ -35,35 +35,35 @@ import {
35
35
  } from "./chunk-3JHCYHWN.js";
36
36
  import {
37
37
  span
38
- } from "./chunk-5N74TKLD.js";
38
+ } from "./chunk-37BUKSLH.js";
39
39
  import {
40
40
  escapeScriptJson,
41
41
  isDangerousMetaRefresh,
42
42
  renderToString
43
- } from "./chunk-HXMS4SNP.js";
44
- import "./chunk-X67UYC74.js";
45
- import "./chunk-RLUJL2MV.js";
43
+ } from "./chunk-R3QEDXFS.js";
44
+ import "./chunk-LU2MQXQQ.js";
45
+ import "./chunk-NHKQKKZU.js";
46
46
  import {
47
47
  dispose,
48
48
  registerDisposer
49
- } from "./chunk-2UPRY23K.js";
49
+ } from "./chunk-5VGSK6D2.js";
50
50
  import {
51
51
  isUrlAttribute,
52
52
  sanitizeCSSValue,
53
53
  sanitizeUrl,
54
54
  stripControlChars
55
- } from "./chunk-HMJFCBRR.js";
55
+ } from "./chunk-L3GAGWCC.js";
56
56
  import {
57
57
  effect
58
- } from "./chunk-FDY42FIU.js";
58
+ } from "./chunk-MHBCEJQO.js";
59
59
  import "./chunk-GOJMFRBL.js";
60
60
  import {
61
61
  signal
62
- } from "./chunk-C427DVQF.js";
62
+ } from "./chunk-WZG2SZOT.js";
63
63
  import {
64
64
  track
65
- } from "./chunk-Z2FWAE4B.js";
66
- import "./chunk-LMLD24FC.js";
65
+ } from "./chunk-TEFZT5PJ.js";
66
+ import "./chunk-COY6PUD2.js";
67
67
 
68
68
  // src/plugins/i18n.ts
69
69
  var [currentLocale, setLocaleInternal] = signal("en");
@@ -1800,7 +1800,7 @@ function hydrateRouter(routes, options) {
1800
1800
  if (container && serverState.path) {
1801
1801
  const resolved = resolveServerRoute(serverState.path, routes);
1802
1802
  if (resolved.component) {
1803
- import("./ssr-2QDQ27EV.js").then(({ hydrate }) => {
1803
+ import("./ssr-6D67RAVB.js").then(({ hydrate }) => {
1804
1804
  if (resolved.component) {
1805
1805
  hydrate(resolved.component, container);
1806
1806
  }
@@ -17,10 +17,10 @@ import {
17
17
  ssrSuspense,
18
18
  suspenseSwapScript,
19
19
  trustHTML
20
- } from "./chunk-HXMS4SNP.js";
21
- import "./chunk-HMJFCBRR.js";
20
+ } from "./chunk-R3QEDXFS.js";
21
+ import "./chunk-L3GAGWCC.js";
22
22
  import "./chunk-GOJMFRBL.js";
23
- import "./chunk-LMLD24FC.js";
23
+ import "./chunk-COY6PUD2.js";
24
24
  export {
25
25
  collectStream,
26
26
  deserializeState,
package/dist/ssr.cjs CHANGED
@@ -66,7 +66,13 @@ module.exports = __toCommonJS(ssr_exports);
66
66
 
67
67
  // src/core/dev.ts
68
68
  function isDev() {
69
- return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
69
+ return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
70
+ // The bare `__SIBU_DEV__` is a bundler define that only exists in
71
+ // production builds; under the test runner it is always undefined, so
72
+ // this branch is unreachable here.
73
+ /* v8 ignore next 2 */
74
+ typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
75
+ );
70
76
  }
71
77
  var _isDev = isDev();
72
78
  function devAssert(condition, message) {
@@ -152,7 +158,9 @@ function sanitizeSrcset(value) {
152
158
  }
153
159
  return out.join(", ");
154
160
  }
161
+ var CSS_DANGER_GATE = /[(:@\\]/;
155
162
  function sanitizeCSSValue(value) {
163
+ if (!CSS_DANGER_GATE.test(value)) return value;
156
164
  const decoded = value.replace(/\\([0-9a-fA-F]{1,6})\s?/g, (_m, hex) => {
157
165
  const code2 = Number.parseInt(hex, 16);
158
166
  if (!Number.isFinite(code2) || code2 < 0 || code2 > 1114111) return "";
@@ -182,8 +190,11 @@ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
182
190
  "ping",
183
191
  "data"
184
192
  ]);
185
- function isUrlAttribute(attr) {
186
- return URL_ATTRIBUTES.has(attr.toLowerCase());
193
+ function sanitizeAttributeString(attr, value) {
194
+ const lower = attr.toLowerCase();
195
+ if (lower === "srcset") return sanitizeSrcset(value);
196
+ if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
197
+ return value;
187
198
  }
188
199
 
189
200
  // src/platform/ssr.ts
@@ -603,7 +614,7 @@ function hydrateProgressively(container, islands, options) {
603
614
  }
604
615
  container.setAttribute("data-sibu-hydrated", "progressive");
605
616
  return () => {
606
- for (const cleanup2 of cleanups) cleanup2();
617
+ for (const cleanup3 of cleanups) cleanup3();
607
618
  };
608
619
  }
609
620
  function resetSSRState() {
@@ -696,7 +707,7 @@ function escapeAttr(str) {
696
707
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
697
708
  }
698
709
 
699
- // src/reactivity/track.ts
710
+ // src/reactivity/track-core.ts
700
711
  var _isDev3 = isDev();
701
712
  var POOL_MAX = 4096;
702
713
  var nodePool = [];
@@ -780,6 +791,7 @@ function unlinkSub(node) {
780
791
  else sub2.depsTail = prev;
781
792
  }
782
793
  var currentSubscriber = null;
794
+ var suspendSavedSub = null;
783
795
  var notifyDepth = 0;
784
796
  var pendingQueue = [];
785
797
  var pendingSet = /* @__PURE__ */ new Set();
@@ -791,6 +803,35 @@ function safeInvoke(sub2) {
791
803
  if (_isDev3) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
792
804
  }
793
805
  }
806
+ var suspendDepth = 0;
807
+ var trackingSuspended = false;
808
+ function suspendTracking() {
809
+ if (suspendDepth === 0) {
810
+ suspendSavedSub = currentSubscriber;
811
+ currentSubscriber = null;
812
+ trackingSuspended = true;
813
+ }
814
+ suspendDepth++;
815
+ }
816
+ function resumeTracking() {
817
+ suspendDepth--;
818
+ if (suspendDepth === 0) {
819
+ currentSubscriber = suspendSavedSub;
820
+ suspendSavedSub = null;
821
+ trackingSuspended = false;
822
+ }
823
+ }
824
+ function isTrackingSuspended() {
825
+ return trackingSuspended;
826
+ }
827
+ function untracked(fn) {
828
+ suspendTracking();
829
+ try {
830
+ return fn();
831
+ } finally {
832
+ resumeTracking();
833
+ }
834
+ }
794
835
  var subscriberEpochCounter = 0;
795
836
  function retrack(effectFn, subscriber) {
796
837
  const prev = currentSubscriber;
@@ -900,6 +941,16 @@ function cleanup(subscriber) {
900
941
  var maxSubscriberRepeats = 50;
901
942
  var maxDrainIterations = 1e6;
902
943
  var drainEpoch = 0;
944
+ function setMaxSubscriberRepeats(n) {
945
+ const prev = maxSubscriberRepeats;
946
+ if (Number.isFinite(n) && n > 0) maxSubscriberRepeats = Math.floor(n);
947
+ return prev;
948
+ }
949
+ function setMaxDrainIterations(n) {
950
+ const prev = maxDrainIterations;
951
+ if (Number.isFinite(n) && n > 0) maxDrainIterations = Math.floor(n);
952
+ return prev;
953
+ }
903
954
  function tickRepeat(sub2) {
904
955
  const s2 = sub2;
905
956
  if (s2._runEpoch !== drainEpoch) {
@@ -1048,6 +1099,85 @@ function notifySubscribers(signal2) {
1048
1099
  }
1049
1100
  }
1050
1101
  }
1102
+ function getSubscriberCount(signal2) {
1103
+ return signal2.__sc ?? 0;
1104
+ }
1105
+ function getSubscriberDeps(subscriber) {
1106
+ const sub2 = subscriber;
1107
+ const out = [];
1108
+ let node = sub2.depsHead ?? null;
1109
+ while (node) {
1110
+ if (node.sig) out.push(node.sig);
1111
+ node = node.subNext;
1112
+ }
1113
+ return out;
1114
+ }
1115
+ function forEachSubscriber(signal2, visit) {
1116
+ let node = signal2.subsHead ?? null;
1117
+ while (node) {
1118
+ const s2 = node.sub;
1119
+ if (s2) visit(s2);
1120
+ node = node.sigNext;
1121
+ }
1122
+ }
1123
+
1124
+ // src/reactivity/track.ts
1125
+ var _isDev4 = isDev();
1126
+ var _runtimeVersion = typeof __SIBU_VERSION__ !== "undefined" ? __SIBU_VERSION__ : "dev";
1127
+ var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
1128
+ function resolveReactiveApi() {
1129
+ const g2 = globalThis;
1130
+ const existing = g2[REGISTRY_KEY];
1131
+ if (existing) {
1132
+ if (_isDev4 && !existing.__dupWarned) {
1133
+ existing.__dupWarned = true;
1134
+ devWarn(
1135
+ `Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity still works \u2014 all copies share the first one \u2014 but de-duplicate sibujs in your bundler (e.g. Vite optimizeDeps.exclude: ['sibujs'] or resolve.dedupe: ['sibujs']).`
1136
+ );
1137
+ }
1138
+ return existing;
1139
+ }
1140
+ const local = {
1141
+ suspendTracking,
1142
+ resumeTracking,
1143
+ isTrackingSuspended,
1144
+ untracked,
1145
+ retrack,
1146
+ track,
1147
+ reactiveBinding,
1148
+ recordDependency,
1149
+ cleanup,
1150
+ setMaxSubscriberRepeats,
1151
+ setMaxDrainIterations,
1152
+ drainNotificationQueue,
1153
+ queueSignalNotification,
1154
+ notifySubscribers,
1155
+ getSubscriberCount,
1156
+ getSubscriberDeps,
1157
+ forEachSubscriber,
1158
+ version: _runtimeVersion
1159
+ };
1160
+ g2[REGISTRY_KEY] = local;
1161
+ return local;
1162
+ }
1163
+ var API = resolveReactiveApi();
1164
+ var suspendTracking2 = API.suspendTracking;
1165
+ var resumeTracking2 = API.resumeTracking;
1166
+ var isTrackingSuspended2 = API.isTrackingSuspended;
1167
+ var untracked2 = API.untracked;
1168
+ var retrack2 = API.retrack;
1169
+ var track2 = API.track;
1170
+ var reactiveBinding2 = API.reactiveBinding;
1171
+ var recordDependency2 = API.recordDependency;
1172
+ var cleanup2 = API.cleanup;
1173
+ var setMaxSubscriberRepeats2 = API.setMaxSubscriberRepeats;
1174
+ var setMaxDrainIterations2 = API.setMaxDrainIterations;
1175
+ var drainNotificationQueue2 = API.drainNotificationQueue;
1176
+ var queueSignalNotification2 = API.queueSignalNotification;
1177
+ var notifySubscribers2 = API.notifySubscribers;
1178
+ var getSubscriberCount2 = API.getSubscriberCount;
1179
+ var getSubscriberDeps2 = API.getSubscriberDeps;
1180
+ var forEachSubscriber2 = API.forEachSubscriber;
1051
1181
 
1052
1182
  // src/core/signals/effect.ts
1053
1183
  var _g = globalThis;
@@ -1069,7 +1199,7 @@ function drainReruns(ctx) {
1069
1199
  do {
1070
1200
  ctx.rerunPending = false;
1071
1201
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1072
- retrack(ctx.bodyFn, ctx.subscriber);
1202
+ retrack2(ctx.bodyFn, ctx.subscriber);
1073
1203
  } while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
1074
1204
  if (ctx.rerunPending) {
1075
1205
  ctx.rerunPending = false;
@@ -1098,7 +1228,7 @@ function disposeEffect(ctx) {
1098
1228
  }
1099
1229
  }
1100
1230
  try {
1101
- cleanup(ctx.subscriber);
1231
+ cleanup2(ctx.subscriber);
1102
1232
  } catch (err) {
1103
1233
  if (typeof console !== "undefined") {
1104
1234
  console.warn("[SibuJS effect] dispose threw:", err);
@@ -1143,7 +1273,7 @@ function effect(effectFn, options) {
1143
1273
  try {
1144
1274
  ctx.rerunPending = false;
1145
1275
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1146
- retrack(ctx.bodyFn, sub2);
1276
+ retrack2(ctx.bodyFn, sub2);
1147
1277
  if (ctx.rerunPending) drainReruns(ctx);
1148
1278
  } finally {
1149
1279
  ctx.running = false;
@@ -1159,7 +1289,7 @@ function effect(effectFn, options) {
1159
1289
  ctx.subscriber = sub2;
1160
1290
  ctx.running = true;
1161
1291
  try {
1162
- retrack(ctx.bodyFn, ctx.subscriber);
1292
+ retrack2(ctx.bodyFn, ctx.subscriber);
1163
1293
  if (ctx.rerunPending) drainReruns(ctx);
1164
1294
  } finally {
1165
1295
  ctx.running = false;
@@ -1207,7 +1337,7 @@ function Head(props) {
1207
1337
  const anchor = document.createComment("sibu-head");
1208
1338
  const managedElements = [];
1209
1339
  const effectCleanups = [];
1210
- const cleanup2 = () => {
1340
+ const cleanup3 = () => {
1211
1341
  for (const el of managedElements) {
1212
1342
  if (el.parentNode) el.parentNode.removeChild(el);
1213
1343
  }
@@ -1216,7 +1346,7 @@ function Head(props) {
1216
1346
  effectCleanups.length = 0;
1217
1347
  };
1218
1348
  const apply = () => {
1219
- cleanup2();
1349
+ cleanup3();
1220
1350
  if (props.title) {
1221
1351
  if (typeof props.title === "function") {
1222
1352
  const cleanupFn = effect(() => {
@@ -1337,7 +1467,7 @@ async function generateStaticSite(options) {
1337
1467
  // src/reactivity/batch.ts
1338
1468
  var batchDepth = 0;
1339
1469
  var pendingSignals = /* @__PURE__ */ new Set();
1340
- function batch(fn) {
1470
+ function batchImpl(fn) {
1341
1471
  batchDepth++;
1342
1472
  try {
1343
1473
  return fn();
@@ -1348,25 +1478,45 @@ function batch(fn) {
1348
1478
  }
1349
1479
  }
1350
1480
  }
1351
- function enqueueBatchedSignal(signal2) {
1481
+ function enqueueBatchedSignalImpl(signal2) {
1352
1482
  if (batchDepth === 0) return false;
1353
1483
  pendingSignals.add(signal2);
1354
1484
  return true;
1355
1485
  }
1486
+ function isBatchingImpl() {
1487
+ return batchDepth > 0;
1488
+ }
1356
1489
  function flushBatch() {
1357
1490
  try {
1358
1491
  for (const signal2 of pendingSignals) {
1359
- queueSignalNotification(signal2);
1492
+ queueSignalNotification2(signal2);
1360
1493
  }
1361
1494
  } finally {
1362
1495
  pendingSignals.clear();
1363
1496
  }
1364
- drainNotificationQueue();
1497
+ drainNotificationQueue2();
1498
+ }
1499
+ var BATCH_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.batch.v1");
1500
+ function resolveBatchApi() {
1501
+ const g2 = globalThis;
1502
+ const existing = g2[BATCH_REGISTRY_KEY];
1503
+ if (existing) return existing;
1504
+ const local = {
1505
+ batch: batchImpl,
1506
+ enqueueBatchedSignal: enqueueBatchedSignalImpl,
1507
+ isBatching: isBatchingImpl
1508
+ };
1509
+ g2[BATCH_REGISTRY_KEY] = local;
1510
+ return local;
1365
1511
  }
1512
+ var API2 = resolveBatchApi();
1513
+ var batch = API2.batch;
1514
+ var enqueueBatchedSignal = API2.enqueueBatchedSignal;
1515
+ var isBatching = API2.isBatching;
1366
1516
 
1367
1517
  // src/core/signals/signal.ts
1368
1518
  var _g2 = globalThis;
1369
- var _isDev4 = isDev();
1519
+ var _isDev5 = isDev();
1370
1520
  function signal(initial, options) {
1371
1521
  const state = {
1372
1522
  value: initial,
@@ -1377,11 +1527,11 @@ function signal(initial, options) {
1377
1527
  __activeNode: null,
1378
1528
  __name: void 0
1379
1529
  };
1380
- const debugName = _isDev4 ? options?.name : void 0;
1530
+ const debugName = _isDev5 ? options?.name : void 0;
1381
1531
  const equalsFn = options?.equals;
1382
1532
  if (debugName) state.__name = debugName;
1383
1533
  function get() {
1384
- recordDependency(state);
1534
+ recordDependency2(state);
1385
1535
  return state.value;
1386
1536
  }
1387
1537
  get.__signal = state;
@@ -1394,15 +1544,15 @@ function signal(initial, options) {
1394
1544
  if (equalsFn(prev, newValue)) return;
1395
1545
  state.value = newValue;
1396
1546
  state.__v++;
1397
- if (_isDev4) {
1547
+ if (_isDev5) {
1398
1548
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1399
1549
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
1400
1550
  }
1401
1551
  if (!enqueueBatchedSignal(state)) {
1402
- notifySubscribers(state);
1552
+ notifySubscribers2(state);
1403
1553
  }
1404
1554
  };
1405
- } else if (_isDev4) {
1555
+ } else if (_isDev5) {
1406
1556
  set = (next) => {
1407
1557
  const prev = state.value;
1408
1558
  const newValue = typeof next === "function" ? next(prev) : next;
@@ -1412,7 +1562,7 @@ function signal(initial, options) {
1412
1562
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1413
1563
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
1414
1564
  if (!enqueueBatchedSignal(state)) {
1415
- notifySubscribers(state);
1565
+ notifySubscribers2(state);
1416
1566
  }
1417
1567
  };
1418
1568
  } else {
@@ -1423,11 +1573,11 @@ function signal(initial, options) {
1423
1573
  state.value = newValue;
1424
1574
  state.__v++;
1425
1575
  if (!enqueueBatchedSignal(state)) {
1426
- notifySubscribers(state);
1576
+ notifySubscribers2(state);
1427
1577
  }
1428
1578
  };
1429
1579
  }
1430
- if (_isDev4) {
1580
+ if (_isDev5) {
1431
1581
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1432
1582
  if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
1433
1583
  }
@@ -1581,13 +1731,13 @@ function createMiddlewareChain() {
1581
1731
  }
1582
1732
 
1583
1733
  // src/reactivity/bindAttribute.ts
1584
- var _isDev5 = isDev();
1734
+ var _isDev6 = isDev();
1585
1735
  function setProp(el, key, val) {
1586
1736
  el[key] = val;
1587
1737
  }
1588
1738
  function bindAttribute(el, attr, getter) {
1589
1739
  if (isEventHandlerAttr(attr)) {
1590
- if (_isDev5)
1740
+ if (_isDev6)
1591
1741
  devWarn(
1592
1742
  `bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
1593
1743
  );
@@ -1599,7 +1749,7 @@ function bindAttribute(el, attr, getter) {
1599
1749
  try {
1600
1750
  value = getter();
1601
1751
  } catch (err) {
1602
- if (_isDev5)
1752
+ if (_isDev6)
1603
1753
  devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
1604
1754
  return;
1605
1755
  }
@@ -1617,15 +1767,15 @@ function bindAttribute(el, attr, getter) {
1617
1767
  if ((attr === "value" || attr === "checked") && attr in el) {
1618
1768
  setProp(el, attr, attr === "checked" ? Boolean(value) : str);
1619
1769
  } else {
1620
- el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
1770
+ el.setAttribute(attr, sanitizeAttributeString(attr, str));
1621
1771
  }
1622
1772
  }
1623
- return reactiveBinding(commit);
1773
+ return reactiveBinding2(commit);
1624
1774
  }
1625
1775
 
1626
1776
  // src/core/rendering/dispose.ts
1627
1777
  var elementDisposers = /* @__PURE__ */ new WeakMap();
1628
- var _isDev6 = isDev();
1778
+ var _isDev7 = isDev();
1629
1779
  var activeBindingCount = 0;
1630
1780
  function registerDisposer(node, teardown) {
1631
1781
  let disposers = elementDisposers.get(node);
@@ -1634,7 +1784,7 @@ function registerDisposer(node, teardown) {
1634
1784
  elementDisposers.set(node, disposers);
1635
1785
  }
1636
1786
  disposers.push(teardown);
1637
- if (_isDev6) activeBindingCount++;
1787
+ if (_isDev7) activeBindingCount++;
1638
1788
  }
1639
1789
  function dispose(node) {
1640
1790
  const stack = [node];
@@ -1653,12 +1803,12 @@ function dispose(node) {
1653
1803
  if (disposers) {
1654
1804
  const snapshot = disposers.slice();
1655
1805
  elementDisposers.delete(current);
1656
- if (_isDev6) activeBindingCount -= snapshot.length;
1806
+ if (_isDev7) activeBindingCount -= snapshot.length;
1657
1807
  for (const d of snapshot) {
1658
1808
  try {
1659
1809
  d();
1660
1810
  } catch (err) {
1661
- if (_isDev6 && typeof console !== "undefined") {
1811
+ if (_isDev7 && typeof console !== "undefined") {
1662
1812
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
1663
1813
  }
1664
1814
  }
@@ -1669,12 +1819,12 @@ function dispose(node) {
1669
1819
  if (!added || added.length === 0) break;
1670
1820
  const moreSnapshot = added.slice();
1671
1821
  elementDisposers.delete(current);
1672
- if (_isDev6) activeBindingCount -= moreSnapshot.length;
1822
+ if (_isDev7) activeBindingCount -= moreSnapshot.length;
1673
1823
  for (const d of moreSnapshot) {
1674
1824
  try {
1675
1825
  d();
1676
1826
  } catch (err) {
1677
- if (_isDev6 && typeof console !== "undefined") {
1827
+ if (_isDev7 && typeof console !== "undefined") {
1678
1828
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
1679
1829
  }
1680
1830
  }
@@ -1685,7 +1835,7 @@ function dispose(node) {
1685
1835
  }
1686
1836
 
1687
1837
  // src/reactivity/bindChildNode.ts
1688
- var _isDev7 = isDev();
1838
+ var _isDev8 = isDev();
1689
1839
  function bindChildNode(placeholder, getter) {
1690
1840
  let lastNodes = [];
1691
1841
  function commit() {
@@ -1693,7 +1843,7 @@ function bindChildNode(placeholder, getter) {
1693
1843
  try {
1694
1844
  result = getter();
1695
1845
  } catch (err) {
1696
- if (_isDev7) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
1846
+ if (_isDev8) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
1697
1847
  return;
1698
1848
  }
1699
1849
  if (result == null || typeof result === "boolean") {
@@ -1719,7 +1869,7 @@ function bindChildNode(placeholder, getter) {
1719
1869
  if (item == null || typeof item === "boolean") continue;
1720
1870
  const node = item instanceof Node ? item : document.createTextNode(String(item));
1721
1871
  if (seen.has(node)) {
1722
- if (_isDev7)
1872
+ if (_isDev8)
1723
1873
  devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
1724
1874
  continue;
1725
1875
  }
@@ -1754,18 +1904,15 @@ function bindChildNode(placeholder, getter) {
1754
1904
  }
1755
1905
  lastNodes = newNodes;
1756
1906
  }
1757
- return reactiveBinding(commit);
1907
+ return reactiveBinding2(commit);
1758
1908
  }
1759
1909
 
1760
1910
  // src/core/rendering/tagFactory.ts
1761
1911
  var SVG_NS = "http://www.w3.org/2000/svg";
1762
- var _isDev8 = isDev();
1912
+ var _isDev9 = isDev();
1763
1913
  var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
1764
- function validateTagName(tag) {
1765
- const lower = tag.toLowerCase();
1766
- if (BLOCKED_TAGS.has(lower)) {
1767
- throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
1768
- }
1914
+ function isBlockedTag(tag) {
1915
+ return BLOCKED_TAGS.has(tag.toLowerCase());
1769
1916
  }
1770
1917
  var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
1771
1918
  "config",
@@ -1805,7 +1952,7 @@ function toKebab(prop) {
1805
1952
  }
1806
1953
  function applyStyle(el, style2) {
1807
1954
  if (typeof style2 === "function") {
1808
- const teardown = track(() => {
1955
+ const teardown = track2(() => {
1809
1956
  el.setAttribute("style", style2());
1810
1957
  });
1811
1958
  registerDisposer(el, teardown);
@@ -1821,7 +1968,7 @@ function applyStyle(el, style2) {
1821
1968
  const name = toKebab(prop);
1822
1969
  if (typeof val === "function") {
1823
1970
  const getter = val;
1824
- const teardown = track(() => {
1971
+ const teardown = track2(() => {
1825
1972
  htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
1826
1973
  });
1827
1974
  registerDisposer(el, teardown);
@@ -1836,7 +1983,7 @@ function applyClass(el, cls) {
1836
1983
  return;
1837
1984
  }
1838
1985
  if (typeof cls === "function") {
1839
- const teardown = track(() => {
1986
+ const teardown = track2(() => {
1840
1987
  el.setAttribute("class", cls());
1841
1988
  });
1842
1989
  registerDisposer(el, teardown);
@@ -1863,7 +2010,7 @@ function applyClass(el, cls) {
1863
2010
  }
1864
2011
  el.setAttribute("class", r);
1865
2012
  };
1866
- const teardown = track(update);
2013
+ const teardown = track2(update);
1867
2014
  registerDisposer(el, teardown);
1868
2015
  } else {
1869
2016
  el.setAttribute("class", result);
@@ -1920,8 +2067,11 @@ function appendChildren(el, nodes) {
1920
2067
  }
1921
2068
  }
1922
2069
  var tagFactory = (tag, ns) => {
2070
+ const blocked = isBlockedTag(tag);
1923
2071
  return (first, second) => {
1924
- validateTagName(tag);
2072
+ if (blocked) {
2073
+ throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
2074
+ }
1925
2075
  const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
1926
2076
  if (first === void 0) return el;
1927
2077
  if (typeof first === "string") {
@@ -1930,7 +2080,7 @@ var tagFactory = (tag, ns) => {
1930
2080
  appendChildren(el, second);
1931
2081
  return el;
1932
2082
  }
1933
- if (_isDev8 && looksLikeClassList(first)) {
2083
+ if (_isDev9 && looksLikeClassList(first)) {
1934
2084
  devWarn(
1935
2085
  `tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`
1936
2086
  );
@@ -1951,7 +2101,7 @@ var tagFactory = (tag, ns) => {
1951
2101
  if (pClass != null) applyClass(el, pClass);
1952
2102
  const pId = props.id;
1953
2103
  if (pId != null) {
1954
- if (_isDev8 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
2104
+ if (_isDev9 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
1955
2105
  devWarn(
1956
2106
  `tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
1957
2107
  );
@@ -1966,7 +2116,7 @@ var tagFactory = (tag, ns) => {
1966
2116
  const handler = pOn[ev];
1967
2117
  if (typeof handler === "function") {
1968
2118
  el.addEventListener(ev, handler);
1969
- } else if (_isDev8) {
2119
+ } else if (_isDev9) {
1970
2120
  devWarn(
1971
2121
  `tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
1972
2122
  );
@@ -1991,7 +2141,6 @@ var tagFactory = (tag, ns) => {
1991
2141
  default: {
1992
2142
  const value = props[key];
1993
2143
  if (value == null) continue;
1994
- const lkey = key.toLowerCase();
1995
2144
  if (isEventHandlerAttr(key)) continue;
1996
2145
  if (typeof value === "function") {
1997
2146
  registerDisposer(el, bindAttribute(el, key, value));
@@ -2004,14 +2153,7 @@ var tagFactory = (tag, ns) => {
2004
2153
  el.removeAttribute(key);
2005
2154
  }
2006
2155
  } else {
2007
- const str = String(value);
2008
- if (lkey === "srcset") {
2009
- el.setAttribute(key, sanitizeSrcset(str));
2010
- } else if (isUrlAttribute(lkey)) {
2011
- el.setAttribute(key, sanitizeUrl(str));
2012
- } else {
2013
- el.setAttribute(key, str);
2014
- }
2156
+ el.setAttribute(key, sanitizeAttributeString(key, String(value)));
2015
2157
  }
2016
2158
  }
2017
2159
  }
@@ -2087,7 +2229,7 @@ var area = tagFactory("area");
2087
2229
  var audio = tagFactory("audio");
2088
2230
  var img = tagFactory("img");
2089
2231
  var map = tagFactory("map");
2090
- var track2 = tagFactory("track");
2232
+ var track3 = tagFactory("track");
2091
2233
  var video = tagFactory("video");
2092
2234
  var embed = tagFactory("embed");
2093
2235
  var iframe = tagFactory("iframe");