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/ui.cjs CHANGED
@@ -87,7 +87,13 @@ module.exports = __toCommonJS(ui_exports);
87
87
 
88
88
  // src/core/dev.ts
89
89
  function isDev() {
90
- return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
90
+ return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
91
+ // The bare `__SIBU_DEV__` is a bundler define that only exists in
92
+ // production builds; under the test runner it is always undefined, so
93
+ // this branch is unreachable here.
94
+ /* v8 ignore next 2 */
95
+ typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
96
+ );
91
97
  }
92
98
  var _isDev = isDev();
93
99
  function devAssert(condition, message) {
@@ -101,7 +107,7 @@ function devWarn(message) {
101
107
  }
102
108
  }
103
109
 
104
- // src/reactivity/track.ts
110
+ // src/reactivity/track-core.ts
105
111
  var _isDev2 = isDev();
106
112
  var POOL_MAX = 4096;
107
113
  var nodePool = [];
@@ -185,6 +191,7 @@ function unlinkSub(node) {
185
191
  else sub.depsTail = prev;
186
192
  }
187
193
  var currentSubscriber = null;
194
+ var suspendSavedSub = null;
188
195
  var notifyDepth = 0;
189
196
  var pendingQueue = [];
190
197
  var pendingSet = /* @__PURE__ */ new Set();
@@ -196,7 +203,35 @@ function safeInvoke(sub) {
196
203
  if (_isDev2) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
197
204
  }
198
205
  }
206
+ var suspendDepth = 0;
199
207
  var trackingSuspended = false;
208
+ function suspendTracking() {
209
+ if (suspendDepth === 0) {
210
+ suspendSavedSub = currentSubscriber;
211
+ currentSubscriber = null;
212
+ trackingSuspended = true;
213
+ }
214
+ suspendDepth++;
215
+ }
216
+ function resumeTracking() {
217
+ suspendDepth--;
218
+ if (suspendDepth === 0) {
219
+ currentSubscriber = suspendSavedSub;
220
+ suspendSavedSub = null;
221
+ trackingSuspended = false;
222
+ }
223
+ }
224
+ function isTrackingSuspended() {
225
+ return trackingSuspended;
226
+ }
227
+ function untracked(fn) {
228
+ suspendTracking();
229
+ try {
230
+ return fn();
231
+ } finally {
232
+ resumeTracking();
233
+ }
234
+ }
200
235
  var subscriberEpochCounter = 0;
