@manyducks.co/dolla 0.78.2 → 1.0.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.
package/lib/index.js CHANGED
@@ -115,7 +115,6 @@ var CrashCollector = class {
115
115
  for (const callback of this.#errorCallbacks) {
116
116
  callback(ctx);
117
117
  }
118
- throw error;
119
118
  }
120
119
  /**
121
120
  * Reports a recoverable error.
@@ -286,8 +285,20 @@ var DebugHub = class {
286
285
  if (hubOptions.info === false || isString(hubOptions.info) && hubOptions.info !== hubOptions.mode || !match(name)) {
287
286
  return noOp;
288
287
  } else {
289
- const label = `%c${name}`;
290
- return _console.info.bind(_console, label, `color:${hash(label)};font-weight:bold`);
288
+ let label = `%c${name}`;
289
+ if (options.id) {
290
+ label += ` %c[uid: %c${options.id}%c]`;
291
+ } else {
292
+ label += `%c%c%c`;
293
+ }
294
+ return _console.info.bind(
295
+ _console,
296
+ label,
297
+ `color:${hash(label)};font-weight:bold`,
298
+ `color:#777`,
299
+ `color:#aaa`,
300
+ `color:#777`
301
+ );
291
302
  }
292
303
  },
293
304
  get log() {
@@ -295,8 +306,20 @@ var DebugHub = class {
295
306
  if (hubOptions.log === false || isString(hubOptions.log) && hubOptions.log !== hubOptions.mode || !match(name)) {
296
307
  return noOp;
297
308
  } else {
298
- const label = `%c${name}`;
299
- return _console.log.bind(_console, label, `color:${hash(label)};font-weight:bold`);
309
+ let label = `%c${name}`;
310
+ if (options.id) {
311
+ label += ` %c[uid: %c${options.id}%c]`;
312
+ } else {
313
+ label += `%c%c%c`;
314
+ }
315
+ return _console.log.bind(
316
+ _console,
317
+ label,
318
+ `color:${hash(label)};font-weight:bold`,
319
+ `color:#777`,
320
+ `color:#aaa`,
321
+ `color:#777`
322
+ );
300
323
  }
301
324
  },
302
325
  get warn() {
@@ -304,8 +327,20 @@ var DebugHub = class {
304
327
  if (hubOptions.warn === false || isString(hubOptions.warn) && hubOptions.warn !== hubOptions.mode || !match(name)) {
305
328
  return noOp;
306
329
  } else {
307
- const label = `%c${name}`;
308
- return _console.warn.bind(_console, label, `color:${hash(label)};font-weight:bold`);
330
+ let label = `%c${name}`;
331
+ if (options.id) {
332
+ label += ` %c[uid: %c${options.id}%c]`;
333
+ } else {
334
+ label += `%c%c%c`;
335
+ }
336
+ return _console.warn.bind(
337
+ _console,
338
+ label,
339
+ `color:${hash(label)};font-weight:bold`,
340
+ `color:#777`,
341
+ `color:#aaa`,
342
+ `color:#777`
343
+ );
309
344
  }
310
345
  },
311
346
  get error() {
@@ -313,8 +348,20 @@ var DebugHub = class {
313
348
  if (hubOptions.error === false || isString(hubOptions.error) && hubOptions.error !== hubOptions.mode || !match(name)) {
314
349
  return noOp;
315
350
  } else {
316
- const label = `%c${name}`;
317
- return _console.error.bind(_console, label, `color:${hash(label)};font-weight:bold`);
351
+ let label = `%c${name}`;
352
+ if (options.id) {
353
+ label += ` %c[uid: %c${options.id}%c]`;
354
+ } else {
355
+ label += `%c%c%c`;
356
+ }
357
+ return _console.error.bind(
358
+ _console,
359
+ label,
360
+ `color:${hash(label)};font-weight:bold`,
361
+ `color:#777`,
362
+ `color:#aaa`,
363
+ `color:#777`
364
+ );
318
365
  }
319
366
  }
320
367
  };
@@ -385,6 +432,106 @@ function makeMatcher(pattern) {
385
432
  };
386
433
  }
387
434
 
435
+ // src/nodes/cond.ts
436
+ var Conditional = class {
437
+ node;
438
+ endNode;
439
+ $predicate;
440
+ stopCallback;
441
+ thenContent;
442
+ elseContent;
443
+ connectedContent = [];
444
+ appContext;
445
+ elementContext;
446
+ initialUpdateHappened = false;
447
+ previousValue;
448
+ constructor(config) {
449
+ this.$predicate = config.$predicate;
450
+ this.thenContent = config.thenContent ? toMarkup(config.thenContent) : void 0;
451
+ this.elseContent = config.elseContent ? toMarkup(config.elseContent) : void 0;
452
+ this.appContext = config.appContext;
453
+ this.elementContext = config.elementContext;
454
+ if (this.appContext.mode === "development") {
455
+ this.node = document.createComment("Conditional");
456
+ this.endNode = document.createComment("/Conditional");
457
+ } else {
458
+ this.node = document.createTextNode("");
459
+ this.endNode = document.createTextNode("");
460
+ }
461
+ }
462
+ get connected() {
463
+ return this.node.parentNode != null;
464
+ }
465
+ connect(parent2, after) {
466
+ if (!this.connected) {
467
+ parent2.insertBefore(this.node, after?.nextSibling ?? null);
468
+ if (this.appContext.mode === "development") {
469
+ parent2.insertBefore(this.endNode, this.node.nextSibling);
470
+ }
471
+ this.stopCallback = this.$predicate.watch((value) => {
472
+ if (!this.initialUpdateHappened || value && !this.previousValue || !value && this.previousValue) {
473
+ this.update(value);
474
+ this.initialUpdateHappened = true;
475
+ this.previousValue = value;
476
+ }
477
+ });
478
+ }
479
+ }
480
+ disconnect() {
481
+ if (this.stopCallback) {
482
+ this.stopCallback();
483
+ this.stopCallback = void 0;
484
+ }
485
+ for (const handle of this.connectedContent) {
486
+ handle.disconnect();
487
+ }
488
+ this.connectedContent = [];
489
+ if (this.connected) {
490
+ this.node.parentNode?.removeChild(this.node);
491
+ this.endNode.parentNode?.removeChild(this.endNode);
492
+ }
493
+ }
494
+ update(value) {
495
+ for (const handle of this.connectedContent) {
496
+ handle.disconnect();
497
+ }
498
+ this.connectedContent = [];
499
+ if (this.node.parentNode == null) {
500
+ return;
501
+ }
502
+ if (value && this.thenContent) {
503
+ this.connectedContent = renderMarkupToDOM(this.thenContent, this);
504
+ } else if (!value && this.elseContent) {
505
+ this.connectedContent = renderMarkupToDOM(this.elseContent, this);
506
+ }
507
+ for (let i = 0; i < this.connectedContent.length; i++) {
508
+ const handle = this.connectedContent[i];
509
+ const previous = this.connectedContent[i - 1]?.node ?? this.node;
510
+ handle.connect(this.node.parentNode, previous);
511
+ }
512
+ if (this.appContext.mode === "development") {
513
+ this.node.textContent = `Conditional (${value ? "truthy" : "falsy"})`;
514
+ }
515
+ }
516
+ async setChildren(children) {
517
+ }
518
+ };
519
+
520
+ // node_modules/nanoid/index.browser.js
521
+ var nanoid = (size = 21) => crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
522
+ byte &= 63;
523
+ if (byte < 36) {
524
+ id += byte.toString(36);
525
+ } else if (byte < 62) {
526
+ id += (byte - 26).toString(36).toUpperCase();
527
+ } else if (byte > 62) {
528
+ id += "-";
529
+ } else {
530
+ id += "_";
531
+ }
532
+ return id;
533
+ }, "");
534
+
388
535
  // src/utils.ts
389
536
  function isPlainObject(value) {
390
537
  return value != null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.getPrototypeOf({});
@@ -393,6 +540,9 @@ function deepEqual(one, two) {
393
540
  if (one === two) {
394
541
  return true;
395
542
  }
543
+ if (isSignal(one) || isSignal(two)) {
544
+ return false;
545
+ }
396
546
  if (isPlainObject(one) && isPlainObject(two)) {
397
547
  const keysOne = Object.keys(one);
398
548
  const keysTwo = Object.keys(two);
@@ -449,335 +599,282 @@ function omit(keys, object) {
449
599
  return process2(object);
450
600
  }
451
601
 
452
- // src/state.ts
453
- var UNOBSERVED = Symbol("Unobserved");
454
- var OBSERVE = Symbol("Observe");
455
- function isReadable(value) {
456
- return value != null && typeof value === "object" && typeof value[OBSERVE] === "function" && typeof value.get === "function";
457
- }
458
- function isWritable(value) {
459
- return isReadable(value) && typeof value.set === "function" && typeof value.update === "function";
460
- }
461
- function $$(initialValue, config) {
462
- if (config) {
463
- return proxy(initialValue, config);
464
- } else {
465
- return writable(initialValue);
602
+ // src/signals.ts
603
+ function isSignal(value) {
604
+ if (value == null || typeof value !== "object") {
605
+ return false;
466
606
  }
607
+ if (typeof value["get"] !== "function") {
608
+ return false;
609
+ }
610
+ if (typeof value["watch"] !== "function") {
611
+ return false;
612
+ }
613
+ return true;
467
614
  }
468
- function $(...args) {
469
- if (args.length > 1) {
470
- const callback = args.pop();
471
- const readables = args.flat().map(readable);
472
- return computed(...readables, callback);
473
- } else {
474
- return readable(args[0]);
615
+ function isSettableSignal(value) {
616
+ if (value == null || typeof value !== "object") {
617
+ return false;
618
+ }
619
+ if (typeof value["set"] !== "function") {
620
+ return false;
621
+ }
622
+ if (typeof value["get"] !== "function") {
623
+ return false;
624
+ }
625
+ if (typeof value["watch"] !== "function") {
626
+ return false;
475
627
  }
628
+ return true;
476
629
  }
477
- function readable(value) {
478
- if (isWritable(value)) {
479
- return {
480
- get: value.get,
481
- [OBSERVE]: value[OBSERVE]
482
- };
630
+ function designalify(value) {
631
+ if (isSignal(value)) {
632
+ return value.get();
633
+ } else {
634
+ return value;
483
635
  }
484
- if (isReadable(value)) {
636
+ }
637
+ function signalify(value) {
638
+ if (isSignal(value)) {
485
639
  return value;
640
+ } else {
641
+ return createStaticSignal(value);
486
642
  }
643
+ }
644
+ function signal(initialValue, options) {
645
+ return createSignal(initialValue, options);
646
+ }
647
+ signal.settable = createSettableSignal;
648
+ signal.toSettable = createSettableSignalFrom;
649
+ signal.createSetter = createSignalSetter;
650
+ function createSettableSignal(initialValue, options) {
651
+ const [$value, setValue] = signal(initialValue, options);
487
652
  return {
488
- get: () => value,
489
- [OBSERVE]: (callback) => {
490
- callback(value);
491
- return function stop() {
492
- };
493
- }
653
+ get: $value.get,
654
+ watch: $value.watch,
655
+ set: setValue
494
656
  };
495
657
  }
496
- function computed(...args) {
497
- const compute = args.pop();
498
- if (typeof compute !== "function") {
499
- throw new TypeError(`Final argument must be a function. Got ${typeOf(compute)}: ${compute}`);
500
- }
501
- if (args.length < 1) {
502
- throw new Error(`Must pass at least one value before the callback function.`);
503
- }
504
- const readables = args;
505
- const observers = [];
506
- let stopCallbacks = [];
507
- let isObserving = false;
508
- let observedValues = [];
509
- let valuesChanged = [];
510
- let latestComputedValue = UNOBSERVED;
511
- let computedStopCallback;
512
- function updateValue() {
513
- if (!valuesChanged.some((x) => x)) {
514
- return;
515
- }
516
- const computedValue = compute(...observedValues);
517
- if (isReadable(computedValue)) {
518
- if (computedStopCallback) {
519
- computedStopCallback();
520
- }
521
- computedStopCallback = computedValue[OBSERVE]((current) => {
522
- latestComputedValue = current;
523
- for (const callback of observers) {
524
- callback(current);
525
- }
526
- });
527
- } else if (!deepEqual(computedValue, latestComputedValue)) {
528
- if (computedStopCallback) {
529
- computedStopCallback();
530
- computedStopCallback = void 0;
531
- }
532
- latestComputedValue = computedValue;
533
- for (const callback of observers) {
534
- callback(computedValue);
535
- }
536
- }
537
- for (let i = 0; i < observedValues.length; i++) {
538
- valuesChanged[i] = false;
539
- }
540
- }
541
- function startObserving() {
542
- if (isObserving)
543
- return;
544
- for (let i = 0; i < readables.length; i++) {
545
- const readable2 = readables[i];
546
- stopCallbacks.push(
547
- observe(readable2, (value) => {
548
- if (!deepEqual(observedValues[i], value)) {
549
- observedValues[i] = value;
550
- valuesChanged[i] = true;
551
- if (isObserving) {
552
- updateValue();
553
- }
554
- }
555
- })
556
- );
557
- }
558
- observedValues = readables.map((x) => x.get());
559
- for (let i = 0; i < observedValues.length; i++) {
560
- valuesChanged[i] = true;
561
- }
562
- isObserving = true;
563
- updateValue();
564
- }
565
- function stopObserving() {
566
- isObserving = false;
567
- for (const callback of stopCallbacks) {
568
- callback();
658
+ function createSettableSignalFrom(signal2, setter) {
659
+ return {
660
+ get: signal2.get,
661
+ watch: signal2.watch,
662
+ set: setter
663
+ };
664
+ }
665
+ function createSignalSetter(signal2, callback) {
666
+ return function setValue(nextOrCallback) {
667
+ const previous = signal2.get();
668
+ let next;
669
+ if (typeof nextOrCallback === "function") {
670
+ next = nextOrCallback(previous);
671
+ } else {
672
+ next = nextOrCallback;
569
673
  }
570
- stopCallbacks = [];
571
- }
674
+ callback(next, previous);
675
+ };
676
+ }
677
+ function createStaticSignal(value) {
572
678
  return {
573
- get: () => {
574
- if (isObserving) {
575
- return latestComputedValue;
576
- } else {
577
- return compute(...readables.map((x) => x.get()));
578
- }
679
+ get() {
680
+ return value;
579
681
  },
580
- [OBSERVE]: (callback) => {
581
- if (!isObserving) {
582
- startObserving();
682
+ watch(callback, options = {}) {
683
+ if (!options.lazy) {
684
+ callback(value);
583
685
  }
584
- callback(latestComputedValue);
585
- observers.push(callback);
586
686
  return function stop() {
587
- observers.splice(observers.indexOf(callback), 1);
588
- if (observers.length === 0) {
589
- stopObserving();
590
- }
591
687
  };
592
688
  }
593
689
  };
594
690
  }
595
- function writable(value) {
596
- if (isWritable(value)) {
597
- return value;
691
+ function createSignal(initialValue, options) {
692
+ let currentValue = initialValue;
693
+ let watchers = [];
694
+ function notify() {
695
+ for (const watcher of watchers) {
696
+ watcher(currentValue);
697
+ }
598
698
  }
599
- if (isReadable(value)) {
600
- throw new TypeError(`Failed to convert Readable into a Writable; can't add write access to a read-only value.`);
699
+ function equal(next, previous) {
700
+ if (options?.equality) {
701
+ return options.equality(next, previous);
702
+ } else {
703
+ return deepEqual(next, previous);
704
+ }
601
705
  }
602
- const observers = [];
603
- let currentValue = value;
604
- return {
605
- // ----- Readable ----- //
606
- get: () => currentValue,
607
- [OBSERVE]: (callback) => {
608
- observers.push(callback);
609
- function stop() {
610
- observers.splice(observers.indexOf(callback), 1);
611
- }
612
- callback(currentValue);
613
- return stop;
706
+ const $value = {
707
+ get() {
708
+ return designalify(currentValue);
614
709
  },
615
- // ----- Writable ----- //
616
- set: (newValue) => {
617
- if (!deepEqual(currentValue, newValue)) {
618
- const previousValue = currentValue;
619
- currentValue = newValue;
620
- for (const callback of observers) {
621
- callback(currentValue, previousValue);
622
- }
623
- }
624
- },
625
- update: (callback) => {
626
- const newValue = callback(currentValue);
627
- if (!deepEqual(currentValue, newValue)) {
628
- const previousValue = currentValue;
629
- currentValue = newValue;
630
- for (const callback2 of observers) {
631
- callback2(currentValue, previousValue);
632
- }
710
+ watch(callback, options2) {
711
+ watchers.push(callback);
712
+ if (!options2?.lazy) {
713
+ callback($value.get());
633
714
  }
715
+ return function stop() {
716
+ watchers.splice(watchers.indexOf(callback), 1);
717
+ };
634
718
  }
635
719
  };
636
- }
637
- function proxy(source, config) {
638
- if (!isReadable(source)) {
639
- throw new TypeError(`Proxy source must be a Readable.`);
640
- }
641
- return {
642
- // ----- Readable ----- //
643
- get: () => config.get(),
644
- [OBSERVE]: (callback) => {
645
- let lastComputedValue = UNOBSERVED;
646
- return observe(source, (_) => {
647
- const computedValue = config.get();
648
- if (!deepEqual(computedValue, lastComputedValue)) {
649
- callback(computedValue);
650
- lastComputedValue = computedValue;
651
- }
652
- });
653
- },
654
- // ----- Writable ----- //
655
- set: (value) => {
656
- config.set(value);
657
- },
658
- update: (callback) => {
659
- config.set(callback(config.get()));
720
+ function setValue(next) {
721
+ let value;
722
+ if (typeof next === "function") {
723
+ value = next(currentValue);
724
+ } else {
725
+ value = next;
726
+ }
727
+ if (!equal(value, currentValue)) {
728
+ currentValue = value;
729
+ notify();
660
730
  }
661
- };
662
- }
663
- function observe(...args) {
664
- const callback = args.pop();
665
- const readables = args.flat().map(readable);
666
- if (readables.length === 0) {
667
- throw new TypeError(`Expected at least one readable.`);
668
- }
669
- if (readables.length > 1) {
670
- return computed(...readables, callback)[OBSERVE](() => null);
671
- } else {
672
- return readables[0][OBSERVE](callback);
673
- }
674
- }
675
- function unwrap(value) {
676
- if (isReadable(value)) {
677
- return value.get();
678
731
  }
679
- return value;
732
+ return [$value, setValue];
680
733
  }
681
-
682
- // src/nodes/cond.ts
683
- var Conditional = class {
684
- node;
685
- endNode;
686
- $predicate;
687
- stopCallback;
688
- thenContent;
689
- elseContent;
690
- connectedContent = [];
691
- appContext;
692
- elementContext;
693
- initialUpdateHappened = false;
694
- previousValue;
695
- constructor(config) {
696
- this.$predicate = config.$predicate;
697
- this.thenContent = config.thenContent ? toMarkup(config.thenContent) : void 0;
698
- this.elseContent = config.elseContent ? toMarkup(config.elseContent) : void 0;
699
- this.appContext = config.appContext;
700
- this.elementContext = config.elementContext;
701
- if (this.appContext.mode === "development") {
702
- this.node = document.createComment("Conditional");
703
- this.endNode = document.createComment("/Conditional");
734
+ var EMPTY = Symbol("EMPTY");
735
+ function derive(signals, fn, options) {
736
+ signals = signals.map((s) => {
737
+ if (isSignal(s)) {
738
+ return s;
704
739
  } else {
705
- this.node = document.createTextNode("");
706
- this.endNode = document.createTextNode("");
740
+ return createStaticSignal(s);
741
+ }
742
+ });
743
+ let previousSourceValues = new Array(signals.length).fill(EMPTY, 0, signals.length);
744
+ let currentValue;
745
+ let watchers = [];
746
+ let watching = false;
747
+ let stoppers = [];
748
+ let stopWatchingCurrentValue;
749
+ let rawCurrentValue;
750
+ function notify(value = getCurrentValue()) {
751
+ for (const watcher of watchers) {
752
+ watcher(value);
753
+ }
754
+ }
755
+ function equal(next, previous) {
756
+ if (options?.equality) {
757
+ return options.equality(next, previous);
758
+ } else {
759
+ return deepEqual(next, previous);
707
760
  }
708
761
  }
709
- get connected() {
710
- return this.node.parentNode != null;
711
- }
712
- connect(parent2, after) {
713
- if (!this.connected) {
714
- parent2.insertBefore(this.node, after?.nextSibling ?? null);
715
- if (this.appContext.mode === "development") {
716
- parent2.insertBefore(this.endNode, this.node.nextSibling);
762
+ function update() {
763
+ const sourceValues = signals.map((s) => s.get());
764
+ for (let i = 0; i < signals.length; i++) {
765
+ if (!equal(sourceValues[i], previousSourceValues[i])) {
766
+ setCurrentValue(fn(...sourceValues));
767
+ previousSourceValues = sourceValues;
768
+ break;
717
769
  }
718
- this.stopCallback = observe(this.$predicate, (value) => {
719
- if (!this.initialUpdateHappened || value && !this.previousValue || !value && this.previousValue) {
720
- this.update(value);
721
- this.initialUpdateHappened = true;
722
- this.previousValue = value;
723
- }
724
- });
725
770
  }
726
771
  }
727
- disconnect() {
728
- if (this.stopCallback) {
729
- this.stopCallback();
730
- this.stopCallback = void 0;
772
+ function getCurrentValue() {
773
+ if (!watching) {
774
+ update();
731
775
  }
732
- for (const handle of this.connectedContent) {
733
- handle.disconnect();
776
+ rawCurrentValue = designalify(currentValue);
777
+ return rawCurrentValue;
778
+ }
779
+ function setCurrentValue(value) {
780
+ if (value === currentValue) {
781
+ return;
734
782
  }
735
- this.connectedContent = [];
736
- if (this.connected) {
737
- this.node.parentNode?.removeChild(this.node);
738
- this.endNode.parentNode?.removeChild(this.endNode);
783
+ if (stopWatchingCurrentValue) {
784
+ stopWatchingCurrentValue();
785
+ stopWatchingCurrentValue = void 0;
786
+ }
787
+ currentValue = value;
788
+ rawCurrentValue = designalify(value);
789
+ if (isSignal(value)) {
790
+ if (watching) {
791
+ stopWatchingCurrentValue = value.watch((current) => {
792
+ const raw = designalify(current);
793
+ if (!equal(raw, rawCurrentValue)) {
794
+ rawCurrentValue = raw;
795
+ notify(raw);
796
+ }
797
+ });
798
+ }
739
799
  }
740
800
  }
741
- update(value) {
742
- for (const handle of this.connectedContent) {
743
- handle.disconnect();
801
+ function startWatchingSources() {
802
+ let startingSourceValues = [...previousSourceValues];
803
+ for (let i = 0; i < signals.length; i++) {
804
+ const signal2 = signals[i];
805
+ stoppers.push(
806
+ signal2.watch((next) => {
807
+ const previous = previousSourceValues[i];
808
+ previousSourceValues[i] = next;
809
+ if (watching && !equal(next, previous)) {
810
+ setCurrentValue(fn(...previousSourceValues));
811
+ notify(designalify(currentValue));
812
+ }
813
+ })
814
+ );
744
815
  }
745
- this.connectedContent = [];
746
- if (this.node.parentNode == null) {
747
- return;
816
+ watching = true;
817
+ for (let i = 0; i < signals.length; i++) {
818
+ if (!equal(previousSourceValues[i], startingSourceValues[i])) {
819
+ setCurrentValue(fn(...previousSourceValues));
820
+ notify(designalify(currentValue));
821
+ break;
822
+ }
748
823
  }
749
- if (value && this.thenContent) {
750
- this.connectedContent = renderMarkupToDOM(this.thenContent, this);
751
- } else if (!value && this.elseContent) {
752
- this.connectedContent = renderMarkupToDOM(this.elseContent, this);
824
+ }
825
+ function stopWatchingSources() {
826
+ for (const stop of stoppers) {
827
+ stop();
753
828
  }
754
- for (let i = 0; i < this.connectedContent.length; i++) {
755
- const handle = this.connectedContent[i];
756
- const previous = this.connectedContent[i - 1]?.node ?? this.node;
757
- handle.connect(this.node.parentNode, previous);
829
+ stoppers = [];
830
+ if (stopWatchingCurrentValue) {
831
+ stopWatchingCurrentValue();
832
+ stopWatchingCurrentValue = void 0;
758
833
  }
759
- if (this.appContext.mode === "development") {
760
- this.node.textContent = `Conditional (${value ? "truthy" : "falsy"})`;
834
+ watching = false;
835
+ }
836
+ const $value = {
837
+ get() {
838
+ return getCurrentValue();
839
+ },
840
+ watch(callback, options2) {
841
+ if (!watching) {
842
+ startWatchingSources();
843
+ }
844
+ watchers.push(callback);
845
+ if (!options2?.lazy) {
846
+ callback(getCurrentValue());
847
+ }
848
+ return function stop() {
849
+ watchers.splice(watchers.indexOf(callback), 1);
850
+ if (watching && watchers.length === 0) {
851
+ stopWatchingSources();
852
+ }
853
+ };
761
854
  }
855
+ };
856
+ return $value;
857
+ }
858
+ function watch(signals, fn) {
859
+ if (signals.length === 0) {
860
+ throw new TypeError(`Expected at least one signal.`);
762
861
  }
763
- async setChildren(children) {
862
+ if (signals.some((s) => !isSignal(s))) {
863
+ throw new TypeError(`All values must be signals`);
764
864
  }
765
- };
766
-
767
- // node_modules/nanoid/index.browser.js
768
- var nanoid = (size = 21) => crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
769
- byte &= 63;
770
- if (byte < 36) {
771
- id += byte.toString(36);
772
- } else if (byte < 62) {
773
- id += (byte - 26).toString(36).toUpperCase();
774
- } else if (byte > 62) {
775
- id += "-";
865
+ signals = signals.map((s) => {
866
+ if (isSignal(s)) {
867
+ return s;
868
+ } else {
869
+ return createStaticSignal(s);
870
+ }
871
+ });
872
+ if (signals.length > 1) {
873
+ return derive(signals, fn).watch(() => null);
776
874
  } else {
777
- id += "_";
875
+ return signals[0].watch(fn);
778
876
  }
779
- return id;
780
- }, "");
877
+ }
781
878
 
782
879
  // src/nodes/html.ts
783
880
  var isCamelCaseEventName = (key) => /^on[A-Z]/.test(key);
@@ -808,12 +905,10 @@ var HTML = class {
808
905
  this.node.dataset.uniqueId = this.uniqueId;
809
906
  }
810
907
  if (props.ref) {
811
- if (isWritable(props.ref)) {
812
- props.ref.set(this.node);
813
- } else if (isFunction(props.ref)) {
814
- props.ref(this.node);
908
+ if (isRef(props.ref)) {
909
+ props.ref.node = this.node;
815
910
  } else {
816
- throw new Error("Expected an instance of Ref. Got: " + props.ref);
911
+ throw new Error("Expected ref to be a Ref object. Got: " + props.ref);
817
912
  }
818
913
  }
819
914
  this.props = {
@@ -880,11 +975,11 @@ var HTML = class {
880
975
  applyProps(element, props) {
881
976
  const render = this.appContext.stores.get("render").instance?.exports;
882
977
  const attachProp = (value, callback, updateKey) => {
883
- if (isReadable(value)) {
978
+ if (isSignal(value)) {
884
979
  this.stopCallbacks.push(
885
- observe(value, (value2) => {
980
+ value.watch((current) => {
886
981
  render.update(() => {
887
- callback(value2);
982
+ callback(current);
888
983
  }, updateKey);
889
984
  })
890
985
  );
@@ -914,22 +1009,37 @@ var HTML = class {
914
1009
  } else if (key === "eventListeners") {
915
1010
  const values = value;
916
1011
  for (const name in values) {
917
- const listener = isReadable(value) ? (e) => value.get()(e) : value;
1012
+ const listener = isSignal(value) ? (e) => value.get()(e) : value;
918
1013
  element.addEventListener(name, listener);
919
1014
  this.stopCallbacks.push(() => {
920
1015
  element.removeEventListener(name, listener);
921
1016
  });
922
1017
  }
1018
+ } else if (key === "onClickOutside" || key === "onclickoutside") {
1019
+ const listener = (e) => {
1020
+ if (this.canClickAway && !element.contains(e.target)) {
1021
+ if (isSignal(value)) {
1022
+ value.get()(e);
1023
+ } else {
1024
+ value(e);
1025
+ }
1026
+ }
1027
+ };
1028
+ const options = { capture: true };
1029
+ window.addEventListener("click", listener, options);
1030
+ this.stopCallbacks.push(() => {
1031
+ window.removeEventListener("click", listener, options);
1032
+ });
923
1033
  } else if (key === "$$value") {
924
- if (!isWritable(value)) {
925
- throw new TypeError(`$$value property must be a Writable. Got: ${value} (${typeof value})`);
1034
+ if (!isSettableSignal(value)) {
1035
+ throw new TypeError(`$$value attribute must be a settable signal. Got: ${value}`);
926
1036
  }
927
1037
  attachProp(
928
1038
  value,
929
1039
  (current) => {
930
1040
  element.value = String(current);
931
1041
  },
932
- this.getUpdateKey("prop", "value")
1042
+ this.getUpdateKey("attr", "value")
933
1043
  );
934
1044
  const listener = (e) => {
935
1045
  const updated = toTypeOf(value.get(), e.currentTarget.value);
@@ -939,24 +1049,9 @@ var HTML = class {
939
1049
  this.stopCallbacks.push(() => {
940
1050
  element.removeEventListener("input", listener);
941
1051
  });
942
- } else if (key === "onClickOutside" || key === "onclickoutside") {
943
- const listener = (e) => {
944
- if (this.canClickAway && !element.contains(e.target)) {
945
- if (isReadable(value)) {
946
- value.get()(e);
947
- } else {
948
- value(e);
949
- }
950
- }
951
- };
952
- const options = { capture: true };
953
- window.addEventListener("click", listener, options);
954
- this.stopCallbacks.push(() => {
955
- window.removeEventListener("click", listener, options);
956
- });
957
1052
  } else if (isCamelCaseEventName(key)) {
958
1053
  const eventName = key.slice(2).toLowerCase();
959
- const listener = isReadable(value) ? (e) => value.get()(e) : value;
1054
+ const listener = isSignal(value) ? (e) => value.get()(e) : value;
960
1055
  element.addEventListener(eventName, listener);
961
1056
  this.stopCallbacks.push(() => {
962
1057
  element.removeEventListener(eventName, listener);
@@ -1077,9 +1172,9 @@ var HTML = class {
1077
1172
  element.style.cssText = "";
1078
1173
  } else if (typeof styles === "string") {
1079
1174
  element.style.cssText = styles;
1080
- } else if (isReadable(styles)) {
1175
+ } else if (isSignal(styles)) {
1081
1176
  let unapply;
1082
- const stop = observe(styles, (current) => {
1177
+ const stop = styles.watch((current) => {
1083
1178
  render.update(
1084
1179
  () => {
1085
1180
  if (isFunction(unapply)) {
@@ -1098,8 +1193,8 @@ var HTML = class {
1098
1193
  for (const key in styles) {
1099
1194
  const value = styles[key];
1100
1195
  const setProperty = key.startsWith("--") ? (key2, value2) => value2 == null ? element.style.removeProperty(key2) : element.style.setProperty(key2, value2) : (key2, value2) => element.style[key2] = value2 ?? "";
1101
- if (isReadable(value)) {
1102
- const stop = observe(value, (current) => {
1196
+ if (isSignal(value)) {
1197
+ const stop = value.watch((current) => {
1103
1198
  render.update(
1104
1199
  () => {
1105
1200
  if (current != null) {
@@ -1134,9 +1229,9 @@ var HTML = class {
1134
1229
  applyClasses(element, classes, stopCallbacks) {
1135
1230
  const render = this.appContext.stores.get("render").instance?.exports;
1136
1231
  const classStopCallbacks = [];
1137
- if (isReadable(classes)) {
1232
+ if (isSignal(classes)) {
1138
1233
  let unapply;
1139
- const stop = observe(classes, (current) => {
1234
+ const stop = classes.watch((current) => {
1140
1235
  render.update(
1141
1236
  () => {
1142
1237
  if (isFunction(unapply)) {
@@ -1154,8 +1249,8 @@ var HTML = class {
1154
1249
  const mapped = getClassMap(classes);
1155
1250
  for (const name in mapped) {
1156
1251
  const value = mapped[name];
1157
- if (isReadable(value)) {
1158
- const stop = observe(value, (current) => {
1252
+ if (isSignal(value)) {
1253
+ const stop = value.watch((current) => {
1159
1254
  render.update(() => {
1160
1255
  if (current) {
1161
1256
  element.classList.add(name);
@@ -1222,7 +1317,7 @@ var Observer = class {
1222
1317
  get connected() {
1223
1318
  return this.node.parentNode != null;
1224
1319
  }
1225
- constructor({ readables, renderFn, appContext, elementContext }) {
1320
+ constructor({ signals, renderFn, appContext, elementContext }) {
1226
1321
  this.appContext = appContext;
1227
1322
  this.elementContext = elementContext;
1228
1323
  this.renderFn = renderFn;
@@ -1233,7 +1328,7 @@ var Observer = class {
1233
1328
  start: () => {
1234
1329
  if (_stop != null)
1235
1330
  return;
1236
- _stop = observe(readables, (...values) => {
1331
+ _stop = watch(signals, (...values) => {
1237
1332
  const rendered = this.renderFn(...values);
1238
1333
  if (!isRenderable(rendered)) {
1239
1334
  console.error(rendered);
@@ -1332,7 +1427,7 @@ var Outlet = class {
1332
1427
  connect(parent2, after) {
1333
1428
  if (!this.connected) {
1334
1429
  parent2.insertBefore(this.node, after?.nextSibling ?? null);
1335
- this.stopCallback = observe(this.$children, (children) => {
1430
+ this.stopCallback = this.$children.watch((children) => {
1336
1431
  this.update(children);
1337
1432
  });
1338
1433
  }
@@ -1419,7 +1514,9 @@ function initView(config) {
1419
1514
  stores: /* @__PURE__ */ new Map(),
