@manyducks.co/dolla 0.68.1 → 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 +888 -1097
- 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/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,34 +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);
|
|
790
738
|
if (isReadable(computedValue)) {
|
|
791
739
|
lastComputedValue = computedValue;
|
|
792
|
-
return computedValue[OBSERVE]((current
|
|
793
|
-
callback(current
|
|
794
|
-
lastObservedValue = current;
|
|
740
|
+
return computedValue[OBSERVE]((current) => {
|
|
741
|
+
callback(current);
|
|
795
742
|
});
|
|
796
743
|
}
|
|
797
744
|
if (!deepEqual(computedValue, lastComputedValue)) {
|
|
798
|
-
|
|
799
|
-
callback(computedValue, previousValue);
|
|
745
|
+
callback(computedValue);
|
|
800
746
|
lastComputedValue = computedValue;
|
|
801
|
-
lastObservedValue = currentValue;
|
|
802
747
|
}
|
|
803
748
|
});
|
|
804
749
|
}
|
|
805
750
|
};
|
|
806
|
-
} else
|
|
751
|
+
} else {
|
|
807
752
|
let updateValue2 = function() {
|
|
808
|
-
const computedValue = compute(observedValues
|
|
753
|
+
const computedValue = compute(...observedValues);
|
|
809
754
|
if (!deepEqual(computedValue, latestComputedValue)) {
|
|
810
|
-
const previousValue = latestComputedValue === UNOBSERVED ? void 0 : latestComputedValue;
|
|
811
755
|
latestComputedValue = computedValue;
|
|
812
|
-
previousObservedValues = observedValues;
|
|
813
756
|
for (const callback of observers) {
|
|
814
|
-
callback(computedValue
|
|
757
|
+
callback(computedValue);
|
|
815
758
|
}
|
|
816
759
|
}
|
|
817
760
|
}, startObserving2 = function() {
|
|
@@ -828,7 +771,6 @@ function computed(...args) {
|
|
|
828
771
|
})
|
|
829
772
|
);
|
|
830
773
|
}
|
|
831
|
-
previousObservedValues = new Array().fill(void 0, 0, readables.length);
|
|
832
774
|
observedValues = readables.map((x) => x.get());
|
|
833
775
|
isObserving = true;
|
|
834
776
|
updateValue2();
|
|
@@ -840,24 +782,9 @@ function computed(...args) {
|
|
|
840
782
|
stopCallbacks = [];
|
|
841
783
|
};
|
|
842
784
|
var updateValue = updateValue2, startObserving = startObserving2, stopObserving = stopObserving2;
|
|
843
|
-
if (typeof args[1] !== "function") {
|
|
844
|
-
throw new TypeError(
|
|
845
|
-
`When first argument is an array of Readables the second argument must be a callback function. Got type: ${typeOf(
|
|
846
|
-
args[1]
|
|
847
|
-
)}, value: ${args[1]}`
|
|
848
|
-
);
|
|
849
|
-
}
|
|
850
|
-
if (!args[0].every(isReadable)) {
|
|
851
|
-
throw new TypeError(
|
|
852
|
-
`Computed expected an array of Readables. Got: [${args[0].map((x) => isReadable(x) ? `Readable<${typeOf(x.get())}>` : typeof x).join(", ")}]`
|
|
853
|
-
);
|
|
854
|
-
}
|
|
855
|
-
const readables = args[0];
|
|
856
|
-
const compute = args[1];
|
|
857
785
|
const observers = [];
|
|
858
786
|
let stopCallbacks = [];
|
|
859
787
|
let isObserving = false;
|
|
860
|
-
let previousObservedValues = [];
|
|
861
788
|
let observedValues = [];
|
|
862
789
|
let latestComputedValue = UNOBSERVED;
|
|
863
790
|
return {
|
|
@@ -865,17 +792,14 @@ function computed(...args) {
|
|
|
865
792
|
if (isObserving) {
|
|
866
793
|
return latestComputedValue;
|
|
867
794
|
} else {
|
|
868
|
-
return compute(
|
|
869
|
-
readables.map((x) => x.get()),
|
|
870
|
-
new Array().fill(void 0, 0, readables.length)
|
|
871
|
-
);
|
|
795
|
+
return compute(...readables.map((x) => x.get()));
|
|
872
796
|
}
|
|
873
797
|
},
|
|
874
798
|
[OBSERVE]: (callback) => {
|
|
875
799
|
if (!isObserving) {
|
|
876
800
|
startObserving2();
|
|
877
801
|
}
|
|
878
|
-
callback(latestComputedValue
|
|
802
|
+
callback(latestComputedValue);
|
|
879
803
|
observers.push(callback);
|
|
880
804
|
return function stop() {
|
|
881
805
|
observers.splice(observers.indexOf(callback), 1);
|
|
@@ -885,42 +809,88 @@ function computed(...args) {
|
|
|
885
809
|
};
|
|
886
810
|
}
|
|
887
811
|
};
|
|
888
|
-
} else {
|
|
889
|
-
throw new TypeError(
|
|
890
|
-
`Expected a Readable or array of Readables as a first argument. Got: ${typeOf(args[0])}, value: ${args[0]}`
|
|
891
|
-
);
|
|
892
812
|
}
|
|
893
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
|
+
}
|
|
894
856
|
function proxy(source, config) {
|
|
895
857
|
if (!isReadable(source)) {
|
|
896
858
|
throw new TypeError(`Proxy source must be a Readable.`);
|
|
897
859
|
}
|
|
898
|
-
const observers = [];
|
|
899
|
-
const currentValue = () => config.get(source);
|
|
900
860
|
return {
|
|
901
861
|
// ----- Readable ----- //
|
|
902
|
-
get: () => config.get(
|
|
862
|
+
get: () => config.get(),
|
|
903
863
|
[OBSERVE]: (callback) => {
|
|
904
864
|
let lastComputedValue = UNOBSERVED;
|
|
905
|
-
return source
|
|
906
|
-
const computedValue = config.get(
|
|
865
|
+
return observe(source, (_) => {
|
|
866
|
+
const computedValue = config.get();
|
|
907
867
|
if (!deepEqual(computedValue, lastComputedValue)) {
|
|
908
|
-
|
|
909
|
-
callback(computedValue, previousValue);
|
|
868
|
+
callback(computedValue);
|
|
910
869
|
lastComputedValue = computedValue;
|
|
911
870
|
}
|
|
912
871
|
});
|
|
913
872
|
},
|
|
914
873
|
// ----- Writable ----- //
|
|
915
|
-
set: (
|
|
916
|
-
config.set(
|
|
874
|
+
set: (value) => {
|
|
875
|
+
config.set(value);
|
|
917
876
|
},
|
|
918
877
|
update: (callback) => {
|
|
919
|
-
|
|
920
|
-
config.set(source, newValue);
|
|
878
|
+
config.set(callback(config.get()));
|
|
921
879
|
}
|
|
922
880
|
};
|
|
923
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
|
+
}
|
|
924
894
|
function unwrap(value) {
|
|
925
895
|
if (isReadable(value)) {
|
|
926
896
|
return value.get();
|
|
@@ -1647,7 +1617,7 @@ function initView(config) {
|
|
|
1647
1617
|
stores: /* @__PURE__ */ new Map(),
|
|
1648
1618
|
parent: config.elementContext
|
|
1649
1619
|
};
|
|
1650
|
-
const $$children =
|
|
1620
|
+
const $$children = $$(renderMarkupToDOM(config.children ?? [], { appContext, elementContext }));
|
|
1651
1621
|
let isConnected = false;
|
|
1652
1622
|
const stopObserverCallbacks = [];
|
|
1653
1623
|
const connectedCallbacks = [];
|
|
@@ -1706,19 +1676,20 @@ function initView(config) {
|
|
|
1706
1676
|
crash(error) {
|
|
1707
1677
|
config.appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
1708
1678
|
},
|
|
1709
|
-
observe(
|
|
1679
|
+
observe(...args) {
|
|
1680
|
+
const callback = args.pop();
|
|
1710
1681
|
if (isConnected) {
|
|
1711
|
-
const stop = observe(
|
|
1682
|
+
const stop = observe(args, callback);
|
|
1712
1683
|
stopObserverCallbacks.push(stop);
|
|
1713
1684
|
} else {
|
|
1714
1685
|
connectedCallbacks.push(() => {
|
|
1715
|
-
const stop = observe(
|
|
1686
|
+
const stop = observe(args, callback);
|
|
1716
1687
|
stopObserverCallbacks.push(stop);
|
|
1717
1688
|
});
|
|
1718
1689
|
}
|
|
1719
1690
|
},
|
|
1720
1691
|
outlet() {
|
|
1721
|
-
return m("$outlet", { $children:
|
|
1692
|
+
return m("$outlet", { $children: $($$children) });
|
|
1722
1693
|
}
|
|
1723
1694
|
};
|
|
1724
1695
|
const debugChannel = appContext.debugHub.channel({
|
|
@@ -1908,8 +1879,8 @@ var Repeat = class {
|
|
|
1908
1879
|
connected.$$index.set(potential.index);
|
|
1909
1880
|
newItems[potential.index] = connected;
|
|
1910
1881
|
} else {
|
|
1911
|
-
const $$value =
|
|
1912
|
-
const $$index =
|
|
1882
|
+
const $$value = $$(potential.value);
|
|
1883
|
+
const $$index = $$(potential.index);
|
|
1913
1884
|
newItems[potential.index] = {
|
|
1914
1885
|
key: potential.key,
|
|
1915
1886
|
$$value,
|
|
@@ -1918,7 +1889,7 @@ var Repeat = class {
|
|
|
1918
1889
|
view: RepeatItemView,
|
|
1919
1890
|
appContext: this.appContext,
|
|
1920
1891
|
elementContext: this.elementContext,
|
|
1921
|
-
props: { $value:
|
|
1892
|
+
props: { $value: $($$value), $index: $($$index), renderFn: this.renderFn }
|
|
1922
1893
|
})
|
|
1923
1894
|
};
|
|
1924
1895
|
}
|
|
@@ -2024,7 +1995,7 @@ function m(type, props, ...children) {
|
|
|
2024
1995
|
};
|
|
2025
1996
|
}
|
|
2026
1997
|
function cond(predicate, thenContent, elseContent) {
|
|
2027
|
-
const $predicate =
|
|
1998
|
+
const $predicate = $(predicate);
|
|
2028
1999
|
return m("$cond", {
|
|
2029
2000
|
$predicate,
|
|
2030
2001
|
thenContent,
|
|
@@ -2032,7 +2003,7 @@ function cond(predicate, thenContent, elseContent) {
|
|
|
2032
2003
|
});
|
|
2033
2004
|
}
|
|
2034
2005
|
function repeat(items, keyFn, renderFn) {
|
|
2035
|
-
const $items =
|
|
2006
|
+
const $items = $(items);
|
|
2036
2007
|
return m("$repeat", { $items, keyFn, renderFn });
|
|
2037
2008
|
}
|
|
2038
2009
|
function portal(content, parent) {
|
|
@@ -2238,7 +2209,9 @@ function initStore(config) {
|
|
|
2238
2209
|
crash(error) {
|
|
2239
2210
|
config.appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
2240
2211
|
},
|
|
2241
|
-
observe(
|
|
2212
|
+
observe(...args) {
|
|
2213
|
+
const callback = args.pop();
|
|
2214
|
+
const readables = args.flat();
|
|
2242
2215
|
if (isConnected) {
|
|
2243
2216
|
const stop = observe(readables, callback);
|
|
2244
2217
|
stopObserverCallbacks.push(stop);
|
|
@@ -2310,130 +2283,13 @@ function initStore(config) {
|
|
|
2310
2283
|
};
|
|
2311
2284
|
}
|
|
2312
2285
|
|
|
2313
|
-
// src/stores/dialog.ts
|
|
2314
|
-
function DialogStore(ctx) {
|
|
2315
|
-
ctx.name = "dolla/dialog";
|
|
2316
|
-
const { appContext, elementContext } = getStoreSecrets(ctx);
|
|
2317
|
-
const container = document.createElement("div");
|
|
2318
|
-
container.style.position = "fixed";
|
|
2319
|
-
container.style.top = "0";
|
|
2320
|
-
container.style.right = "0";
|
|
2321
|
-
container.style.bottom = "0";
|
|
2322
|
-
container.style.left = "0";
|
|
2323
|
-
container.style.zIndex = "99999";
|
|
2324
|
-
const $$dialogs = writable([]);
|
|
2325
|
-
let activeDialogs = [];
|
|
2326
|
-
function dialogChangedCallback() {
|
|
2327
|
-
if (activeDialogs.length > 0) {
|
|
2328
|
-
if (!container.parentNode) {
|
|
2329
|
-
document.body.appendChild(container);
|
|
2330
|
-
}
|
|
2331
|
-
} else {
|
|
2332
|
-
if (container.parentNode) {
|
|
2333
|
-
document.body.removeChild(container);
|
|
2334
|
-
}
|
|
2335
|
-
}
|
|
2336
|
-
}
|
|
2337
|
-
ctx.observe($$dialogs, (dialogs) => {
|
|
2338
|
-
requestAnimationFrame(() => {
|
|
2339
|
-
let removed = [];
|
|
2340
|
-
let added = [];
|
|
2341
|
-
for (const dialog of activeDialogs) {
|
|
2342
|
-
if (!dialogs.includes(dialog)) {
|
|
2343
|
-
removed.push(dialog);
|
|
2344
|
-
}
|
|
2345
|
-
}
|
|
2346
|
-
for (const dialog of dialogs) {
|
|
2347
|
-
if (!activeDialogs.includes(dialog)) {
|
|
2348
|
-
added.push(dialog);
|
|
2349
|
-
}
|
|
2350
|
-
}
|
|
2351
|
-
for (const dialog of removed) {
|
|
2352
|
-
if (dialog.transitionOutCallback) {
|
|
2353
|
-
dialog.transitionOutCallback().then(() => {
|
|
2354
|
-
dialog.instance.disconnect();
|
|
2355
|
-
activeDialogs.splice(activeDialogs.indexOf(dialog), 1);
|
|
2356
|
-
dialogChangedCallback();
|
|
2357
|
-
});
|
|
2358
|
-
} else {
|
|
2359
|
-
dialog.instance.disconnect();
|
|
2360
|
-
activeDialogs.splice(activeDialogs.indexOf(dialog), 1);
|
|
2361
|
-
}
|
|
2362
|
-
}
|
|
2363
|
-
for (const dialog of added) {
|
|
2364
|
-
dialog.instance.connect(container);
|
|
2365
|
-
if (dialog.transitionInCallback) {
|
|
2366
|
-
dialog.transitionInCallback();
|
|
2367
|
-
}
|
|
2368
|
-
activeDialogs.push(dialog);
|
|
2369
|
-
}
|
|
2370
|
-
dialogChangedCallback();
|
|
2371
|
-
});
|
|
2372
|
-
});
|
|
2373
|
-
ctx.onDisconnected(() => {
|
|
2374
|
-
if (container.parentNode) {
|
|
2375
|
-
document.body.removeChild(container);
|
|
2376
|
-
}
|
|
2377
|
-
});
|
|
2378
|
-
function open(view, props) {
|
|
2379
|
-
const $$open = writable(true);
|
|
2380
|
-
let dialog;
|
|
2381
|
-
let transitionInCallback;
|
|
2382
|
-
let transitionOutCallback;
|
|
2383
|
-
let instance = initView({
|
|
2384
|
-
view,
|
|
2385
|
-
appContext,
|
|
2386
|
-
elementContext,
|
|
2387
|
-
props: {
|
|
2388
|
-
...props,
|
|
2389
|
-
$$open,
|
|
2390
|
-
transitionIn: (callback) => {
|
|
2391
|
-
transitionInCallback = callback;
|
|
2392
|
-
},
|
|
2393
|
-
transitionOut: (callback) => {
|
|
2394
|
-
transitionOutCallback = callback;
|
|
2395
|
-
}
|
|
2396
|
-
}
|
|
2397
|
-
});
|
|
2398
|
-
dialog = {
|
|
2399
|
-
instance,
|
|
2400
|
-
// These must be getters because the fns passed to props aren't called until before connect.
|
|
2401
|
-
get transitionInCallback() {
|
|
2402
|
-
return transitionInCallback;
|
|
2403
|
-
},
|
|
2404
|
-
get transitionOutCallback() {
|
|
2405
|
-
return transitionOutCallback;
|
|
2406
|
-
}
|
|
2407
|
-
};
|
|
2408
|
-
$$dialogs.update((current) => {
|
|
2409
|
-
return [...current, dialog];
|
|
2410
|
-
});
|
|
2411
|
-
const stopObserver = observe($$open, (value) => {
|
|
2412
|
-
if (!value) {
|
|
2413
|
-
closeDialog();
|
|
2414
|
-
}
|
|
2415
|
-
});
|
|
2416
|
-
function closeDialog() {
|
|
2417
|
-
$$dialogs.update((current) => {
|
|
2418
|
-
return current.filter((x) => x !== dialog);
|
|
2419
|
-
});
|
|
2420
|
-
dialog = void 0;
|
|
2421
|
-
stopObserver();
|
|
2422
|
-
}
|
|
2423
|
-
return closeDialog;
|
|
2424
|
-
}
|
|
2425
|
-
return {
|
|
2426
|
-
open
|
|
2427
|
-
};
|
|
2428
|
-
}
|
|
2429
|
-
|
|
2430
2286
|
// src/stores/document.ts
|
|
2431
2287
|
function DocumentStore(ctx) {
|
|
2432
2288
|
ctx.name = "dolla/document";
|
|
2433
|
-
const $$title =
|
|
2434
|
-
const $$visibility =
|
|
2435
|
-
const $$orientation =
|
|
2436
|
-
const $$colorScheme =
|
|
2289
|
+
const $$title = $$(document.title);
|
|
2290
|
+
const $$visibility = $$(document.visibilityState);
|
|
2291
|
+
const $$orientation = $$("landscape");
|
|
2292
|
+
const $$colorScheme = $$("light");
|
|
2437
2293
|
ctx.observe($$title, (current) => {
|
|
2438
2294
|
document.title = current;
|
|
2439
2295
|
});
|
|
@@ -2467,337 +2323,12 @@ function DocumentStore(ctx) {
|
|
|
2467
2323
|
});
|
|
2468
2324
|
return {
|
|
2469
2325
|
$$title,
|
|
2470
|
-
$visibility:
|
|
2471
|
-
$orientation:
|
|
2472
|
-
$colorScheme:
|
|
2326
|
+
$visibility: $($$visibility),
|
|
2327
|
+
$orientation: $($$orientation),
|
|
2328
|
+
$colorScheme: $($$colorScheme)
|
|
2473
2329
|
};
|
|
2474
2330
|
}
|
|
2475
2331
|
|
|
2476
|
-
// src/stores/http.ts
|
|
2477
|
-
function HTTPStore(ctx) {
|
|
2478
|
-
ctx.name = "dolla/http";
|
|
2479
|
-
const fetch = ctx.options.fetch ?? getDefaultFetch();
|
|
2480
|
-
const middleware = [];
|
|
2481
|
-
async function request(method, uri, options) {
|
|
2482
|
-
return makeRequest({ ...options, method, uri, middleware, fetch });
|
|
2483
|
-
}
|
|
2484
|
-
return {
|
|
2485
|
-
/**
|
|
2486
|
-
* Adds a new middleware that will apply to subsequent requests.
|
|
2487
|
-
* Returns a function to remove this middleware.
|
|
2488
|
-
*
|
|
2489
|
-
* @param middleware - A middleware function that will intercept requests.
|
|
2490
|
-
*/
|
|
2491
|
-
middleware(fn) {
|
|
2492
|
-
middleware.push(fn);
|
|
2493
|
-
return function remove() {
|
|
2494
|
-
middleware.splice(middleware.indexOf(fn), 1);
|
|
2495
|
-
};
|
|
2496
|
-
},
|
|
2497
|
-
async get(uri, options) {
|
|
2498
|
-
return request("get", uri, options);
|
|
2499
|
-
},
|
|
2500
|
-
async put(uri, options) {
|
|
2501
|
-
return request("put", uri, options);
|
|
2502
|
-
},
|
|
2503
|
-
async patch(uri, options) {
|
|
2504
|
-
return request("patch", uri, options);
|
|
2505
|
-
},
|
|
2506
|
-
async post(uri, options) {
|
|
2507
|
-
return request("post", uri, options);
|
|
2508
|
-
},
|
|
2509
|
-
async delete(uri, options) {
|
|
2510
|
-
return request("delete", uri, options);
|
|
2511
|
-
},
|
|
2512
|
-
async head(uri, options) {
|
|
2513
|
-
return request("head", uri, options);
|
|
2514
|
-
},
|
|
2515
|
-
async options(uri, options) {
|
|
2516
|
-
return request("options", uri, options);
|
|
2517
|
-
},
|
|
2518
|
-
async trace(uri, options) {
|
|
2519
|
-
return request("trace", uri, options);
|
|
2520
|
-
}
|
|
2521
|
-
};
|
|
2522
|
-
}
|
|
2523
|
-
function getDefaultFetch() {
|
|
2524
|
-
if (typeof window !== "undefined" && window.fetch) {
|
|
2525
|
-
return window.fetch.bind(window);
|
|
2526
|
-
}
|
|
2527
|
-
if (typeof global !== "undefined" && global.fetch) {
|
|
2528
|
-
return global.fetch.bind(global);
|
|
2529
|
-
}
|
|
2530
|
-
throw new Error("Running in neither browser nor node. Please run this app in one of the supported environments.");
|
|
2531
|
-
}
|
|
2532
|
-
var HTTPResponseError = class extends Error {
|
|
2533
|
-
response;
|
|
2534
|
-
constructor(response) {
|
|
2535
|
-
const { status, statusText, method, uri } = response;
|
|
2536
|
-
const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${uri})`;
|
|
2537
|
-
super(message);
|
|
2538
|
-
this.response = response;
|
|
2539
|
-
}
|
|
2540
|
-
};
|
|
2541
|
-
async function makeRequest(config) {
|
|
2542
|
-
const { headers, query, fetch, middleware } = config;
|
|
2543
|
-
const request = {
|
|
2544
|
-
method: config.method,
|
|
2545
|
-
uri: config.uri,
|
|
2546
|
-
get sameOrigin() {
|
|
2547
|
-
return !request.uri.startsWith("http");
|
|
2548
|
-
},
|
|
2549
|
-
query: new URLSearchParams(),
|
|
2550
|
-
headers: new Headers(),
|
|
2551
|
-
body: config.body
|
|
2552
|
-
};
|
|
2553
|
-
if (headers) {
|
|
2554
|
-
if (headers instanceof Map || headers instanceof Headers) {
|
|
2555
|
-
headers.forEach((value, key) => {
|
|
2556
|
-
request.headers.set(key, value);
|
|
2557
|
-
});
|
|
2558
|
-
} else if (headers != null && typeof headers === "object" && !Array.isArray(headers)) {
|
|
2559
|
-
for (const name in headers) {
|
|
2560
|
-
request.headers.set(name, String(headers[name]));
|
|
2561
|
-
}
|
|
2562
|
-
} else {
|
|
2563
|
-
throw new TypeError(`Unknown headers type. Got: ${headers}`);
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
if (query) {
|
|
2567
|
-
if (query instanceof Map || query instanceof URLSearchParams) {
|
|
2568
|
-
query.forEach((value, key) => {
|
|
2569
|
-
request.query.set(key, value);
|
|
2570
|
-
});
|
|
2571
|
-
} else if (query != null && typeof query === "object" && !Array.isArray(query)) {
|
|
2572
|
-
for (const name in query) {
|
|
2573
|
-
request.query.set(name, String(query[name]));
|
|
2574
|
-
}
|
|
2575
|
-
} else {
|
|
2576
|
-
throw new TypeError(`Unknown query params type. Got: ${query}`);
|
|
2577
|
-
}
|
|
2578
|
-
}
|
|
2579
|
-
let response;
|
|
2580
|
-
const handler = async () => {
|
|
2581
|
-
const query2 = request.query.toString();
|
|
2582
|
-
const fullURL = query2.length > 0 ? request.uri + "?" + query2 : request.uri;
|
|
2583
|
-
let reqBody;
|
|
2584
|
-
if (!request.headers.has("content-type") && isObject(request.body)) {
|
|
2585
|
-
request.headers.set("content-type", "application/json");
|
|
2586
|
-
reqBody = JSON.stringify(request.body);
|
|
2587
|
-
} else {
|
|
2588
|
-
reqBody = request.body;
|
|
2589
|
-
}
|
|
2590
|
-
const fetched = await fetch(fullURL, {
|
|
2591
|
-
method: request.method,
|
|
2592
|
-
headers: request.headers,
|
|
2593
|
-
body: reqBody
|
|
2594
|
-
});
|
|
2595
|
-
const headers2 = Object.fromEntries(fetched.headers.entries());
|
|
2596
|
-
const contentType = headers2["content-type"];
|
|
2597
|
-
let body;
|
|
2598
|
-
if (contentType?.includes("application/json")) {
|
|
2599
|
-
body = await fetched.json();
|
|
2600
|
-
} else if (contentType?.includes("application/x-www-form-urlencoded")) {
|
|
2601
|
-
body = await fetched.formData();
|
|
2602
|
-
} else {
|
|
2603
|
-
body = await fetched.text();
|
|
2604
|
-
}
|
|
2605
|
-
response = {
|
|
2606
|
-
method: request.method,
|
|
2607
|
-
uri: request.uri,
|
|
2608
|
-
status: fetched.status,
|
|
2609
|
-
statusText: fetched.statusText,
|
|
2610
|
-
headers: headers2,
|
|
2611
|
-
body
|
|
2612
|
-
};
|
|
2613
|
-
};
|
|
2614
|
-
if (middleware.length > 0) {
|
|
2615
|
-
const mount = (index = 0) => {
|
|
2616
|
-
const current = middleware[index];
|
|
2617
|
-
const next = middleware[index + 1] ? mount(index + 1) : handler;
|
|
2618
|
-
return async () => current(request, async () => {
|
|
2619
|
-
await next();
|
|
2620
|
-
return response;
|
|
2621
|
-
});
|
|
2622
|
-
};
|
|
2623
|
-
await mount()();
|
|
2624
|
-
} else {
|
|
2625
|
-
await handler();
|
|
2626
|
-
}
|
|
2627
|
-
if (response.status < 200 || response.status >= 400) {
|
|
2628
|
-
throw new HTTPResponseError(response);
|
|
2629
|
-
}
|
|
2630
|
-
return response;
|
|
2631
|
-
}
|
|
2632
|
-
|
|
2633
|
-
// src/stores/language.ts
|
|
2634
|
-
function LanguageStore(ctx) {
|
|
2635
|
-
ctx.name = "dolla/language";
|
|
2636
|
-
const languages = /* @__PURE__ */ new Map();
|
|
2637
|
-
Object.entries(ctx.options.languages).forEach(([tag, config]) => {
|
|
2638
|
-
languages.set(tag, new Language(tag, config));
|
|
2639
|
-
});
|
|
2640
|
-
ctx.info(
|
|
2641
|
-
`App supports ${languages.size} language${languages.size === 1 ? "" : "s"}: '${[...languages.keys()].join("', '")}'`
|
|
2642
|
-
);
|
|
2643
|
-
const $$isLoaded = writable(false);
|
|
2644
|
-
const $$language = writable(void 0);
|
|
2645
|
-
const $$translation = writable(void 0);
|
|
2646
|
-
const $noLanguageValue = readable("[NO LANGUAGE SET]");
|
|
2647
|
-
const translationCache = [];
|
|
2648
|
-
function getCached(key, values) {
|
|
2649
|
-
for (const entry of translationCache) {
|
|
2650
|
-
if (entry[0] === key && deepEqual(entry[1], values)) {
|
|
2651
|
-
return entry[2];
|
|
2652
|
-
}
|
|
2653
|
-
}
|
|
2654
|
-
}
|
|
2655
|
-
function replaceMustaches(template, values) {
|
|
2656
|
-
for (const name in values) {
|
|
2657
|
-
template = template.replace(`{{${name}}}`, String(values[name]));
|
|
2658
|
-
}
|
|
2659
|
-
return template;
|
|
2660
|
-
}
|
|
2661
|
-
const currentLanguage = ctx.options.currentLanguage ? languages.get(ctx.options.currentLanguage) : languages.get([...languages.keys()][0]);
|
|
2662
|
-
if (currentLanguage == null) {
|
|
2663
|
-
$$isLoaded.set(true);
|
|
2664
|
-
} else {
|
|
2665
|
-
ctx.info(`Current language is '${currentLanguage.tag}'.`);
|
|
2666
|
-
currentLanguage.getTranslation().then((translation) => {
|
|
2667
|
-
$$language.set(currentLanguage.tag);
|
|
2668
|
-
$$translation.set(translation);
|
|
2669
|
-
$$isLoaded.set(true);
|
|
2670
|
-
});
|
|
2671
|
-
}
|
|
2672
|
-
return {
|
|
2673
|
-
$isLoaded: readable($$isLoaded),
|
|
2674
|
-
$currentLanguage: readable($$language),
|
|
2675
|
-
supportedLanguages: [...languages.keys()],
|
|
2676
|
-
async setLanguage(tag) {
|
|
2677
|
-
if (!languages.has(tag)) {
|
|
2678
|
-
throw new Error(`Language '${tag}' is not supported.`);
|
|
2679
|
-
}
|
|
2680
|
-
const lang = languages.get(tag);
|
|
2681
|
-
try {
|
|
2682
|
-
const translation = await lang.getTranslation();
|
|
2683
|
-
$$translation.set(translation);
|
|
2684
|
-
$$language.set(tag);
|
|
2685
|
-
ctx.info("set language to " + tag);
|
|
2686
|
-
} catch (error) {
|
|
2687
|
-
if (error instanceof Error) {
|
|
2688
|
-
ctx.crash(error);
|
|
2689
|
-
}
|
|
2690
|
-
}
|
|
2691
|
-
},
|
|
2692
|
-
/**
|
|
2693
|
-
* Returns a Readable of the translated value.
|
|
2694
|
-
|
|
2695
|
-
* @param key - Key to the translated value.
|
|
2696
|
-
* @param values - A map of {{placeholder}} names and the values to replace them with.
|
|
2697
|
-
*/
|
|
2698
|
-
translate(key, values) {
|
|
2699
|
-
if (!$$language.get()) {
|
|
2700
|
-
return $noLanguageValue;
|
|
2701
|
-
}
|
|
2702
|
-
const cached = getCached(key, values);
|
|
2703
|
-
if (cached) {
|
|
2704
|
-
return cached;
|
|
2705
|
-
}
|
|
2706
|
-
if (values) {
|
|
2707
|
-
const readableValues = {};
|
|
2708
|
-
for (const [key2, value] of Object.entries(values)) {
|
|
2709
|
-
if (isReadable(value)) {
|
|
2710
|
-
readableValues[key2] = value;
|
|
2711
|
-
}
|
|
2712
|
-
}
|
|
2713
|
-
const readableEntries = Object.entries(readableValues);
|
|
2714
|
-
if (readableEntries.length > 0) {
|
|
2715
|
-
const $merged = computed([$$translation, ...readableEntries.map((x) => x[1])], ([t, ...entryValues]) => {
|
|
2716
|
-
const entries = entryValues.map((_, i) => readableEntries[i]);
|
|
2717
|
-
const mergedValues = {
|
|
2718
|
-
...values
|
|
2719
|
-
};
|
|
2720
|
-
for (let i = 0; i < entries.length; i++) {
|
|
2721
|
-
const key2 = entries[i][0];
|
|
2722
|
-
mergedValues[key2] = entryValues[i];
|
|
2723
|
-
}
|
|
2724
|
-
const result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
2725
|
-
return replaceMustaches(result, mergedValues);
|
|
2726
|
-
});
|
|
2727
|
-
translationCache.push([key, values, $merged]);
|
|
2728
|
-
return $merged;
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
const $replaced = computed($$translation, (t) => {
|
|
2732
|
-
let result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
2733
|
-
if (values) {
|
|
2734
|
-
result = replaceMustaches(result, values);
|
|
2735
|
-
}
|
|
2736
|
-
return result;
|
|
2737
|
-
});
|
|
2738
|
-
translationCache.push([key, values, $replaced]);
|
|
2739
|
-
return $replaced;
|
|
2740
|
-
}
|
|
2741
|
-
};
|
|
2742
|
-
}
|
|
2743
|
-
function resolve(object, key) {
|
|
2744
|
-
const parsed = String(key).split(/[\.\[\]]/).filter((part) => part.trim() !== "");
|
|
2745
|
-
let value = object;
|
|
2746
|
-
while (parsed.length > 0) {
|
|
2747
|
-
const part = parsed.shift();
|
|
2748
|
-
if (value != null) {
|
|
2749
|
-
value = value[part];
|
|
2750
|
-
} else {
|
|
2751
|
-
value = void 0;
|
|
2752
|
-
}
|
|
2753
|
-
}
|
|
2754
|
-
return value;
|
|
2755
|
-
}
|
|
2756
|
-
var Language = class {
|
|
2757
|
-
#tag;
|
|
2758
|
-
#config;
|
|
2759
|
-
#translation;
|
|
2760
|
-
get tag() {
|
|
2761
|
-
return this.#tag;
|
|
2762
|
-
}
|
|
2763
|
-
constructor(tag, config) {
|
|
2764
|
-
this.#tag = tag;
|
|
2765
|
-
this.#config = config;
|
|
2766
|
-
}
|
|
2767
|
-
async getTranslation() {
|
|
2768
|
-
if (!this.#translation) {
|
|
2769
|
-
if (isFunction(this.#config.translation)) {
|
|
2770
|
-
const result = this.#config.translation();
|
|
2771
|
-
if (isPromise(result)) {
|
|
2772
|
-
const resolved = await result;
|
|
2773
|
-
assertObject(
|
|
2774
|
-
resolved,
|
|
2775
|
-
`Translation promise of language '${this.#tag}' must resolve to an object of translated strings. Got type: %t, value: %v`
|
|
2776
|
-
);
|
|
2777
|
-
this.#translation = resolved;
|
|
2778
|
-
} else if (isObject(result)) {
|
|
2779
|
-
this.#translation = result;
|
|
2780
|
-
} else {
|
|
2781
|
-
throw new TypeError(
|
|
2782
|
-
`Translation function of '${this.#tag}' must return an object or promise. Got type: ${typeOf(
|
|
2783
|
-
result
|
|
2784
|
-
)}, value: ${result}`
|
|
2785
|
-
);
|
|
2786
|
-
}
|
|
2787
|
-
} else if (isObject(this.#config.translation)) {
|
|
2788
|
-
this.#translation = this.#config.translation;
|
|
2789
|
-
} else {
|
|
2790
|
-
throw new TypeError(
|
|
2791
|
-
`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(
|
|
2792
|
-
this.#config.translation
|
|
2793
|
-
)}, value: ${this.#config.translation}`
|
|
2794
|
-
);
|
|
2795
|
-
}
|
|
2796
|
-
}
|
|
2797
|
-
return this.#translation;
|
|
2798
|
-
}
|
|
2799
|
-
};
|
|
2800
|
-
|
|
2801
2332
|
// src/stores/render.ts
|
|
2802
2333
|
function RenderStore(ctx) {
|
|
2803
2334
|
ctx.name = "dolla/render";
|
|
@@ -2882,10 +2413,290 @@ function RenderStore(ctx) {
|
|
|
2882
2413
|
};
|
|
2883
2414
|
}
|
|
2884
2415
|
|
|
2885
|
-
//
|
|
2886
|
-
function
|
|
2887
|
-
|
|
2888
|
-
|
|
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() {
|
|
2698
|
+
_extends = Object.assign || function(target) {
|
|
2699
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
2889
2700
|
var source = arguments[i];
|
|
2890
2701
|
for (var key in source) {
|
|
2891
2702
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
@@ -3336,9 +3147,11 @@ function parsePath(path) {
|
|
|
3336
3147
|
}
|
|
3337
3148
|
|
|
3338
3149
|
// src/stores/router.ts
|
|
3150
|
+
var DefaultView = (_, ctx) => ctx.outlet();
|
|
3339
3151
|
function RouterStore(ctx) {
|
|
3340
3152
|
ctx.name = "dolla/router";
|
|
3341
3153
|
const { appContext, elementContext } = getStoreSecrets(ctx);
|
|
3154
|
+
const render = ctx.getStore("render");
|
|
3342
3155
|
let history;
|
|
3343
3156
|
if (ctx.options.history) {
|
|
3344
3157
|
history = ctx.options.history;
|
|
@@ -3347,30 +3160,96 @@ function RouterStore(ctx) {
|
|
|
3347
3160
|
} else {
|
|
3348
3161
|
history = createBrowserHistory();
|
|
3349
3162
|
}
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
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
|
+
}
|
|
3359
3187
|
}
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3188
|
+
routes2.push({
|
|
3189
|
+
pattern: route.path,
|
|
3190
|
+
meta: {
|
|
3191
|
+
redirect
|
|
3363
3192
|
}
|
|
3364
3193
|
});
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3194
|
+
return routes2;
|
|
3195
|
+
}
|
|
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
|
+
}
|
|
3368
3244
|
}
|
|
3369
3245
|
}
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
const $$
|
|
3246
|
+
ctx.onConnected(() => {
|
|
3247
|
+
ctx.info(`Total routes: ${routes.length}`);
|
|
3248
|
+
});
|
|
3249
|
+
const $$pattern = $$(null);
|
|
3250
|
+
const $$path = $$("");
|
|
3251
|
+
const $$params = $$({});
|
|
3252
|
+
const $$query = $$({});
|
|
3374
3253
|
let isRouteChange = true;
|
|
3375
3254
|
ctx.observe($$query, (current) => {
|
|
3376
3255
|
if (isRouteChange) {
|
|
@@ -3405,7 +3284,7 @@ function RouterStore(ctx) {
|
|
|
3405
3284
|
isRouteChange = true;
|
|
3406
3285
|
$$query.set(parseQueryParams(location.search.startsWith("?") ? location.search.slice(1) : location.search));
|
|
3407
3286
|
}
|
|
3408
|
-
const matched = matchRoutes(
|
|
3287
|
+
const matched = matchRoutes(routes, location.pathname);
|
|
3409
3288
|
if (!matched) {
|
|
3410
3289
|
$$pattern.set(null);
|
|
3411
3290
|
$$path.set(location.pathname);
|
|
@@ -3444,7 +3323,7 @@ function RouterStore(ctx) {
|
|
|
3444
3323
|
const renderContext = { appContext, elementContext };
|
|
3445
3324
|
const rendered = renderMarkupToDOM(matchedLayer.markup, renderContext);
|
|
3446
3325
|
const handle = getRenderHandle(rendered);
|
|
3447
|
-
|
|
3326
|
+
render.update(() => {
|
|
3448
3327
|
if (activeLayer && activeLayer.handle.connected) {
|
|
3449
3328
|
activeLayer.handle.disconnect();
|
|
3450
3329
|
}
|
|
@@ -3453,7 +3332,7 @@ function RouterStore(ctx) {
|
|
|
3453
3332
|
} else {
|
|
3454
3333
|
appContext.rootView.setChildren(rendered);
|
|
3455
3334
|
}
|
|
3456
|
-
});
|
|
3335
|
+
}, "dolla-router-change");
|
|
3457
3336
|
activeLayers.push({ id: matchedLayer.id, handle });
|
|
3458
3337
|
}
|
|
3459
3338
|
}
|
|
@@ -3478,15 +3357,15 @@ function RouterStore(ctx) {
|
|
|
3478
3357
|
/**
|
|
3479
3358
|
* The currently matched route pattern, if any.
|
|
3480
3359
|
*/
|
|
3481
|
-
$pattern:
|
|
3360
|
+
$pattern: $($$pattern),
|
|
3482
3361
|
/**
|
|
3483
3362
|
* The current URL path.
|
|
3484
3363
|
*/
|
|
3485
|
-
$path:
|
|
3364
|
+
$path: $($$path),
|
|
3486
3365
|
/**
|
|
3487
3366
|
* The current named path params.
|
|
3488
3367
|
*/
|
|
3489
|
-
$params:
|
|
3368
|
+
$params: $($$params),
|
|
3490
3369
|
/**
|
|
3491
3370
|
* The current query params. Changes to this object will be reflected in the URL.
|
|
3492
3371
|
*/
|
|
@@ -3547,542 +3426,454 @@ function catchLinks(root, callback, _window = window) {
|
|
|
3547
3426
|
};
|
|
3548
3427
|
}
|
|
3549
3428
|
|
|
3550
|
-
// src/
|
|
3551
|
-
function
|
|
3552
|
-
|
|
3553
|
-
}
|
|
3554
|
-
function makeApp(options) {
|
|
3555
|
-
if (options && !isObject(options)) {
|
|
3556
|
-
throw new TypeError(`App options must be an object. Got: ${options}`);
|
|
3557
|
-
}
|
|
3558
|
-
let isConnected = false;
|
|
3559
|
-
let mainView = m(DefaultRootView);
|
|
3560
|
-
let configureCallback;
|
|
3561
|
-
const settings = merge(
|
|
3562
|
-
{
|
|
3563
|
-
debug: {
|
|
3564
|
-
filter: "*,-dolla/*",
|
|
3565
|
-
log: "development",
|
|
3566
|
-
// Only print logs in development.
|
|
3567
|
-
warn: "development",
|
|
3568
|
-
// Only print warnings in development.
|
|
3569
|
-
error: true
|
|
3570
|
-
// Always print errors.
|
|
3571
|
-
},
|
|
3572
|
-
router: {
|
|
3573
|
-
hash: false
|
|
3574
|
-
},
|
|
3575
|
-
mode: "production"
|
|
3576
|
-
},
|
|
3577
|
-
options ?? {}
|
|
3578
|
-
);
|
|
3579
|
-
const stores = /* @__PURE__ */ new Map([
|
|
3580
|
-
["dialog", { store: DialogStore }],
|
|
3581
|
-
["router", { store: RouterStore }],
|
|
3582
|
-
["document", { store: DocumentStore }],
|
|
3583
|
-
["http", { store: HTTPStore }],
|
|
3584
|
-
["language", { store: LanguageStore }],
|
|
3585
|
-
["render", { store: RenderStore }]
|
|
3586
|
-
]);
|
|
3429
|
+
// src/stores/language.ts
|
|
3430
|
+
function LanguageStore(ctx) {
|
|
3431
|
+
ctx.name = "dolla/language";
|
|
3587
3432
|
const languages = /* @__PURE__ */ new Map();
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
if (
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
if (
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
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;
|
|
3607
3467
|
}
|
|
3608
|
-
routes2.push({
|
|
3609
|
-
pattern: route.pattern,
|
|
3610
|
-
meta: {
|
|
3611
|
-
redirect
|
|
3612
|
-
}
|
|
3613
|
-
});
|
|
3614
|
-
return routes2;
|
|
3615
3468
|
}
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
const
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
route: (pattern, view2, subroutes) => {
|
|
3629
|
-
pattern = joinPath([...parts, pattern]);
|
|
3630
|
-
routes2.push(...prepareRoute({ pattern, view: view2, subroutes }));
|
|
3631
|
-
return router;
|
|
3632
|
-
},
|
|
3633
|
-
redirect: (pattern, redirect) => {
|
|
3634
|
-
pattern = joinPath([...parts, pattern]);
|
|
3635
|
-
routes2.push(...prepareRoute({ pattern, redirect }));
|
|
3636
|
-
return router;
|
|
3637
|
-
}
|
|
3638
|
-
};
|
|
3639
|
-
route.subroutes(router);
|
|
3640
|
-
} else {
|
|
3641
|
-
routes2.push({
|
|
3642
|
-
pattern: route.pattern,
|
|
3643
|
-
meta: {
|
|
3644
|
-
pattern: route.pattern,
|
|
3645
|
-
layers: [...layers, layer]
|
|
3646
|
-
}
|
|
3647
|
-
});
|
|
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
|
+
}
|
|
3648
3481
|
}
|
|
3649
|
-
return routes2;
|
|
3650
3482
|
}
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
crashCollector.onError(async ({ error, severity, componentName }) => {
|
|
3655
|
-
if (severity === "crash") {
|
|
3656
|
-
await disconnect();
|
|
3657
|
-
const instance = initView({
|
|
3658
|
-
view: DefaultCrashPage,
|
|
3659
|
-
appContext,
|
|
3660
|
-
elementContext,
|
|
3661
|
-
props: {
|
|
3662
|
-
message: error.message,
|
|
3663
|
-
error,
|
|
3664
|
-
componentName
|
|
3665
|
-
}
|
|
3666
|
-
});
|
|
3667
|
-
instance.connect(appContext.rootElement);
|
|
3483
|
+
function replaceMustaches(template, values) {
|
|
3484
|
+
for (const name in values) {
|
|
3485
|
+
template = template.replace(`{{${name}}}`, String(values[name]));
|
|
3668
3486
|
}
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
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.`);
|
|
3676
3507
|
}
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
}
|
|
3687
|
-
});
|
|
3688
|
-
const router = stores.get("router");
|
|
3689
|
-
stores.set("router", {
|
|
3690
|
-
...router,
|
|
3691
|
-
options: {
|
|
3692
|
-
options: settings.router,
|
|
3693
|
-
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);
|
|
3694
3517
|
}
|
|
3695
|
-
});
|
|
3696
|
-
debugChannel.info(`Total routes: ${routes.length}`);
|
|
3697
|
-
appContext.rootView = initView({
|
|
3698
|
-
view: mainView.type,
|
|
3699
|
-
props: mainView.props,
|
|
3700
|
-
appContext,
|
|
3701
|
-
elementContext
|
|
3702
|
-
});
|
|
3703
|
-
for (let [key, item] of stores.entries()) {
|
|
3704
|
-
const { store, options: options2 } = item;
|
|
3705
|
-
const channelPrefix = isString(key) ? "dolla/store" : "store";
|
|
3706
|
-
const label = isString(key) ? key : store.name ?? "(anonymous)";
|
|
3707
|
-
const config = {
|
|
3708
|
-
store,
|
|
3709
|
-
appContext,
|
|
3710
|
-
elementContext,
|
|
3711
|
-
channelPrefix,
|
|
3712
|
-
label,
|
|
3713
|
-
options: options2 ?? {}
|
|
3714
|
-
};
|
|
3715
|
-
const instance = initStore(config);
|
|
3716
|
-
instance.setup();
|
|
3717
|
-
stores.set(key, { ...item, instance });
|
|
3718
3518
|
}
|
|
3719
|
-
|
|
3720
|
-
|
|
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;
|
|
3721
3529
|
}
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
});
|
|
3530
|
+
const cached = getCached(key, values);
|
|
3531
|
+
if (cached) {
|
|
3532
|
+
return cached;
|
|
3726
3533
|
}
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
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
|
+
}
|
|
3735
3559
|
}
|
|
3736
|
-
const
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3560
|
+
const $replaced = $($$translation, (t) => {
|
|
3561
|
+
let result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
3562
|
+
if (values) {
|
|
3563
|
+
result = replaceMustaches(result, values);
|
|
3740
3564
|
}
|
|
3565
|
+
return result;
|
|
3741
3566
|
});
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
async function disconnect() {
|
|
3745
|
-
if (isConnected) {
|
|
3746
|
-
appContext.rootView.disconnect();
|
|
3747
|
-
isConnected = false;
|
|
3748
|
-
for (const { instance } of stores.values()) {
|
|
3749
|
-
instance.disconnect();
|
|
3750
|
-
}
|
|
3567
|
+
translationCache.push([key, values, $replaced]);
|
|
3568
|
+
return $replaced;
|
|
3751
3569
|
}
|
|
3752
|
-
}
|
|
3753
|
-
const appContext = {
|
|
3754
|
-
crashCollector,
|
|
3755
|
-
debugHub,
|
|
3756
|
-
stores,
|
|
3757
|
-
mode: settings.mode ?? "production"
|
|
3758
|
-
// $dialogs - added by dialog store
|
|
3759
|
-
};
|
|
3760
|
-
const elementContext = {
|
|
3761
|
-
stores: /* @__PURE__ */ new Map()
|
|
3762
3570
|
};
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
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
|
+
};
|
|
3768
3606
|
},
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
debugChannel.warn(`Root view is already defined. Only the final main call will take effect.`);
|
|
3772
|
-
}
|
|
3773
|
-
if (typeof view === "function") {
|
|
3774
|
-
mainView = m(view, attributes);
|
|
3775
|
-
} else {
|
|
3776
|
-
throw new TypeError(`Expected a view function. Got type: ${typeOf(view)}, value: ${view}`);
|
|
3777
|
-
}
|
|
3778
|
-
return app;
|
|
3607
|
+
async get(uri, options) {
|
|
3608
|
+
return request("get", uri, options);
|
|
3779
3609
|
},
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
if (isFunction(store)) {
|
|
3783
|
-
config = { store, options: options2 };
|
|
3784
|
-
} else {
|
|
3785
|
-
throw new TypeError(`Expected a store function. Got type: ${typeOf(store)}, value: ${store}`);
|
|
3786
|
-
}
|
|
3787
|
-
assertFunction(store, "Expected a store function or a store config object. Got type: %t, value: %v");
|
|
3788
|
-
stores.set(store, config);
|
|
3789
|
-
return app;
|
|
3610
|
+
async put(uri, options) {
|
|
3611
|
+
return request("put", uri, options);
|
|
3790
3612
|
},
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
const name = isString(store) ? store : store.name;
|
|
3794
|
-
if (!match) {
|
|
3795
|
-
throw new Error(`Store '${name}' is not registered on this app.`);
|
|
3796
|
-
}
|
|
3797
|
-
if (!match.instance) {
|
|
3798
|
-
throw new Error(`Store '${name}' is not yet initialized. App must be connected first.`);
|
|
3799
|
-
}
|
|
3800
|
-
return match.instance.exports;
|
|
3613
|
+
async patch(uri, options) {
|
|
3614
|
+
return request("patch", uri, options);
|
|
3801
3615
|
},
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
return app;
|
|
3616
|
+
async post(uri, options) {
|
|
3617
|
+
return request("post", uri, options);
|
|
3805
3618
|
},
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
let tags = [];
|
|
3809
|
-
if (typeof navigator === "object") {
|
|
3810
|
-
const nav = navigator;
|
|
3811
|
-
if (nav.languages?.length > 0) {
|
|
3812
|
-
tags.push(...nav.languages);
|
|
3813
|
-
} else if (nav.language) {
|
|
3814
|
-
tags.push(nav.language);
|
|
3815
|
-
} else if (nav.browserLanguage) {
|
|
3816
|
-
tags.push(nav.browserLanguage);
|
|
3817
|
-
} else if (nav.userLanguage) {
|
|
3818
|
-
tags.push(nav.userLanguage);
|
|
3819
|
-
}
|
|
3820
|
-
}
|
|
3821
|
-
for (const tag2 of tags) {
|
|
3822
|
-
if (languages.has(tag2)) {
|
|
3823
|
-
currentLanguage = tag2;
|
|
3824
|
-
return this;
|
|
3825
|
-
}
|
|
3826
|
-
}
|
|
3827
|
-
if (!currentLanguage && fallback) {
|
|
3828
|
-
if (languages.has(fallback)) {
|
|
3829
|
-
currentLanguage = fallback;
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
|
-
} else {
|
|
3833
|
-
if (languages.has(tag)) {
|
|
3834
|
-
currentLanguage = tag;
|
|
3835
|
-
} else {
|
|
3836
|
-
throw new Error(`Language '${tag}' has not been added to this app yet.`);
|
|
3837
|
-
}
|
|
3838
|
-
}
|
|
3839
|
-
return app;
|
|
3619
|
+
async delete(uri, options) {
|
|
3620
|
+
return request("delete", uri, options);
|
|
3840
3621
|
},
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
if (view == null) {
|
|
3844
|
-
assertFunction(subroutes, "Sub routes must be defined when `view` is null.");
|
|
3845
|
-
}
|
|
3846
|
-
prepareRoute({ pattern, view, subroutes }).forEach((route) => {
|
|
3847
|
-
routes.push({
|
|
3848
|
-
pattern: route.pattern,
|
|
3849
|
-
meta: route.meta,
|
|
3850
|
-
fragments: patternToFragments(route.pattern)
|
|
3851
|
-
});
|
|
3852
|
-
});
|
|
3853
|
-
return app;
|
|
3622
|
+
async head(uri, options) {
|
|
3623
|
+
return request("head", uri, options);
|
|
3854
3624
|
},
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
throw new TypeError(`Expected a redirect path or function. Got type: ${typeOf(redirect)}, value: ${redirect}`);
|
|
3858
|
-
}
|
|
3859
|
-
prepareRoute({ pattern, redirect }).forEach((route) => {
|
|
3860
|
-
routes.push({
|
|
3861
|
-
pattern: route.pattern,
|
|
3862
|
-
meta: route.meta,
|
|
3863
|
-
fragments: patternToFragments(route.pattern)
|
|
3864
|
-
});
|
|
3865
|
-
});
|
|
3866
|
-
return app;
|
|
3625
|
+
async options(uri, options) {
|
|
3626
|
+
return request("options", uri, options);
|
|
3867
3627
|
},
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
debugChannel.warn(`Configure callback is already defined. Only the final configure call will take effect.`);
|
|
3871
|
-
}
|
|
3872
|
-
configureCallback = callback;
|
|
3873
|
-
return app;
|
|
3628
|
+
async trace(uri, options) {
|
|
3629
|
+
return request("trace", uri, options);
|
|
3874
3630
|
}
|
|
3875
3631
|
};
|
|
3876
|
-
return app;
|
|
3877
3632
|
}
|
|
3878
|
-
function
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
position: "fixed",
|
|
3887
|
-
inset: 0,
|
|
3888
|
-
fontSize: "20px"
|
|
3889
|
-
}
|
|
3890
|
-
},
|
|
3891
|
-
m("h1", { style: { marginBottom: "0.5rem" } }, "The app has crashed"),
|
|
3892
|
-
m(
|
|
3893
|
-
"p",
|
|
3894
|
-
{ style: { marginBottom: "0.25rem" } },
|
|
3895
|
-
m("span", { style: { fontFamily: "monospace" } }, componentName),
|
|
3896
|
-
" says:"
|
|
3897
|
-
),
|
|
3898
|
-
m(
|
|
3899
|
-
"blockquote",
|
|
3900
|
-
{
|
|
3901
|
-
style: {
|
|
3902
|
-
backgroundColor: "#991111",
|
|
3903
|
-
padding: "0.25em",
|
|
3904
|
-
borderRadius: "6px",
|
|
3905
|
-
fontFamily: "monospace",
|
|
3906
|
-
marginBottom: "1rem"
|
|
3907
|
-
}
|
|
3908
|
-
},
|
|
3909
|
-
m(
|
|
3910
|
-
"span",
|
|
3911
|
-
{
|
|
3912
|
-
style: {
|
|
3913
|
-
display: "inline-block",
|
|
3914
|
-
backgroundColor: "red",
|
|
3915
|
-
padding: "0.1em 0.4em",
|
|
3916
|
-
marginRight: "0.5em",
|
|
3917
|
-
borderRadius: "4px",
|
|
3918
|
-
fontSize: "0.9em",
|
|
3919
|
-
fontWeight: "bold"
|
|
3920
|
-
}
|
|
3921
|
-
},
|
|
3922
|
-
error.name
|
|
3923
|
-
),
|
|
3924
|
-
message
|
|
3925
|
-
),
|
|
3926
|
-
m("p", {}, "Please see the browser console for details.")
|
|
3927
|
-
);
|
|
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.");
|
|
3928
3641
|
}
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
const animateTo = async (endValue, options2) => {
|
|
3946
|
-
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
3947
|
-
if (mediaQuery.matches) {
|
|
3948
|
-
return snapTo(endValue);
|
|
3949
|
-
}
|
|
3950
|
-
const _endAmplitude = readable(options2?.endAmplitude ?? endAmplitude).get();
|
|
3951
|
-
const _endWindow = readable(options2?.endWindow ?? endWindow).get();
|
|
3952
|
-
return new Promise((resolve2) => {
|
|
3953
|
-
const id = nextId++;
|
|
3954
|
-
const amplitude = makeAmplitudeMeasurer(_endWindow);
|
|
3955
|
-
const springParams = {
|
|
3956
|
-
mass: options2?.mass ?? mass,
|
|
3957
|
-
stiffness: options2?.stiffness ?? stiffness,
|
|
3958
|
-
damping: options2?.damping ?? damping,
|
|
3959
|
-
velocity: options2?.velocity ?? velocity
|
|
3960
|
-
};
|
|
3961
|
-
const startTime = Date.now();
|
|
3962
|
-
const startValue = $$currentValue.get();
|
|
3963
|
-
const step = () => {
|
|
3964
|
-
if (currentAnimationId !== id) {
|
|
3965
|
-
resolve2();
|
|
3966
|
-
return;
|
|
3967
|
-
}
|
|
3968
|
-
const elapsedTime = Date.now() - startTime;
|
|
3969
|
-
const proportion = solve(springParams, elapsedTime / 1e3);
|
|
3970
|
-
$$currentValue.set(startValue + (endValue - startValue) * proportion);
|
|
3971
|
-
amplitude.sample(proportion);
|
|
3972
|
-
if (amplitude.value && amplitude.value < _endAmplitude) {
|
|
3973
|
-
currentAnimationId = void 0;
|
|
3974
|
-
$$currentValue.set(endValue);
|
|
3975
|
-
}
|
|
3976
|
-
window.requestAnimationFrame(step);
|
|
3977
|
-
};
|
|
3978
|
-
currentAnimationId = id;
|
|
3979
|
-
window.requestAnimationFrame(step);
|
|
3980
|
-
});
|
|
3981
|
-
};
|
|
3982
|
-
return {
|
|
3983
|
-
get: $$currentValue.get,
|
|
3984
|
-
set: snapTo,
|
|
3985
|
-
update: (callback) => {
|
|
3986
|
-
const newValue = callback($$currentValue.get());
|
|
3987
|
-
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");
|
|
3988
3658
|
},
|
|
3989
|
-
|
|
3990
|
-
|
|
3659
|
+
query: new URLSearchParams(),
|
|
3660
|
+
headers: new Headers(),
|
|
3661
|
+
body: config.body
|
|
3991
3662
|
};
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
let B;
|
|
4001
|
-
let position;
|
|
4002
|
-
if (dampingRatio < 1) {
|
|
4003
|
-
const dampedSpeed = speed * Math.sqrt(1 - dampingRatio * dampingRatio);
|
|
4004
|
-
B = (dampingRatio * speed + -initialVelocity) / dampedSpeed;
|
|
4005
|
-
position = (Math.cos(dampedSpeed * elapsedSeconds) + B * Math.sin(dampedSpeed * elapsedSeconds)) * Math.exp(-elapsedSeconds * speed * dampingRatio);
|
|
4006
|
-
} else {
|
|
4007
|
-
B = speed + -initialVelocity;
|
|
4008
|
-
position = (1 + B * elapsedSeconds) * Math.exp(-elapsedSeconds * speed);
|
|
4009
|
-
}
|
|
4010
|
-
return 1 - position;
|
|
4011
|
-
}
|
|
4012
|
-
function makeAmplitudeMeasurer(resolution) {
|
|
4013
|
-
const samples = [];
|
|
4014
|
-
return {
|
|
4015
|
-
sample(value) {
|
|
4016
|
-
samples.push(value);
|
|
4017
|
-
while (samples.length > resolution) {
|
|
4018
|
-
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]));
|
|
4019
3671
|
}
|
|
4020
|
-
}
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
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]));
|
|
4024
3684
|
}
|
|
4025
|
-
|
|
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();
|
|
4026
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
|
+
};
|
|
4027
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;
|
|
4028
3741
|
}
|
|
4029
3742
|
|
|
4030
|
-
// src/
|
|
4031
|
-
function
|
|
4032
|
-
|
|
4033
|
-
}
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
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
|
+
}
|
|
4044
3762
|
} else {
|
|
4045
|
-
|
|
4046
|
-
|
|
3763
|
+
if (container.parentNode) {
|
|
3764
|
+
document.body.removeChild(container);
|
|
3765
|
+
}
|
|
4047
3766
|
}
|
|
4048
|
-
const instance = initStore({
|
|
4049
|
-
store,
|
|
4050
|
-
options,
|
|
4051
|
-
appContext,
|
|
4052
|
-
elementContext
|
|
4053
|
-
});
|
|
4054
|
-
instance.setup();
|
|
4055
|
-
elementContext.stores.set(store, { store, options, instance });
|
|
4056
|
-
instances.push(instance);
|
|
4057
3767
|
}
|
|
4058
|
-
ctx.
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
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
|
+
});
|
|
4062
3803
|
});
|
|
4063
3804
|
ctx.onDisconnected(() => {
|
|
4064
|
-
|
|
4065
|
-
|
|
3805
|
+
if (container.parentNode) {
|
|
3806
|
+
document.body.removeChild(container);
|
|
4066
3807
|
}
|
|
4067
3808
|
});
|
|
4068
|
-
|
|
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
|
+
};
|
|
4069
3859
|
}
|
|
4070
3860
|
export {
|
|
3861
|
+
$,
|
|
3862
|
+
$$,
|
|
3863
|
+
App,
|
|
3864
|
+
DialogStore,
|
|
4071
3865
|
Fragment,
|
|
3866
|
+
HTTPStore,
|
|
3867
|
+
LanguageStore,
|
|
3868
|
+
RouterStore,
|
|
4072
3869
|
StoreScope,
|
|
4073
|
-
computed,
|
|
4074
3870
|
cond,
|
|
4075
3871
|
isReadable,
|
|
4076
3872
|
isWritable,
|
|
4077
3873
|
m,
|
|
4078
|
-
makeApp,
|
|
4079
3874
|
observe,
|
|
4080
3875
|
portal,
|
|
4081
|
-
proxy,
|
|
4082
|
-
readable,
|
|
4083
3876
|
repeat,
|
|
4084
|
-
|
|
4085
|
-
unwrap,
|
|
4086
|
-
writable
|
|
3877
|
+
unwrap
|
|
4087
3878
|
};
|
|
4088
3879
|
//# sourceMappingURL=index.js.map
|