@event-calendar/core 5.3.1 → 5.3.2
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 +2 -2
- package/dist/index.css +1 -1
- package/dist/index.js +68 -67
- package/package.json +2 -2
- package/src/Calendar.svelte +2 -13
- package/src/lib/utils.js +4 -0
- package/src/plugins/interaction/Action.svelte +2 -2
- package/src/plugins/resource-timeline/Expander.svelte +2 -3
- package/src/storage/effects.js +3 -2
- package/src/storage/options.svelte.js +20 -31
- package/src/storage/proxy.svelte.js +48 -0
- package/src/storage/state.svelte.js +5 -4
package/README.md
CHANGED
|
@@ -251,8 +251,8 @@ This bundle contains a version of the calendar that includes all plugins and is
|
|
|
251
251
|
|
|
252
252
|
The first step is to include the following lines of code in the `<head>` section of your page:
|
|
253
253
|
```html
|
|
254
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@event-calendar/build@5.3.
|
|
255
|
-
<script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@5.3.
|
|
254
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@event-calendar/build@5.3.2/dist/event-calendar.min.css">
|
|
255
|
+
<script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@5.3.2/dist/event-calendar.min.js"></script>
|
|
256
256
|
```
|
|
257
257
|
|
|
258
258
|
<details>
|
package/dist/index.css
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* EventCalendar v5.3.
|
|
2
|
+
* EventCalendar v5.3.2
|
|
3
3
|
* https://github.com/vkurko/calendar
|
|
4
4
|
*/
|
|
5
5
|
import { untrack, tick, getAbortSignal, getContext, setContext, onMount, mount, unmount } from "svelte";
|
|
@@ -72,6 +72,9 @@ function keys(object) {
|
|
|
72
72
|
function entries(object) {
|
|
73
73
|
return Object.entries(object);
|
|
74
74
|
}
|
|
75
|
+
function hasOwn(object, property) {
|
|
76
|
+
return Object.hasOwn(object, property);
|
|
77
|
+
}
|
|
75
78
|
function floor(value) {
|
|
76
79
|
return Math.floor(value);
|
|
77
80
|
}
|
|
@@ -770,6 +773,34 @@ function createSlotTimeLimits(slotMinTime, slotMaxTime, flexibleSlotTimeLimits,
|
|
|
770
773
|
}
|
|
771
774
|
return { min: min$1, max: max$1 };
|
|
772
775
|
}
|
|
776
|
+
function arrayProxy(array) {
|
|
777
|
+
let counter = 0;
|
|
778
|
+
let version = $.state($.proxy(counter));
|
|
779
|
+
return proxy(array, () => $.get(version), () => true, () => $.set(version, ++counter, true));
|
|
780
|
+
}
|
|
781
|
+
function objectProxy(object) {
|
|
782
|
+
let counter = 0;
|
|
783
|
+
let versions = $.proxy({});
|
|
784
|
+
return proxy(object, (prop) => versions[prop], (a, b) => a !== b, (prop) => versions[prop] = ++counter);
|
|
785
|
+
}
|
|
786
|
+
function proxy(target, setDependency, hasEffect, invokeEffect) {
|
|
787
|
+
return new Proxy(target, {
|
|
788
|
+
get(target2, prop, receiver) {
|
|
789
|
+
if (hasOwn(target2, prop)) {
|
|
790
|
+
setDependency(prop);
|
|
791
|
+
}
|
|
792
|
+
return Reflect.get(target2, prop, receiver);
|
|
793
|
+
},
|
|
794
|
+
set(target2, prop, value, receiver) {
|
|
795
|
+
let has = hasEffect(target2[prop], value);
|
|
796
|
+
Reflect.set(target2, prop, value, receiver);
|
|
797
|
+
if (has) {
|
|
798
|
+
invokeEffect(prop);
|
|
799
|
+
}
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
}
|
|
773
804
|
function createOptions(plugins) {
|
|
774
805
|
let options = {
|
|
775
806
|
buttonText: { today: "today" },
|
|
@@ -888,13 +919,12 @@ function optionsState(mainState, plugins, userOptions) {
|
|
|
888
919
|
userOptions = parseOptions(userOptions, parsers);
|
|
889
920
|
let defViewsOptions = extractOption(defOptions, "views") ?? {};
|
|
890
921
|
let userViewsOptions = extractOption(userOptions, "views") ?? {};
|
|
891
|
-
let options =
|
|
892
|
-
|
|
922
|
+
let options = objectProxy({});
|
|
923
|
+
assign(options, defOptions);
|
|
893
924
|
let setters = {};
|
|
894
|
-
let currentOpts = {};
|
|
895
925
|
function initEffects() {
|
|
896
926
|
if (userOptions.view) {
|
|
897
|
-
options
|
|
927
|
+
options["view"] = userOptions.view;
|
|
898
928
|
}
|
|
899
929
|
let views = /* @__PURE__ */ new Set([...keys(defViewsOptions), ...keys(userViewsOptions)]);
|
|
900
930
|
for (let view2 of views) {
|
|
@@ -904,7 +934,7 @@ function optionsState(mainState, plugins, userOptions) {
|
|
|
904
934
|
let component = extractOption(opts, "component");
|
|
905
935
|
delete opts.view;
|
|
906
936
|
for (let key of keys(opts)) {
|
|
907
|
-
if (options
|
|
937
|
+
if (hasOwn(options, key)) {
|
|
908
938
|
if (!setters[key]) {
|
|
909
939
|
setters[key] = [];
|
|
910
940
|
}
|
|
@@ -914,35 +944,31 @@ function optionsState(mainState, plugins, userOptions) {
|
|
|
914
944
|
}
|
|
915
945
|
}
|
|
916
946
|
$.user_pre_effect(() => {
|
|
917
|
-
let newView = options
|
|
947
|
+
let newView = options["view"];
|
|
918
948
|
untrack(() => {
|
|
919
949
|
if (newView === view2) {
|
|
920
950
|
mainState.setViewComponent(component);
|
|
921
|
-
|
|
922
|
-
setOptions(options, opts);
|
|
951
|
+
assign(options, opts);
|
|
923
952
|
}
|
|
924
953
|
});
|
|
925
954
|
});
|
|
926
955
|
}
|
|
927
956
|
}
|
|
928
957
|
return {
|
|
929
|
-
|
|
930
|
-
set(options2, key, value) {
|
|
931
|
-
currentOpts[key] = value;
|
|
932
|
-
options2.set(key, value);
|
|
933
|
-
return true;
|
|
934
|
-
},
|
|
935
|
-
get(options2, key) {
|
|
936
|
-
return options2.get(key);
|
|
937
|
-
}
|
|
938
|
-
}),
|
|
958
|
+
state: options,
|
|
939
959
|
setOption(key, value, parsed) {
|
|
940
|
-
if (options
|
|
941
|
-
if (!parsed
|
|
942
|
-
|
|
960
|
+
if (hasOwn(options, key)) {
|
|
961
|
+
if (!parsed) {
|
|
962
|
+
if (key in parsers) {
|
|
963
|
+
value = parsers[key](value);
|
|
964
|
+
} else if (isPlainObject(value)) {
|
|
965
|
+
value = { ...value };
|
|
966
|
+
} else if (isArray(value)) {
|
|
967
|
+
value = [...value];
|
|
968
|
+
}
|
|
943
969
|
}
|
|
944
970
|
setters[key]?.forEach((set) => set(value));
|
|
945
|
-
options
|
|
971
|
+
options[key] = value;
|
|
946
972
|
}
|
|
947
973
|
},
|
|
948
974
|
initEffects
|
|
@@ -981,11 +1007,6 @@ function mergeOpts(...args) {
|
|
|
981
1007
|
}
|
|
982
1008
|
return result;
|
|
983
1009
|
}
|
|
984
|
-
function setOptions(map, options) {
|
|
985
|
-
for (let [key, value] of entries(options)) {
|
|
986
|
-
map.set(key, value);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
1010
|
function diff(options, prevOptions) {
|
|
990
1011
|
let diff2 = [];
|
|
991
1012
|
for (let key of keys(options)) {
|
|
@@ -1008,7 +1029,7 @@ function loadEvents(mainState, loadingInvoker) {
|
|
|
1008
1029
|
eventSources.map((source) => isFunction(source.events) ? source.events : source),
|
|
1009
1030
|
events,
|
|
1010
1031
|
createEvents,
|
|
1011
|
-
(result) => mainState.events = result,
|
|
1032
|
+
(result) => mainState.events = arrayProxy(result),
|
|
1012
1033
|
activeRange2,
|
|
1013
1034
|
fetchedRange,
|
|
1014
1035
|
viewDates2,
|
|
@@ -1032,7 +1053,7 @@ function loadResources(mainState, loadingInvoker) {
|
|
|
1032
1053
|
isArray(resources) ? [] : [resources],
|
|
1033
1054
|
resources,
|
|
1034
1055
|
createResources,
|
|
1035
|
-
(result) => mainState.resources = result,
|
|
1056
|
+
(result) => mainState.resources = arrayProxy(result),
|
|
1036
1057
|
activeRange2,
|
|
1037
1058
|
fetchedRange,
|
|
1038
1059
|
viewDates2,
|
|
@@ -1436,18 +1457,18 @@ class State {
|
|
|
1436
1457
|
}
|
|
1437
1458
|
#setOption;
|
|
1438
1459
|
constructor(plugins, options) {
|
|
1439
|
-
let {
|
|
1440
|
-
this.options =
|
|
1460
|
+
let { state, setOption, initEffects } = optionsState(this, plugins, options);
|
|
1461
|
+
this.options = state;
|
|
1441
1462
|
this.#setOption = setOption;
|
|
1442
1463
|
this.#auxComponents = $.state($.proxy([]));
|
|
1443
1464
|
this.#currentRange = $.derived(currentRange(this));
|
|
1444
1465
|
this.#activeRange = $.derived(activeRange(this));
|
|
1445
1466
|
this.#fetchedRange = $.state($.proxy({ events: {}, resources: {} }));
|
|
1446
|
-
this.#events = $.state([]);
|
|
1467
|
+
this.#events = $.state(arrayProxy([]));
|
|
1447
1468
|
this.#filteredEvents = $.derived(filteredEvents(this));
|
|
1448
1469
|
this.#mainEl = $.state();
|
|
1449
1470
|
this.#now = $.state($.proxy(createDate()));
|
|
1450
|
-
this.#resources = $.state([]);
|
|
1471
|
+
this.#resources = $.state(arrayProxy([]));
|
|
1451
1472
|
this.#today = $.state($.proxy(setMidnight(createDate())));
|
|
1452
1473
|
this.#intlEventTime = $.derived(intlRange(this, "eventTimeFormat"));
|
|
1453
1474
|
this.#intlDayHeader = $.derived(intl(this, "dayHeaderFormat"));
|
|
@@ -1783,12 +1804,6 @@ function Calendar($$anchor, $$props) {
|
|
|
1783
1804
|
assign(prevOptions, options());
|
|
1784
1805
|
});
|
|
1785
1806
|
function setOption(name, value) {
|
|
1786
|
-
if (isPlainObject(value)) {
|
|
1787
|
-
value = { ...value };
|
|
1788
|
-
}
|
|
1789
|
-
if (isArray(value)) {
|
|
1790
|
-
value = [...value];
|
|
1791
|
-
}
|
|
1792
1807
|
mainState.setOption(name, value, false);
|
|
1793
1808
|
return this;
|
|
1794
1809
|
}
|
|
@@ -1819,7 +1834,6 @@ function Calendar($$anchor, $$props) {
|
|
|
1819
1834
|
function addEvent(event) {
|
|
1820
1835
|
event = createEvents([event])[0];
|
|
1821
1836
|
$.get(events).push(event);
|
|
1822
|
-
mainState.events = [...$.get(events)];
|
|
1823
1837
|
return toEventWithLocalDates(event);
|
|
1824
1838
|
}
|
|
1825
1839
|
function updateEvent(event) {
|
|
@@ -1828,7 +1842,6 @@ function Calendar($$anchor, $$props) {
|
|
|
1828
1842
|
if (idx >= 0) {
|
|
1829
1843
|
event = createEvents([event])[0];
|
|
1830
1844
|
$.get(events)[idx] = event;
|
|
1831
|
-
mainState.events = [...$.get(events)];
|
|
1832
1845
|
return toEventWithLocalDates(event);
|
|
1833
1846
|
}
|
|
1834
1847
|
return null;
|
|
@@ -1838,7 +1851,6 @@ function Calendar($$anchor, $$props) {
|
|
|
1838
1851
|
let idx = $.get(events).findIndex((event) => event.id === id);
|
|
1839
1852
|
if (idx >= 0) {
|
|
1840
1853
|
$.get(events).splice(idx, 1);
|
|
1841
|
-
mainState.events = [...$.get(events)];
|
|
1842
1854
|
}
|
|
1843
1855
|
return this;
|
|
1844
1856
|
}
|
|
@@ -1887,27 +1899,17 @@ function Calendar($$anchor, $$props) {
|
|
|
1887
1899
|
var node = $.child(div);
|
|
1888
1900
|
Toolbar(node, {});
|
|
1889
1901
|
var node_1 = $.sibling(node, 2);
|
|
1890
|
-
{
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
};
|
|
1899
|
-
$.if(node_1, ($$render) => {
|
|
1900
|
-
if ($.get(View2)) $$render(consequent);
|
|
1901
|
-
});
|
|
1902
|
-
}
|
|
1903
|
-
var node_3 = $.sibling(node_1, 2);
|
|
1904
|
-
$.each(node_3, 17, () => $.get(auxComponents), $.index, ($$anchor2, AuxComponent) => {
|
|
1905
|
-
var fragment_1 = $.comment();
|
|
1906
|
-
var node_4 = $.first_child(fragment_1);
|
|
1907
|
-
$.component(node_4, () => $.get(AuxComponent), ($$anchor3, AuxComponent_1) => {
|
|
1902
|
+
$.component(node_1, () => $.get(View2), ($$anchor2, View_12) => {
|
|
1903
|
+
View_12($$anchor2, {});
|
|
1904
|
+
});
|
|
1905
|
+
var node_2 = $.sibling(node_1, 2);
|
|
1906
|
+
$.each(node_2, 17, () => $.get(auxComponents), $.index, ($$anchor2, AuxComponent) => {
|
|
1907
|
+
var fragment = $.comment();
|
|
1908
|
+
var node_3 = $.first_child(fragment);
|
|
1909
|
+
$.component(node_3, () => $.get(AuxComponent), ($$anchor3, AuxComponent_1) => {
|
|
1908
1910
|
AuxComponent_1($$anchor3, {});
|
|
1909
1911
|
});
|
|
1910
|
-
$.append($$anchor2,
|
|
1912
|
+
$.append($$anchor2, fragment);
|
|
1911
1913
|
});
|
|
1912
1914
|
$.reset(div);
|
|
1913
1915
|
$.template_effect(
|
|
@@ -3352,7 +3354,7 @@ function Action($$anchor, $$props) {
|
|
|
3352
3354
|
addDuration(iEvent.end, extraDuration);
|
|
3353
3355
|
}
|
|
3354
3356
|
event.display = "ghost";
|
|
3355
|
-
|
|
3357
|
+
$.get(events).length = $.get(events).length;
|
|
3356
3358
|
}
|
|
3357
3359
|
function createIEventSelect() {
|
|
3358
3360
|
iEvent = {
|
|
@@ -3380,7 +3382,7 @@ function Action($$anchor, $$props) {
|
|
|
3380
3382
|
}
|
|
3381
3383
|
function updateEvent(target, source) {
|
|
3382
3384
|
copyIEventData(target, source);
|
|
3383
|
-
|
|
3385
|
+
$.get(events).length = $.get(events).length;
|
|
3384
3386
|
}
|
|
3385
3387
|
function updateIEvent(source) {
|
|
3386
3388
|
iEvent = copyIEventData(iEvent, source);
|
|
@@ -5560,8 +5562,7 @@ var root_2 = $.from_html(`<button><!></button>`);
|
|
|
5560
5562
|
var root = $.from_html(`<!> <span><!></span>`, 1);
|
|
5561
5563
|
function Expander($$anchor, $$props) {
|
|
5562
5564
|
$.push($$props, true);
|
|
5563
|
-
let $$d = $.derived(() => getContext("state")),
|
|
5564
|
-
let resources = $.derived(() => $.get(options).resources), theme = $.derived(() => $.get(options).theme);
|
|
5565
|
+
let $$d = $.derived(() => getContext("state")), resources = $.derived(() => $.get($$d).resources), theme = $.derived(() => $.get($$d).options.theme);
|
|
5565
5566
|
let payload = $.state({});
|
|
5566
5567
|
let expanded = $.state(true);
|
|
5567
5568
|
$.user_pre_effect(() => {
|
|
@@ -5572,7 +5573,7 @@ function Expander($$anchor, $$props) {
|
|
|
5572
5573
|
$.set(expanded, !$.get(expanded));
|
|
5573
5574
|
$.get(payload).expanded = $.get(expanded);
|
|
5574
5575
|
toggle($.get(payload).children, $.get(expanded));
|
|
5575
|
-
$.get(
|
|
5576
|
+
$.get(resources).length = $.get(resources).length;
|
|
5576
5577
|
}
|
|
5577
5578
|
function toggle(children, expand) {
|
|
5578
5579
|
for (let child of children) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@event-calendar/core",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.2",
|
|
4
4
|
"title": "Event Calendar Core package",
|
|
5
5
|
"description": "Full-sized drag & drop event calendar with resource & timeline views",
|
|
6
6
|
"keywords": [
|
|
@@ -32,6 +32,6 @@
|
|
|
32
32
|
"#components": "./src/lib/components/index.js"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"svelte": "^5.49.
|
|
35
|
+
"svelte": "^5.49.1"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/src/Calendar.svelte
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import './styles/index.css';
|
|
3
3
|
import {setContext, untrack} from 'svelte';
|
|
4
4
|
import {
|
|
5
|
-
assign, cloneDate, createEvents, getElementWithPayload, getPayload,
|
|
5
|
+
assign, cloneDate, createEvents, getElementWithPayload, getPayload, isDate, nextDate,
|
|
6
6
|
prevDate, toEventWithLocalDates, toLocalDate, toViewWithLocalDates
|
|
7
7
|
} from '#lib';
|
|
8
8
|
import MainState from './storage/state.svelte.js';
|
|
@@ -33,12 +33,6 @@
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
export function setOption(name, value) {
|
|
36
|
-
if (isPlainObject(value)) {
|
|
37
|
-
value = {...value};
|
|
38
|
-
}
|
|
39
|
-
if (isArray(value)) {
|
|
40
|
-
value = [...value];
|
|
41
|
-
}
|
|
42
36
|
mainState.setOption(name, value, false);
|
|
43
37
|
return this;
|
|
44
38
|
}
|
|
@@ -75,7 +69,6 @@
|
|
|
75
69
|
export function addEvent(event) {
|
|
76
70
|
event = createEvents([event])[0];
|
|
77
71
|
events.push(event);
|
|
78
|
-
mainState.events = [...events];
|
|
79
72
|
return toEventWithLocalDates(event);
|
|
80
73
|
}
|
|
81
74
|
|
|
@@ -85,7 +78,6 @@
|
|
|
85
78
|
if (idx >= 0) {
|
|
86
79
|
event = createEvents([event])[0];
|
|
87
80
|
events[idx] = event;
|
|
88
|
-
mainState.events = [...events];
|
|
89
81
|
return toEventWithLocalDates(event);
|
|
90
82
|
}
|
|
91
83
|
return null;
|
|
@@ -96,7 +88,6 @@
|
|
|
96
88
|
let idx = events.findIndex(event => event.id === id);
|
|
97
89
|
if (idx >= 0) {
|
|
98
90
|
events.splice(idx, 1);
|
|
99
|
-
mainState.events = [...events];
|
|
100
91
|
}
|
|
101
92
|
return this;
|
|
102
93
|
}
|
|
@@ -143,9 +134,7 @@
|
|
|
143
134
|
role="{features.includes('list') ? 'list' : 'table'}"
|
|
144
135
|
>
|
|
145
136
|
<Toolbar/>
|
|
146
|
-
|
|
147
|
-
<View/>
|
|
148
|
-
{/if}
|
|
137
|
+
<View/>
|
|
149
138
|
{#each auxComponents as AuxComponent}
|
|
150
139
|
<AuxComponent/>
|
|
151
140
|
{/each}
|
package/src/lib/utils.js
CHANGED
|
@@ -487,7 +487,7 @@
|
|
|
487
487
|
addDuration(iEvent.end, extraDuration);
|
|
488
488
|
}
|
|
489
489
|
event.display = 'ghost';
|
|
490
|
-
|
|
490
|
+
events.length = events.length;
|
|
491
491
|
}
|
|
492
492
|
|
|
493
493
|
function createIEventSelect() {
|
|
@@ -519,7 +519,7 @@
|
|
|
519
519
|
|
|
520
520
|
function updateEvent(target, source) {
|
|
521
521
|
copyIEventData(target, source);
|
|
522
|
-
|
|
522
|
+
events.length = events.length;
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
function updateIEvent(source) {
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
let {resource} = $props();
|
|
6
6
|
|
|
7
|
-
let {options} = $derived(getContext('state'));
|
|
8
|
-
let {resources, theme} = $derived(options);
|
|
7
|
+
let {resources, options: {theme}} = $derived(getContext('state'));
|
|
9
8
|
|
|
10
9
|
let payload = $state.raw({});
|
|
11
10
|
let expanded = $state(true);
|
|
@@ -19,7 +18,7 @@
|
|
|
19
18
|
expanded = !expanded;
|
|
20
19
|
payload.expanded = expanded;
|
|
21
20
|
toggle(payload.children, expanded);
|
|
22
|
-
|
|
21
|
+
resources.length = resources.length;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
function toggle(children, expand) {
|
package/src/storage/effects.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
assign, cloneDate, createDate, createEvents, createResources, datesEqual, empty, isArray, isFunction, setMidnight,
|
|
4
4
|
toISOString, toLocalDate, toViewWithLocalDates
|
|
5
5
|
} from '#lib';
|
|
6
|
+
import {arrayProxy} from './proxy.svelte.js';
|
|
6
7
|
|
|
7
8
|
export function loadEvents(mainState, loadingInvoker) {
|
|
8
9
|
return () => {
|
|
@@ -15,7 +16,7 @@ export function loadEvents(mainState, loadingInvoker) {
|
|
|
15
16
|
eventSources.map(source => isFunction(source.events) ? source.events : source),
|
|
16
17
|
events,
|
|
17
18
|
createEvents,
|
|
18
|
-
result => mainState.events = result,
|
|
19
|
+
result => mainState.events = arrayProxy(result),
|
|
19
20
|
activeRange,
|
|
20
21
|
fetchedRange,
|
|
21
22
|
viewDates,
|
|
@@ -38,7 +39,7 @@ export function loadResources(mainState, loadingInvoker) {
|
|
|
38
39
|
isArray(resources) ? [] : [resources],
|
|
39
40
|
resources,
|
|
40
41
|
createResources,
|
|
41
|
-
result => mainState.resources = result,
|
|
42
|
+
result => mainState.resources = arrayProxy(result),
|
|
42
43
|
activeRange,
|
|
43
44
|
fetchedRange,
|
|
44
45
|
viewDates,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {untrack} from 'svelte';
|
|
2
2
|
import {
|
|
3
|
-
createDate, createDateRange, createDuration, createEvents, createEventSources, createResources,
|
|
4
|
-
isFunction, keys, setMidnight
|
|
3
|
+
assign, createDate, createDateRange, createDuration, createEvents, createEventSources, createResources, hasOwn,
|
|
4
|
+
isArray, isFunction, isPlainObject, keys, setMidnight
|
|
5
5
|
} from '#lib';
|
|
6
|
-
import {
|
|
6
|
+
import {objectProxy} from './proxy.svelte.js';
|
|
7
7
|
|
|
8
8
|
function createOptions(plugins) {
|
|
9
9
|
let options = {
|
|
@@ -146,16 +146,15 @@ export function optionsState(mainState, plugins, userOptions) {
|
|
|
146
146
|
let userViewsOptions = extractOption(userOptions, 'views') ?? {};
|
|
147
147
|
|
|
148
148
|
// Create options state
|
|
149
|
-
let options =
|
|
150
|
-
|
|
149
|
+
let options = objectProxy({});
|
|
150
|
+
assign(options, defOptions);
|
|
151
151
|
|
|
152
152
|
let setters = {};
|
|
153
|
-
let currentOpts = {};
|
|
154
153
|
|
|
155
154
|
function initEffects() {
|
|
156
155
|
// Set initial view based on input
|
|
157
156
|
if (userOptions.view) {
|
|
158
|
-
options
|
|
157
|
+
options['view'] = userOptions.view;
|
|
159
158
|
}
|
|
160
159
|
// Set options for each view
|
|
161
160
|
let views = new Set([...keys(defViewsOptions), ...keys(userViewsOptions)]);
|
|
@@ -168,7 +167,7 @@ export function optionsState(mainState, plugins, userOptions) {
|
|
|
168
167
|
delete opts.view;
|
|
169
168
|
// Set up option setters and delete unknown options
|
|
170
169
|
for (let key of keys(opts)) {
|
|
171
|
-
if (options
|
|
170
|
+
if (hasOwn(options, key)) {
|
|
172
171
|
if (!setters[key]) {
|
|
173
172
|
setters[key] = [];
|
|
174
173
|
}
|
|
@@ -183,14 +182,13 @@ export function optionsState(mainState, plugins, userOptions) {
|
|
|
183
182
|
}
|
|
184
183
|
// When view changes...
|
|
185
184
|
$effect.pre(() => {
|
|
186
|
-
let newView = options
|
|
185
|
+
let newView = options['view'];
|
|
187
186
|
untrack(() => {
|
|
188
187
|
if (newView === view) {
|
|
189
188
|
// ...switch view component
|
|
190
189
|
mainState.setViewComponent(component);
|
|
191
190
|
// ...and update options
|
|
192
|
-
|
|
193
|
-
setOptions(options, opts);
|
|
191
|
+
assign(options, opts);
|
|
194
192
|
}
|
|
195
193
|
});
|
|
196
194
|
});
|
|
@@ -198,24 +196,21 @@ export function optionsState(mainState, plugins, userOptions) {
|
|
|
198
196
|
}
|
|
199
197
|
|
|
200
198
|
return {
|
|
201
|
-
|
|
202
|
-
set(options, key, value) {
|
|
203
|
-
currentOpts[key] = value;
|
|
204
|
-
options.set(key, value);
|
|
205
|
-
return true;
|
|
206
|
-
},
|
|
207
|
-
get(options, key) {
|
|
208
|
-
return options.get(key);
|
|
209
|
-
}
|
|
210
|
-
}),
|
|
199
|
+
state: options,
|
|
211
200
|
setOption(key, value, parsed) {
|
|
212
|
-
if (options
|
|
213
|
-
if (!parsed
|
|
214
|
-
|
|
201
|
+
if (hasOwn(options, key)) {
|
|
202
|
+
if (!parsed) {
|
|
203
|
+
if (key in parsers) {
|
|
204
|
+
value = parsers[key](value);
|
|
205
|
+
} else if (isPlainObject(value)) {
|
|
206
|
+
value = {...value};
|
|
207
|
+
} else if (isArray(value)) {
|
|
208
|
+
value = [...value];
|
|
209
|
+
}
|
|
215
210
|
}
|
|
216
211
|
// Set value for all views
|
|
217
212
|
setters[key]?.forEach(set => set(value));
|
|
218
|
-
options
|
|
213
|
+
options[key] = value;
|
|
219
214
|
}
|
|
220
215
|
},
|
|
221
216
|
initEffects
|
|
@@ -262,12 +257,6 @@ function mergeOpts(...args) {
|
|
|
262
257
|
return result;
|
|
263
258
|
}
|
|
264
259
|
|
|
265
|
-
function setOptions(map, options) {
|
|
266
|
-
for (let [key, value] of entries(options)) {
|
|
267
|
-
map.set(key, value);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
260
|
export function diff(options, prevOptions) {
|
|
272
261
|
let diff = [];
|
|
273
262
|
for (let key of keys(options)) {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {hasOwn} from '#lib';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Array proxy that triggers the effect on any assignment to first-level elements or length property
|
|
5
|
+
*/
|
|
6
|
+
export function arrayProxy(array) {
|
|
7
|
+
let counter = 0;
|
|
8
|
+
let version = $state(counter);
|
|
9
|
+
return proxy(
|
|
10
|
+
array,
|
|
11
|
+
() => version,
|
|
12
|
+
() => true,
|
|
13
|
+
() => version = ++counter
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Object proxy that triggers the effect on changes to first-level properties
|
|
19
|
+
*/
|
|
20
|
+
export function objectProxy(object) {
|
|
21
|
+
let counter = 0;
|
|
22
|
+
let versions = $state({});
|
|
23
|
+
return proxy(
|
|
24
|
+
object,
|
|
25
|
+
prop => versions[prop],
|
|
26
|
+
(a, b) => a !== b,
|
|
27
|
+
prop => versions[prop] = ++counter
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function proxy(target, setDependency, hasEffect, invokeEffect) {
|
|
32
|
+
return new Proxy(target, {
|
|
33
|
+
get(target, prop, receiver) {
|
|
34
|
+
if (hasOwn(target, prop)) {
|
|
35
|
+
setDependency(prop);
|
|
36
|
+
}
|
|
37
|
+
return Reflect.get(target, prop, receiver);
|
|
38
|
+
},
|
|
39
|
+
set(target, prop, value, receiver) {
|
|
40
|
+
let has = hasEffect(target[prop], value);
|
|
41
|
+
Reflect.set(target, prop, value, receiver);
|
|
42
|
+
if (has) {
|
|
43
|
+
invokeEffect(prop);
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
createLoadingInvoker, loadEvents, loadResources, runDatesSet, runEventAllUpdated, runViewDidMount, setNowAndToday
|
|
6
6
|
} from './effects.js';
|
|
7
7
|
import {activeRange, currentRange, filteredEvents, view, viewDates, viewTitle} from './derived.js';
|
|
8
|
+
import {arrayProxy} from './proxy.svelte.js';
|
|
8
9
|
|
|
9
10
|
export default class State {
|
|
10
11
|
|
|
@@ -12,8 +13,8 @@ export default class State {
|
|
|
12
13
|
|
|
13
14
|
constructor(plugins, options) {
|
|
14
15
|
// Create options state
|
|
15
|
-
let {
|
|
16
|
-
this.options =
|
|
16
|
+
let {state, setOption, initEffects} = optionsState(this, plugins, options);
|
|
17
|
+
this.options = state;
|
|
17
18
|
this.#setOption = setOption;
|
|
18
19
|
|
|
19
20
|
// Create other states
|
|
@@ -21,11 +22,11 @@ export default class State {
|
|
|
21
22
|
this.currentRange = $derived.by(currentRange(this));
|
|
22
23
|
this.activeRange = $derived.by(activeRange(this));
|
|
23
24
|
this.fetchedRange = $state({events: {}, resources: {}});
|
|
24
|
-
this.events = $state.raw([]);
|
|
25
|
+
this.events = $state.raw(arrayProxy([]));
|
|
25
26
|
this.filteredEvents = $derived.by(filteredEvents(this));
|
|
26
27
|
this.mainEl = $state();
|
|
27
28
|
this.now = $state(createDate());
|
|
28
|
-
this.resources = $state.raw([]);
|
|
29
|
+
this.resources = $state.raw(arrayProxy([]));
|
|
29
30
|
this.today = $state(setMidnight(createDate()));
|
|
30
31
|
this.intlEventTime = $derived.by(intlRange(this, 'eventTimeFormat'));
|
|
31
32
|
this.intlDayHeader = $derived.by(intl(this, 'dayHeaderFormat'));
|