201
236
  function retrack(effectFn, subscriber) {
202
237
  const prev = currentSubscriber;
@@ -306,6 +341,16 @@ function cleanup(subscriber) {
306
341
  var maxSubscriberRepeats = 50;
307
342
  var maxDrainIterations = 1e6;
308
343
  var drainEpoch = 0;
344
+ function setMaxSubscriberRepeats(n) {
345
+ const prev = maxSubscriberRepeats;
346
+ if (Number.isFinite(n) && n > 0) maxSubscriberRepeats = Math.floor(n);
347
+ return prev;
348
+ }
349
+ function setMaxDrainIterations(n) {
350
+ const prev = maxDrainIterations;
351
+ if (Number.isFinite(n) && n > 0) maxDrainIterations = Math.floor(n);
352
+ return prev;
353
+ }
309
354
  function tickRepeat(sub) {
310
355
  const s = sub;
311
356
  if (s._runEpoch !== drainEpoch) {
@@ -347,6 +392,20 @@ function drainQueue() {
347
392
  safeInvoke(sub);
348
393
  }
349
394
  }
395
+ function drainNotificationQueue() {
396
+ if (notifyDepth > 0) return;
397
+ notifyDepth++;
398
+ drainEpoch++;
399
+ try {
400
+ drainQueue();
401
+ } finally {
402
+ notifyDepth--;
403
+ if (notifyDepth === 0) {
404
+ pendingQueue.length = 0;
405
+ pendingSet.clear();
406
+ }
407
+ }
408
+ }
350
409
  function propagateDirty(sub) {
351
410
  sub();
352
411
  const rootSig = sub._sig;
@@ -379,6 +438,22 @@ function propagateDirty(sub) {
379
438
  }
380
439
  }
381
440
  }
441
+ function queueSignalNotification(signal2) {
442
+ const sig = signal2;
443
+ let node = sig.subsHead ?? null;
444
+ while (node) {
445
+ const s = node.sub;
446
+ if (s) {
447
+ if (s._c) {
448
+ propagateDirty(s);
449
+ } else if (!pendingSet.has(s)) {
450
+ pendingSet.add(s);
451
+ pendingQueue.push(s);
452
+ }
453
+ }
454
+ node = node.sigNext;
455
+ }
456
+ }
382
457
  function notifySubscribers(signal2) {
383
458
  const sig = signal2;
384
459
  const head = sig.subsHead;
@@ -424,6 +499,85 @@ function notifySubscribers(signal2) {
424
499
  }
425
500
  }
426
501
  }
502
+ function getSubscriberCount(signal2) {
503
+ return signal2.__sc ?? 0;
504
+ }
505
+ function getSubscriberDeps(subscriber) {
506
+ const sub = subscriber;
507
+ const out = [];
508
+ let node = sub.depsHead ?? null;
509
+ while (node) {
510
+ if (node.sig) out.push(node.sig);
511
+ node = node.subNext;
512
+ }
513
+ return out;
514
+ }
515
+ function forEachSubscriber(signal2, visit) {
516
+ let node = signal2.subsHead ?? null;
517
+ while (node) {
518
+ const s = node.sub;
519
+ if (s) visit(s);
520
+ node = node.sigNext;
521
+ }
522
+ }
523
+
524
+ // src/reactivity/track.ts
525
+ var _isDev3 = isDev();
526
+ var _runtimeVersion = typeof __SIBU_VERSION__ !== "undefined" ? __SIBU_VERSION__ : "dev";
527
+ var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
528
+ function resolveReactiveApi() {
529
+ const g = globalThis;
530
+ const existing = g[REGISTRY_KEY];
531
+ if (existing) {
532
+ if (_isDev3 && !existing.__dupWarned) {
533
+ existing.__dupWarned = true;
534
+ devWarn(
535
+ `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']).`
536
+ );
537
+ }
538
+ return existing;
539
+ }
540
+ const local = {
541
+ suspendTracking,
542
+ resumeTracking,
543
+ isTrackingSuspended,
544
+ untracked,
545
+ retrack,
546
+ track,
547
+ reactiveBinding,
548
+ recordDependency,
549
+ cleanup,
550
+ setMaxSubscriberRepeats,
551
+ setMaxDrainIterations,
552
+ drainNotificationQueue,
553
+ queueSignalNotification,
554
+ notifySubscribers,
555
+ getSubscriberCount,
556
+ getSubscriberDeps,
557
+ forEachSubscriber,
558
+ version: _runtimeVersion
559
+ };
560
+ g[REGISTRY_KEY] = local;
561
+ return local;
562
+ }
563
+ var API = resolveReactiveApi();
564
+ var suspendTracking2 = API.suspendTracking;
565
+ var resumeTracking2 = API.resumeTracking;
566
+ var isTrackingSuspended2 = API.isTrackingSuspended;
567
+ var untracked2 = API.untracked;
568
+ var retrack2 = API.retrack;
569
+ var track2 = API.track;
570
+ var reactiveBinding2 = API.reactiveBinding;
571
+ var recordDependency2 = API.recordDependency;
572
+ var cleanup2 = API.cleanup;
573
+ var setMaxSubscriberRepeats2 = API.setMaxSubscriberRepeats;
574
+ var setMaxDrainIterations2 = API.setMaxDrainIterations;
575
+ var drainNotificationQueue2 = API.drainNotificationQueue;
576
+ var queueSignalNotification2 = API.queueSignalNotification;
577
+ var notifySubscribers2 = API.notifySubscribers;
578
+ var getSubscriberCount2 = API.getSubscriberCount;
579
+ var getSubscriberDeps2 = API.getSubscriberDeps;
580
+ var forEachSubscriber2 = API.forEachSubscriber;
427
581
 
428
582
  // src/core/signals/derived.ts
429
583
  function derived(getter, options) {
@@ -447,7 +601,7 @@ function derived(getter, options) {
447
601
  cs._d = false;
448
602
  cs._init = true;
449
603
  };
450
- track(() => {
604
+ track2(() => {
451
605
  let threw = true;
452
606
  try {
453
607
  cs._v = getter();
@@ -466,12 +620,12 @@ function derived(getter, options) {
466
620
  `[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
467
621
  );
468
622
  }
469
- if (trackingSuspended) {
623
+ if (isTrackingSuspended2()) {
470
624
  if (cs._d) {
471
625
  const prev = cs._v;
472
626
  evaluating = true;
473
627
  try {
474
- retrack(recompute, markDirty);
628
+ retrack2(recompute, markDirty);
475
629
  if (!Object.is(prev, cs._v)) cs.__v++;
476
630
  } finally {
477
631
  evaluating = false;
@@ -479,12 +633,12 @@ function derived(getter, options) {
479
633
  }
480
634
  return cs._v;
481
635
  }
482
- recordDependency(cs);
636
+ recordDependency2(cs);
483
637
  if (cs._d) {
484
638
  const oldValue = cs._v;
485
639
  evaluating = true;
486
640
  try {
487
- retrack(recompute, markDirty);
641
+ retrack2(recompute, markDirty);
488
642
  if (!Object.is(oldValue, cs._v)) cs.__v++;
489
643
  } finally {
490
644
  evaluating = false;
@@ -507,15 +661,56 @@ function derived(getter, options) {
507
661
  // src/reactivity/batch.ts
508
662
  var batchDepth = 0;
509
663
  var pendingSignals = /* @__PURE__ */ new Set();
510
- function enqueueBatchedSignal(signal2) {
664
+ function batchImpl(fn) {
665
+ batchDepth++;
666
+ try {
667
+ return fn();
668
+ } finally {
669
+ batchDepth--;
670
+ if (batchDepth === 0) {
671
+ flushBatch();
672
+ }
673
+ }
674
+ }
675
+ function enqueueBatchedSignalImpl(signal2) {
511
676
  if (batchDepth === 0) return false;
512
677
  pendingSignals.add(signal2);
513
678
  return true;
514
679
  }
680
+ function isBatchingImpl() {
681
+ return batchDepth > 0;
682
+ }
683
+ function flushBatch() {
684
+ try {
685
+ for (const signal2 of pendingSignals) {
686
+ queueSignalNotification2(signal2);
687
+ }
688
+ } finally {
689
+ pendingSignals.clear();
690
+ }
691
+ drainNotificationQueue2();
692
+ }
693
+ var BATCH_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.batch.v1");
694
+ function resolveBatchApi() {
695
+ const g = globalThis;
696
+ const existing = g[BATCH_REGISTRY_KEY];
697
+ if (existing) return existing;
698
+ const local = {
699
+ batch: batchImpl,
700
+ enqueueBatchedSignal: enqueueBatchedSignalImpl,
701
+ isBatching: isBatchingImpl
702
+ };
703
+ g[BATCH_REGISTRY_KEY] = local;
704
+ return local;
705
+ }
706
+ var API2 = resolveBatchApi();
707
+ var batch = API2.batch;
708
+ var enqueueBatchedSignal = API2.enqueueBatchedSignal;
709
+ var isBatching = API2.isBatching;
515
710
 
516
711
  // src/core/signals/signal.ts
517
712
  var _g = globalThis;
518
- var _isDev3 = isDev();
713
+ var _isDev4 = isDev();
519
714
  function signal(initial, options) {
520
715
  const state = {
521
716
  value: initial,
@@ -526,11 +721,11 @@ function signal(initial, options) {
526
721
  __activeNode: null,
527
722
  __name: void 0
528
723
  };
529
- const debugName = _isDev3 ? options?.name : void 0;
724
+ const debugName = _isDev4 ? options?.name : void 0;
530
725
  const equalsFn = options?.equals;
531
726
  if (debugName) state.__name = debugName;
532
727
  function get() {
533
- recordDependency(state);
728
+ recordDependency2(state);
534
729
  return state.value;
535
730
  }
536
731
  get.__signal = state;
@@ -543,15 +738,15 @@ function signal(initial, options) {
543
738
  if (equalsFn(prev, newValue)) return;
544
739
  state.value = newValue;
545
740
  state.__v++;
546
- if (_isDev3) {
741
+ if (_isDev4) {
547
742
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
548
743
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
549
744
  }
550
745
  if (!enqueueBatchedSignal(state)) {
551
- notifySubscribers(state);
746
+ notifySubscribers2(state);
552
747
  }
553
748
  };
554
- } else if (_isDev3) {
749
+ } else if (_isDev4) {
555
750
  set = (next) => {
556
751
  const prev = state.value;
557
752
  const newValue = typeof next === "function" ? next(prev) : next;
@@ -561,7 +756,7 @@ function signal(initial, options) {
561
756
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
562
757
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
563
758
  if (!enqueueBatchedSignal(state)) {
564
- notifySubscribers(state);
759
+ notifySubscribers2(state);
565
760
  }
566
761
  };
567
762
  } else {
@@ -572,11 +767,11 @@ function signal(initial, options) {
572
767
  state.value = newValue;
573
768
  state.__v++;
574
769
  if (!enqueueBatchedSignal(state)) {
575
- notifySubscribers(state);
770
+ notifySubscribers2(state);
576
771
  }
577
772
  };
578
773
  }
579
- if (_isDev3) {
774
+ if (_isDev4) {
580
775
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
581
776
  if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
582
777
  }
@@ -818,7 +1013,7 @@ function formAction(fn) {
818
1013
 
819
1014
  // src/core/rendering/dispose.ts
820
1015
  var elementDisposers = /* @__PURE__ */ new WeakMap();
821
- var _isDev4 = isDev();
1016
+ var _isDev5 = isDev();
822
1017
  var activeBindingCount = 0;
823
1018
  function registerDisposer(node, teardown) {
824
1019
  let disposers = elementDisposers.get(node);
@@ -827,7 +1022,7 @@ function registerDisposer(node, teardown) {
827
1022
  elementDisposers.set(node, disposers);
828
1023
  }
829
1024
  disposers.push(teardown);
830
- if (_isDev4) activeBindingCount++;
1025
+ if (_isDev5) activeBindingCount++;
831
1026
  }
832
1027
  function dispose(node) {
833
1028
  const stack = [node];
@@ -846,12 +1041,12 @@ function dispose(node) {
846
1041
  if (disposers) {
847
1042
  const snapshot = disposers.slice();
848
1043
  elementDisposers.delete(current);
849
- if (_isDev4) activeBindingCount -= snapshot.length;
1044
+ if (_isDev5) activeBindingCount -= snapshot.length;
850
1045
  for (const d of snapshot) {
851
1046
  try {
852
1047
  d();
853
1048
  } catch (err) {
854
- if (_isDev4 && typeof console !== "undefined") {
1049
+ if (_isDev5 && typeof console !== "undefined") {
855
1050
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
856
1051
  }
857
1052
  }
@@ -862,12 +1057,12 @@ function dispose(node) {
862
1057
  if (!added || added.length === 0) break;
863
1058
  const moreSnapshot = added.slice();
864
1059
  elementDisposers.delete(current);
865
- if (_isDev4) activeBindingCount -= moreSnapshot.length;
1060
+ if (_isDev5) activeBindingCount -= moreSnapshot.length;
866
1061
  for (const d of moreSnapshot) {
867
1062
  try {
868
1063
  d();
869
1064
  } catch (err) {
870
- if (_isDev4 && typeof console !== "undefined") {
1065
+ if (_isDev5 && typeof console !== "undefined") {
871
1066
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
872
1067
  }
873
1068
  }
@@ -926,7 +1121,7 @@ function drainReruns(ctx) {
926
1121
  do {
927
1122
  ctx.rerunPending = false;
928
1123
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
929
- retrack(ctx.bodyFn, ctx.subscriber);
1124
+ retrack2(ctx.bodyFn, ctx.subscriber);
930
1125
  } while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
931
1126
  if (ctx.rerunPending) {
932
1127
  ctx.rerunPending = false;
@@ -955,7 +1150,7 @@ function disposeEffect(ctx) {
955
1150
  }
956
1151
  }
957
1152
  try {
958
- cleanup(ctx.subscriber);
1153
+ cleanup2(ctx.subscriber);
959
1154
  } catch (err) {
960
1155
  if (typeof console !== "undefined") {
961
1156
  console.warn("[SibuJS effect] dispose threw:", err);
@@ -1000,7 +1195,7 @@ function effect(effectFn, options) {
1000
1195
  try {
1001
1196
  ctx.rerunPending = false;
1002
1197
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1003
- retrack(ctx.bodyFn, sub);
1198
+ retrack2(ctx.bodyFn, sub);
1004
1199
  if (ctx.rerunPending) drainReruns(ctx);
1005
1200
  } finally {
1006
1201
  ctx.running = false;
@@ -1016,7 +1211,7 @@ function effect(effectFn, options) {
1016
1211
  ctx.subscriber = sub;
1017
1212
  ctx.running = true;
1018
1213
  try {
1019
- retrack(ctx.bodyFn, ctx.subscriber);
1214
+ retrack2(ctx.bodyFn, ctx.subscriber);
1020
1215
  if (ctx.rerunPending) drainReruns(ctx);
1021
1216
  } finally {
1022
1217
  ctx.running = false;
@@ -1255,7 +1450,7 @@ function aria(element, attrs) {
1255
1450
  const getter = value;
1256
1451
  registerDisposer(
1257
1452
  element,
1258
- track(() => {
1453
+ track2(() => {
1259
1454
  element.setAttribute(ariaKey, String(getter()));
1260
1455
  })
1261
1456
  );
@@ -1740,6 +1935,20 @@ function sanitizeUrl(url) {
1740
1935
  if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
1741
1936
  return trimmed;
1742
1937
  }
1938
+ function sanitizeSrcset(value) {
1939
+ const parts = value.split(",");
1940
+ const out = [];
1941
+ for (let i = 0; i < parts.length; i++) {
1942
+ const part = parts[i].trim();
1943
+ if (!part) continue;
1944
+ const m = part.match(/^(\S+)(\s+.+)?$/);
1945
+ if (!m) continue;
1946
+ const safe = sanitizeUrl(m[1]);
1947
+ if (!safe) continue;
1948
+ out.push(m[2] ? `${safe}${m[2]}` : safe);
1949
+ }
1950
+ return out.join(", ");
1951
+ }
1743
1952
  var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
1744
1953
  "href",
1745
1954
  "xlink:href",
@@ -1754,18 +1963,21 @@ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
1754
1963
  "ping",
1755
1964
  "data"
1756
1965
  ]);
1757
- function isUrlAttribute(attr) {
1758
- return URL_ATTRIBUTES.has(attr.toLowerCase());
1966
+ function sanitizeAttributeString(attr, value) {
1967
+ const lower = attr.toLowerCase();
1968
+ if (lower === "srcset") return sanitizeSrcset(value);
1969
+ if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
1970
+ return value;
1759
1971
  }
1760
1972
 
1761
1973
  // src/reactivity/bindAttribute.ts
1762
- var _isDev5 = isDev();
1974
+ var _isDev6 = isDev();
1763
1975
  function setProp(el, key, val) {
1764
1976
  el[key] = val;
1765
1977
  }
1766
1978
  function bindAttribute(el, attr, getter) {
1767
1979
  if (isEventHandlerAttr(attr)) {
1768
- if (_isDev5)
1980
+ if (_isDev6)
1769
1981
  devWarn(
1770
1982
  `bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
1771
1983
  );
@@ -1777,7 +1989,7 @@ function bindAttribute(el, attr, getter) {
1777
1989
  try {
1778
1990
  value = getter();
1779
1991
  } catch (err) {
1780
- if (_isDev5)
1992
+ if (_isDev6)
1781
1993
  devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
1782
1994
  return;
1783
1995
  }
@@ -1795,10 +2007,10 @@ function bindAttribute(el, attr, getter) {
1795
2007
  if ((attr === "value" || attr === "checked") && attr in el) {
1796
2008
  setProp(el, attr, attr === "checked" ? Boolean(value) : str);
1797
2009
  } else {
1798
- el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
2010
+ el.setAttribute(attr, sanitizeAttributeString(attr, str));
1799
2011
  }
1800
2012
  }
1801
- return reactiveBinding(commit);
2013
+ return reactiveBinding2(commit);
1802
2014
  }
1803
2015
 
1804
2016
  // src/ui/reactiveAttr.ts
@@ -1848,7 +2060,7 @@ function bindBoolAttr(el, attr, getter) {
1848
2060
  el.removeAttribute(attr);
1849
2061
  }
1850
2062
  }
1851
- const teardown = track(commit);
2063
+ const teardown = track2(commit);
1852
2064
  return teardown;
1853
2065
  }
1854
2066
  function bindData(el, key, getter) {
package/dist/ui.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  toast,
39
39
  withScopedStyle,
40
40
  zipMask
41
- } from "./chunk-NPIEEKPT.js";
41
+ } from "./chunk-RYMOSG5B.js";
42
42
  import {
43
43
  RenderProp,
44
44
  assertType,
@@ -58,21 +58,21 @@ import {
58
58
  import {
59
59
  createId
60
60
  } from "./chunk-YT6HQ6AM.js";
61
- import "./chunk-RLUJL2MV.js";
62
- import "./chunk-JYXOEYI4.js";
61
+ import "./chunk-NHKQKKZU.js";
62
+ import "./chunk-WW6DAGGR.js";
63
63
  import {
64
64
  registerDisposer
65
- } from "./chunk-2UPRY23K.js";
66
- import "./chunk-HMJFCBRR.js";
65
+ } from "./chunk-5VGSK6D2.js";
66
+ import "./chunk-L3GAGWCC.js";
67
67
  import {
68
68
  effect
69
- } from "./chunk-FDY42FIU.js";
69
+ } from "./chunk-MHBCEJQO.js";
70
70
  import "./chunk-GOJMFRBL.js";
71
71
  import {
72
72
  signal
73
- } from "./chunk-C427DVQF.js";
74
- import "./chunk-Z2FWAE4B.js";
75
- import "./chunk-LMLD24FC.js";
73
+ } from "./chunk-WZG2SZOT.js";
74
+ import "./chunk-TEFZT5PJ.js";
75
+ import "./chunk-COY6PUD2.js";
76
76
 
77
77
  // src/ui/formAction.ts
78
78
  function formAction(fn) {