@manyducks.co/dolla 0.78.2 → 1.0.0

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