@event-calendar/core 5.3.0 → 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 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.0/dist/event-calendar.min.css">
255
- <script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@5.3.0/dist/event-calendar.min.js"></script>
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>
@@ -1546,7 +1546,7 @@ This option is used instead of the `events` option.
1546
1546
 
1547
1547
  `EventSource` should be an object with one of the following sets of properties:
1548
1548
 
1549
- #### 1. Fetch events JSON from a URL
1549
+ #### 1. Fetch events from a URL
1550
1550
  <table>
1551
1551
  <tr>
1552
1552
  <td>
@@ -2033,13 +2033,13 @@ The function is triggered during resizing for each cursor movement and takes the
2033
2033
  - Type `array`, `object` or `function`
2034
2034
  - Default `[]`
2035
2035
 
2036
- The source of resource data displayed in resource views. It can be provided in one of three ways:
2036
+ Defines the source of resource data displayed in resource views. It can be provided in one of three ways:
2037
2037
 
2038
2038
  #### 1. Array of plain objects
2039
- The provided plain objects will be parsed into [Resource](#resource-object) objects.
2039
+ If the resources are predefined and do not change, then pass them as an array of plain objects. The provided plain objects will be [parsed]((#parsing-resource-from-a-plain-object)) into [Resource](#resource-object) objects.
2040
2040
 
2041
- #### 2. Fetch resources JSON from a URL
2042
- For this option, provide an object with the following properties:
2041
+ #### 2. Fetch resources from a URL
2042
+ To make the calendar load resources from a URL, specify `resources` option as an object with the following properties:
2043
2043
  <table>
2044
2044
  <tr>
2045
2045
  <td>
@@ -2056,7 +2056,7 @@ A URL from which the calendar will fetch an array of [parsable](#parsing-resourc
2056
2056
  `start`
2057
2057
  </td>
2058
2058
  <td>
2059
- Start date of the range the calendar needs events for
2059
+ Start date of the range the calendar needs resources for
2060
2060
  </td>
2061
2061
  </tr>
2062
2062
  <tr>
@@ -2065,7 +2065,7 @@ Start date of the range the calendar needs events for
2065
2065
  `end`
2066
2066
  </td>
2067
2067
  <td>
2068
- End date of the range the calendar needs events for
2068
+ End date of the range the calendar needs resources for
2069
2069
  </td>
2070
2070
  </tr>
2071
2071
  </table>
@@ -2094,26 +2094,26 @@ Other GET/POST data you want to send to the server. Can be a plain object or a f
2094
2094
  </table>
2095
2095
 
2096
2096
  #### 3. Execute custom function
2097
- You can also provide a custom function that returns an array of resources.
2097
+ You can also specify `resources` as a custom function that provides resource data.
2098
2098
  ```js
2099
2099
  function(fetchInfo, successCallback, failureCallback) { }
2100
2100
  ```
2101
2101
  If [refetchResourcesOnNavigate](#refetchresourcesonnavigate) is enabled, the function will be called every time the user navigates to a different date. In this case,
2102
- `fetchInfo` will be an object with the following properties (otherwise, it is an empty object):
2102
+ `fetchInfo` will be an object with the following properties (it is an empty object otherwise):
2103
2103
  <table>
2104
2104
  <tr>
2105
2105
  <td>
2106
2106
 
2107
2107
  `start`
2108
2108
  </td>
2109
- <td>JavaScript Date object for the beginning of the range the calendar needs events for</td>
2109
+ <td>JavaScript Date object for the beginning of the range the calendar needs resources for</td>
2110
2110
  </tr>
2111
2111
  <tr>
2112
2112
  <td>
2113
2113
 
2114
2114
  `end`
2115
2115
  </td>
2116
- <td>JavaScript Date object for the end of the range the calendar needs events for. Note: This value is exclusive</td>
2116
+ <td>JavaScript Date object for the end of the range the calendar needs resources for. Note: This value is exclusive</td>
2117
2117
  </tr>
2118
2118
  <tr>
2119
2119
  <td>
package/dist/index.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * EventCalendar v5.3.0
2
+ * EventCalendar v5.3.2
3
3
  * https://github.com/vkurko/calendar
4
4
  */
5
5
  .ec {
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * EventCalendar v5.3.0
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 = new SvelteMap();
892
- setOptions(options, defOptions);
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.set("view", userOptions.view);
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.has(key)) {
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.get("view");
947
+ let newView = options["view"];
918
948
  untrack(() => {
919
949
  if (newView === view2) {
920
950
  mainState.setViewComponent(component);
921
- currentOpts = opts;
922
- setOptions(options, opts);
951
+ assign(options, opts);
923
952
  }
924
953
  });
925
954
  });
926
955
  }
927
956
  }
928
957
  return {
929
- proxy: new Proxy(options, {
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.has(key)) {
941
- if (!parsed && key in parsers) {
942
- value = parsers[key](value);
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.set(key, currentOpts[key] ?? value);
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 { proxy, setOption, initEffects } = optionsState(this, plugins, options);
1440
- this.options = proxy;
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
- var consequent = ($$anchor2) => {
1892
- var fragment = $.comment();
1893
- var node_2 = $.first_child(fragment);
1894
- $.component(node_2, () => $.get(View2), ($$anchor3, View_12) => {
1895
- View_12($$anchor3, {});
1896
- });
1897
- $.append($$anchor2, fragment);
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, fragment_1);
1912
+ $.append($$anchor2, fragment);
1911
1913
  });
1912
1914
  $.reset(div);
1913
1915
  $.template_effect(
@@ -3282,16 +3284,19 @@ function Action($$anchor, $$props) {
3282
3284
  }
3283
3285
  }
3284
3286
  }
3285
- interacting = false;
3286
- action = fromX = fromY = toX = toY = event = display = date = newDate = resource = newResource = delta = extraDuration = allDay = minResize = selectStep = margin = gridEl = viewport = snapDuration = void 0;
3287
- mainState.iClass = void 0;
3288
- if (timer) {
3289
- clearTimeout(timer);
3290
- timer = void 0;
3291
- }
3287
+ handlePointerCancel();
3292
3288
  }
3293
3289
  noDateClick = false;
3294
3290
  }
3291
+ function handlePointerCancel() {
3292
+ interacting = false;
3293
+ action = fromX = fromY = toX = toY = event = display = date = newDate = resource = newResource = delta = extraDuration = allDay = minResize = selectStep = margin = gridEl = viewport = snapDuration = void 0;
3294
+ mainState.iClass = void 0;
3295
+ if (timer) {
3296
+ clearTimeout(timer);
3297
+ timer = void 0;
3298
+ }
3299
+ }
3295
3300
  function findDayEl() {
3296
3301
  return getElementWithPayload(limit(toX, viewport.left, viewport.right), limit(toY, viewport.top, viewport.bottom));
3297
3302
  }
@@ -3349,7 +3354,7 @@ function Action($$anchor, $$props) {
3349
3354
  addDuration(iEvent.end, extraDuration);
3350
3355
  }
3351
3356
  event.display = "ghost";
3352
- mainState.events = [...$.get(events)];
3357
+ $.get(events).length = $.get(events).length;
3353
3358
  }