1420
1515
  parent: config.elementContext
1421
1516
  };
1422
- const $$children = $$(renderMarkupToDOM(config.children ?? [], { appContext, elementContext }));
1517
+ const [$children, setChildren] = signal(
1518
+ renderMarkupToDOM(config.children ?? [], { appContext, elementContext })
1519
+ );
1423
1520
  let isConnected = false;
1424
1521
  const stopObserverCallbacks = [];
1425
1522
  const connectedCallbacks = [];
@@ -1428,7 +1525,7 @@ function initView(config) {
1428
1525
  const beforeDisconnectCallbacks = [];
1429
1526
  const uniqueId = nanoid();
1430
1527
  const ctx = {
1431
- get uniqueId() {
1528
+ get uid() {
1432
1529
  return uniqueId;
1433
1530
  },
1434
1531
  name: config.view.name ?? "anonymous",
@@ -1475,28 +1572,47 @@ function initView(config) {
1475
1572
  beforeDisconnect(callback) {
1476
1573
  beforeDisconnectCallbacks.push(callback);
1477
1574
  },
1575
+ onMount(callback) {
1576
+ connectedCallbacks.push(callback);
1577
+ },
1578
+ onUnmount(callback) {
1579
+ disconnectedCallbacks.push(callback);
1580
+ },
1478
1581
  crash(error) {
1479
1582
  config.appContext.crashCollector.crash({ error, componentName: ctx.name });
1480
1583
  },
1481
- observe(...args) {
1482
- const callback = args.pop();
1584
+ watch(signals, callback) {
1483
1585
  if (isConnected) {
1484
- const stop = observe(args, callback);
1586
+ const stop = watch(signals, callback);
1485
1587
  stopObserverCallbacks.push(stop);
1588
+ return stop;
1486
1589
  } else {
1590
+ let stop;
1591
+ let stopped = false;
1487
1592
  connectedCallbacks.push(() => {
1488
- const stop = observe(args, callback);
1489
- stopObserverCallbacks.push(stop);
1593
+ if (!stopped) {
1594
+ stop = watch(signals, callback);
1595
+ stopObserverCallbacks.push(stop);
1596
+ }
1490
1597
  });
1598
+ return function stop2() {
1599
+ if (stop2 != null) {
1600
+ stopped = true;
1601
+ stop2();
1602
+ }
1603
+ };
1491
1604
  }
1492
1605
  },
1493
1606
  outlet() {
1494
- return m("$outlet", { $children: $($$children) });
1607
+ return m("$outlet", { $children });
1495
1608
  }
1496
1609
  };
1497
1610
  const debugChannel = appContext.debugHub.channel({
1498
1611
  get name() {
1499
1612
  return ctx.name;
1613
+ },
1614
+ get id() {
1615
+ return uniqueId;
1500
1616
  }
1501
1617
  });
1502
1618
  Object.defineProperties(ctx, Object.getOwnPropertyDescriptors(debugChannel));
@@ -1530,9 +1646,9 @@ function initView(config) {
1530
1646
  rendered = getRenderHandle(renderMarkupToDOM(m("$node", { value: result }), { appContext, elementContext }));
1531
1647
  } else if (isMarkup(result) || isArrayOf(isMarkup, result)) {
1532
1648
  rendered = getRenderHandle(renderMarkupToDOM(result, { appContext, elementContext }));
1533
- } else if (isReadable(result)) {
1649
+ } else if (isSignal(result)) {
1534
1650
  rendered = getRenderHandle(
1535
- renderMarkupToDOM(m("$observer", { readables: [result], renderFn: (x) => x }), { appContext, elementContext })
1651
+ renderMarkupToDOM(m("$observer", { signals: [result], renderFn: (x) => x }), { appContext, elementContext })
1536
1652
  );
1537
1653
  } else {
1538
1654
  console.warn(result, config);
@@ -1592,7 +1708,7 @@ function initView(config) {
1592
1708
  }
1593
1709
  },
1594
1710
  async setChildren(children) {
1595
- $$children.set(children);
1711
+ setChildren(children);
1596
1712
  }
1597
1713
  };
1598
1714
  return handle;
@@ -1629,7 +1745,7 @@ var Repeat = class {
1629
1745
  connect(parent2, after) {
1630
1746
  if (!this.connected) {
1631
1747
  parent2.insertBefore(this.node, after?.nextSibling ?? null);
1632
- this.stopCallback = observe(this.$items, (value) => {
1748
+ this.stopCallback = this.$items.watch((value) => {
1633
1749
  this._update(Array.from(value));
1634
1750
  });
1635
1751
  }
@@ -1677,21 +1793,23 @@ var Repeat = class {
1677
1793
  for (const potential of potentialItems) {
1678
1794
  const connected = this.connectedItems.find((item) => item.key === potential.key);
1679
1795
  if (connected) {
1680
- connected.$$value.set(potential.value);
1681
- connected.$$index.set(potential.index);
1796
+ connected.setValue(potential.value);
1797
+ connected.setIndex(potential.index);
1682
1798
  newItems[potential.index] = connected;
1683
1799
  } else {
1684
- const $$value = $$(potential.value);
1685
- const $$index = $$(potential.index);
1800
+ const [$value, setValue] = signal(potential.value);
1801
+ const [$index, setIndex] = signal(potential.index);
1686
1802
  newItems[potential.index] = {
1687
1803
  key: potential.key,
1688
- $$value,
1689
- $$index,
1804
+ $value,
1805
+ setValue,
1806
+ $index,
1807
+ setIndex,
1690
1808
  handle: initView({
1691
1809
  view: RepeatItemView,
1692
1810
  appContext: this.appContext,
1693
1811
  elementContext: this.elementContext,
1694
- props: { $value: $($$value), $index: $($$index), renderFn: this.renderFn }
1812
+ props: { $value, $index, renderFn: this.renderFn }
1695
1813
  })
1696
1814
  };
1697
1815
  }
@@ -1726,8 +1844,8 @@ var Text = class {
1726
1844
  }
1727
1845
  async connect(parent2, after = null) {
1728
1846
  if (!this.connected) {
1729
- if (isReadable(this.value)) {
1730
- this.stopCallback = observe(this.value, (value) => {
1847
+ if (isSignal(this.value)) {
1848
+ this.stopCallback = this.value.watch((value) => {
1731
1849
  this.update(value);
1732
1850
  });
1733
1851
  } else {
@@ -1778,9 +1896,9 @@ function toMarkup(renderables) {
1778
1896
  if (isString(x) || isNumber(x)) {
1779
1897
  return m("$text", { value: x });
1780
1898
  }
1781
- if (isReadable(x)) {
1899
+ if (isSignal(x)) {
1782
1900
  return m("$observer", {
1783
- readables: [x],
1901
+ signals: [x],
1784
1902
  renderFn: (x2) => x2
1785
1903
  });
1786
1904
  }
@@ -1789,6 +1907,9 @@ function toMarkup(renderables) {
1789
1907
  });
1790
1908
  }
1791
1909
  function m(type, props, ...children) {
1910
+ if (props != null) {
1911
+ _assertPropTypes(props);
1912
+ }
1792
1913
  return {
1793
1914
  [MARKUP]: true,
1794
1915
  type,
@@ -1796,8 +1917,27 @@ function m(type, props, ...children) {
1796
1917
  children: toMarkup(children)
1797
1918
  };
1798
1919
  }
1920
+ function _assertPropTypes(props) {
1921
+ if (props.ref) {
1922
+ if (!isRef(props.ref)) {
1923
+ console.warn(props.ref);
1924
+ throw new TypeError(`Prop 'ref' must be a Ref object. Got: ${props.ref}`);
1925
+ }
1926
+ }
1927
+ for (const key in props) {
1928
+ if (key.startsWith("$$") && props[key] !== void 0) {
1929
+ if (!isSettableSignal(props[key])) {
1930
+ throw new TypeError(`Prop '${key}' is named as a SettableSignal but value is not. Got: ${props[key]}`);
1931
+ }
1932
+ } else if (key.startsWith("$") && props[key] !== void 0) {
1933
+ if (!isSignal(props[key])) {
1934
+ throw new TypeError(`Prop '${key}' is named as a Signal but value is not. Got: ${props[key]}`);
1935
+ }
1936
+ }
1937
+ }
1938
+ }
1799
1939
  function cond(predicate, thenContent, elseContent) {
1800
- const $predicate = $(predicate);
1940
+ const $predicate = signalify(predicate);
1801
1941
  return m("$cond", {
1802
1942
  $predicate,
1803
1943
  thenContent,
@@ -1805,12 +1945,34 @@ function cond(predicate, thenContent, elseContent) {
1805
1945
  });
1806
1946
  }
1807
1947
  function repeat(items, keyFn, renderFn) {
1808
- const $items = $(items);
1948
+ const $items = signalify(items);
1809
1949
  return m("$repeat", { $items, keyFn, renderFn });
1810
1950
  }
1811
1951
  function portal(content, parent2) {
1812
1952
  return m("$portal", { content, parent: parent2 });
1813
1953
  }
1954
+ function ref() {
1955
+ const [$node, setNode] = signal();
1956
+ return {
1957
+ get: $node.get,
1958
+ watch: $node.watch,
1959
+ get node() {
1960
+ return $node.get();
1961
+ },
1962
+ set node(node) {
1963
+ setNode(node);
1964
+ }
1965
+ };
1966
+ }
1967
+ function isRef(value) {
1968
+ if (value == null || typeof value !== "object") {
1969
+ return false;
1970
+ }
1971
+ if (!value.hasOwnProperty("node")) {
1972
+ return false;
1973
+ }
1974
+ return true;
1975
+ }
1814
1976
  var NodeHandle = class {
1815
1977
  node;
1816
1978
  get connected() {
@@ -1876,7 +2038,7 @@ function renderMarkupToDOM(markup, ctx) {
1876
2038
  case "$observer": {
1877
2039
  const attrs = item.props;
1878
2040
  return new Observer({
1879
- readables: attrs.readables,
2041
+ signals: attrs.signals,
1880
2042
  renderFn: attrs.renderFn,
1881
2043
  appContext: ctx.appContext,
1882
2044
  elementContext: ctx.elementContext
@@ -1952,7 +2114,7 @@ function getRenderHandle(handles) {
1952
2114
  };
1953
2115
  }
1954
2116
  function isRenderable(value) {
1955
- return value == null || value === false || typeof value === "string" || typeof value === "number" || isMarkup(value) || isReadable(value) || isArrayOf(isRenderable, value);
2117
+ return value == null || value === false || typeof value === "string" || typeof value === "number" || isMarkup(value) || isSignal(value) || isArrayOf(isRenderable, value);
1956
2118
  }
1957
2119
 
1958
2120
  // src/store.ts
@@ -2012,17 +2174,26 @@ function initStore(config) {
2012
2174
  crash(error) {
2013
2175
  config.appContext.crashCollector.crash({ error, componentName: ctx.name });
2014
2176
  },
2015
- observe(...args) {
2016
- const callback = args.pop();
2017
- const readables = args.flat();
2177
+ watch(signals, callback) {
2018
2178
  if (isConnected) {
2019
- const stop = observe(readables, callback);
2179
+ const stop = watch(signals, callback);
2020
2180
  stopObserverCallbacks.push(stop);
2181
+ return stop;
2021
2182
  } else {
2183
+ let stop;
2184
+ let stopped = false;
2022
2185
  connectedCallbacks.push(() => {
2023
- const stop = observe(readables, callback);
2024
- stopObserverCallbacks.push(stop);
2186
+ if (!stopped) {
2187
+ stop = watch(signals, callback);
2188
+ stopObserverCallbacks.push(stop);
2189
+ }
2025
2190
  });
2191
+ return function() {
2192
+ if (stop != null) {
2193
+ stopped = true;
2194
+ stop();
2195
+ }
2196
+ };
2026
2197
  }
2027
2198
  }
2028
2199
  };
@@ -2089,27 +2260,27 @@ function initStore(config) {
2089
2260
  // src/stores/document.ts
2090
2261
  function DocumentStore(ctx) {
2091
2262
  ctx.name = "dolla/document";
2092
- const $$title = $$(document.title);
2093
- const $$visibility = $$(document.visibilityState);
2094
- const $$orientation = $$("landscape");
2095
- const $$colorScheme = $$("light");
2096
- ctx.observe($$title, (current) => {
2263
+ const [$title, setTitle] = signal(document.title);
2264
+ const [$visibility, setVisibility] = signal(document.visibilityState);
2265
+ const [$orientation, setOrientation] = signal("landscape");
2266
+ const [$colorScheme, setColorScheme] = signal("light");
2267
+ ctx.watch([$title], (current) => {
2097
2268
  document.title = current;
2098
2269
  });
2099
2270
  const onVisibilityChange = () => {
2100
- $$visibility.set(document.visibilityState);
2271
+ setVisibility(document.visibilityState);
2101
2272
  };
2102
2273
  const onFocus = () => {
2103
- $$visibility.set("visible");
2274
+ setVisibility("visible");
2104
2275
  };
2105
2276
  const landscapeQuery = window.matchMedia("(orientation: landscape)");
2106
2277
  function onOrientationChange(e) {
2107
- $$orientation.set(e.matches ? "landscape" : "portrait");
2278
+ setOrientation(e.matches ? "landscape" : "portrait");
2108
2279
  }
2109
2280
  onOrientationChange(landscapeQuery);
2110
2281
  const colorSchemeQuery = window.matchMedia("(prefers-color-scheme: dark)");
2111
2282
  function onColorChange(e) {
2112
- $$colorScheme.set(e.matches ? "dark" : "light");
2283
+ setColorScheme(e.matches ? "dark" : "light");
2113
2284
  }
2114
2285
  onColorChange(colorSchemeQuery);
2115
2286
  ctx.onConnected(function() {
@@ -2125,10 +2296,11 @@ function DocumentStore(ctx) {
2125
2296
  window.removeEventListener("focus", onFocus);
2126
2297
  });
2127
2298
  return {
2128
- $$title,
2129
- $visibility: $($$visibility),
2130
- $orientation: $($$orientation),
2131
- $colorScheme: $($$colorScheme)
2299
+ $title,
2300
+ setTitle,
2301
+ $visibility,
2302
+ $orientation,
2303
+ $colorScheme
2132
2304
  };
2133
2305
  }
2134
2306
 
@@ -3257,11 +3429,11 @@ function RouterStore(ctx) {
3257
3429
  ctx.onConnected(() => {
3258
3430
  ctx.info("Routes registered:", routes);
3259
3431
  });
3260
- const $$pattern = $$(null);
3261
- const $$path = $$("");
3262
- const $$params = $$({});
3263
- const $$query = $$(parseQueryParams(window.location.search));
3264
- ctx.observe($$query, (current) => {
3432
+ const [$pattern, setPattern] = signal(null);
3433
+ const [$path, setPath] = signal("");
3434
+ const [$params, setParams] = signal({});
3435
+ const [$query, setQuery] = signal(parseQueryParams(window.location.search));
3436
+ ctx.watch([$query], (current) => {
3265
3437
  const params = new URLSearchParams();
3266
3438
  for (const key in current) {
3267
3439
  params.set(key, String(current[key]));
@@ -3292,13 +3464,13 @@ function RouterStore(ctx) {
3292
3464
  const onRouteChange = async ({ location }) => {
3293
3465
  if (location.search !== lastQuery) {
3294
3466
  lastQuery = location.search;
3295
- $$query.set(parseQueryParams(location.search));
3467
+ setQuery(parseQueryParams(location.search));
3296
3468
  }
3297
3469
  const matched = matchRoutes(routes, location.pathname);
3298
3470
  if (!matched) {
3299
- $$pattern.set(null);
3300
- $$path.set(location.pathname);
3301
- $$params.set({
3471
+ setPattern(null);
3472
+ setPath(location.pathname);
3473
+ setParams({
3302
3474
  wildcard: location.pathname
3303
3475
  });
3304
3476
  return;
@@ -3367,10 +3539,10 @@ function RouterStore(ctx) {
3367
3539
  throw new TypeError(`Redirect must either be a path string or a function.`);
3368
3540
  }
3369
3541
  } else {
3370
- $$path.set(matched.path);
3371
- $$params.set(matched.params);
3372
- if (matched.pattern !== $$pattern.get()) {
3373
- $$pattern.set(matched.pattern);
3542
+ setPath(matched.path);
3543
+ setParams(matched.params);
3544
+ if (matched.pattern !== $pattern.get()) {
3545
+ setPattern(matched.pattern);
3374
3546
  const layers = matched.meta.layers;
3375
3547
  for (let i = 0; i < layers.length; i++) {
3376
3548
  const matchedLayer = layers[i];
@@ -3417,19 +3589,20 @@ function RouterStore(ctx) {
3417
3589
  /**
3418
3590
  * The currently matched route pattern, if any.
3419
3591
  */
3420
- $pattern: $($$pattern),
3592
+ $pattern,
3421
3593
  /**
3422
3594
  * The current URL path.
3423
3595
  */
3424
- $path: $($$path),
3596
+ $path,
3425
3597
  /**
3426
3598
  * The current named path params.
3427
3599
  */
3428
- $params: $($$params),
3600
+ $params,
3429
3601
  /**
3430
3602
  * The current query params. Changes to this object will be reflected in the URL.
3431
3603
  */
3432
- $$query,
3604
+ $query,
3605
+ setQuery,
3433
3606
  /**
3434
3607
  * Navigate backward. Pass a number of steps to hit the back button that many times.
3435
3608
  */
@@ -3543,10 +3716,10 @@ function LanguageStore(ctx) {
3543
3716
  }
3544
3717
  return cache.get(config.name);
3545
3718
  }
3546
- const $$isLoaded = $$(false);
3547
- const $$language = $$();
3548
- const $$translation = $$();
3549
- const $noLanguageValue = $("[NO LANGUAGE SET]");
3719
+ const [$loaded, setLoaded] = signal(false);
3720
+ const [$language, _setLanguage] = signal();
3721
+ const [$translation, setTranslation] = signal();
3722
+ const [$noLanguageValue] = signal("[NO LANGUAGE SET]");
3550
3723
  const translationCache = [];
3551
3724
  function getCached(key, values) {
3552
3725
  for (const entry of translationCache) {
@@ -3599,8 +3772,8 @@ function LanguageStore(ctx) {
3599
3772
  const lang = languages.get(realTag);
3600
3773
  try {
3601
3774
  const translation = await getTranslation(lang);
3602
- $$translation.set(translation);
3603
- $$language.set(realTag);
3775
+ setTranslation(translation);
3776
+ _setLanguage(realTag);
3604
3777
  ctx.info("set language to " + realTag);
3605
3778
  } catch (error) {
3606
3779
  if (error instanceof Error) {
@@ -3609,11 +3782,11 @@ function LanguageStore(ctx) {
3609
3782
  }
3610
3783
  }
3611
3784
  setLanguage(ctx.options.defaultLanguage ?? "auto").then(() => {
3612
- $$isLoaded.set(true);
3785
+ setLoaded(true);
3613
3786
  });
3614
3787
  return {
3615
3788
  loaded: new Promise((resolve2, reject) => {
3616
- const stop = observe($$isLoaded, (isLoaded) => {
3789
+ const stop = $loaded.watch((isLoaded) => {
3617
3790
  if (isLoaded) {
3618
3791
  setTimeout(() => {
3619
3792
  stop();
@@ -3622,8 +3795,8 @@ function LanguageStore(ctx) {
3622
3795
  }
3623
3796
  });
3624
3797
  }),
3625
- $isLoaded: $($$isLoaded),
3626
- $currentLanguage: $($$language),
3798
+ $isLoaded: $loaded,
3799
+ $currentLanguage: $language,
3627
3800
  supportedLanguages: [...languages.keys()],
3628
3801
  setLanguage,
3629
3802
  /**
@@ -3633,7 +3806,7 @@ function LanguageStore(ctx) {
3633
3806
  * @param values - A map of {{placeholder}} names and the values to replace them with.
3634
3807
  */
3635
3808
  translate(key, values) {
3636
- if (!$$language.get()) {
3809
+ if (!$language.get()) {
3637
3810
  return $noLanguageValue;
3638
3811
  }
3639
3812
  const cached = getCached(key, values);
@@ -3641,16 +3814,16 @@ function LanguageStore(ctx) {
3641
3814
  return cached;
3642
3815
  }
3643
3816
  if (values) {
3644
- const readableValues = {};
3817
+ const signalValues = {};
3645
3818
  for (const [key2, value] of Object.entries(values)) {
3646
- if (isReadable(value)) {
3647
- readableValues[key2] = value;
3819
+ if (isSignal(value)) {
3820
+ signalValues[key2] = value;
3648
3821
  }
3649
3822
  }
3650
- const readableEntries = Object.entries(readableValues);
3823
+ const readableEntries = Object.entries(signalValues);
3651
3824
  if (readableEntries.length > 0) {
3652
3825
  const readables = readableEntries.map((x) => x[1]);
3653
- const $merged = $([$$translation, ...readables], (t, ...entryValues) => {
3826
+ const $merged = derive([$translation, ...readables], (t, ...entryValues) => {
3654
3827
  const entries = entryValues.map((_, i) => readableEntries[i]);
3655
3828
  const mergedValues = {
3656
3829
  ...values
@@ -3666,7 +3839,7 @@ function LanguageStore(ctx) {
3666
3839
  return $merged;
3667
3840
  }
3668
3841
  }
3669
- const $replaced = $($$translation, (t) => {
3842
+ const $replaced = derive([$translation], (t) => {
3670
3843
  let result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
3671
3844
  if (values) {
3672
3845
  result = replaceMustaches(result, values);
@@ -3871,7 +4044,7 @@ function DialogStore(ctx) {
3871
4044
  container.style.bottom = "0";
3872
4045
  container.style.left = "0";
3873
4046
  container.style.zIndex = "99999";
3874
- const $$dialogs = $$([]);
4047
+ const [$dialogs, setDialogs] = signal([]);
3875
4048
  let activeDialogs = [];
3876
4049
  function dialogChangedCallback() {
3877
4050
  if (activeDialogs.length > 0) {
@@ -3884,7 +4057,7 @@ function DialogStore(ctx) {
3884
4057
  }
3885
4058
  }
3886
4059
  }
3887
- ctx.observe($$dialogs, (dialogs) => {
4060
+ ctx.watch([$dialogs], (dialogs) => {
3888
4061
  render.update(() => {
3889
4062
  let removed = [];
3890
4063
  let added = [];
@@ -3926,7 +4099,7 @@ function DialogStore(ctx) {
3926
4099
  }
3927
4100
  });
3928
4101
  function open(view, props) {
3929
- const $$open = $$(true);
4102
+ const $$open = signal.settable(true);
3930
4103
  let dialog;
3931
4104
  let transitionInCallback;
3932
4105
  let transitionOutCallback;
@@ -3936,12 +4109,14 @@ function DialogStore(ctx) {
3936
4109
  elementContext,
3937
4110
  props: {
3938
4111
  ...props,
3939
- $$open,
3940
- transitionIn: (callback) => {
3941
- transitionInCallback = callback;
3942
- },
3943
- transitionOut: (callback) => {
3944
- transitionOutCallback = callback;
4112
+ dialog: {
4113
+ $$open,
4114
+ transitionIn: (callback) => {
4115
+ transitionInCallback = callback;
4116
+ },
4117
+ transitionOut: (callback) => {
4118
+ transitionOutCallback = callback;
4119
+ }
3945
4120
  }
3946
4121
  }
3947
4122
  });
@@ -3955,16 +4130,16 @@ function DialogStore(ctx) {
3955
4130
  return transitionOutCallback;
3956
4131
  }
3957
4132
  };
3958
- $$dialogs.update((current) => {
4133
+ setDialogs((current) => {
3959
4134
  return [...current, dialog];
3960
4135
  });
3961
- const stopObserver = observe($$open, (value) => {
4136
+ const stopObserver = $$open.watch((value) => {
3962
4137
  if (!value) {
3963
4138
  closeDialog();
3964
4139
  }
3965
4140
  });
3966
4141
  function closeDialog() {
3967
- $$dialogs.update((current) => {
4142
+ setDialogs((current) => {
3968
4143
  return current.filter((x) => x !== dialog);
3969
4144
  });
3970
4145
  dialog = void 0;
@@ -3977,8 +4152,6 @@ function DialogStore(ctx) {
3977
4152
  };
3978
4153
  }
3979
4154
  export {
3980
- $,
3981
- $$,
3982
4155
  App,
3983
4156
  DialogStore,
3984
4157
  Fragment,
@@ -3987,12 +4160,17 @@ export {
3987
4160
  RouterStore,
3988
4161
  StoreScope,
3989
4162
  cond,
3990
- isReadable,
3991
- isWritable,
4163
+ derive,
4164
+ designalify,
4165
+ isRef,
4166
+ isSettableSignal,
4167
+ isSignal,
3992
4168
  m,
3993
- observe,
3994
4169
  portal,
4170
+ ref,
3995
4171
  repeat,
3996
- unwrap
4172
+ signal,
4173
+ signalify,
4174
+ watch
3997
4175
  };
3998
4176
  //# sourceMappingURL=index.js.map