@event-calendar/core 5.3.2 → 5.3.3

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
@@ -5,7 +5,7 @@ See [demo](https://vkurko.github.io/calendar/) and [changelog](CHANGELOG.md).
5
5
  Full-sized drag & drop JavaScript event calendar with resource & timeline views:
6
6
 
7
7
  * Lightweight (35kb [br](https://en.wikipedia.org/wiki/Brotli) compressed)
8
- * 100% human-coded
8
+ * Feature-rich, performant, and with minimal DOM structure (thanks to [CSS Grid](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Grid_layout))
9
9
  * Zero-dependency (standalone bundle)
10
10
  * Used on over 70,000 websites with [Bookly](https://wordpress.org/plugins/bookly-responsive-appointment-booking-tool/)
11
11
 
@@ -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.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>
254
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@event-calendar/build@5.3.3/dist/event-calendar.min.css">
255
+ <script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@5.3.3/dist/event-calendar.min.js"></script>
256
256
  ```
257
257
 
258
258
  <details>
package/dist/index.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * EventCalendar v5.3.2
2
+ * EventCalendar v5.3.3
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.2
2
+ * EventCalendar v5.3.3
3
3
  * https://github.com/vkurko/calendar
4
4
  */
5
5
  import { untrack, tick, getAbortSignal, getContext, setContext, onMount, mount, unmount } from "svelte";
@@ -793,24 +793,32 @@ function proxy(target, setDependency, hasEffect, invokeEffect) {
793
793
  },
794
794
  set(target2, prop, value, receiver) {
795
795
  let has = hasEffect(target2[prop], value);
796
- Reflect.set(target2, prop, value, receiver);
796
+ let result = Reflect.set(target2, prop, value, receiver);
797
797
  if (has) {
798
798
  invokeEffect(prop);
799
799
  }
800
- return true;
800
+ return result;
801
801
  }
802
802
  });
803
803
  }
804
804
  function createOptions(plugins) {
805
805
  let options = {
806
- buttonText: { today: "today" },
806
+ buttonText: {
807
+ today: "today"
808
+ },
807
809
  customButtons: {},
808
810
  customScrollbars: false,
809
811
  // ec option
810
812
  date: /* @__PURE__ */ new Date(),
811
813
  datesSet: void 0,
812
- dayHeaderFormat: { weekday: "short", month: "numeric", day: "numeric" },
813
- dayHeaderAriaLabelFormat: { dateStyle: "full" },
814
+ dayHeaderFormat: {
815
+ weekday: "short",
816
+ month: "numeric",
817
+ day: "numeric"
818
+ },
819
+ dayHeaderAriaLabelFormat: {
820
+ dateStyle: "full"
821
+ },
814
822
  displayEventEnd: true,
815
823
  duration: { weeks: 1 },
816
824
  events: [],
@@ -828,10 +836,17 @@ function createOptions(plugins) {
828
836
  eventOrder: void 0,
829
837
  eventSources: [],
830
838
  eventTextColor: void 0,
831
- eventTimeFormat: { hour: "numeric", minute: "2-digit" },
839
+ eventTimeFormat: {
840
+ hour: "numeric",
841
+ minute: "2-digit"
842
+ },
832
843
  filterEventsWithResources: false,
833
844
  firstDay: 0,
834
- headerToolbar: { start: "title", center: "", end: "today prev,next" },
845
+ headerToolbar: {
846
+ start: "title",
847
+ center: "",
848
+ end: "today prev,next"
849
+ },
835
850
  height: void 0,
836
851
  hiddenDays: [],
837
852
  highlightedDates: [],
@@ -874,17 +889,13 @@ function createOptions(plugins) {
874
889
  title: "ec-title",
875
890
  toolbar: "ec-toolbar",
876
891
  view: "",
877
- weekdays: [
878
- "ec-sun",
879
- "ec-mon",
880
- "ec-tue",
881
- "ec-wed",
882
- "ec-thu",
883
- "ec-fri",
884
- "ec-sat"
885
- ]
892
+ weekdays: ["ec-sun", "ec-mon", "ec-tue", "ec-wed", "ec-thu", "ec-fri", "ec-sat"]
893
+ },
894
+ titleFormat: {
895
+ year: "numeric",
896
+ month: "short",
897
+ day: "numeric"
886
898
  },
887
- titleFormat: { year: "numeric", month: "short", day: "numeric" },
888
899
  validRange: void 0,
889
900
  view: void 0,
890
901
  viewDidMount: void 0,
@@ -912,51 +923,47 @@ function createParsers(plugins) {
912
923
  return parsers;
913
924
  }
914
925
  const specialOptions = ["buttonText", "customButtons", "theme"];
915
- function optionsState(mainState, plugins, userOptions) {
926
+ function optionsState(plugins, userOptions) {
916
927
  let defOptions = createOptions(plugins);
917
928
  let parsers = createParsers(plugins);
918
929
  defOptions = parseOptions(defOptions, parsers);
919
930
  userOptions = parseOptions(userOptions, parsers);
920
- let defViewsOptions = extractOption(defOptions, "views") ?? {};
921
- let userViewsOptions = extractOption(userOptions, "views") ?? {};
931
+ let defViews = extractOption(defOptions, "views") ?? {};
932
+ let userViews = extractOption(userOptions, "views") ?? {};
922
933
  let options = objectProxy({});
923
934
  assign(options, defOptions);
935
+ if (userOptions.view) {
936
+ options.view = userOptions.view;
937
+ }
924
938
  let setters = {};
925
- function initEffects() {
926
- if (userOptions.view) {
927
- options["view"] = userOptions.view;
928
- }
929
- let views = /* @__PURE__ */ new Set([...keys(defViewsOptions), ...keys(userViewsOptions)]);
930
- for (let view2 of views) {
931
- let userViewOptions = userViewsOptions[view2] ?? {};
932
- let defOpts = mergeOpts(defOptions, defViewsOptions[view2] ?? defViewsOptions[userViewOptions.type] ?? {});
933
- let opts = mergeOpts(defOpts, userOptions, userViewOptions);
934
- let component = extractOption(opts, "component");
935
- delete opts.view;
936
- for (let key of keys(opts)) {
937
- if (hasOwn(options, key)) {
938
- if (!setters[key]) {
939
- setters[key] = [];
940
- }
941
- setters[key].push(specialOptions.includes(key) ? (value) => opts[key] = isFunction(value) ? value(defOpts[key]) : value : (value) => opts[key] = value);
942
- } else {
943
- delete opts[key];
939
+ let viewOptions = {};
940
+ let viewComponents = {};
941
+ let views = /* @__PURE__ */ new Set([...keys(defViews), ...keys(userViews)]);
942
+ for (let view2 of views) {
943
+ let userViewOptions = userViews[view2] ?? {};
944
+ let defOpts = mergeOpts(defOptions, defViews[view2] ?? defViews[userViewOptions.type] ?? {});
945
+ let opts = mergeOpts(defOpts, userOptions, userViewOptions);
946
+ let component = extractOption(opts, "component");
947
+ delete opts.view;
948
+ for (let key of keys(opts)) {
949
+ if (hasOwn(options, key)) {
950
+ if (!setters[key]) {
951
+ setters[key] = [];
944
952
  }
953
+ setters[key].push(
954
+ specialOptions.includes(key) ? (value) => opts[key] = isFunction(value) ? value(defOpts[key]) : value : (value) => opts[key] = value
955
+ );
956
+ } else {
957
+ delete opts[key];
945
958
  }
946
- $.user_pre_effect(() => {
947
- let newView = options["view"];
948
- untrack(() => {
949
- if (newView === view2) {
950
- mainState.setViewComponent(component);
951
- assign(options, opts);
952
- }
953
- });
954
- });
955
959
  }
960
+ viewOptions[view2] = opts;
961
+ viewComponents[view2] = component;
956
962
  }
957
- return {
958
- state: options,
959
- setOption(key, value, parsed) {
963
+ assign(options, viewOptions[options.view]);
964
+ return [
965
+ options,
966
+ function setOption(key, value, parsed = true) {
960
967
  if (hasOwn(options, key)) {
961
968
  if (!parsed) {
962
969
  if (key in parsers) {
@@ -971,8 +978,11 @@ function optionsState(mainState, plugins, userOptions) {
971
978
  options[key] = value;
972
979
  }
973
980
  },
974
- initEffects
975
- };
981
+ function setViewOptions(view2) {
982
+ assign(options, viewOptions[view2]);
983
+ return viewComponents[view2];
984
+ }
985
+ ];
976
986
  }
977
987
  function parseOptions(opts, parsers) {
978
988
  let result = { ...opts };
@@ -1003,7 +1013,11 @@ function mergeOpts(...args) {
1003
1013
  override[key] = opts[key](result[key]);
1004
1014
  }
1005
1015
  }
1006
- result = { ...result, ...opts, ...override };
1016
+ result = {
1017
+ ...result,
1018
+ ...opts,
1019
+ ...override
1020
+ };
1007
1021
  }
1008
1022
  return result;
1009
1023
  }
@@ -1016,6 +1030,17 @@ function diff(options, prevOptions) {
1016
1030
  }
1017
1031
  return diff2;
1018
1032
  }
1033
+ function switchView(mainState) {
1034
+ return () => {
1035
+ let { options: { view: view2 } } = mainState;
1036
+ untrack(() => {
1037
+ let initComponent = mainState.setViewOptions(view2);
1038
+ mainState.extensions = {};
1039
+ mainState.features = [];
1040
+ mainState.viewComponent = initComponent(mainState);
1041
+ });
1042
+ };
1043
+ }
1019
1044
  function loadEvents(mainState, loadingInvoker) {
1020
1045
  return () => {
1021
1046
  let {
@@ -1120,10 +1145,10 @@ function load(sources, defaultResult, parseResult, applyResult, activeRange2, fe
1120
1145
  assign(fetchedRange, activeRange2);
1121
1146
  }
1122
1147
  }
1123
- function createLoadingInvoker(options) {
1148
+ function createLoadingInvoker(mainState) {
1124
1149
  let counter = 0;
1125
1150
  function invoke(value) {
1126
- let { loading } = options;
1151
+ let { options: { loading } } = mainState;
1127
1152
  if (isFunction(loading)) {
1128
1153
  loading(value);
1129
1154
  }
@@ -1455,20 +1480,20 @@ class State {
1455
1480
  set iClass(value) {
1456
1481
  $.set(this.#iClass, value, true);
1457
1482
  }
1458
- #setOption;
1483
+ options;
1484
+ setOption;
1485
+ setViewOptions;
1459
1486
  constructor(plugins, options) {
1460
- let { state, setOption, initEffects } = optionsState(this, plugins, options);
1461
- this.options = state;
1462
- this.#setOption = setOption;
1487
+ [this.options, this.setOption, this.setViewOptions] = optionsState(plugins, options);
1463
1488
  this.#auxComponents = $.state($.proxy([]));
1464
1489
  this.#currentRange = $.derived(currentRange(this));
1465
1490
  this.#activeRange = $.derived(activeRange(this));
1466
1491
  this.#fetchedRange = $.state($.proxy({ events: {}, resources: {} }));
1467
- this.#events = $.state(arrayProxy([]));
1492
+ this.#events = $.state(arrayProxy(this.options.events));
1468
1493
  this.#filteredEvents = $.derived(filteredEvents(this));
1469
1494
  this.#mainEl = $.state();
1470
1495
  this.#now = $.state($.proxy(createDate()));
1471
- this.#resources = $.state(arrayProxy([]));
1496
+ this.#resources = $.state(arrayProxy(this.options.resources));
1472
1497
  this.#today = $.state($.proxy(setMidnight(createDate())));
1473
1498
  this.#intlEventTime = $.derived(intlRange(this, "eventTimeFormat"));
1474
1499
  this.#intlDayHeader = $.derived(intl(this, "dayHeaderFormat"));
@@ -1487,11 +1512,11 @@ class State {
1487
1512
  for (let plugin of plugins) {
1488
1513
  plugin.initState?.(this);
1489
1514
  }
1490
- initEffects();
1491
1515
  this.#initEffects();
1492
1516
  }
1493
1517
  #initEffects() {
1494
- let loading = createLoadingInvoker(this.options);
1518
+ let loading = createLoadingInvoker(this);
1519
+ $.user_pre_effect(switchView(this));
1495
1520
  $.user_pre_effect(setNowAndToday(this));
1496
1521
  $.user_effect(loadEvents(this, loading));
1497
1522
  $.user_effect(loadResources(this, loading));
@@ -1499,14 +1524,6 @@ class State {
1499
1524
  $.user_effect(runEventAllUpdated(this));
1500
1525
  $.user_effect(runViewDidMount(this));
1501
1526
  }
1502
- setViewComponent(component) {
1503
- this.extensions = {};
1504
- this.features = [];
1505
- this.viewComponent = component(this);
1506
- }
1507
- setOption(name, value, parsed = true) {
1508
- this.#setOption(name, value, parsed);
1509
- }
1510
1527
  }
1511
1528
  var root_2$5 = $.from_html(`<h2></h2>`);
1512
1529
  var root_4$1 = $.from_html(`<button><i></i></button>`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event-calendar/core",
3
- "version": "5.3.2",
3
+ "version": "5.3.3",
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.1"
35
+ "svelte": "^5.50.1"
36
36
  }
37
37
  }
@@ -6,7 +6,7 @@
6
6
  prevDate, toEventWithLocalDates, toLocalDate, toViewWithLocalDates
7
7
  } from '#lib';
8
8
  import MainState from './storage/state.svelte.js';
9
- import {diff} from './storage/options.svelte.js';
9
+ import {diff} from './storage/options.js';
10
10
  import Toolbar from './Toolbar.svelte';
11
11
 
12
12
  let {plugins = [], options = {}} = $props();
@@ -5,6 +5,20 @@ import {
5
5
  } from '#lib';
6
6
  import {arrayProxy} from './proxy.svelte.js';
7
7
 
8
+ export function switchView(mainState) {
9
+ return () => {
10
+ // Dependencies
11
+ let {options: {view}} = mainState;
12
+
13
+ untrack(() => {
14
+ let initComponent = mainState.setViewOptions(view);
15
+ mainState.extensions = {};
16
+ mainState.features = [];
17
+ mainState.viewComponent = initComponent(mainState);
18
+ });
19
+ };
20
+ }
21
+
8
22
  export function loadEvents(mainState, loadingInvoker) {
9
23
  return () => {
10
24
  // Dependencies
@@ -125,10 +139,10 @@ function load(sources, defaultResult, parseResult, applyResult, activeRange, fet
125
139
  }
126
140
  }
127
141
 
128
- export function createLoadingInvoker(options) {
142
+ export function createLoadingInvoker(mainState) {
129
143
  let counter = 0;
130
144
  function invoke(value) {
131
- let {loading} = options;
145
+ let {options: {loading}} = mainState;
132
146
  if (isFunction(loading)) {
133
147
  loading(value);
134
148
  }
@@ -132,7 +132,7 @@ function createParsers(plugins) {
132
132
  // Options where default value is passed to the function
133
133
  const specialOptions = ['buttonText', 'customButtons', 'theme'];
134
134
 
135
- export function optionsState(mainState, plugins, userOptions) {
135
+ export function optionsState(plugins, userOptions) {
136
136
  // Create default options and parsers
137
137
  let defOptions = createOptions(plugins);
138
138
  let parsers = createParsers(plugins);
@@ -142,62 +142,53 @@ export function optionsState(mainState, plugins, userOptions) {
142
142
  userOptions = parseOptions(userOptions, parsers);
143
143
 
144
144
  // Extract view-specific options
145
- let defViewsOptions = extractOption(defOptions, 'views') ?? {};
146
- let userViewsOptions = extractOption(userOptions, 'views') ?? {};
145
+ let defViews = extractOption(defOptions, 'views') ?? {};
146
+ let userViews = extractOption(userOptions, 'views') ?? {};
147
147
 
148
148
  // Create options state
149
149
  let options = objectProxy({});
150
150
  assign(options, defOptions);
151
+ // Set initial view based on input
152
+ if (userOptions.view) {
153
+ options.view = userOptions.view;
154
+ }
151
155
 
156
+ // Set options for each view
152
157
  let setters = {};
153
-
154
- function initEffects() {
155
- // Set initial view based on input
156
- if (userOptions.view) {
157
- options['view'] = userOptions.view;
158
- }
159
- // Set options for each view
160
- let views = new Set([...keys(defViewsOptions), ...keys(userViewsOptions)]);
161
- for (let view of views) {
162
- let userViewOptions = userViewsOptions[view] ?? {};
163
- let defOpts = mergeOpts(defOptions, defViewsOptions[view] ?? defViewsOptions[userViewOptions.type] ?? {});
164
- let opts = mergeOpts(defOpts, userOptions, userViewOptions);
165
- let component = extractOption(opts, 'component');
166
- // View has been set
167
- delete opts.view;
168
- // Set up option setters and delete unknown options
169
- for (let key of keys(opts)) {
170
- if (hasOwn(options, key)) {
171
- if (!setters[key]) {
172
- setters[key] = [];
173
- }
174
- setters[key].push(
175
- specialOptions.includes(key)
176
- ? value => opts[key] = isFunction(value) ? value(defOpts[key]) : value
177
- : value => opts[key] = value
178
- );
179
- } else {
180
- delete opts[key];
158
+ let viewOptions = {};
159
+ let viewComponents = {};
160
+ let views = new Set([...keys(defViews), ...keys(userViews)]);
161
+ for (let view of views) {
162
+ let userViewOptions = userViews[view] ?? {};
163
+ let defOpts = mergeOpts(defOptions, defViews[view] ?? defViews[userViewOptions.type] ?? {});
164
+ let opts = mergeOpts(defOpts, userOptions, userViewOptions);
165
+ let component = extractOption(opts, 'component');
166
+ // View has been set
167
+ delete opts.view;
168
+ // Set up option setters and delete unknown options
169
+ for (let key of keys(opts)) {
170
+ if (hasOwn(options, key)) {
171
+ if (!setters[key]) {
172
+ setters[key] = [];
181
173
  }
174
+ setters[key].push(
175
+ specialOptions.includes(key)
176
+ ? value => opts[key] = isFunction(value) ? value(defOpts[key]) : value
177
+ : value => opts[key] = value
178
+ );
179
+ } else {
180
+ delete opts[key];
182
181
  }
183
- // When view changes...
184
- $effect.pre(() => {
185
- let newView = options['view'];
186
- untrack(() => {
187
- if (newView === view) {
188
- // ...switch view component
189
- mainState.setViewComponent(component);
190
- // ...and update options
191
- assign(options, opts);
192
- }
193
- });
194
- });
195
182
  }
183
+ viewOptions[view] = opts;
184
+ viewComponents[view] = component;
196
185
  }
197
186
 
198
- return {
199
- state: options,
200
- setOption(key, value, parsed) {
187
+ assign(options, viewOptions[options.view]);
188
+
189
+ return [
190
+ options,
191
+ function setOption(key, value, parsed = true) {
201
192
  if (hasOwn(options, key)) {
202
193
  if (!parsed) {
203
194
  if (key in parsers) {
@@ -213,8 +204,11 @@ export function optionsState(mainState, plugins, userOptions) {
213
204
  options[key] = value;
214
205
  }
215
206
  },
216
- initEffects
217
- };
207
+ function setViewOptions(view) {
208
+ assign(options, viewOptions[view]);
209
+ return viewComponents[view];
210
+ }
211
+ ];
218
212
  }
219
213
 
220
214
  function parseOptions(opts, parsers) {
@@ -38,11 +38,11 @@ function proxy(target, setDependency, hasEffect, invokeEffect) {
38
38
  },
39
39
  set(target, prop, value, receiver) {
40
40
  let has = hasEffect(target[prop], value);
41
- Reflect.set(target, prop, value, receiver);
41
+ let result = Reflect.set(target, prop, value, receiver);
42
42
  if (has) {
43
43
  invokeEffect(prop);
44
44
  }
45
- return true;
45
+ return result;
46
46
  }
47
47
  });
48
48
  }
@@ -1,32 +1,33 @@
1
1
  import {SvelteMap} from 'svelte/reactivity';
2
2
  import {createDate, identity, intl, intlRange, setMidnight} from '#lib';
3
- import {optionsState} from './options.svelte.js';
3
+ import {optionsState} from './options.js';
4
4
  import {
5
- createLoadingInvoker, loadEvents, loadResources, runDatesSet, runEventAllUpdated, runViewDidMount, setNowAndToday
5
+ createLoadingInvoker, loadEvents, loadResources, runDatesSet, runEventAllUpdated, runViewDidMount, setNowAndToday,
6
+ switchView
6
7
  } from './effects.js';
7
8
  import {activeRange, currentRange, filteredEvents, view, viewDates, viewTitle} from './derived.js';
8
9
  import {arrayProxy} from './proxy.svelte.js';
9
10
 
10
11
  export default class State {
11
12
 
12
- #setOption;
13
+ options;
14
+ setOption;
15
+ setViewOptions;
13
16
 
14
17
  constructor(plugins, options) {
15
18
  // Create options state
16
- let {state, setOption, initEffects} = optionsState(this, plugins, options);
17
- this.options = state;
18
- this.#setOption = setOption;
19
+ ([this.options, this.setOption, this.setViewOptions] = optionsState(plugins, options));
19
20
 
20
21
  // Create other states
21
22
  this.auxComponents = $state([]);
22
23
  this.currentRange = $derived.by(currentRange(this));
23
24
  this.activeRange = $derived.by(activeRange(this));
24
25
  this.fetchedRange = $state({events: {}, resources: {}});
25
- this.events = $state.raw(arrayProxy([]));
26
+ this.events = $state.raw(arrayProxy(this.options.events));
26
27
  this.filteredEvents = $derived.by(filteredEvents(this));
27
28
  this.mainEl = $state();
28
29
  this.now = $state(createDate());
29
- this.resources = $state.raw(arrayProxy([]));
30
+ this.resources = $state.raw(arrayProxy(this.options.resources));
30
31
  this.today = $state(setMidnight(createDate()));
31
32
  this.intlEventTime = $derived.by(intlRange(this, 'eventTimeFormat'));
32
33
  this.intlDayHeader = $derived.by(intl(this, 'dayHeaderFormat'));
@@ -49,12 +50,12 @@ export default class State {
49
50
  plugin.initState?.(this);
50
51
  }
51
52
 
52
- initEffects();
53
53
  this.#initEffects();
54
54
  }
55
55
 
56
56
  #initEffects() {
57
- let loading = createLoadingInvoker(this.options);
57
+ let loading = createLoadingInvoker(this);
58
+ $effect.pre(switchView(this));
58
59
  $effect.pre(setNowAndToday(this));
59
60
  $effect(loadEvents(this, loading));
60
61
  $effect(loadResources(this, loading));
@@ -62,14 +63,4 @@ export default class State {
62
63
  $effect(runEventAllUpdated(this));
63
64
  $effect(runViewDidMount(this));
64
65
  }
65
-
66
- setViewComponent(component) {
67
- this.extensions = {};
68
- this.features = [];
69
- this.viewComponent = component(this);
70
- }
71
-
72
- setOption(name, value, parsed = true) {
73
- this.#setOption(name, value, parsed);
74
- }
75
66
  }