@manyducks.co/dolla 0.68.0 → 0.69.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/README.md +133 -107
- package/lib/app.d.ts +13 -73
- package/lib/index.d.ts +7 -9
- package/lib/index.js +894 -1096
- package/lib/index.js.map +4 -4
- package/lib/nodes/observer.d.ts +1 -1
- package/lib/nodes/outlet.d.ts +1 -1
- package/lib/nodes/repeat.d.ts +1 -1
- package/lib/spring.d.ts +0 -40
- package/lib/state.d.ts +54 -36
- package/lib/store.d.ts +12 -3
- package/lib/stores/language.d.ts +5 -9
- package/lib/stores/router.d.ts +17 -16
- package/lib/types.d.ts +4 -12
- package/lib/view.d.ts +12 -3
- package/lib/views/store-scope.d.ts +3 -3
- package/notes/state.md +71 -0
- package/notes/views.md +28 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -677,6 +677,20 @@ function isReadable(value) {
|
|
|
677
677
|
function isWritable(value) {
|
|
678
678
|
return isReadable(value) && typeof value.set === "function" && typeof value.update === "function";
|
|
679
679
|
}
|
|
680
|
+
function $$(initialValue, config) {
|
|
681
|
+
if (config) {
|
|
682
|
+
return proxy(initialValue, config);
|
|
683
|
+
} else {
|
|
684
|
+
return writable(initialValue);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
function $(...args) {
|
|
688
|
+
if (args.length > 1) {
|
|
689
|
+
return computed(...args);
|
|
690
|
+
} else {
|
|
691
|
+
return readable(args[0]);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
680
694
|
function readable(value) {
|
|
681
695
|
if (isWritable(value)) {
|
|
682
696
|
return {
|
|
@@ -690,89 +704,24 @@ function readable(value) {
|
|
|
690
704
|
return {
|
|
691
705
|
get: () => value,
|
|
692
706
|
[OBSERVE]: (callback) => {
|
|
693
|
-
callback(value
|
|
707
|
+
callback(value);
|
|
694
708
|
return function stop() {
|
|
695
709
|
};
|
|
696
710
|
}
|
|
697
711
|
};
|
|
698
712
|
}
|
|
699
|
-
function
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
if (isReadable(value)) {
|
|
704
|
-
throw new TypeError(`Failed to convert Readable into a Writable; can't add write access to a read-only value.`);
|
|
705
|
-
}
|
|
706
|
-
const observers = [];
|
|
707
|
-
let currentValue = value;
|
|
708
|
-
return {
|
|
709
|
-
// ----- Readable ----- //
|
|
710
|
-
get: () => currentValue,
|
|
711
|
-
[OBSERVE]: (callback) => {
|
|
712
|
-
observers.push(callback);
|
|
713
|
-
function stop() {
|
|
714
|
-
observers.splice(observers.indexOf(callback), 1);
|
|
715
|
-
}
|
|
716
|
-
callback(currentValue, void 0);
|
|
717
|
-
return stop;
|
|
718
|
-
},
|
|
719
|
-
// ----- Writable ----- //
|
|
720
|
-
set: (newValue) => {
|
|
721
|
-
if (!deepEqual(currentValue, newValue)) {
|
|
722
|
-
const previousValue = currentValue;
|
|
723
|
-
currentValue = newValue;
|
|
724
|
-
for (const callback of observers) {
|
|
725
|
-
callback(currentValue, previousValue);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
},
|
|
729
|
-
update: (callback) => {
|
|
730
|
-
const newValue = callback(currentValue);
|
|
731
|
-
if (!deepEqual(currentValue, newValue)) {
|
|
732
|
-
const previousValue = currentValue;
|
|
733
|
-
currentValue = newValue;
|
|
734
|
-
for (const callback2 of observers) {
|
|
735
|
-
callback2(currentValue, previousValue);
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
function observe(readable2, callback) {
|
|
742
|
-
const readables = [];
|
|
743
|
-
if (Array.isArray(readable2) && readable2.every(isReadable)) {
|
|
744
|
-
readables.push(...readable2);
|
|
745
|
-
} else if (isReadable(readable2)) {
|
|
746
|
-
readables.push(readable2);
|
|
747
|
-
} else {
|
|
748
|
-
console.warn(readable2);
|
|
749
|
-
throw new TypeError(
|
|
750
|
-
`Expected one Readable or an array of Readables as the first argument. Got value: ${readable2}, type: ${typeOf(
|
|
751
|
-
readable2
|
|
752
|
-
)}`
|
|
753
|
-
);
|
|
754
|
-
}
|
|
755
|
-
if (readables.length === 0) {
|
|
756
|
-
throw new TypeError(`Expected at least one readable.`);
|
|
713
|
+
function computed(...args) {
|
|
714
|
+
const compute = args.pop();
|
|
715
|
+
if (typeof compute !== "function") {
|
|
716
|
+
throw new TypeError(`Final argument must be a function. Got ${typeOf(compute)}: ${compute}`);
|
|
757
717
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
} else {
|
|
762
|
-
return readables[0][OBSERVE](callback);
|
|
718
|
+
args = args.flat();
|
|
719
|
+
if (args.length < 1) {
|
|
720
|
+
throw new Error(`Must pass at least one state before the callback function.`);
|
|
763
721
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
if (typeof args[1] !== "function") {
|
|
768
|
-
throw new TypeError(
|
|
769
|
-
`When first argument is a Readable the second argument must be a callback function. Got type: ${typeOf(
|
|
770
|
-
args[1]
|
|
771
|
-
)}, value: ${args[1]}`
|
|
772
|
-
);
|
|
773
|
-
}
|
|
774
|
-
const readable2 = args[0];
|
|
775
|
-
const compute = args[1];
|
|
722
|
+
const readables = args;
|
|
723
|
+
if (readables.length === 1) {
|
|
724
|
+
const readable2 = readables[0];
|
|
776
725
|
return {
|
|
777
726
|
get: () => {
|
|
778
727
|
const computed2 = compute(readable2.get());
|
|
@@ -784,27 +733,28 @@ function computed(...args) {
|
|
|
784
733
|
},
|
|
785
734
|
[OBSERVE]: (callback) => {
|
|
786
735
|
let lastComputedValue = UNOBSERVED;
|
|
787
|
-
let lastObservedValue;
|
|
788
736
|
return readable2[OBSERVE]((currentValue) => {
|
|
789
|
-
const computedValue = compute(currentValue
|
|
737
|
+
const computedValue = compute(currentValue);
|
|
738
|
+
if (isReadable(computedValue)) {
|
|
739
|
+
lastComputedValue = computedValue;
|
|
740
|
+
return computedValue[OBSERVE]((current) => {
|
|
741
|
+
callback(current);
|
|
742
|
+
});
|
|
743
|
+
}
|
|
790
744
|
if (!deepEqual(computedValue, lastComputedValue)) {
|
|
791
|
-
|
|
792
|
-
callback(computedValue, previousValue);
|
|
745
|
+
callback(computedValue);
|
|
793
746
|
lastComputedValue = computedValue;
|
|
794
|
-
lastObservedValue = currentValue;
|
|
795
747
|
}
|
|
796
748
|
});
|
|
797
749
|
}
|
|
798
750
|
};
|
|
799
|
-
} else
|
|
751
|
+
} else {
|
|
800
752
|
let updateValue2 = function() {
|
|
801
|
-
const computedValue = compute(observedValues
|
|
753
|
+
const computedValue = compute(...observedValues);
|
|
802
754
|
if (!deepEqual(computedValue, latestComputedValue)) {
|
|
803
|
-
const previousValue = latestComputedValue === UNOBSERVED ? void 0 : latestComputedValue;
|
|
804
755
|
latestComputedValue = computedValue;
|
|
805
|
-
previousObservedValues = observedValues;
|
|
806
756
|
for (const callback of observers) {
|
|
807
|
-
callback(computedValue
|
|
757
|
+
callback(computedValue);
|
|
808
758
|
}
|
|
809
759
|
}
|
|
810
760
|
}, startObserving2 = function() {
|
|
@@ -821,7 +771,6 @@ function computed(...args) {
|
|
|
821
771
|
})
|
|
822
772
|
);
|
|
823
773
|
}
|
|
824
|
-
previousObservedValues = new Array().fill(void 0, 0, readables.length);
|
|
825
774
|
observedValues = readables.map((x) => x.get());
|
|
826
775
|
isObserving = true;
|
|
827
776
|
updateValue2();
|
|
@@ -833,24 +782,9 @@ function computed(...args) {
|
|
|
833
782
|
stopCallbacks = [];
|
|
834
783
|
};
|
|
835
784
|
var updateValue = updateValue2, startObserving = startObserving2, stopObserving = stopObserving2;
|
|
836
|
-
if (typeof args[1] !== "function") {
|
|
837
|
-
throw new TypeError(
|
|
838
|
-
`When first argument is an array of Readables the second argument must be a callback function. Got type: ${typeOf(
|
|
839
|
-
args[1]
|
|
840
|
-
)}, value: ${args[1]}`
|
|
841
|
-
);
|
|
842
|
-
}
|
|
843
|
-
if (!args[0].every(isReadable)) {
|
|
844
|
-
throw new TypeError(
|
|
845
|
-
`Computed expected an array of Readables. Got: [${args[0].map((x) => isReadable(x) ? `Readable<${typeOf(x.get())}>` : typeof x).join(", ")}]`
|
|
846
|
-
);
|
|
847
|
-
}
|
|
848
|
-
const readables = args[0];
|
|
849
|
-
const compute = args[1];
|
|
850
785
|
const observers = [];
|
|
851
786
|
let stopCallbacks = [];
|
|
852
787
|
let isObserving = false;
|
|
853
|
-
let previousObservedValues = [];
|
|
854
788
|
let observedValues = [];
|
|
855
789
|
let latestComputedValue = UNOBSERVED;
|
|
856
790
|
return {
|
|
@@ -858,17 +792,14 @@ function computed(...args) {
|
|
|
858
792
|
if (isObserving) {
|
|
859
793
|
return latestComputedValue;
|
|
860
794
|
} else {
|
|
861
|
-
return compute(
|
|
862
|
-
readables.map((x) => x.get()),
|
|
863
|
-
new Array().fill(void 0, 0, readables.length)
|
|
864
|
-
);
|
|
795
|
+
return compute(...readables.map((x) => x.get()));
|
|
865
796
|
}
|
|
866
797
|
},
|
|
867
798
|
[OBSERVE]: (callback) => {
|
|
868
799
|
if (!isObserving) {
|
|
869
800
|
startObserving2();
|
|
870
801
|
}
|
|
871
|
-
callback(latestComputedValue
|
|
802
|
+
callback(latestComputedValue);
|
|
872
803
|
observers.push(callback);
|
|
873
804
|
return function stop() {
|
|
874
805
|
observers.splice(observers.indexOf(callback), 1);
|
|
@@ -878,42 +809,88 @@ function computed(...args) {
|
|
|
878
809
|
};
|
|
879
810
|
}
|
|
880
811
|
};
|
|
881
|
-
} else {
|
|
882
|
-
throw new TypeError(
|
|
883
|
-
`Expected a Readable or array of Readables as a first argument. Got: ${typeOf(args[0])}, value: ${args[0]}`
|
|
884
|
-
);
|
|
885
812
|
}
|
|
886
813
|
}
|
|
814
|
+
function writable(value) {
|
|
815
|
+
if (isWritable(value)) {
|
|
816
|
+
return value;
|
|
817
|
+
}
|
|
818
|
+
if (isReadable(value)) {
|
|
819
|
+
throw new TypeError(`Failed to convert Readable into a Writable; can't add write access to a read-only value.`);
|
|
820
|
+
}
|
|
821
|
+
const observers = [];
|
|
822
|
+
let currentValue = value;
|
|
823
|
+
return {
|
|
824
|
+
// ----- Readable ----- //
|
|
825
|
+
get: () => currentValue,
|
|
826
|
+
[OBSERVE]: (callback) => {
|
|
827
|
+
observers.push(callback);
|
|
828
|
+
function stop() {
|
|
829
|
+
observers.splice(observers.indexOf(callback), 1);
|
|
830
|
+
}
|
|
831
|
+
callback(currentValue);
|
|
832
|
+
return stop;
|
|
833
|
+
},
|
|
834
|
+
// ----- Writable ----- //
|
|
835
|
+
set: (newValue) => {
|
|
836
|
+
if (!deepEqual(currentValue, newValue)) {
|
|
837
|
+
const previousValue = currentValue;
|
|
838
|
+
currentValue = newValue;
|
|
839
|
+
for (const callback of observers) {
|
|
840
|
+
callback(currentValue, previousValue);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
},
|
|
844
|
+
update: (callback) => {
|
|
845
|
+
const newValue = callback(currentValue);
|
|
846
|
+
if (!deepEqual(currentValue, newValue)) {
|
|
847
|
+
const previousValue = currentValue;
|
|
848
|
+
currentValue = newValue;
|
|
849
|
+
for (const callback2 of observers) {
|
|
850
|
+
callback2(currentValue, previousValue);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
}
|
|
887
856
|
function proxy(source, config) {
|
|
888
857
|
if (!isReadable(source)) {
|
|
889
858
|
throw new TypeError(`Proxy source must be a Readable.`);
|
|
890
859
|
}
|
|
891
|
-
const observers = [];
|
|
892
|
-
const currentValue = () => config.get(source);
|
|
893
860
|
return {
|
|
894
861
|
// ----- Readable ----- //
|
|
895
|
-
get: () => config.get(
|
|
862
|
+
get: () => config.get(),
|
|
896
863
|
[OBSERVE]: (callback) => {
|
|
897
864
|
let lastComputedValue = UNOBSERVED;
|
|
898
|
-
return source
|
|
899
|
-
const computedValue = config.get(
|
|
865
|
+
return observe(source, (_) => {
|
|
866
|
+
const computedValue = config.get();
|
|
900
867
|
if (!deepEqual(computedValue, lastComputedValue)) {
|
|
901
|
-
|
|
902
|
-
callback(computedValue, previousValue);
|
|
868
|
+
callback(computedValue);
|
|
903
869
|
lastComputedValue = computedValue;
|
|
904
870
|
}
|
|
905
871
|
});
|
|
906
872
|
},
|
|
907
873
|
// ----- Writable ----- //
|
|
908
|
-
set: (
|
|
909
|
-
config.set(
|
|
874
|
+
set: (value) => {
|
|
875
|
+
config.set(value);
|
|
910
876
|
},
|
|
911
877
|
update: (callback) => {
|
|
912
|
-
|
|
913
|
-
config.set(source, newValue);
|
|
878
|
+
config.set(callback(config.get()));
|
|
914
879
|
}
|
|
915
880
|
};
|
|
916
881
|
}
|
|
882
|
+
function observe(...args) {
|
|
883
|
+
const callback = args.pop();
|
|
884
|
+
const readables = args.flat();
|
|
885
|
+
if (readables.length === 0) {
|
|
886
|
+
throw new TypeError(`Expected at least one readable.`);
|
|
887
|
+
}
|
|
888
|
+
if (readables.length > 1) {
|
|
889
|
+
return computed(...readables, callback)[OBSERVE](() => null);
|
|
890
|
+
} else {
|
|
891
|
+
return readables[0][OBSERVE](callback);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
917
894
|
function unwrap(value) {
|
|
918
895
|
if (isReadable(value)) {
|
|
919
896
|
return value.get();
|
|
@@ -1640,7 +1617,7 @@ function initView(config) {
|
|
|
1640
1617
|
stores: /* @__PURE__ */ new Map(),
|
|
1641
1618
|
parent: config.elementContext
|
|
1642
1619
|
};
|
|
1643
|
-
const $$children =
|
|
1620
|
+
const $$children = $$(renderMarkupToDOM(config.children ?? [], { appContext, elementContext }));
|
|
1644
1621
|
let isConnected = false;
|
|
1645
1622
|
const stopObserverCallbacks = [];
|
|
1646
1623
|
const connectedCallbacks = [];
|
|
@@ -1699,19 +1676,20 @@ function initView(config) {
|
|
|
1699
1676
|
crash(error) {
|
|
1700
1677
|
config.appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
1701
1678
|
},
|
|
1702
|
-
observe(
|
|
1679
|
+
observe(...args) {
|
|
1680
|
+
const callback = args.pop();
|
|
1703
1681
|
if (isConnected) {
|
|
1704
|
-
const stop = observe(
|
|
1682
|
+
const stop = observe(args, callback);
|
|
1705
1683
|
stopObserverCallbacks.push(stop);
|
|
1706
1684
|
} else {
|
|
1707
1685
|
connectedCallbacks.push(() => {
|
|
1708
|
-
const stop = observe(
|
|
1686
|
+
const stop = observe(args, callback);
|
|
1709
1687
|
stopObserverCallbacks.push(stop);
|
|
1710
1688
|
});
|
|
1711
1689
|
}
|
|
1712
1690
|
},
|
|
1713
1691
|
outlet() {
|
|
1714
|
-
return m("$outlet", { $children:
|
|
1692
|
+
return m("$outlet", { $children: $($$children) });
|
|
1715
1693
|
}
|
|
1716
1694
|
};
|
|
1717
1695
|
const debugChannel = appContext.debugHub.channel({
|
|
@@ -1901,8 +1879,8 @@ var Repeat = class {
|
|
|
1901
1879
|
connected.$$index.set(potential.index);
|
|
1902
1880
|
newItems[potential.index] = connected;
|
|
1903
1881
|
} else {
|
|
1904
|
-
const $$value =
|
|
1905
|
-
const $$index =
|
|
1882
|
+
const $$value = $$(potential.value);
|
|
1883
|
+
const $$index = $$(potential.index);
|
|
1906
1884
|
newItems[potential.index] = {
|
|
1907
1885
|
key: potential.key,
|
|
1908
1886
|
$$value,
|
|
@@ -1911,7 +1889,7 @@ var Repeat = class {
|
|
|
1911
1889
|
view: RepeatItemView,
|
|
1912
1890
|
appContext: this.appContext,
|
|
1913
1891
|
elementContext: this.elementContext,
|
|
1914
|
-
props: { $value:
|
|
1892
|
+
props: { $value: $($$value), $index: $($$index), renderFn: this.renderFn }
|
|
1915
1893
|
})
|
|
1916
1894
|
};
|
|
1917
1895
|
}
|
|
@@ -2017,7 +1995,7 @@ function m(type, props, ...children) {
|
|
|
2017
1995
|
};
|
|
2018
1996
|
}
|
|
2019
1997
|
function cond(predicate, thenContent, elseContent) {
|
|
2020
|
-
const $predicate =
|
|
1998
|
+
const $predicate = $(predicate);
|
|
2021
1999
|
return m("$cond", {
|
|
2022
2000
|
$predicate,
|
|
2023
2001
|
thenContent,
|
|
@@ -2025,7 +2003,7 @@ function cond(predicate, thenContent, elseContent) {
|
|
|
2025
2003
|
});
|
|
2026
2004
|
}
|
|
2027
2005
|
function repeat(items, keyFn, renderFn) {
|
|
2028
|
-
const $items =
|
|
2006
|
+
const $items = $(items);
|
|
2029
2007
|
return m("$repeat", { $items, keyFn, renderFn });
|
|
2030
2008
|
}
|
|
2031
2009
|
function portal(content, parent) {
|
|
@@ -2231,7 +2209,9 @@ function initStore(config) {
|
|
|
2231
2209
|
crash(error) {
|
|
2232
2210
|
config.appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
2233
2211
|
},
|
|
2234
|
-
observe(
|
|
2212
|
+
observe(...args) {
|
|
2213
|
+
const callback = args.pop();
|
|
2214
|
+
const readables = args.flat();
|
|
2235
2215
|
if (isConnected) {
|
|
2236
2216
|
const stop = observe(readables, callback);
|
|
2237
2217
|
stopObserverCallbacks.push(stop);
|
|
@@ -2303,130 +2283,13 @@ function initStore(config) {
|
|
|
2303
2283
|
};
|
|
2304
2284
|
}
|
|
2305
2285
|
|
|
2306
|
-
// src/stores/dialog.ts
|
|
2307
|
-
function DialogStore(ctx) {
|
|
2308
|
-
ctx.name = "dolla/dialog";
|
|
2309
|
-
const { appContext, elementContext } = getStoreSecrets(ctx);
|
|
2310
|
-
const container = document.createElement("div");
|
|
2311
|
-
container.style.position = "fixed";
|
|
2312
|
-
container.style.top = "0";
|
|
2313
|
-
container.style.right = "0";
|
|
2314
|
-
container.style.bottom = "0";
|
|
2315
|
-
container.style.left = "0";
|
|
2316
|
-
container.style.zIndex = "99999";
|
|
2317
|
-
const $$dialogs = writable([]);
|
|
2318
|
-
let activeDialogs = [];
|
|
2319
|
-
function dialogChangedCallback() {
|
|
2320
|
-
if (activeDialogs.length > 0) {
|
|
2321
|
-
if (!container.parentNode) {
|
|
2322
|
-
document.body.appendChild(container);
|
|
2323
|
-
}
|
|
2324
|
-
} else {
|
|
2325
|
-
if (container.parentNode) {
|
|
2326
|
-
document.body.removeChild(container);
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2330
|
-
ctx.observe($$dialogs, (dialogs) => {
|
|
2331
|
-
requestAnimationFrame(() => {
|
|
2332
|
-
let removed = [];
|
|
2333
|
-
let added = [];
|
|
2334
|
-
for (const dialog of activeDialogs) {
|
|
2335
|
-
if (!dialogs.includes(dialog)) {
|
|
2336
|
-
removed.push(dialog);
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
for (const dialog of dialogs) {
|
|
2340
|
-
if (!activeDialogs.includes(dialog)) {
|
|
2341
|
-
added.push(dialog);
|
|
2342
|
-
}
|
|
2343
|
-
}
|
|
2344
|
-
for (const dialog of removed) {
|
|
2345
|
-
if (dialog.transitionOutCallback) {
|
|
2346
|
-
dialog.transitionOutCallback().then(() => {
|
|
2347
|
-
dialog.instance.disconnect();
|
|
2348
|
-
activeDialogs.splice(activeDialogs.indexOf(dialog), 1);
|
|
2349
|
-
dialogChangedCallback();
|
|
2350
|
-
});
|
|
2351
|
-
} else {
|
|
2352
|
-
dialog.instance.disconnect();
|
|
2353
|
-
activeDialogs.splice(activeDialogs.indexOf(dialog), 1);
|
|
2354
|
-
}
|
|
2355
|
-
}
|
|
2356
|
-
for (const dialog of added) {
|
|
2357
|
-
dialog.instance.connect(container);
|
|
2358
|
-
if (dialog.transitionInCallback) {
|
|
2359
|
-
dialog.transitionInCallback();
|
|
2360
|
-
}
|
|
2361
|
-
activeDialogs.push(dialog);
|
|
2362
|
-
}
|
|
2363
|
-
dialogChangedCallback();
|
|
2364
|
-
});
|
|
2365
|
-
});
|
|
2366
|
-
ctx.onDisconnected(() => {
|
|
2367
|
-
if (container.parentNode) {
|
|
2368
|
-
document.body.removeChild(container);
|
|
2369
|
-
}
|
|
2370
|
-
});
|
|
2371
|
-
function open(view, props) {
|
|
2372
|
-
const $$open = writable(true);
|
|
2373
|
-
let dialog;
|
|
2374
|
-
let transitionInCallback;
|
|
2375
|
-
let transitionOutCallback;
|
|
2376
|
-
let instance = initView({
|
|
2377
|
-
view,
|
|
2378
|
-
appContext,
|
|
2379
|
-
elementContext,
|
|
2380
|
-
props: {
|
|
2381
|
-
...props,
|
|
2382
|
-
$$open,
|
|
2383
|
-
transitionIn: (callback) => {
|
|
2384
|
-
transitionInCallback = callback;
|
|
2385
|
-
},
|
|
2386
|
-
transitionOut: (callback) => {
|
|
2387
|
-
transitionOutCallback = callback;
|
|
2388
|
-
}
|
|
2389
|
-
}
|
|
2390
|
-
});
|
|
2391
|
-
dialog = {
|
|
2392
|
-
instance,
|
|
2393
|
-
// These must be getters because the fns passed to props aren't called until before connect.
|
|
2394
|
-
get transitionInCallback() {
|
|
2395
|
-
return transitionInCallback;
|
|
2396
|
-
},
|
|
2397
|
-
get transitionOutCallback() {
|
|
2398
|
-
return transitionOutCallback;
|
|
2399
|
-
}
|
|
2400
|
-
};
|
|
2401
|
-
$$dialogs.update((current) => {
|
|
2402
|
-
return [...current, dialog];
|
|
2403
|
-
});
|
|
2404
|
-
const stopObserver = observe($$open, (value) => {
|
|
2405
|
-
if (!value) {
|
|
2406
|
-
closeDialog();
|
|
2407
|
-
}
|
|
2408
|
-
});
|
|
2409
|
-
function closeDialog() {
|
|
2410
|
-
$$dialogs.update((current) => {
|
|
2411
|
-
return current.filter((x) => x !== dialog);
|
|
2412
|
-
});
|
|
2413
|
-
dialog = void 0;
|
|
2414
|
-
stopObserver();
|
|
2415
|
-
}
|
|
2416
|
-
return closeDialog;
|
|
2417
|
-
}
|
|
2418
|
-
return {
|
|
2419
|
-
open
|
|
2420
|
-
};
|
|
2421
|
-
}
|
|
2422
|
-
|
|
2423
2286
|
// src/stores/document.ts
|
|
2424
2287
|
function DocumentStore(ctx) {
|
|
2425
2288
|
ctx.name = "dolla/document";
|
|
2426
|
-
const $$title =
|
|
2427
|
-
const $$visibility =
|
|
2428
|
-
const $$orientation =
|
|
2429
|
-
const $$colorScheme =
|
|
2289
|
+
const $$title = $$(document.title);
|
|
2290
|
+
const $$visibility = $$(document.visibilityState);
|
|
2291
|
+
const $$orientation = $$("landscape");
|
|
2292
|
+
const $$colorScheme = $$("light");
|
|
2430
2293
|
ctx.observe($$title, (current) => {
|
|
2431
2294
|
document.title = current;
|
|
2432
2295
|
});
|
|
@@ -2460,337 +2323,12 @@ function DocumentStore(ctx) {
|
|
|
2460
2323
|
});
|
|
2461
2324
|
return {
|
|
2462
2325
|
$$title,
|
|
2463
|
-
$visibility:
|
|
2464
|
-
$orientation:
|
|
2465
|
-
$colorScheme:
|
|
2326
|
+
$visibility: $($$visibility),
|
|
2327
|
+
$orientation: $($$orientation),
|
|
2328
|
+
$colorScheme: $($$colorScheme)
|
|
2466
2329
|
};
|
|
2467
2330
|
}
|
|
2468
2331
|
|
|
2469
|
-
// src/stores/http.ts
|
|
2470
|
-
function HTTPStore(ctx) {
|
|
2471
|
-
ctx.name = "dolla/http";
|
|
2472
|
-
const fetch = ctx.options.fetch ?? getDefaultFetch();
|
|
2473
|
-
const middleware = [];
|
|
2474
|
-
async function request(method, uri, options) {
|
|
2475
|
-
return makeRequest({ ...options, method, uri, middleware, fetch });
|
|
2476
|
-
}
|
|
2477
|
-
return {
|
|
2478
|
-
/**
|
|
2479
|
-
* Adds a new middleware that will apply to subsequent requests.
|
|
2480
|
-
* Returns a function to remove this middleware.
|
|
2481
|
-
*
|
|
2482
|
-
* @param middleware - A middleware function that will intercept requests.
|
|
2483
|
-
*/
|
|
2484
|
-
middleware(fn) {
|
|
2485
|
-
middleware.push(fn);
|
|
2486
|
-
return function remove() {
|
|
2487
|
-
middleware.splice(middleware.indexOf(fn), 1);
|
|
2488
|
-
};
|
|
2489
|
-
},
|
|
2490
|
-
async get(uri, options) {
|
|
2491
|
-
return request("get", uri, options);
|
|
2492
|
-
},
|
|
2493
|
-
async put(uri, options) {
|
|
2494
|
-
return request("put", uri, options);
|
|
2495
|
-
},
|
|
2496
|
-
async patch(uri, options) {
|
|
2497
|
-
return request("patch", uri, options);
|
|
2498
|
-
},
|
|
2499
|
-
async post(uri, options) {
|
|
2500
|
-
return request("post", uri, options);
|
|
2501
|
-
},
|
|
2502
|
-
async delete(uri, options) {
|
|
2503
|
-
return request("delete", uri, options);
|
|
2504
|
-
},
|
|
2505
|
-
async head(uri, options) {
|
|
2506
|
-
return request("head", uri, options);
|
|
2507
|
-
},
|
|
2508
|
-
async options(uri, options) {
|
|
2509
|
-
return request("options", uri, options);
|
|
2510
|
-
},
|
|
2511
|
-
async trace(uri, options) {
|
|
2512
|
-
return request("trace", uri, options);
|
|
2513
|
-
}
|
|
2514
|
-
};
|
|
2515
|
-
}
|
|
2516
|
-
function getDefaultFetch() {
|
|
2517
|
-
if (typeof window !== "undefined" && window.fetch) {
|
|
2518
|
-
return window.fetch.bind(window);
|
|
2519
|
-
}
|
|
2520
|
-
if (typeof global !== "undefined" && global.fetch) {
|
|
2521
|
-
return global.fetch.bind(global);
|
|
2522
|
-
}
|
|
2523
|
-
throw new Error("Running in neither browser nor node. Please run this app in one of the supported environments.");
|
|
2524
|
-
}
|
|
2525
|
-
var HTTPResponseError = class extends Error {
|
|
2526
|
-
response;
|
|
2527
|
-
constructor(response) {
|
|
2528
|
-
const { status, statusText, method, uri } = response;
|
|
2529
|
-
const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${uri})`;
|
|
2530
|
-
super(message);
|
|
2531
|
-
this.response = response;
|
|
2532
|
-
}
|
|
2533
|
-
};
|
|
2534
|
-
async function makeRequest(config) {
|
|
2535
|
-
const { headers, query, fetch, middleware } = config;
|
|
2536
|
-
const request = {
|
|
2537
|
-
method: config.method,
|
|
2538
|
-
uri: config.uri,
|
|
2539
|
-
get sameOrigin() {
|
|
2540
|
-
return !request.uri.startsWith("http");
|
|
2541
|
-
},
|
|
2542
|
-
query: new URLSearchParams(),
|
|
2543
|
-
headers: new Headers(),
|
|
2544
|
-
body: config.body
|
|
2545
|
-
};
|
|
2546
|
-
if (headers) {
|
|
2547
|
-
if (headers instanceof Map || headers instanceof Headers) {
|
|
2548
|
-
headers.forEach((value, key) => {
|
|
2549
|
-
request.headers.set(key, value);
|
|
2550
|
-
});
|
|
2551
|
-
} else if (headers != null && typeof headers === "object" && !Array.isArray(headers)) {
|
|
2552
|
-
for (const name in headers) {
|
|
2553
|
-
request.headers.set(name, String(headers[name]));
|
|
2554
|
-
}
|
|
2555
|
-
} else {
|
|
2556
|
-
throw new TypeError(`Unknown headers type. Got: ${headers}`);
|
|
2557
|
-
}
|
|
2558
|
-
}
|
|
2559
|
-
if (query) {
|
|
2560
|
-
if (query instanceof Map || query instanceof URLSearchParams) {
|
|
2561
|
-
query.forEach((value, key) => {
|
|
2562
|
-
request.query.set(key, value);
|
|
2563
|
-
});
|
|
2564
|
-
} else if (query != null && typeof query === "object" && !Array.isArray(query)) {
|
|
2565
|
-
for (const name in query) {
|
|
2566
|
-
request.query.set(name, String(query[name]));
|
|
2567
|
-
}
|
|
2568
|
-
} else {
|
|
2569
|
-
throw new TypeError(`Unknown query params type. Got: ${query}`);
|
|
2570
|
-
}
|
|
2571
|
-
}
|
|
2572
|
-
let response;
|
|
2573
|
-
const handler = async () => {
|
|
2574
|
-
const query2 = request.query.toString();
|
|
2575
|
-
const fullURL = request.query.keys.length > 0 ? request.uri + "?" + query2 : request.uri;
|
|
2576
|
-
let reqBody;
|
|
2577
|
-
if (!request.headers.has("content-type") && isObject(request.body)) {
|
|
2578
|
-
request.headers.set("content-type", "application/json");
|
|
2579
|
-
reqBody = JSON.stringify(request.body);
|
|
2580
|
-
} else {
|
|
2581
|
-
reqBody = request.body;
|
|
2582
|
-
}
|
|
2583
|
-
const fetched = await fetch(fullURL, {
|
|
2584
|
-
method: request.method,
|
|
2585
|
-
headers: request.headers,
|
|
2586
|
-
body: reqBody
|
|
2587
|
-
});
|
|
2588
|
-
const headers2 = Object.fromEntries(fetched.headers.entries());
|
|
2589
|
-
const contentType = headers2["content-type"];
|
|
2590
|
-
let body;
|
|
2591
|
-
if (contentType?.includes("application/json")) {
|
|
2592
|
-
body = await fetched.json();
|
|
2593
|
-
} else if (contentType?.includes("application/x-www-form-urlencoded")) {
|
|
2594
|
-
body = await fetched.formData();
|
|
2595
|
-
} else {
|
|
2596
|
-
body = await fetched.text();
|
|
2597
|
-
}
|
|
2598
|
-
response = {
|
|
2599
|
-
method: request.method,
|
|
2600
|
-
uri: request.uri,
|
|
2601
|
-
status: fetched.status,
|
|
2602
|
-
statusText: fetched.statusText,
|
|
2603
|
-
headers: headers2,
|
|
2604
|
-
body
|
|
2605
|
-
};
|
|
2606
|
-
};
|
|
2607
|
-
if (middleware.length > 0) {
|
|
2608
|
-
const mount = (index = 0) => {
|
|
2609
|
-
const current = middleware[index];
|
|
2610
|
-
const next = middleware[index + 1] ? mount(index + 1) : handler;
|
|
2611
|
-
return async () => current(request, async () => {
|
|
2612
|
-
await next();
|
|
2613
|
-
return response;
|
|
2614
|
-
});
|
|
2615
|
-
};
|
|
2616
|
-
await mount()();
|
|
2617
|
-
} else {
|
|
2618
|
-
await handler();
|
|
2619
|
-
}
|
|
2620
|
-
if (response.status < 200 || response.status >= 400) {
|
|
2621
|
-
throw new HTTPResponseError(response);
|
|
2622
|
-
}
|
|
2623
|
-
return response;
|
|
2624
|
-
}
|
|
2625
|
-
|
|
2626
|
-
// src/stores/language.ts
|
|
2627
|
-
function LanguageStore(ctx) {
|
|
2628
|
-
ctx.name = "dolla/language";
|
|
2629
|
-
const languages = /* @__PURE__ */ new Map();
|
|
2630
|
-
Object.entries(ctx.options.languages).forEach(([tag, config]) => {
|
|
2631
|
-
languages.set(tag, new Language(tag, config));
|
|
2632
|
-
});
|
|
2633
|
-
ctx.info(
|
|
2634
|
-
`App supports ${languages.size} language${languages.size === 1 ? "" : "s"}: '${[...languages.keys()].join("', '")}'`
|
|
2635
|
-
);
|
|
2636
|
-
const $$isLoaded = writable(false);
|
|
2637
|
-
const $$language = writable(void 0);
|
|
2638
|
-
const $$translation = writable(void 0);
|
|
2639
|
-
const $noLanguageValue = readable("[NO LANGUAGE SET]");
|
|
2640
|
-
const translationCache = [];
|
|
2641
|
-
function getCached(key, values) {
|
|
2642
|
-
for (const entry of translationCache) {
|
|
2643
|
-
if (entry[0] === key && deepEqual(entry[1], values)) {
|
|
2644
|
-
return entry[2];
|
|
2645
|
-
}
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
function replaceMustaches(template, values) {
|
|
2649
|
-
for (const name in values) {
|
|
2650
|
-
template = template.replace(`{{${name}}}`, String(values[name]));
|
|
2651
|
-
}
|
|
2652
|
-
return template;
|
|
2653
|
-
}
|
|
2654
|
-
const currentLanguage = ctx.options.currentLanguage ? languages.get(ctx.options.currentLanguage) : languages.get([...languages.keys()][0]);
|
|
2655
|
-
if (currentLanguage == null) {
|
|
2656
|
-
$$isLoaded.set(true);
|
|
2657
|
-
} else {
|
|
2658
|
-
ctx.info(`Current language is '${currentLanguage.tag}'.`);
|
|
2659
|
-
currentLanguage.getTranslation().then((translation) => {
|
|
2660
|
-
$$language.set(currentLanguage.tag);
|
|
2661
|
-
$$translation.set(translation);
|
|
2662
|
-
$$isLoaded.set(true);
|
|
2663
|
-
});
|
|
2664
|
-
}
|
|
2665
|
-
return {
|
|
2666
|
-
$isLoaded: readable($$isLoaded),
|
|
2667
|
-
$currentLanguage: readable($$language),
|
|
2668
|
-
supportedLanguages: [...languages.keys()],
|
|
2669
|
-
async setLanguage(tag) {
|
|
2670
|
-
if (!languages.has(tag)) {
|
|
2671
|
-
throw new Error(`Language '${tag}' is not supported.`);
|
|
2672
|
-
}
|
|
2673
|
-
const lang = languages.get(tag);
|
|
2674
|
-
try {
|
|
2675
|
-
const translation = await lang.getTranslation();
|
|
2676
|
-
$$translation.set(translation);
|
|
2677
|
-
$$language.set(tag);
|
|
2678
|
-
ctx.info("set language to " + tag);
|
|
2679
|
-
} catch (error) {
|
|
2680
|
-
if (error instanceof Error) {
|
|
2681
|
-
ctx.crash(error);
|
|
2682
|
-
}
|
|
2683
|
-
}
|
|
2684
|
-
},
|
|
2685
|
-
/**
|
|
2686
|
-
* Returns a Readable of the translated value.
|
|
2687
|
-
|
|
2688
|
-
* @param key - Key to the translated value.
|
|
2689
|
-
* @param values - A map of {{placeholder}} names and the values to replace them with.
|
|
2690
|
-
*/
|
|
2691
|
-
translate(key, values) {
|
|
2692
|
-
if (!$$language.get()) {
|
|
2693
|
-
return $noLanguageValue;
|
|
2694
|
-
}
|
|
2695
|
-
const cached = getCached(key, values);
|
|
2696
|
-
if (cached) {
|
|
2697
|
-
return cached;
|
|
2698
|
-
}
|
|
2699
|
-
if (values) {
|
|
2700
|
-
const readableValues = {};
|
|
2701
|
-
for (const [key2, value] of Object.entries(values)) {
|
|
2702
|
-
if (isReadable(value)) {
|
|
2703
|
-
readableValues[key2] = value;
|
|
2704
|
-
}
|
|
2705
|
-
}
|
|
2706
|
-
const readableEntries = Object.entries(readableValues);
|
|
2707
|
-
if (readableEntries.length > 0) {
|
|
2708
|
-
const $merged = computed([$$translation, ...readableEntries.map((x) => x[1])], ([t, ...entryValues]) => {
|
|
2709
|
-
const entries = entryValues.map((_, i) => readableEntries[i]);
|
|
2710
|
-
const mergedValues = {
|
|
2711
|
-
...values
|
|
2712
|
-
};
|
|
2713
|
-
for (let i = 0; i < entries.length; i++) {
|
|
2714
|
-
const key2 = entries[i][0];
|
|
2715
|
-
mergedValues[key2] = entryValues[i];
|
|
2716
|
-
}
|
|
2717
|
-
const result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
2718
|
-
return replaceMustaches(result, mergedValues);
|
|
2719
|
-
});
|
|
2720
|
-
translationCache.push([key, values, $merged]);
|
|
2721
|
-
return $merged;
|
|
2722
|
-
}
|
|
2723
|
-
}
|
|
2724
|
-
const $replaced = computed($$translation, (t) => {
|
|
2725
|
-
let result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
2726
|
-
if (values) {
|
|
2727
|
-
result = replaceMustaches(result, values);
|
|
2728
|
-
}
|
|
2729
|
-
return result;
|
|
2730
|
-
});
|
|
2731
|
-
translationCache.push([key, values, $replaced]);
|
|
2732
|
-
return $replaced;
|
|
2733
|
-
}
|
|
2734
|
-
};
|
|
2735
|
-
}
|
|
2736
|
-
function resolve(object, key) {
|
|
2737
|
-
const parsed = String(key).split(/[\.\[\]]/).filter((part) => part.trim() !== "");
|
|
2738
|
-
let value = object;
|
|
2739
|
-
while (parsed.length > 0) {
|
|
2740
|
-
const part = parsed.shift();
|
|
2741
|
-
if (value != null) {
|
|
2742
|
-
value = value[part];
|
|
2743
|
-
} else {
|
|
2744
|
-
value = void 0;
|
|
2745
|
-
}
|
|
2746
|
-
}
|
|
2747
|
-
return value;
|
|
2748
|
-
}
|
|
2749
|
-
var Language = class {
|
|
2750
|
-
#tag;
|
|
2751
|
-
#config;
|
|
2752
|
-
#translation;
|
|
2753
|
-
get tag() {
|
|
2754
|
-
return this.#tag;
|
|
2755
|
-
}
|
|
2756
|
-
constructor(tag, config) {
|
|
2757
|
-
this.#tag = tag;
|
|
2758
|
-
this.#config = config;
|
|
2759
|
-
}
|
|
2760
|
-
async getTranslation() {
|
|
2761
|
-
if (!this.#translation) {
|
|
2762
|
-
if (isFunction(this.#config.translation)) {
|
|
2763
|
-
const result = this.#config.translation();
|
|
2764
|
-
if (isPromise(result)) {
|
|
2765
|
-
const resolved = await result;
|
|
2766
|
-
assertObject(
|
|
2767
|
-
resolved,
|
|
2768
|
-
`Translation promise of language '${this.#tag}' must resolve to an object of translated strings. Got type: %t, value: %v`
|
|
2769
|
-
);
|
|
2770
|
-
this.#translation = resolved;
|
|
2771
|
-
} else if (isObject(result)) {
|
|
2772
|
-
this.#translation = result;
|
|
2773
|
-
} else {
|
|
2774
|
-
throw new TypeError(
|
|
2775
|
-
`Translation function of '${this.#tag}' must return an object or promise. Got type: ${typeOf(
|
|
2776
|
-
result
|
|
2777
|
-
)}, value: ${result}`
|
|
2778
|
-
);
|
|
2779
|
-
}
|
|
2780
|
-
} else if (isObject(this.#config.translation)) {
|
|
2781
|
-
this.#translation = this.#config.translation;
|
|
2782
|
-
} else {
|
|
2783
|
-
throw new TypeError(
|
|
2784
|
-
`Translation of '${this.#tag}' must be an object of translated strings, a function that returns one, or an async function that resolves to one. Got type: ${typeOf(
|
|
2785
|
-
this.#config.translation
|
|
2786
|
-
)}, value: ${this.#config.translation}`
|
|
2787
|
-
);
|
|
2788
|
-
}
|
|
2789
|
-
}
|
|
2790
|
-
return this.#translation;
|
|
2791
|
-
}
|
|
2792
|
-
};
|
|
2793
|
-
|
|
2794
2332
|
// src/stores/render.ts
|
|
2795
2333
|
function RenderStore(ctx) {
|
|
2796
2334
|
ctx.name = "dolla/render";
|
|
@@ -2875,8 +2413,288 @@ function RenderStore(ctx) {
|
|
|
2875
2413
|
};
|
|
2876
2414
|
}
|
|
2877
2415
|
|
|
2878
|
-
//
|
|
2879
|
-
function
|
|
2416
|
+
// src/app.ts
|
|
2417
|
+
function DefaultRootView(_, ctx) {
|
|
2418
|
+
return ctx.outlet();
|
|
2419
|
+
}
|
|
2420
|
+
function isAppOptions(value) {
|
|
2421
|
+
return isObject(value);
|
|
2422
|
+
}
|
|
2423
|
+
function App(options) {
|
|
2424
|
+
if (options && !isAppOptions(options)) {
|
|
2425
|
+
throw new TypeError(`App options must be an object. Got: ${options}`);
|
|
2426
|
+
}
|
|
2427
|
+
let isConnected = false;
|
|
2428
|
+
let mainView = m(options?.view ?? DefaultRootView);
|
|
2429
|
+
let configureCallback;
|
|
2430
|
+
const settings = merge(
|
|
2431
|
+
{
|
|
2432
|
+
debug: {
|
|
2433
|
+
filter: "*,-dolla/*",
|
|
2434
|
+
log: "development",
|
|
2435
|
+
// Only print logs in development.
|
|
2436
|
+
warn: "development",
|
|
2437
|
+
// Only print warnings in development.
|
|
2438
|
+
error: true
|
|
2439
|
+
// Always print errors.
|
|
2440
|
+
},
|
|
2441
|
+
mode: "production"
|
|
2442
|
+
},
|
|
2443
|
+
options ?? {}
|
|
2444
|
+
);
|
|
2445
|
+
const stores = /* @__PURE__ */ new Map([
|
|
2446
|
+
["render", { store: RenderStore }],
|
|
2447
|
+
["document", { store: DocumentStore }]
|
|
2448
|
+
]);
|
|
2449
|
+
if (options?.stores) {
|
|
2450
|
+
for (const entry of options.stores) {
|
|
2451
|
+
assertFunction(entry.store, `Expected a store function. Got type: %t, value: %v`);
|
|
2452
|
+
stores.set(entry.store, entry);
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
const crashCollector = new CrashCollector();
|
|
2456
|
+
const debugHub = new DebugHub({ ...settings.debug, crashCollector, mode: settings.mode });
|
|
2457
|
+
const debugChannel = debugHub.channel({ name: "dolla/App" });
|
|
2458
|
+
crashCollector.onError(async ({ error, severity, componentName }) => {
|
|
2459
|
+
if (severity === "crash") {
|
|
2460
|
+
await disconnect();
|
|
2461
|
+
const instance = initView({
|
|
2462
|
+
view: DefaultCrashPage,
|
|
2463
|
+
appContext,
|
|
2464
|
+
elementContext,
|
|
2465
|
+
props: {
|
|
2466
|
+
message: error.message,
|
|
2467
|
+
error,
|
|
2468
|
+
componentName
|
|
2469
|
+
}
|
|
2470
|
+
});
|
|
2471
|
+
instance.connect(appContext.rootElement);
|
|
2472
|
+
}
|
|
2473
|
+
});
|
|
2474
|
+
async function connect(selector) {
|
|
2475
|
+
return new Promise(async (resolve2) => {
|
|
2476
|
+
let element = null;
|
|
2477
|
+
if (isString(selector)) {
|
|
2478
|
+
element = document.querySelector(selector);
|
|
2479
|
+
assertInstanceOf(HTMLElement, element, `Selector string '${selector}' did not match any element.`);
|
|
2480
|
+
}
|
|
2481
|
+
assertInstanceOf(HTMLElement, element, "Expected a DOM node or a selector string. Got type: %t, value: %v");
|
|
2482
|
+
appContext.rootElement = element;
|
|
2483
|
+
appContext.rootView = initView({
|
|
2484
|
+
view: mainView.type,
|
|
2485
|
+
props: mainView.props,
|
|
2486
|
+
appContext,
|
|
2487
|
+
elementContext
|
|
2488
|
+
});
|
|
2489
|
+
for (let [key, item] of stores.entries()) {
|
|
2490
|
+
const { store, options: options2 } = item;
|
|
2491
|
+
const channelPrefix = isString(key) ? "dolla/store" : "store";
|
|
2492
|
+
const label = isString(key) ? key : store.name ?? "(anonymous)";
|
|
2493
|
+
const config = {
|
|
2494
|
+
store,
|
|
2495
|
+
appContext,
|
|
2496
|
+
elementContext,
|
|
2497
|
+
channelPrefix,
|
|
2498
|
+
label,
|
|
2499
|
+
options: options2 ?? {}
|
|
2500
|
+
};
|
|
2501
|
+
const instance = initStore(config);
|
|
2502
|
+
instance.setup();
|
|
2503
|
+
stores.set(key, { ...item, instance });
|
|
2504
|
+
}
|
|
2505
|
+
for (const { instance } of stores.values()) {
|
|
2506
|
+
instance.connect();
|
|
2507
|
+
}
|
|
2508
|
+
if (configureCallback) {
|
|
2509
|
+
await configureCallback({
|
|
2510
|
+
// TODO: Add context methods
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
const done = () => {
|
|
2514
|
+
appContext.rootView.connect(appContext.rootElement);
|
|
2515
|
+
isConnected = true;
|
|
2516
|
+
resolve2();
|
|
2517
|
+
};
|
|
2518
|
+
done();
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2521
|
+
async function disconnect() {
|
|
2522
|
+
if (isConnected) {
|
|
2523
|
+
appContext.rootView.disconnect();
|
|
2524
|
+
isConnected = false;
|
|
2525
|
+
for (const { instance } of stores.values()) {
|
|
2526
|
+
instance.disconnect();
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
const appContext = {
|
|
2531
|
+
crashCollector,
|
|
2532
|
+
debugHub,
|
|
2533
|
+
stores,
|
|
2534
|
+
mode: settings.mode ?? "production"
|
|
2535
|
+
};
|
|
2536
|
+
const elementContext = {
|
|
2537
|
+
stores: /* @__PURE__ */ new Map()
|
|
2538
|
+
};
|
|
2539
|
+
const app = {
|
|
2540
|
+
connect,
|
|
2541
|
+
disconnect,
|
|
2542
|
+
get isConnected() {
|
|
2543
|
+
return isConnected;
|
|
2544
|
+
},
|
|
2545
|
+
// language(tag: string, config: LanguageConfig) {
|
|
2546
|
+
// languages.set(tag, config);
|
|
2547
|
+
//
|
|
2548
|
+
// return app;
|
|
2549
|
+
// },
|
|
2550
|
+
//
|
|
2551
|
+
// setLanguage(tag: string, fallback?: string) {
|
|
2552
|
+
// if (tag === "auto") {
|
|
2553
|
+
// let tags = [];
|
|
2554
|
+
//
|
|
2555
|
+
// if (typeof navigator === "object") {
|
|
2556
|
+
// const nav = navigator as any;
|
|
2557
|
+
//
|
|
2558
|
+
// if (nav.languages?.length > 0) {
|
|
2559
|
+
// tags.push(...nav.languages);
|
|
2560
|
+
// } else if (nav.language) {
|
|
2561
|
+
// tags.push(nav.language);
|
|
2562
|
+
// } else if (nav.browserLanguage) {
|
|
2563
|
+
// tags.push(nav.browserLanguage);
|
|
2564
|
+
// } else if (nav.userLanguage) {
|
|
2565
|
+
// tags.push(nav.userLanguage);
|
|
2566
|
+
// }
|
|
2567
|
+
// }
|
|
2568
|
+
//
|
|
2569
|
+
// for (const tag of tags) {
|
|
2570
|
+
// if (languages.has(tag)) {
|
|
2571
|
+
// // Found a matching language.
|
|
2572
|
+
// currentLanguage = tag;
|
|
2573
|
+
// return this;
|
|
2574
|
+
// }
|
|
2575
|
+
// }
|
|
2576
|
+
//
|
|
2577
|
+
// if (!currentLanguage && fallback) {
|
|
2578
|
+
// if (languages.has(fallback)) {
|
|
2579
|
+
// currentLanguage = fallback;
|
|
2580
|
+
// }
|
|
2581
|
+
// }
|
|
2582
|
+
// } else {
|
|
2583
|
+
// // Tag is the actual tag to set.
|
|
2584
|
+
// if (languages.has(tag)) {
|
|
2585
|
+
// currentLanguage = tag;
|
|
2586
|
+
// } else {
|
|
2587
|
+
// throw new Error(`Language '${tag}' has not been added to this app yet.`);
|
|
2588
|
+
// }
|
|
2589
|
+
// }
|
|
2590
|
+
//
|
|
2591
|
+
// return app;
|
|
2592
|
+
// },
|
|
2593
|
+
configure(callback) {
|
|
2594
|
+
if (configureCallback !== void 0) {
|
|
2595
|
+
debugChannel.warn(`Configure callback is already defined. Only the final configure call will take effect.`);
|
|
2596
|
+
}
|
|
2597
|
+
configureCallback = callback;
|
|
2598
|
+
return app;
|
|
2599
|
+
}
|
|
2600
|
+
};
|
|
2601
|
+
return app;
|
|
2602
|
+
}
|
|
2603
|
+
function DefaultCrashPage({ message, error, componentName }) {
|
|
2604
|
+
return m(
|
|
2605
|
+
"div",
|
|
2606
|
+
{
|
|
2607
|
+
style: {
|
|
2608
|
+
backgroundColor: "#880000",
|
|
2609
|
+
color: "#fff",
|
|
2610
|
+
padding: "2rem",
|
|
2611
|
+
position: "fixed",
|
|
2612
|
+
inset: 0,
|
|
2613
|
+
fontSize: "20px"
|
|
2614
|
+
}
|
|
2615
|
+
},
|
|
2616
|
+
m("h1", { style: { marginBottom: "0.5rem" } }, "The app has crashed"),
|
|
2617
|
+
m(
|
|
2618
|
+
"p",
|
|
2619
|
+
{ style: { marginBottom: "0.25rem" } },
|
|
2620
|
+
m("span", { style: { fontFamily: "monospace" } }, componentName),
|
|
2621
|
+
" says:"
|
|
2622
|
+
),
|
|
2623
|
+
m(
|
|
2624
|
+
"blockquote",
|
|
2625
|
+
{
|
|
2626
|
+
style: {
|
|
2627
|
+
backgroundColor: "#991111",
|
|
2628
|
+
padding: "0.25em",
|
|
2629
|
+
borderRadius: "6px",
|
|
2630
|
+
fontFamily: "monospace",
|
|
2631
|
+
marginBottom: "1rem"
|
|
2632
|
+
}
|
|
2633
|
+
},
|
|
2634
|
+
m(
|
|
2635
|
+
"span",
|
|
2636
|
+
{
|
|
2637
|
+
style: {
|
|
2638
|
+
display: "inline-block",
|
|
2639
|
+
backgroundColor: "red",
|
|
2640
|
+
padding: "0.1em 0.4em",
|
|
2641
|
+
marginRight: "0.5em",
|
|
2642
|
+
borderRadius: "4px",
|
|
2643
|
+
fontSize: "0.9em",
|
|
2644
|
+
fontWeight: "bold"
|
|
2645
|
+
}
|
|
2646
|
+
},
|
|
2647
|
+
error.name
|
|
2648
|
+
),
|
|
2649
|
+
message
|
|
2650
|
+
),
|
|
2651
|
+
m("p", {}, "Please see the browser console for details.")
|
|
2652
|
+
);
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
// src/views/fragment.ts
|
|
2656
|
+
function Fragment(_, ctx) {
|
|
2657
|
+
return ctx.outlet();
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
// src/views/store-scope.ts
|
|
2661
|
+
function StoreScope(props, ctx) {
|
|
2662
|
+
const { appContext, elementContext } = getViewSecrets(ctx);
|
|
2663
|
+
const instances = [];
|
|
2664
|
+
for (const config of props.stores) {
|
|
2665
|
+
let store;
|
|
2666
|
+
let options;
|
|
2667
|
+
if (isFunction(config)) {
|
|
2668
|
+
store = config;
|
|
2669
|
+
} else {
|
|
2670
|
+
store = config.store;
|
|
2671
|
+
options = config.options;
|
|
2672
|
+
}
|
|
2673
|
+
const instance = initStore({
|
|
2674
|
+
store,
|
|
2675
|
+
options,
|
|
2676
|
+
appContext,
|
|
2677
|
+
elementContext
|
|
2678
|
+
});
|
|
2679
|
+
instance.setup();
|
|
2680
|
+
elementContext.stores.set(store, { store, options, instance });
|
|
2681
|
+
instances.push(instance);
|
|
2682
|
+
}
|
|
2683
|
+
ctx.beforeConnect(() => {
|
|
2684
|
+
for (const instance of instances) {
|
|
2685
|
+
instance.connect();
|
|
2686
|
+
}
|
|
2687
|
+
});
|
|
2688
|
+
ctx.onDisconnected(() => {
|
|
2689
|
+
for (const instance of instances) {
|
|
2690
|
+
instance.disconnect();
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
return ctx.outlet();
|
|
2694
|
+
}
|
|
2695
|
+
|
|
2696
|
+
// node_modules/@babel/runtime/helpers/esm/extends.js
|
|
2697
|
+
function _extends() {
|
|
2880
2698
|
_extends = Object.assign || function(target) {
|
|
2881
2699
|
for (var i = 1; i < arguments.length; i++) {
|
|
2882
2700
|
var source = arguments[i];
|
|
@@ -3329,9 +3147,11 @@ function parsePath(path) {
|
|
|
3329
3147
|
}
|
|
3330
3148
|
|
|
3331
3149
|
// src/stores/router.ts
|
|
3150
|
+
var DefaultView = (_, ctx) => ctx.outlet();
|
|
3332
3151
|
function RouterStore(ctx) {
|
|
3333
3152
|
ctx.name = "dolla/router";
|
|
3334
3153
|
const { appContext, elementContext } = getStoreSecrets(ctx);
|
|
3154
|
+
const render = ctx.getStore("render");
|
|
3335
3155
|
let history;
|
|
3336
3156
|
if (ctx.options.history) {
|
|
3337
3157
|
history = ctx.options.history;
|
|
@@ -3340,32 +3160,98 @@ function RouterStore(ctx) {
|
|
|
3340
3160
|
} else {
|
|
3341
3161
|
history = createBrowserHistory();
|
|
3342
3162
|
}
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3163
|
+
let layerId = 0;
|
|
3164
|
+
function prepareRoute(route, layers = []) {
|
|
3165
|
+
if (!(typeof route === "object" && !Array.isArray(route)) || !(typeof route.path === "string")) {
|
|
3166
|
+
throw new TypeError(`Route configs must be objects with a 'path' string property. Got: ${route}`);
|
|
3167
|
+
}
|
|
3168
|
+
if (route.redirect && route.routes) {
|
|
3169
|
+
throw new Error(`Route cannot have both a 'redirect' and nested 'routes'.`);
|
|
3170
|
+
} else if (route.redirect && route.view) {
|
|
3171
|
+
throw new Error(`Route cannot have both a 'redirect' and a 'view'.`);
|
|
3172
|
+
} else if (!route.view && !route.routes && !route.redirect) {
|
|
3173
|
+
throw new Error(`Route must have a 'view', a 'redirect', or a set of nested 'routes'.`);
|
|
3174
|
+
}
|
|
3175
|
+
const parts = splitPath(route.path);
|
|
3176
|
+
if (parts[parts.length - 1] === "*") {
|
|
3177
|
+
parts.pop();
|
|
3178
|
+
}
|
|
3179
|
+
const routes2 = [];
|
|
3180
|
+
if (route.redirect) {
|
|
3181
|
+
let redirect = route.redirect;
|
|
3182
|
+
if (isString(redirect)) {
|
|
3183
|
+
redirect = resolvePath(joinPath(parts), redirect);
|
|
3184
|
+
if (!redirect.startsWith("/")) {
|
|
3185
|
+
redirect = "/" + redirect;
|
|
3186
|
+
}
|
|
3352
3187
|
}
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3188
|
+
routes2.push({
|
|
3189
|
+
pattern: route.path,
|
|
3190
|
+
meta: {
|
|
3191
|
+
redirect
|
|
3356
3192
|
}
|
|
3357
3193
|
});
|
|
3358
|
-
|
|
3359
|
-
throw new Error(`Found a redirect to an undefined URL. From '${route.pattern}' to '${route.meta.redirect}'`);
|
|
3360
|
-
}
|
|
3194
|
+
return routes2;
|
|
3361
3195
|
}
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3196
|
+
let view = DefaultView;
|
|
3197
|
+
if (typeof route.view === "function") {
|
|
3198
|
+
view = route.view;
|
|
3199
|
+
} else if (route.view) {
|
|
3200
|
+
throw new TypeError(`Route '${route.path}' expected a view function or undefined. Got: ${route.view}`);
|
|
3201
|
+
}
|
|
3202
|
+
if (route.routes) {
|
|
3203
|
+
for (const subroute of route.routes) {
|
|
3204
|
+
routes2.push(...prepareRoute(subroute));
|
|
3205
|
+
}
|
|
3206
|
+
} else {
|
|
3207
|
+
const markup = m(view);
|
|
3208
|
+
const layer = { id: layerId++, markup };
|
|
3209
|
+
routes2.push({
|
|
3210
|
+
pattern: route.path,
|
|
3211
|
+
meta: {
|
|
3212
|
+
pattern: route.path,
|
|
3213
|
+
layers: [...layers, layer]
|
|
3214
|
+
}
|
|
3215
|
+
});
|
|
3216
|
+
}
|
|
3217
|
+
return routes2;
|
|
3218
|
+
}
|
|
3219
|
+
const routes = sortRoutes(
|
|
3220
|
+
ctx.options.routes.flatMap((route) => prepareRoute(route)).map((route) => ({
|
|
3221
|
+
pattern: route.pattern,
|
|
3222
|
+
meta: route.meta,
|
|
3223
|
+
fragments: patternToFragments(route.pattern)
|
|
3224
|
+
}))
|
|
3225
|
+
);
|
|
3226
|
+
for (const route of routes) {
|
|
3227
|
+
if (route.meta.redirect) {
|
|
3228
|
+
let redirectPath;
|
|
3229
|
+
if (isFunction(route.meta.redirect)) {
|
|
3230
|
+
throw new Error(`Redirect functions are not yet supported.`);
|
|
3231
|
+
} else if (isString(route.meta.redirect)) {
|
|
3232
|
+
redirectPath = route.meta.redirect;
|
|
3233
|
+
} else {
|
|
3234
|
+
throw new TypeError(`Expected a string or redirect function. Got: ${route.meta.redirect}`);
|
|
3235
|
+
}
|
|
3236
|
+
const match = matchRoutes(routes, redirectPath, {
|
|
3237
|
+
willMatch(r) {
|
|
3238
|
+
return r !== route;
|
|
3239
|
+
}
|
|
3240
|
+
});
|
|
3241
|
+
if (!match) {
|
|
3242
|
+
throw new Error(`Found a redirect to an undefined URL. From '${route.pattern}' to '${route.meta.redirect}'`);
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
ctx.onConnected(() => {
|
|
3247
|
+
ctx.info(`Total routes: ${routes.length}`);
|
|
3248
|
+
});
|
|
3249
|
+
const $$pattern = $$(null);
|
|
3250
|
+
const $$path = $$("");
|
|
3251
|
+
const $$params = $$({});
|
|
3252
|
+
const $$query = $$({});
|
|
3253
|
+
let isRouteChange = true;
|
|
3254
|
+
ctx.observe($$query, (current) => {
|
|
3369
3255
|
if (isRouteChange) {
|
|
3370
3256
|
isRouteChange = false;
|
|
3371
3257
|
return;
|
|
@@ -3396,9 +3282,9 @@ function RouterStore(ctx) {
|
|
|
3396
3282
|
if (location.search !== lastQuery) {
|
|
3397
3283
|
lastQuery = location.search;
|
|
3398
3284
|
isRouteChange = true;
|
|
3399
|
-
$$query.set(parseQueryParams(location.search));
|
|
3285
|
+
$$query.set(parseQueryParams(location.search.startsWith("?") ? location.search.slice(1) : location.search));
|
|
3400
3286
|
}
|
|
3401
|
-
const matched = matchRoutes(
|
|
3287
|
+
const matched = matchRoutes(routes, location.pathname);
|
|
3402
3288
|
if (!matched) {
|
|
3403
3289
|
$$pattern.set(null);
|
|
3404
3290
|
$$path.set(location.pathname);
|
|
@@ -3437,7 +3323,7 @@ function RouterStore(ctx) {
|
|
|
3437
3323
|
const renderContext = { appContext, elementContext };
|
|
3438
3324
|
const rendered = renderMarkupToDOM(matchedLayer.markup, renderContext);
|
|
3439
3325
|
const handle = getRenderHandle(rendered);
|
|
3440
|
-
|
|
3326
|
+
render.update(() => {
|
|
3441
3327
|
if (activeLayer && activeLayer.handle.connected) {
|
|
3442
3328
|
activeLayer.handle.disconnect();
|
|
3443
3329
|
}
|
|
@@ -3446,7 +3332,7 @@ function RouterStore(ctx) {
|
|
|
3446
3332
|
} else {
|
|
3447
3333
|
appContext.rootView.setChildren(rendered);
|
|
3448
3334
|
}
|
|
3449
|
-
});
|
|
3335
|
+
}, "dolla-router-change");
|
|
3450
3336
|
activeLayers.push({ id: matchedLayer.id, handle });
|
|
3451
3337
|
}
|
|
3452
3338
|
}
|
|
@@ -3471,15 +3357,15 @@ function RouterStore(ctx) {
|
|
|
3471
3357
|
/**
|
|
3472
3358
|
* The currently matched route pattern, if any.
|
|
3473
3359
|
*/
|
|
3474
|
-
$pattern:
|
|
3360
|
+
$pattern: $($$pattern),
|
|
3475
3361
|
/**
|
|
3476
3362
|
* The current URL path.
|
|
3477
3363
|
*/
|
|
3478
|
-
$path:
|
|
3364
|
+
$path: $($$path),
|
|
3479
3365
|
/**
|
|
3480
3366
|
* The current named path params.
|
|
3481
3367
|
*/
|
|
3482
|
-
$params:
|
|
3368
|
+
$params: $($$params),
|
|
3483
3369
|
/**
|
|
3484
3370
|
* The current query params. Changes to this object will be reflected in the URL.
|
|
3485
3371
|
*/
|
|
@@ -3540,542 +3426,454 @@ function catchLinks(root, callback, _window = window) {
|
|
|
3540
3426
|
};
|
|
3541
3427
|
}
|
|
3542
3428
|
|
|
3543
|
-
// src/
|
|
3544
|
-
function
|
|
3545
|
-
|
|
3546
|
-
}
|
|
3547
|
-
function makeApp(options) {
|
|
3548
|
-
if (options && !isObject(options)) {
|
|
3549
|
-
throw new TypeError(`App options must be an object. Got: ${options}`);
|
|
3550
|
-
}
|
|
3551
|
-
let isConnected = false;
|
|
3552
|
-
let mainView = m(DefaultRootView);
|
|
3553
|
-
let configureCallback;
|
|
3554
|
-
const settings = merge(
|
|
3555
|
-
{
|
|
3556
|
-
debug: {
|
|
3557
|
-
filter: "*,-dolla/*",
|
|
3558
|
-
log: "development",
|
|
3559
|
-
// Only print logs in development.
|
|
3560
|
-
warn: "development",
|
|
3561
|
-
// Only print warnings in development.
|
|
3562
|
-
error: true
|
|
3563
|
-
// Always print errors.
|
|
3564
|
-
},
|
|
3565
|
-
router: {
|
|
3566
|
-
hash: false
|
|
3567
|
-
},
|
|
3568
|
-
mode: "production"
|
|
3569
|
-
},
|
|
3570
|
-
options ?? {}
|
|
3571
|
-
);
|
|
3572
|
-
const stores = /* @__PURE__ */ new Map([
|
|
3573
|
-
["dialog", { store: DialogStore }],
|
|
3574
|
-
["router", { store: RouterStore }],
|
|
3575
|
-
["document", { store: DocumentStore }],
|
|
3576
|
-
["http", { store: HTTPStore }],
|
|
3577
|
-
["language", { store: LanguageStore }],
|
|
3578
|
-
["render", { store: RenderStore }]
|
|
3579
|
-
]);
|
|
3429
|
+
// src/stores/language.ts
|
|
3430
|
+
function LanguageStore(ctx) {
|
|
3431
|
+
ctx.name = "dolla/language";
|
|
3580
3432
|
const languages = /* @__PURE__ */ new Map();
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
if (
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
if (
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3433
|
+
const cache = /* @__PURE__ */ new Map();
|
|
3434
|
+
ctx.options.languages.forEach((entry) => {
|
|
3435
|
+
languages.set(entry.name, entry);
|
|
3436
|
+
});
|
|
3437
|
+
ctx.info(
|
|
3438
|
+
`App supports ${languages.size} language${languages.size === 1 ? "" : "s"}: '${[...languages.keys()].join("', '")}'`
|
|
3439
|
+
);
|
|
3440
|
+
async function getTranslation(config) {
|
|
3441
|
+
if (!cache.has(config.name)) {
|
|
3442
|
+
let fn;
|
|
3443
|
+
if (isString(config.translations)) {
|
|
3444
|
+
fn = async () => {
|
|
3445
|
+
return fetch(config.translations).then((res) => res.json());
|
|
3446
|
+
};
|
|
3447
|
+
} else if (isFunction(config.translations)) {
|
|
3448
|
+
fn = async () => config.translations();
|
|
3449
|
+
} else if (isObject(config.translations)) {
|
|
3450
|
+
fn = async () => config.translations;
|
|
3451
|
+
} else {
|
|
3452
|
+
throw new TypeError(
|
|
3453
|
+
`Translation of '${config.name}' must be an object of translated strings, a path to an object of translated strings, a function that returns one, or an async function that resolves to one. Got type: ${typeOf(
|
|
3454
|
+
config.translations
|
|
3455
|
+
)}, value: ${config.translations}`
|
|
3456
|
+
);
|
|
3457
|
+
}
|
|
3458
|
+
try {
|
|
3459
|
+
const translation = await fn();
|
|
3460
|
+
assertObject(
|
|
3461
|
+
translation,
|
|
3462
|
+
`Expected '${config.name}' translations to resolve to an object. Got type: %t, value: %v`
|
|
3463
|
+
);
|
|
3464
|
+
cache.set(config.name, translation);
|
|
3465
|
+
} catch (err) {
|
|
3466
|
+
throw err;
|
|
3600
3467
|
}
|
|
3601
|
-
routes2.push({
|
|
3602
|
-
pattern: route.pattern,
|
|
3603
|
-
meta: {
|
|
3604
|
-
redirect
|
|
3605
|
-
}
|
|
3606
|
-
});
|
|
3607
|
-
return routes2;
|
|
3608
3468
|
}
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
const
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
route: (pattern, view2, subroutes) => {
|
|
3622
|
-
pattern = joinPath([...parts, pattern]);
|
|
3623
|
-
routes2.push(...prepareRoute({ pattern, view: view2, subroutes }));
|
|
3624
|
-
return router;
|
|
3625
|
-
},
|
|
3626
|
-
redirect: (pattern, redirect) => {
|
|
3627
|
-
pattern = joinPath([...parts, pattern]);
|
|
3628
|
-
routes2.push(...prepareRoute({ pattern, redirect }));
|
|
3629
|
-
return router;
|
|
3630
|
-
}
|
|
3631
|
-
};
|
|
3632
|
-
route.subroutes(router);
|
|
3633
|
-
} else {
|
|
3634
|
-
routes2.push({
|
|
3635
|
-
pattern: route.pattern,
|
|
3636
|
-
meta: {
|
|
3637
|
-
pattern: route.pattern,
|
|
3638
|
-
layers: [...layers, layer]
|
|
3639
|
-
}
|
|
3640
|
-
});
|
|
3469
|
+
return cache.get(config.name);
|
|
3470
|
+
}
|
|
3471
|
+
const $$isLoaded = $$(false);
|
|
3472
|
+
const $$language = $$();
|
|
3473
|
+
const $$translation = $$();
|
|
3474
|
+
const $noLanguageValue = $("[NO LANGUAGE SET]");
|
|
3475
|
+
const translationCache = [];
|
|
3476
|
+
function getCached(key, values) {
|
|
3477
|
+
for (const entry of translationCache) {
|
|
3478
|
+
if (entry[0] === key && deepEqual(entry[1], values)) {
|
|
3479
|
+
return entry[2];
|
|
3480
|
+
}
|
|
3641
3481
|
}
|
|
3642
|
-
return routes2;
|
|
3643
3482
|
}
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
crashCollector.onError(async ({ error, severity, componentName }) => {
|
|
3648
|
-
if (severity === "crash") {
|
|
3649
|
-
await disconnect();
|
|
3650
|
-
const instance = initView({
|
|
3651
|
-
view: DefaultCrashPage,
|
|
3652
|
-
appContext,
|
|
3653
|
-
elementContext,
|
|
3654
|
-
props: {
|
|
3655
|
-
message: error.message,
|
|
3656
|
-
error,
|
|
3657
|
-
componentName
|
|
3658
|
-
}
|
|
3659
|
-
});
|
|
3660
|
-
instance.connect(appContext.rootElement);
|
|
3483
|
+
function replaceMustaches(template, values) {
|
|
3484
|
+
for (const name in values) {
|
|
3485
|
+
template = template.replace(`{{${name}}}`, String(values[name]));
|
|
3661
3486
|
}
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3487
|
+
return template;
|
|
3488
|
+
}
|
|
3489
|
+
const currentLanguage = ctx.options.default ? languages.get(ctx.options.default) : languages.get([...languages.keys()][0]);
|
|
3490
|
+
if (currentLanguage == null) {
|
|
3491
|
+
$$isLoaded.set(true);
|
|
3492
|
+
} else {
|
|
3493
|
+
ctx.info(`Current language is '${currentLanguage.name}'.`);
|
|
3494
|
+
getTranslation(currentLanguage).then((translation) => {
|
|
3495
|
+
$$language.set(currentLanguage.name);
|
|
3496
|
+
$$translation.set(translation);
|
|
3497
|
+
$$isLoaded.set(true);
|
|
3498
|
+
});
|
|
3499
|
+
}
|
|
3500
|
+
return {
|
|
3501
|
+
$isLoaded: $($$isLoaded),
|
|
3502
|
+
$currentLanguage: $($$language),
|
|
3503
|
+
supportedLanguages: [...languages.keys()],
|
|
3504
|
+
async setLanguage(tag) {
|
|
3505
|
+
if (!languages.has(tag)) {
|
|
3506
|
+
throw new Error(`Language '${tag}' is not supported.`);
|
|
3669
3507
|
}
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
}
|
|
3680
|
-
});
|
|
3681
|
-
const router = stores.get("router");
|
|
3682
|
-
stores.set("router", {
|
|
3683
|
-
...router,
|
|
3684
|
-
options: {
|
|
3685
|
-
options: settings.router,
|
|
3686
|
-
routes
|
|
3508
|
+
const lang = languages.get(tag);
|
|
3509
|
+
try {
|
|
3510
|
+
const translation = await getTranslation(lang);
|
|
3511
|
+
$$translation.set(translation);
|
|
3512
|
+
$$language.set(tag);
|
|
3513
|
+
ctx.info("set language to " + tag);
|
|
3514
|
+
} catch (error) {
|
|
3515
|
+
if (error instanceof Error) {
|
|
3516
|
+
ctx.crash(error);
|
|
3687
3517
|
}
|
|
3688
|
-
});
|
|
3689
|
-
debugChannel.info(`Total routes: ${routes.length}`);
|
|
3690
|
-
appContext.rootView = initView({
|
|
3691
|
-
view: mainView.type,
|
|
3692
|
-
props: mainView.props,
|
|
3693
|
-
appContext,
|
|
3694
|
-
elementContext
|
|
3695
|
-
});
|
|
3696
|
-
for (let [key, item] of stores.entries()) {
|
|
3697
|
-
const { store, options: options2 } = item;
|
|
3698
|
-
const channelPrefix = isString(key) ? "dolla/store" : "store";
|
|
3699
|
-
const label = isString(key) ? key : store.name ?? "(anonymous)";
|
|
3700
|
-
const config = {
|
|
3701
|
-
store,
|
|
3702
|
-
appContext,
|
|
3703
|
-
elementContext,
|
|
3704
|
-
channelPrefix,
|
|
3705
|
-
label,
|
|
3706
|
-
options: options2 ?? {}
|
|
3707
|
-
};
|
|
3708
|
-
const instance = initStore(config);
|
|
3709
|
-
instance.setup();
|
|
3710
|
-
stores.set(key, { ...item, instance });
|
|
3711
3518
|
}
|
|
3712
|
-
|
|
3713
|
-
|
|
3519
|
+
},
|
|
3520
|
+
/**
|
|
3521
|
+
* Returns a Readable of the translated value.
|
|
3522
|
+
|
|
3523
|
+
* @param key - Key to the translated value.
|
|
3524
|
+
* @param values - A map of {{placeholder}} names and the values to replace them with.
|
|
3525
|
+
*/
|
|
3526
|
+
translate(key, values) {
|
|
3527
|
+
if (!$$language.get()) {
|
|
3528
|
+
return $noLanguageValue;
|
|
3714
3529
|
}
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
});
|
|
3530
|
+
const cached = getCached(key, values);
|
|
3531
|
+
if (cached) {
|
|
3532
|
+
return cached;
|
|
3719
3533
|
}
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3534
|
+
if (values) {
|
|
3535
|
+
const readableValues = {};
|
|
3536
|
+
for (const [key2, value] of Object.entries(values)) {
|
|
3537
|
+
if (isReadable(value)) {
|
|
3538
|
+
readableValues[key2] = value;
|
|
3539
|
+
}
|
|
3540
|
+
}
|
|
3541
|
+
const readableEntries = Object.entries(readableValues);
|
|
3542
|
+
if (readableEntries.length > 0) {
|
|
3543
|
+
const readables = readableEntries.map((x) => x[1]);
|
|
3544
|
+
const $merged = $([$$translation, ...readables], (t, ...entryValues) => {
|
|
3545
|
+
const entries = entryValues.map((_, i) => readableEntries[i]);
|
|
3546
|
+
const mergedValues = {
|
|
3547
|
+
...values
|
|
3548
|
+
};
|
|
3549
|
+
for (let i = 0; i < entries.length; i++) {
|
|
3550
|
+
const key2 = entries[i][0];
|
|
3551
|
+
mergedValues[key2] = entryValues[i];
|
|
3552
|
+
}
|
|
3553
|
+
const result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
3554
|
+
return replaceMustaches(result, mergedValues);
|
|
3555
|
+
});
|
|
3556
|
+
translationCache.push([key, values, $merged]);
|
|
3557
|
+
return $merged;
|
|
3558
|
+
}
|
|
3728
3559
|
}
|
|
3729
|
-
const
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3560
|
+
const $replaced = $($$translation, (t) => {
|
|
3561
|
+
let result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
3562
|
+
if (values) {
|
|
3563
|
+
result = replaceMustaches(result, values);
|
|
3733
3564
|
}
|
|
3565
|
+
return result;
|
|
3734
3566
|
});
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
async function disconnect() {
|
|
3738
|
-
if (isConnected) {
|
|
3739
|
-
appContext.rootView.disconnect();
|
|
3740
|
-
isConnected = false;
|
|
3741
|
-
for (const { instance } of stores.values()) {
|
|
3742
|
-
instance.disconnect();
|
|
3743
|
-
}
|
|
3567
|
+
translationCache.push([key, values, $replaced]);
|
|
3568
|
+
return $replaced;
|
|
3744
3569
|
}
|
|
3745
|
-
}
|
|
3746
|
-
const appContext = {
|
|
3747
|
-
crashCollector,
|
|
3748
|
-
debugHub,
|
|
3749
|
-
stores,
|
|
3750
|
-
mode: settings.mode ?? "production"
|
|
3751
|
-
// $dialogs - added by dialog store
|
|
3752
3570
|
};
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3571
|
+
}
|
|
3572
|
+
function resolve(object, key) {
|
|
3573
|
+
const parsed = String(key).split(/[\.\[\]]/).filter((part) => part.trim() !== "");
|
|
3574
|
+
let value = object;
|
|
3575
|
+
while (parsed.length > 0) {
|
|
3576
|
+
const part = parsed.shift();
|
|
3577
|
+
if (value != null) {
|
|
3578
|
+
value = value[part];
|
|
3579
|
+
} else {
|
|
3580
|
+
value = void 0;
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
return value;
|
|
3584
|
+
}
|
|
3585
|
+
|
|
3586
|
+
// src/stores/http.ts
|
|
3587
|
+
function HTTPStore(ctx) {
|
|
3588
|
+
ctx.name = "dolla/http";
|
|
3589
|
+
const fetch2 = ctx.options.fetch ?? getDefaultFetch();
|
|
3590
|
+
const middleware = [];
|
|
3591
|
+
async function request(method, uri, options) {
|
|
3592
|
+
return makeRequest({ ...options, method, uri, middleware, fetch: fetch2 });
|
|
3593
|
+
}
|
|
3594
|
+
return {
|
|
3595
|
+
/**
|
|
3596
|
+
* Adds a new middleware that will apply to subsequent requests.
|
|
3597
|
+
* Returns a function to remove this middleware.
|
|
3598
|
+
*
|
|
3599
|
+
* @param middleware - A middleware function that will intercept requests.
|
|
3600
|
+
*/
|
|
3601
|
+
middleware(fn) {
|
|
3602
|
+
middleware.push(fn);
|
|
3603
|
+
return function remove() {
|
|
3604
|
+
middleware.splice(middleware.indexOf(fn), 1);
|
|
3605
|
+
};
|
|
3761
3606
|
},
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
debugChannel.warn(`Root view is already defined. Only the final main call will take effect.`);
|
|
3765
|
-
}
|
|
3766
|
-
if (typeof view === "function") {
|
|
3767
|
-
mainView = m(view, attributes);
|
|
3768
|
-
} else {
|
|
3769
|
-
throw new TypeError(`Expected a view function. Got type: ${typeOf(view)}, value: ${view}`);
|
|
3770
|
-
}
|
|
3771
|
-
return app;
|
|
3607
|
+
async get(uri, options) {
|
|
3608
|
+
return request("get", uri, options);
|
|
3772
3609
|
},
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
if (isFunction(store)) {
|
|
3776
|
-
config = { store, options: options2 };
|
|
3777
|
-
} else {
|
|
3778
|
-
throw new TypeError(`Expected a store function. Got type: ${typeOf(store)}, value: ${store}`);
|
|
3779
|
-
}
|
|
3780
|
-
assertFunction(store, "Expected a store function or a store config object. Got type: %t, value: %v");
|
|
3781
|
-
stores.set(store, config);
|
|
3782
|
-
return app;
|
|
3610
|
+
async put(uri, options) {
|
|
3611
|
+
return request("put", uri, options);
|
|
3783
3612
|
},
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
const name = isString(store) ? store : store.name;
|
|
3787
|
-
if (!match) {
|
|
3788
|
-
throw new Error(`Store '${name}' is not registered on this app.`);
|
|
3789
|
-
}
|
|
3790
|
-
if (!match.instance) {
|
|
3791
|
-
throw new Error(`Store '${name}' is not yet initialized. App must be connected first.`);
|
|
3792
|
-
}
|
|
3793
|
-
return match.instance.exports;
|
|
3613
|
+
async patch(uri, options) {
|
|
3614
|
+
return request("patch", uri, options);
|
|
3794
3615
|
},
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
return app;
|
|
3616
|
+
async post(uri, options) {
|
|
3617
|
+
return request("post", uri, options);
|
|
3798
3618
|
},
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
let tags = [];
|
|
3802
|
-
if (typeof navigator === "object") {
|
|
3803
|
-
const nav = navigator;
|
|
3804
|
-
if (nav.languages?.length > 0) {
|
|
3805
|
-
tags.push(...nav.languages);
|
|
3806
|
-
} else if (nav.language) {
|
|
3807
|
-
tags.push(nav.language);
|
|
3808
|
-
} else if (nav.browserLanguage) {
|
|
3809
|
-
tags.push(nav.browserLanguage);
|
|
3810
|
-
} else if (nav.userLanguage) {
|
|
3811
|
-
tags.push(nav.userLanguage);
|
|
3812
|
-
}
|
|
3813
|
-
}
|
|
3814
|
-
for (const tag2 of tags) {
|
|
3815
|
-
if (languages.has(tag2)) {
|
|
3816
|
-
currentLanguage = tag2;
|
|
3817
|
-
return this;
|
|
3818
|
-
}
|
|
3819
|
-
}
|
|
3820
|
-
if (!currentLanguage && fallback) {
|
|
3821
|
-
if (languages.has(fallback)) {
|
|
3822
|
-
currentLanguage = fallback;
|
|
3823
|
-
}
|
|
3824
|
-
}
|
|
3825
|
-
} else {
|
|
3826
|
-
if (languages.has(tag)) {
|
|
3827
|
-
currentLanguage = tag;
|
|
3828
|
-
} else {
|
|
3829
|
-
throw new Error(`Language '${tag}' has not been added to this app yet.`);
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
|
-
return app;
|
|
3619
|
+
async delete(uri, options) {
|
|
3620
|
+
return request("delete", uri, options);
|
|
3833
3621
|
},
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
if (view == null) {
|
|
3837
|
-
assertFunction(subroutes, "Sub routes must be defined when `view` is null.");
|
|
3838
|
-
}
|
|
3839
|
-
prepareRoute({ pattern, view, subroutes }).forEach((route) => {
|
|
3840
|
-
routes.push({
|
|
3841
|
-
pattern: route.pattern,
|
|
3842
|
-
meta: route.meta,
|
|
3843
|
-
fragments: patternToFragments(route.pattern)
|
|
3844
|
-
});
|
|
3845
|
-
});
|
|
3846
|
-
return app;
|
|
3622
|
+
async head(uri, options) {
|
|
3623
|
+
return request("head", uri, options);
|
|
3847
3624
|
},
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
throw new TypeError(`Expected a redirect path or function. Got type: ${typeOf(redirect)}, value: ${redirect}`);
|
|
3851
|
-
}
|
|
3852
|
-
prepareRoute({ pattern, redirect }).forEach((route) => {
|
|
3853
|
-
routes.push({
|
|
3854
|
-
pattern: route.pattern,
|
|
3855
|
-
meta: route.meta,
|
|
3856
|
-
fragments: patternToFragments(route.pattern)
|
|
3857
|
-
});
|
|
3858
|
-
});
|
|
3859
|
-
return app;
|
|
3625
|
+
async options(uri, options) {
|
|
3626
|
+
return request("options", uri, options);
|
|
3860
3627
|
},
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
debugChannel.warn(`Configure callback is already defined. Only the final configure call will take effect.`);
|
|
3864
|
-
}
|
|
3865
|
-
configureCallback = callback;
|
|
3866
|
-
return app;
|
|
3628
|
+
async trace(uri, options) {
|
|
3629
|
+
return request("trace", uri, options);
|
|
3867
3630
|
}
|
|
3868
3631
|
};
|
|
3869
|
-
return app;
|
|
3870
3632
|
}
|
|
3871
|
-
function
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
position: "fixed",
|
|
3880
|
-
inset: 0,
|
|
3881
|
-
fontSize: "20px"
|
|
3882
|
-
}
|
|
3883
|
-
},
|
|
3884
|
-
m("h1", { style: { marginBottom: "0.5rem" } }, "The app has crashed"),
|
|
3885
|
-
m(
|
|
3886
|
-
"p",
|
|
3887
|
-
{ style: { marginBottom: "0.25rem" } },
|
|
3888
|
-
m("span", { style: { fontFamily: "monospace" } }, componentName),
|
|
3889
|
-
" says:"
|
|
3890
|
-
),
|
|
3891
|
-
m(
|
|
3892
|
-
"blockquote",
|
|
3893
|
-
{
|
|
3894
|
-
style: {
|
|
3895
|
-
backgroundColor: "#991111",
|
|
3896
|
-
padding: "0.25em",
|
|
3897
|
-
borderRadius: "6px",
|
|
3898
|
-
fontFamily: "monospace",
|
|
3899
|
-
marginBottom: "1rem"
|
|
3900
|
-
}
|
|
3901
|
-
},
|
|
3902
|
-
m(
|
|
3903
|
-
"span",
|
|
3904
|
-
{
|
|
3905
|
-
style: {
|
|
3906
|
-
display: "inline-block",
|
|
3907
|
-
backgroundColor: "red",
|
|
3908
|
-
padding: "0.1em 0.4em",
|
|
3909
|
-
marginRight: "0.5em",
|
|
3910
|
-
borderRadius: "4px",
|
|
3911
|
-
fontSize: "0.9em",
|
|
3912
|
-
fontWeight: "bold"
|
|
3913
|
-
}
|
|
3914
|
-
},
|
|
3915
|
-
error.name
|
|
3916
|
-
),
|
|
3917
|
-
message
|
|
3918
|
-
),
|
|
3919
|
-
m("p", {}, "Please see the browser console for details.")
|
|
3920
|
-
);
|
|
3633
|
+
function getDefaultFetch() {
|
|
3634
|
+
if (typeof window !== "undefined" && window.fetch) {
|
|
3635
|
+
return window.fetch.bind(window);
|
|
3636
|
+
}
|
|
3637
|
+
if (typeof global !== "undefined" && global.fetch) {
|
|
3638
|
+
return global.fetch.bind(global);
|
|
3639
|
+
}
|
|
3640
|
+
throw new Error("Running in neither browser nor node. Please run this app in one of the supported environments.");
|
|
3921
3641
|
}
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
const animateTo = async (endValue, options2) => {
|
|
3939
|
-
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
3940
|
-
if (mediaQuery.matches) {
|
|
3941
|
-
return snapTo(endValue);
|
|
3942
|
-
}
|
|
3943
|
-
const _endAmplitude = readable(options2?.endAmplitude ?? endAmplitude).get();
|
|
3944
|
-
const _endWindow = readable(options2?.endWindow ?? endWindow).get();
|
|
3945
|
-
return new Promise((resolve2) => {
|
|
3946
|
-
const id = nextId++;
|
|
3947
|
-
const amplitude = makeAmplitudeMeasurer(_endWindow);
|
|
3948
|
-
const springParams = {
|
|
3949
|
-
mass: options2?.mass ?? mass,
|
|
3950
|
-
stiffness: options2?.stiffness ?? stiffness,
|
|
3951
|
-
damping: options2?.damping ?? damping,
|
|
3952
|
-
velocity: options2?.velocity ?? velocity
|
|
3953
|
-
};
|
|
3954
|
-
const startTime = Date.now();
|
|
3955
|
-
const startValue = $$currentValue.get();
|
|
3956
|
-
const step = () => {
|
|
3957
|
-
if (currentAnimationId !== id) {
|
|
3958
|
-
resolve2();
|
|
3959
|
-
return;
|
|
3960
|
-
}
|
|
3961
|
-
const elapsedTime = Date.now() - startTime;
|
|
3962
|
-
const proportion = solve(springParams, elapsedTime / 1e3);
|
|
3963
|
-
$$currentValue.set(startValue + (endValue - startValue) * proportion);
|
|
3964
|
-
amplitude.sample(proportion);
|
|
3965
|
-
if (amplitude.value && amplitude.value < _endAmplitude) {
|
|
3966
|
-
currentAnimationId = void 0;
|
|
3967
|
-
$$currentValue.set(endValue);
|
|
3968
|
-
}
|
|
3969
|
-
window.requestAnimationFrame(step);
|
|
3970
|
-
};
|
|
3971
|
-
currentAnimationId = id;
|
|
3972
|
-
window.requestAnimationFrame(step);
|
|
3973
|
-
});
|
|
3974
|
-
};
|
|
3975
|
-
return {
|
|
3976
|
-
get: $$currentValue.get,
|
|
3977
|
-
set: snapTo,
|
|
3978
|
-
update: (callback) => {
|
|
3979
|
-
const newValue = callback($$currentValue.get());
|
|
3980
|
-
snapTo(newValue);
|
|
3642
|
+
var HTTPResponseError = class extends Error {
|
|
3643
|
+
response;
|
|
3644
|
+
constructor(response) {
|
|
3645
|
+
const { status, statusText, method, uri } = response;
|
|
3646
|
+
const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${uri})`;
|
|
3647
|
+
super(message);
|
|
3648
|
+
this.response = response;
|
|
3649
|
+
}
|
|
3650
|
+
};
|
|
3651
|
+
async function makeRequest(config) {
|
|
3652
|
+
const { headers, query, fetch: fetch2, middleware } = config;
|
|
3653
|
+
const request = {
|
|
3654
|
+
method: config.method,
|
|
3655
|
+
uri: config.uri,
|
|
3656
|
+
get sameOrigin() {
|
|
3657
|
+
return !request.uri.startsWith("http");
|
|
3981
3658
|
},
|
|
3982
|
-
|
|
3983
|
-
|
|
3659
|
+
query: new URLSearchParams(),
|
|
3660
|
+
headers: new Headers(),
|
|
3661
|
+
body: config.body
|
|
3984
3662
|
};
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
let B;
|
|
3994
|
-
let position;
|
|
3995
|
-
if (dampingRatio < 1) {
|
|
3996
|
-
const dampedSpeed = speed * Math.sqrt(1 - dampingRatio * dampingRatio);
|
|
3997
|
-
B = (dampingRatio * speed + -initialVelocity) / dampedSpeed;
|
|
3998
|
-
position = (Math.cos(dampedSpeed * elapsedSeconds) + B * Math.sin(dampedSpeed * elapsedSeconds)) * Math.exp(-elapsedSeconds * speed * dampingRatio);
|
|
3999
|
-
} else {
|
|
4000
|
-
B = speed + -initialVelocity;
|
|
4001
|
-
position = (1 + B * elapsedSeconds) * Math.exp(-elapsedSeconds * speed);
|
|
4002
|
-
}
|
|
4003
|
-
return 1 - position;
|
|
4004
|
-
}
|
|
4005
|
-
function makeAmplitudeMeasurer(resolution) {
|
|
4006
|
-
const samples = [];
|
|
4007
|
-
return {
|
|
4008
|
-
sample(value) {
|
|
4009
|
-
samples.push(value);
|
|
4010
|
-
while (samples.length > resolution) {
|
|
4011
|
-
samples.shift();
|
|
3663
|
+
if (headers) {
|
|
3664
|
+
if (headers instanceof Map || headers instanceof Headers) {
|
|
3665
|
+
headers.forEach((value, key) => {
|
|
3666
|
+
request.headers.set(key, value);
|
|
3667
|
+
});
|
|
3668
|
+
} else if (headers != null && typeof headers === "object" && !Array.isArray(headers)) {
|
|
3669
|
+
for (const name in headers) {
|
|
3670
|
+
request.headers.set(name, String(headers[name]));
|
|
4012
3671
|
}
|
|
4013
|
-
}
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
3672
|
+
} else {
|
|
3673
|
+
throw new TypeError(`Unknown headers type. Got: ${headers}`);
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
if (query) {
|
|
3677
|
+
if (query instanceof Map || query instanceof URLSearchParams) {
|
|
3678
|
+
query.forEach((value, key) => {
|
|
3679
|
+
request.query.set(key, value);
|
|
3680
|
+
});
|
|
3681
|
+
} else if (query != null && typeof query === "object" && !Array.isArray(query)) {
|
|
3682
|
+
for (const name in query) {
|
|
3683
|
+
request.query.set(name, String(query[name]));
|
|
4017
3684
|
}
|
|
4018
|
-
|
|
3685
|
+
} else {
|
|
3686
|
+
throw new TypeError(`Unknown query params type. Got: ${query}`);
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
let response;
|
|
3690
|
+
const handler = async () => {
|
|
3691
|
+
const query2 = request.query.toString();
|
|
3692
|
+
const fullURL = query2.length > 0 ? request.uri + "?" + query2 : request.uri;
|
|
3693
|
+
let reqBody;
|
|
3694
|
+
if (!request.headers.has("content-type") && isObject(request.body)) {
|
|
3695
|
+
request.headers.set("content-type", "application/json");
|
|
3696
|
+
reqBody = JSON.stringify(request.body);
|
|
3697
|
+
} else {
|
|
3698
|
+
reqBody = request.body;
|
|
3699
|
+
}
|
|
3700
|
+
const fetched = await fetch2(fullURL, {
|
|
3701
|
+
method: request.method,
|
|
3702
|
+
headers: request.headers,
|
|
3703
|
+
body: reqBody
|
|
3704
|
+
});
|
|
3705
|
+
const headers2 = Object.fromEntries(fetched.headers.entries());
|
|
3706
|
+
const contentType = headers2["content-type"];
|
|
3707
|
+
let body;
|
|
3708
|
+
if (contentType?.includes("application/json")) {
|
|
3709
|
+
body = await fetched.json();
|
|
3710
|
+
} else if (contentType?.includes("application/x-www-form-urlencoded")) {
|
|
3711
|
+
body = await fetched.formData();
|
|
3712
|
+
} else {
|
|
3713
|
+
body = await fetched.text();
|
|
4019
3714
|
}
|
|
3715
|
+
response = {
|
|
3716
|
+
method: request.method,
|
|
3717
|
+
uri: request.uri,
|
|
3718
|
+
status: fetched.status,
|
|
3719
|
+
statusText: fetched.statusText,
|
|
3720
|
+
headers: headers2,
|
|
3721
|
+
body
|
|
3722
|
+
};
|
|
4020
3723
|
};
|
|
3724
|
+
if (middleware.length > 0) {
|
|
3725
|
+
const mount = (index = 0) => {
|
|
3726
|
+
const current = middleware[index];
|
|
3727
|
+
const next = middleware[index + 1] ? mount(index + 1) : handler;
|
|
3728
|
+
return async () => current(request, async () => {
|
|
3729
|
+
await next();
|
|
3730
|
+
return response;
|
|
3731
|
+
});
|
|
3732
|
+
};
|
|
3733
|
+
await mount()();
|
|
3734
|
+
} else {
|
|
3735
|
+
await handler();
|
|
3736
|
+
}
|
|
3737
|
+
if (response.status < 200 || response.status >= 400) {
|
|
3738
|
+
throw new HTTPResponseError(response);
|
|
3739
|
+
}
|
|
3740
|
+
return response;
|
|
4021
3741
|
}
|
|
4022
3742
|
|
|
4023
|
-
// src/
|
|
4024
|
-
function
|
|
4025
|
-
|
|
4026
|
-
}
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
3743
|
+
// src/stores/dialog.ts
|
|
3744
|
+
function DialogStore(ctx) {
|
|
3745
|
+
ctx.name = "dolla/dialog";
|
|
3746
|
+
const { appContext, elementContext } = getStoreSecrets(ctx);
|
|
3747
|
+
const render = ctx.getStore("render");
|
|
3748
|
+
const container = document.createElement("div");
|
|
3749
|
+
container.style.position = "fixed";
|
|
3750
|
+
container.style.top = "0";
|
|
3751
|
+
container.style.right = "0";
|
|
3752
|
+
container.style.bottom = "0";
|
|
3753
|
+
container.style.left = "0";
|
|
3754
|
+
container.style.zIndex = "99999";
|
|
3755
|
+
const $$dialogs = $$([]);
|
|
3756
|
+
let activeDialogs = [];
|
|
3757
|
+
function dialogChangedCallback() {
|
|
3758
|
+
if (activeDialogs.length > 0) {
|
|
3759
|
+
if (!container.parentNode) {
|
|
3760
|
+
document.body.appendChild(container);
|
|
3761
|
+
}
|
|
4037
3762
|
} else {
|
|
4038
|
-
|
|
4039
|
-
|
|
3763
|
+
if (container.parentNode) {
|
|
3764
|
+
document.body.removeChild(container);
|
|
3765
|
+
}
|
|
4040
3766
|
}
|
|
4041
|
-
const instance = initStore({
|
|
4042
|
-
store,
|
|
4043
|
-
options,
|
|
4044
|
-
appContext,
|
|
4045
|
-
elementContext
|
|
4046
|
-
});
|
|
4047
|
-
instance.setup();
|
|
4048
|
-
elementContext.stores.set(store, { store, options, instance });
|
|
4049
|
-
instances.push(instance);
|
|
4050
3767
|
}
|
|
4051
|
-
ctx.
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
3768
|
+
ctx.observe($$dialogs, (dialogs) => {
|
|
3769
|
+
render.update(() => {
|
|
3770
|
+
let removed = [];
|
|
3771
|
+
let added = [];
|
|
3772
|
+
for (const dialog of activeDialogs) {
|
|
3773
|
+
if (!dialogs.includes(dialog)) {
|
|
3774
|
+
removed.push(dialog);
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
for (const dialog of dialogs) {
|
|
3778
|
+
if (!activeDialogs.includes(dialog)) {
|
|
3779
|
+
added.push(dialog);
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
for (const dialog of removed) {
|
|
3783
|
+
if (dialog.transitionOutCallback) {
|
|
3784
|
+
dialog.transitionOutCallback().then(() => {
|
|
3785
|
+
dialog.instance.disconnect();
|
|
3786
|
+
activeDialogs.splice(activeDialogs.indexOf(dialog), 1);
|
|
3787
|
+
dialogChangedCallback();
|
|
3788
|
+
});
|
|
3789
|
+
} else {
|
|
3790
|
+
dialog.instance.disconnect();
|
|
3791
|
+
activeDialogs.splice(activeDialogs.indexOf(dialog), 1);
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
for (const dialog of added) {
|
|
3795
|
+
dialog.instance.connect(container);
|
|
3796
|
+
if (dialog.transitionInCallback) {
|
|
3797
|
+
dialog.transitionInCallback();
|
|
3798
|
+
}
|
|
3799
|
+
activeDialogs.push(dialog);
|
|
3800
|
+
}
|
|
3801
|
+
dialogChangedCallback();
|
|
3802
|
+
});
|
|
4055
3803
|
});
|
|
4056
3804
|
ctx.onDisconnected(() => {
|
|
4057
|
-
|
|
4058
|
-
|
|
3805
|
+
if (container.parentNode) {
|
|
3806
|
+
document.body.removeChild(container);
|
|
4059
3807
|
}
|
|
4060
3808
|
});
|
|
4061
|
-
|
|
3809
|
+
function open(view, props) {
|
|
3810
|
+
const $$open = $$(true);
|
|
3811
|
+
let dialog;
|
|
3812
|
+
let transitionInCallback;
|
|
3813
|
+
let transitionOutCallback;
|
|
3814
|
+
let instance = initView({
|
|
3815
|
+
view,
|
|
3816
|
+
appContext,
|
|
3817
|
+
elementContext,
|
|
3818
|
+
props: {
|
|
3819
|
+
...props,
|
|
3820
|
+
$$open,
|
|
3821
|
+
transitionIn: (callback) => {
|
|
3822
|
+
transitionInCallback = callback;
|
|
3823
|
+
},
|
|
3824
|
+
transitionOut: (callback) => {
|
|
3825
|
+
transitionOutCallback = callback;
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3828
|
+
});
|
|
3829
|
+
dialog = {
|
|
3830
|
+
instance,
|
|
3831
|
+
// These must be getters because the fns passed to props aren't called until before connect.
|
|
3832
|
+
get transitionInCallback() {
|
|
3833
|
+
return transitionInCallback;
|
|
3834
|
+
},
|
|
3835
|
+
get transitionOutCallback() {
|
|
3836
|
+
return transitionOutCallback;
|
|
3837
|
+
}
|
|
3838
|
+
};
|
|
3839
|
+
$$dialogs.update((current) => {
|
|
3840
|
+
return [...current, dialog];
|
|
3841
|
+
});
|
|
3842
|
+
const stopObserver = observe($$open, (value) => {
|
|
3843
|
+
if (!value) {
|
|
3844
|
+
closeDialog();
|
|
3845
|
+
}
|
|
3846
|
+
});
|
|
3847
|
+
function closeDialog() {
|
|
3848
|
+
$$dialogs.update((current) => {
|
|
3849
|
+
return current.filter((x) => x !== dialog);
|
|
3850
|
+
});
|
|
3851
|
+
dialog = void 0;
|
|
3852
|
+
stopObserver();
|
|
3853
|
+
}
|
|
3854
|
+
return closeDialog;
|
|
3855
|
+
}
|
|
3856
|
+
return {
|
|
3857
|
+
open
|
|
3858
|
+
};
|
|
4062
3859
|
}
|
|
4063
3860
|
export {
|
|
3861
|
+
$,
|
|
3862
|
+
$$,
|
|
3863
|
+
App,
|
|
3864
|
+
DialogStore,
|
|
4064
3865
|
Fragment,
|
|
3866
|
+
HTTPStore,
|
|
3867
|
+
LanguageStore,
|
|
3868
|
+
RouterStore,
|
|
4065
3869
|
StoreScope,
|
|
4066
|
-
computed,
|
|
4067
3870
|
cond,
|
|
4068
3871
|
isReadable,
|
|
4069
3872
|
isWritable,
|
|
4070
3873
|
m,
|
|
4071
|
-
makeApp,
|
|
4072
3874
|
observe,
|
|
4073
3875
|
portal,
|
|
4074
|
-
proxy,
|
|
4075
|
-
readable,
|
|
4076
3876
|
repeat,
|
|
4077
|
-
|
|
4078
|
-
unwrap,
|
|
4079
|
-
writable
|
|
3877
|
+
unwrap
|
|
4080
3878
|
};
|
|
4081
3879
|
//# sourceMappingURL=index.js.map
|