3354
3359
  function createIEventSelect() {
3355
3360
  iEvent = {
@@ -3377,7 +3382,7 @@ function Action($$anchor, $$props) {
3377
3382
  }
3378
3383
  function updateEvent(target, source) {
3379
3384
  copyIEventData(target, source);
3380
- mainState.events = [...$.get(events)];
3385
+ $.get(events).length = $.get(events).length;
3381
3386
  }
3382
3387
  function updateIEvent(source) {
3383
3388
  iEvent = copyIEventData(iEvent, source);
@@ -3482,7 +3487,7 @@ function Action($$anchor, $$props) {
3482
3487
  };
3483
3488
  $.event("pointermove", $.window, handlePointerMove);
3484
3489
  $.event("pointerup", $.window, handlePointerUp);
3485
- $.event("pointercancel", $.window, handlePointerUp);
3490
+ $.event("pointercancel", $.window, handlePointerCancel);
3486
3491
  $.event("scroll", $.window, handleScroll2);
3487
3492
  var event_handler = $.derived(() => createPreventDefaultHandler(complexAction));
3488
3493
  $.event("selectstart", $.window, function(...$$args) {
@@ -5557,8 +5562,7 @@ var root_2 = $.from_html(`<button><!></button>`);
5557
5562
  var root = $.from_html(`<!> <span><!></span>`, 1);
5558
5563
  function Expander($$anchor, $$props) {
5559
5564
  $.push($$props, true);
5560
- let $$d = $.derived(() => getContext("state")), options = $.derived(() => $.get($$d).options);
5561
- 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);
5562
5566
  let payload = $.state({});
5563
5567
  let expanded = $.state(true);
5564
5568
  $.user_pre_effect(() => {
@@ -5569,7 +5573,7 @@ function Expander($$anchor, $$props) {
5569
5573
  $.set(expanded, !$.get(expanded));
5570
5574
  $.get(payload).expanded = $.get(expanded);
5571
5575
  toggle($.get(payload).children, $.get(expanded));
5572
- $.get(options).resources = [...$.get(resources)];
5576
+ $.get(resources).length = $.get(resources).length;
5573
5577
  }
5574
5578
  function toggle(children, expand) {
5575
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.0",
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.48.0"
35
+ "svelte": "^5.49.1"
36
36
  }
37
37
  }
@@ -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, isArray, isDate, isPlainObject, nextDate,
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
- {#if View} <!-- temporary fix for https://github.com/sveltejs/kit/issues/15109 -->
147
- <View/>
148
- {/if}
137
+ <View/>
149
138
  {#each auxComponents as AuxComponent}
150
139
  <AuxComponent/>
151
140
  {/each}
package/src/lib/utils.js CHANGED
@@ -10,6 +10,10 @@ export function entries(object) {
10
10
  return Object.entries(object);
11
11
  }
12
12
 
13
+ export function hasOwn(object, property) {
14
+ return Object.hasOwn(object, property);
15
+ }
16
+
13
17
  export function floor(value) {
14
18
  return Math.floor(value);
15
19
  }
@@ -393,21 +393,24 @@
393
393
  }
394
394
  }
395
395
  }
396
-
397
- interacting = false;
398
- action = fromX = fromY = toX = toY = event = display = date = newDate = resource = newResource = delta =
399
- extraDuration = allDay = minResize = selectStep = margin = gridEl = viewport = snapDuration = undefined;
400
- mainState.iClass = undefined;
401
-
402
- if (timer) {
403
- clearTimeout(timer);
404
- timer = undefined;
405
- }
396
+ handlePointerCancel();
406
397
  }
407
398
 
408
399
  noDateClick = false;
409
400
  }
410
401
 
402
+ function handlePointerCancel() {
403
+ interacting = false;
404
+ action = fromX = fromY = toX = toY = event = display = date = newDate = resource = newResource = delta =
405
+ extraDuration = allDay = minResize = selectStep = margin = gridEl = viewport = snapDuration = undefined;
406
+ mainState.iClass = undefined;
407
+
408
+ if (timer) {
409
+ clearTimeout(timer);
410
+ timer = undefined;
411
+ }
412
+ }
413
+
411
414
  function findDayEl() {
412
415
  // Limit coordinates to viewport
413
416
  return getElementWithPayload(
@@ -484,7 +487,7 @@
484
487
  addDuration(iEvent.end, extraDuration);
485
488
  }
486
489
  event.display = 'ghost';
487
- mainState.events = [...events];
490
+ events.length = events.length;
488
491
  }
489
492
 
490
493
  function createIEventSelect() {
@@ -516,7 +519,7 @@
516
519
 
517
520
  function updateEvent(target, source) {
518
521
  copyIEventData(target, source);
519
- mainState.events = [...events];
522
+ events.length = events.length;
520
523
  }
521
524
 
522
525
  function updateIEvent(source) {
@@ -641,7 +644,7 @@
641
644
  <svelte:window
642
645
  onpointermove={handlePointerMove}
643
646
  onpointerup={handlePointerUp}
644
- onpointercancel={handlePointerUp}
647
+ onpointercancel={handlePointerCancel}
645
648
  onscroll={handleScroll}
646
649
  onselectstart={createPreventDefaultHandler(complexAction)}
647
650
  oncontextmenu={createPreventDefaultHandler(() => timer)}
@@ -30,9 +30,11 @@
30
30
  </script>
31
31
 
32
32
  {#if resizable && eventResizableFromStart}
33
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
33
34
  <div class="{theme.resizer} {theme.start}" onpointerdown={createResizeHandler(true)}></div>
34
35
  {/if}
35
36
  {@render children()}
36
37
  {#if resizable}
38
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
37
39
  <div class="{theme.resizer}" onpointerdown={createResizeHandler(false)}></div>
38
40
  {/if}
@@ -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
- options.resources = [...resources];
21
+ resources.length = resources.length;
23
22
  }
24
23
 
25
24
  function toggle(children, expand) {
@@ -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, entries, isArray,
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 {SvelteMap} from "svelte/reactivity";
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 = new SvelteMap();
150
- setOptions(options, defOptions);
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.set('view', userOptions.view);
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.has(key)) {
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.get('view');
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
- currentOpts = opts;
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
- proxy: new Proxy(options, {
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.has(key)) {
213
- if (!parsed && key in parsers) {
214
- value = parsers[key](value);
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.set(key, currentOpts[key] ?? value);
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 {proxy, setOption, initEffects} = optionsState(this, plugins, options);
16
- this.options = proxy;
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'));