@event-calendar/core 3.0.2 → 3.1.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 CHANGED
@@ -4,7 +4,7 @@ See [demo](https://vkurko.github.io/calendar/) and [changelog](CHANGELOG.md).
4
4
 
5
5
  Full-sized drag & drop JavaScript event calendar with resource & timeline views:
6
6
 
7
- * Lightweight (34kb [br](https://en.wikipedia.org/wiki/Brotli) compressed)
7
+ * Lightweight (39kb [br](https://en.wikipedia.org/wiki/Brotli) compressed)
8
8
  * Zero-dependency (pre-built bundle)
9
9
  * Used on over 70,000 websites with [Bookly](https://wordpress.org/plugins/bookly-responsive-appointment-booking-tool/)
10
10
 
@@ -115,10 +115,10 @@ Inspired by [FullCalendar](https://fullcalendar.io/), implements similar options
115
115
  - [setOption](#setoption-name-value-)
116
116
  </td><td>
117
117
 
118
- - [getEvents](#getevents)
118
+ - [addEvent](#addevent-event-)
119
119
  - [getEventById](#geteventbyid-id-)
120
+ - [getEvents](#getevents)
120
121
  - [removeEventById](#removeeventbyid-id-)
121
- - [addEvent](#addevent-event-)
122
122
  - [updateEvent](#updateevent-event-)
123
123
  - [refetchEvents](#refetchevents)
124
124
  </td><td>
@@ -126,6 +126,8 @@ Inspired by [FullCalendar](https://fullcalendar.io/), implements similar options
126
126
  - [dateFromPoint](#datefrompoint-x-y-)
127
127
  - [destroy](#destroy)
128
128
  - [getView](#getview)
129
+ - [next](#next)
130
+ - [prev](#prev)
129
131
  - [unselect](#unselect-1)
130
132
  </td></tr>
131
133
  </table>
@@ -202,8 +204,8 @@ import '@event-calendar/core/index.css';
202
204
  ### Pre-built browser ready bundle
203
205
  Include the following lines of code in the `<head>` section of your page:
204
206
  ```html
205
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@event-calendar/build@3.0.2/event-calendar.min.css">
206
- <script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@3.0.2/event-calendar.min.js"></script>
207
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@event-calendar/build@3.1.0/event-calendar.min.css">
208
+ <script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@3.1.0/event-calendar.min.js"></script>
207
209
  ```
208
210
 
209
211
  <details>
@@ -292,21 +294,21 @@ When hidden with `false`, all-day events will not be displayed in `timeGrid`/`re
292
294
 
293
295
  ### buttonText
294
296
  - Type `object` or `function`
295
- - Default `{close: 'Close', dayGridMonth: 'month', listDay: 'list', listMonth: 'list', listWeek: 'list', listYear: 'list', resourceTimelineDay: 'timeline', resourceTimelineWeek: 'timeline', resourceTimeGridDay: 'resources', resourceTimeGridWeek: 'resources', timeGridDay: 'day', timeGridWeek: 'week', today: 'today'}`
297
+ - Default `{close: 'Close', dayGridMonth: 'month', listDay: 'list', listMonth: 'list', listWeek: 'list', listYear: 'list', resourceTimeGridDay: 'resources', resourceTimeGridWeek: 'resources', resourceTimelineDay: 'timeline', resourceTimelineMonth: 'timeline', resourceTimelineWeek: 'timeline', timeGridDay: 'day', timeGridWeek: 'week', today: 'today'}`
296
298
  > Views override the default value as follows:
297
299
  > - dayGridMonth `text => ({...text, next: 'Next month', prev: 'Previous month'})`
298
300
  > - listDay `text => ({...text, next: 'Next day', prev: 'Previous day'})`
299
301
  > - listMonth `text => ({...text, next: 'Next month', prev: 'Previous month'})`
300
302
  > - listWeek `text => ({...text, next: 'Next week', prev: 'Previous week'})`
301
303
  > - listYear `text => ({...text, next: 'Next year', prev: 'Previous year'})`
302
- > - resourceTimelineDay `text => ({...text, next: 'Next day', prev: 'Previous day'})`
303
- > - resourceTimelineWeek `text => ({...text, next: 'Next week', prev: 'Previous week'})`
304
304
  > - resourceTimeGridDay `text => ({...text, next: 'Next day', prev: 'Previous day'})`
305
305
  > - resourceTimeGridWeek `text => ({...text, next: 'Next week', prev: 'Previous week'})`
306
+ > - resourceTimelineDay `text => ({...text, next: 'Next day', prev: 'Previous day'})`
307
+ > - resourceTimelineMonth `text => ({...text, next: 'Next month', prev: 'Previous month'})`
308
+ > - resourceTimelineWeek `text => ({...text, next: 'Next week', prev: 'Previous week'})`
306
309
  > - timeGridDay `text => ({...text, next: 'Next day', prev: 'Previous day'})`
307
310
  > - timeGridWeek `text => ({...text, next: 'Next week', prev: 'Previous week'})`
308
311
 
309
-
310
312
  Text that is displayed in buttons of the header toolbar.
311
313
 
312
314
  This value can be either a plain object with all necessary properties, or a callback function that receives default button text object and should return a new one:
@@ -538,8 +540,6 @@ function (date) {
538
540
  - Default `{dateStyle: 'long'}`
539
541
  > Views override the default value as follows:
540
542
  > - dayGridMonth `{weekday: 'long'}`
541
- > - resourceTimelineDay `{dateStyle: 'long', timeStyle: 'short'}`
542
- > - resourceTimelineWeek `{dateStyle: 'long', timeStyle: 'short'}`
543
543
 
544
544
  Defines the text that is used inside the `aria-label` attribute in calendar column headings.
545
545
 
@@ -565,6 +565,7 @@ function (date) {
565
565
  - Default `{weekday: 'short', month: 'numeric', day: 'numeric'}`
566
566
  > Views override the default value as follows:
567
567
  > - dayGridMonth `{weekday: 'short'}`
568
+ > - resourceTimelineMonth `{weekday: 'short', day: 'numeric'}`
568
569
  > - timeGridDay `{weekday: 'long'}`
569
570
 
570
571
  Defines the text that is displayed on the calendar’s column headings.
@@ -614,6 +615,9 @@ function (date) {
614
615
  - Default `true`
615
616
  > Views override the default value as follows:
616
617
  > - dayGridMonth `false`
618
+ > - resourceTimelineDay `false`
619
+ > - resourceTimelineMonth `false`
620
+ > - resourceTimelineWeek `false`
617
621
 
618
622
  Determines whether to display an event’s end time.
619
623
 
@@ -632,8 +636,9 @@ Determines whether the calendar should automatically scroll during the event dra
632
636
  > - listDay `{days: 1}`
633
637
  > - listMonth `{months: 1}`
634
638
  > - listYear `{years: 1}`
635
- > - resourceTimelineDay `{days: 1}`
636
639
  > - resourceTimeGridDay `{days: 1}`
640
+ > - resourceTimelineDay `{days: 1}`
641
+ > - resourceTimelineMonth `{months: 1}`
637
642
  > - timeGridDay `{days: 1}`
638
643
 
639
644
  Sets the duration of a view.
@@ -1691,7 +1696,7 @@ function (isLoading) { }
1691
1696
  - Type `string`
1692
1697
  - Default `undefined`
1693
1698
 
1694
- Defines the `locales` parameter for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object that the Event Calendar uses to format date and time strings in options such as [dayHeaderFormat](#dayheaderformat), [eventTimeFormat](#eventtimeformat), etc.
1699
+ Defines the `locales` parameter for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#locales) object that the Event Calendar uses to format date and time strings in options such as [dayHeaderFormat](#dayheaderformat), [eventTimeFormat](#eventtimeformat), etc.
1695
1700
 
1696
1701
  ### longPressDelay
1697
1702
  - Type `integer`
@@ -1990,6 +1995,8 @@ This should be a value that can be parsed into a [Duration](#duration-object) ob
1990
1995
  ### slotDuration
1991
1996
  - Type `string`, `integer` or `object`
1992
1997
  - Default `'00:30:00'`
1998
+ > Views override the default value as follows:
1999
+ > - resourceTimelineMonth `{days: 1}`
1993
2000
 
1994
2001
  Defines the frequency for displaying time slots.
1995
2002
 
@@ -2077,6 +2084,9 @@ Defines the time slot width in pixels in `ResourceTimeline` views. When changing
2077
2084
  > - listYear `theme => ({...theme, view: 'ec-list ec-year-view'})`
2078
2085
  > - resourceTimeGridDay `theme => ({...theme, view: 'ec-time-grid ec-resource-day-view'})`
2079
2086
  > - resourceTimeGridWeek `theme => ({...theme, view: 'ec-time-grid ec-resource-week-view'})`
2087
+ > - resourceTimelineDay `theme => ({...theme, view: 'ec-timeline ec-resource-day-view'})`
2088
+ > - resourceTimelineMonth `theme => ({...theme, view: 'ec-timeline ec-resource-month-view'})`
2089
+ > - resourceTimelineWeek `theme => ({...theme, view: 'ec-timeline ec-resource-week-view'})`
2080
2090
  > - timeGridDay `theme => ({...theme, view: 'ec-time-grid ec-day-view'})`
2081
2091
  > - timeGridWeek `theme => ({...theme, view: 'ec-time-grid ec-week-view'})`
2082
2092
 
@@ -2194,7 +2204,7 @@ Clicking on elements that match this CSS selector will prevent the current selec
2194
2204
  - Type `string`
2195
2205
  - Default `'resourceTimeGridWeek'`
2196
2206
 
2197
- The view that is displayed in the calendar. Can be `'dayGridMonth'`, `'listDay'`, `'listWeek'`, `'listMonth'`, `'listYear'`, `'resourceTimelineDay'`, `'resourceTimelineWeek'`, `'resourceTimeGridDay'`, `'resourceTimeGridWeek'`, `'timeGridDay'` or `'timeGridWeek'`.
2207
+ The view that is displayed in the calendar. Can be `'dayGridMonth'`, `'listDay'`, `'listWeek'`, `'listMonth'`, `'listYear'`, `'resourceTimeGridDay'`, `'resourceTimeGridWeek'`, `'resourceTimelineDay'`, `'resourceTimelineWeek'`, `'resourceTimelineMonth'`, `'timeGridDay'` or `'timeGridWeek'`.
2198
2208
 
2199
2209
  ### viewDidMount
2200
2210
  - Type `function`
@@ -2277,10 +2287,13 @@ This method allows you to set new value to any calendar option.
2277
2287
  // E.g. Change the current date
2278
2288
  ec.setOption('date', new Date());
2279
2289
  ```
2280
- ### getEvents()
2281
- - Return value `Event[]` Array of [Event](#event-object) objects
2282
2290
 
2283
- Returns an array of events that the calendar has in memory.
2291
+ ### addEvent( event )
2292
+ - Parameters
2293
+ - `event` `object` A plain object that will be parsed into an [Event](#event-object) object
2294
+ - Return value [Event](#event-object) object or `null`
2295
+
2296
+ Adds a new event to the calendar.
2284
2297
 
2285
2298
  ### getEventById( id )
2286
2299
  - Parameters
@@ -2289,6 +2302,11 @@ Returns an array of events that the calendar has in memory.
2289
2302
 
2290
2303
  Returns a single event with the matching `id`.
2291
2304
 
2305
+ ### getEvents()
2306
+ - Return value `Event[]` Array of [Event](#event-object) objects
2307
+
2308
+ Returns an array of events that the calendar has in memory.
2309
+
2292
2310
  ### removeEventById( id )
2293
2311
  - Parameters
2294
2312
  - `id` `string|integer` The ID of the event
@@ -2296,13 +2314,6 @@ Returns a single event with the matching `id`.
2296
2314
 
2297
2315
  Removes a single event with the matching `id`.
2298
2316
 
2299
- ### addEvent( event )
2300
- - Parameters
2301
- - `event` `object` A plain object that will be parsed into an [Event](#event-object) object
2302
- - Return value [Event](#event-object) object or `null`
2303
-
2304
- Adds a new event to the calendar.
2305
-
2306
2317
  ### updateEvent( event )
2307
2318
  - Parameters
2308
2319
  - `event` `object` A plain object or [Event](#event-object) object
@@ -2369,6 +2380,16 @@ Destroys the calendar, removing all DOM elements, event handlers, and internal d
2369
2380
 
2370
2381
  Returns the [View](#view-object) object for the current view.
2371
2382
 
2383
+ ### next()
2384
+ - Return value `EventCalendar` The calendar instance for chaining
2385
+
2386
+ Moves the current calendar date forward by 1 day/week/month (depending on the current view).
2387
+
2388
+ ### prev()
2389
+ - Return value `EventCalendar` The calendar instance for chaining
2390
+
2391
+ Moves the current calendar date backward by 1 day/week/month (depending on the current view).
2392
+
2372
2393
  ### unselect()
2373
2394
  - Return value `EventCalendar` The calendar instance for chaining
2374
2395
 
package/index.css CHANGED
@@ -112,21 +112,23 @@
112
112
  }
113
113
  .ec-timeline .ec-times {
114
114
  display: flex;
115
- border-style: solid none none;
115
+ border-top: 1px solid var(--ec-border-color);
116
116
  }
117
117
  .ec-timeline .ec-time {
118
118
  border-left: 1px solid var(--ec-border-color);
119
119
  box-sizing: border-box;
120
+ font-size: 0.95em;
120
121
  min-height: 24px;
121
122
  overflow: hidden;
122
123
  text-overflow: ellipsis;
123
124
  }
124
125
  .ec-timeline .ec-time, .ec-timeline .ec-line {
125
- width: 52px;
126
+ width: 72px;
126
127
  }
127
128
  .ec-timeline .ec-events {
128
129
  position: relative;
129
130
  height: 100%;
131
+ margin: 0;
130
132
  }
131
133
  .ec-timeline .ec-event {
132
134
  position: absolute;
@@ -356,7 +358,6 @@
356
358
  .ec-body,
357
359
  .ec-days,
358
360
  .ec-day,
359
- .ec-times,
360
361
  .ec-day-head {
361
362
  border: 1px solid var(--ec-border-color);
362
363
  }
package/index.js CHANGED
@@ -179,6 +179,27 @@ function toSeconds(duration, defaultValue = 0) {
179
179
  return duration?.seconds ?? defaultValue;
180
180
  }
181
181
 
182
+ /**
183
+ * Move the date forward (when pressing the next button)
184
+ */
185
+ function nextDate(date, duration) {
186
+ addDuration(date, duration);
187
+ return date;
188
+ }
189
+
190
+ /**
191
+ * Move the date backward (when pressing the prev button)
192
+ */
193
+ function prevDate(date, duration, hiddenDays) {
194
+ subtractDuration(date, duration);
195
+ if (hiddenDays.length && hiddenDays.length < 7) {
196
+ while (hiddenDays.includes(date.getUTCDay())) {
197
+ subtractDay(date);
198
+ }
199
+ }
200
+ return date;
201
+ }
202
+
182
203
  /**
183
204
  * Private functions
184
205
  */
@@ -732,7 +753,7 @@ function viewResources(state) {
732
753
  );
733
754
  }
734
755
 
735
- function createTimes(date, $slotDuration, $_slotTimeLimits, $_intlSlotLabel, $_intlDayHeaderAL) {
756
+ function createTimes(date, $slotDuration, $_slotTimeLimits, $_intlSlotLabel) {
736
757
  date = cloneDate(date);
737
758
  let compact = $slotDuration.seconds < 3600;
738
759
  let times = [];
@@ -744,8 +765,7 @@ function createTimes(date, $slotDuration, $_slotTimeLimits, $_intlSlotLabel, $_i
744
765
  times.push([
745
766
  toISOString(date),
746
767
  $_intlSlotLabel.format(date),
747
- times.length && (i || !compact),
748
- $_intlDayHeaderAL && $_intlDayHeaderAL.format(date)
768
+ times.length && (i || !compact)
749
769
  ]);
750
770
  addDuration(date, $slotDuration);
751
771
  i = 1 - i;
@@ -811,7 +831,7 @@ function createOptions(plugins) {
811
831
  day: 'numeric'
812
832
  },
813
833
  dayHeaderAriaLabelFormat: {
814
- dateStyle: 'long'
834
+ dateStyle: 'full'
815
835
  },
816
836
  displayEventEnd: true,
817
837
  duration: {weeks: 1},
@@ -860,7 +880,7 @@ function createOptions(plugins) {
860
880
  },
861
881
  slotMaxTime: '24:00:00',
862
882
  slotMinTime: '00:00:00',
863
- slotWidth: 52,
883
+ slotWidth: 72,
864
884
  theme: {
865
885
  allDay: 'ec-all-day',
866
886
  active: 'ec-active',
@@ -956,6 +976,10 @@ function dayGrid(state) {
956
976
  return derived(state.view, $view => $view?.startsWith('dayGrid'));
957
977
  }
958
978
 
979
+ function monthView(state) {
980
+ return derived(state.view, $view => $view?.includes('Month'));
981
+ }
982
+
959
983
  function activeRange(state) {
960
984
  return derived(
961
985
  [state._currentRange, state.firstDay, state.slotMaxTime, state._dayGrid],
@@ -982,10 +1006,10 @@ function activeRange(state) {
982
1006
 
983
1007
  function currentRange(state) {
984
1008
  return derived(
985
- [state.date, state.duration, state.firstDay, state._dayGrid],
986
- ([$date, $duration, $firstDay, $_dayGrid]) => {
1009
+ [state.date, state.duration, state.firstDay, state._monthView],
1010
+ ([$date, $duration, $firstDay, $_monthView]) => {
987
1011
  let start = cloneDate($date), end;
988
- if ($_dayGrid) {
1012
+ if ($_monthView) {
989
1013
  start.setUTCDate(1);
990
1014
  } else if ($duration.inWeeks) {
991
1015
  // First day of week
@@ -1164,6 +1188,7 @@ class State {
1164
1188
  this._tasks = new Map(); // timeout IDs for tasks
1165
1189
  this._auxiliary = writable([]); // auxiliary components
1166
1190
  this._dayGrid = dayGrid(this);
1191
+ this._monthView = monthView(this);
1167
1192
  this._currentRange = currentRange(this);
1168
1193
  this._activeRange = activeRange(this);
1169
1194
  this._fetchedRange = writable({start: undefined, end: undefined});
@@ -1306,7 +1331,7 @@ function validKey(key, state) {
1306
1331
  return state.hasOwnProperty(key) && key[0] !== '_';
1307
1332
  }
1308
1333
 
1309
- /* packages/core/src/Buttons.svelte generated by Svelte v4.2.16 */
1334
+ /* packages/core/src/Buttons.svelte generated by Svelte v4.2.18 */
1310
1335
 
1311
1336
  function get_each_context$2(ctx, list, i) {
1312
1337
  const child_ctx = ctx.slice();
@@ -1314,7 +1339,7 @@ function get_each_context$2(ctx, list, i) {
1314
1339
  return child_ctx;
1315
1340
  }
1316
1341
 
1317
- // (57:27)
1342
+ // (51:27)
1318
1343
  function create_if_block_5(ctx) {
1319
1344
  let button_1;
1320
1345
  let t_value = /*$buttonText*/ ctx[5][/*button*/ ctx[25]] + "";
@@ -1366,7 +1391,7 @@ function create_if_block_5(ctx) {
1366
1391
  };
1367
1392
  }
1368
1393
 
1369
- // (52:37)
1394
+ // (46:37)
1370
1395
  function create_if_block_4(ctx) {
1371
1396
  let button_1;
1372
1397
  let t_value = /*$customButtons*/ ctx[6][/*button*/ ctx[25]].text + "";
@@ -1412,7 +1437,7 @@ function create_if_block_4(ctx) {
1412
1437
  };
1413
1438
  }
1414
1439
 
1415
- // (46:32)
1440
+ // (40:32)
1416
1441
  function create_if_block_3(ctx) {
1417
1442
  let button_1;
1418
1443
  let t_value = /*$buttonText*/ ctx[5][/*button*/ ctx[25]] + "";
@@ -1459,7 +1484,7 @@ function create_if_block_3(ctx) {
1459
1484
  };
1460
1485
  }
1461
1486
 
1462
- // (39:31)
1487
+ // (33:31)
1463
1488
  function create_if_block_2(ctx) {
1464
1489
  let button_1;
1465
1490
  let i;
@@ -1516,7 +1541,7 @@ function create_if_block_2(ctx) {
1516
1541
  };
1517
1542
  }
1518
1543
 
1519
- // (32:31)
1544
+ // (26:31)
1520
1545
  function create_if_block_1(ctx) {
1521
1546
  let button_1;
1522
1547
  let i;
@@ -1573,7 +1598,7 @@ function create_if_block_1(ctx) {
1573
1598
  };
1574
1599
  }
1575
1600
 
1576
- // (29:4) {#if button == 'title'}
1601
+ // (23:4) {#if button == 'title'}
1577
1602
  function create_if_block$1(ctx) {
1578
1603
  let h2;
1579
1604
  let h2_class_value;
@@ -1612,7 +1637,7 @@ function create_if_block$1(ctx) {
1612
1637
  };
1613
1638
  }
1614
1639
 
1615
- // (28:0) {#each buttons as button}
1640
+ // (22:0) {#each buttons as button}
1616
1641
  function create_each_block$2(ctx) {
1617
1642
  let if_block_anchor;
1618
1643
 
@@ -1748,19 +1773,11 @@ function instance$3($$self, $$props, $$invalidate) {
1748
1773
  let today = setMidnight(createDate()), isToday;
1749
1774
 
1750
1775
  function prev() {
1751
- let d = subtractDuration($date, $duration);
1752
-
1753
- if ($hiddenDays.length && $hiddenDays.length < 7) {
1754
- while ($hiddenDays.includes(d.getUTCDay())) {
1755
- subtractDay(d);
1756
- }
1757
- }
1758
-
1759
- set_store_value(date, $date = d, $date);
1776
+ set_store_value(date, $date = prevDate($date, $duration, $hiddenDays), $date);
1760
1777
  }
1761
1778
 
1762
1779
  function next() {
1763
- set_store_value(date, $date = addDuration($date, $duration), $date);
1780
+ set_store_value(date, $date = nextDate($date, $duration), $date);
1764
1781
  }
1765
1782
 
1766
1783
  const click_handler = () => set_store_value(date, $date = cloneDate(today), $date);
@@ -1810,7 +1827,7 @@ class Buttons extends SvelteComponent {
1810
1827
  }
1811
1828
  }
1812
1829
 
1813
- /* packages/core/src/Toolbar.svelte generated by Svelte v4.2.16 */
1830
+ /* packages/core/src/Toolbar.svelte generated by Svelte v4.2.18 */
1814
1831
 
1815
1832
  function get_each_context$1(ctx, list, i) {
1816
1833
  const child_ctx = ctx.slice();
@@ -1824,7 +1841,7 @@ function get_each_context_1(ctx, list, i) {
1824
1841
  return child_ctx;
1825
1842
  }
1826
1843
 
1827
- // (28:16) {:else}
1844
+ // (29:16) {:else}
1828
1845
  function create_else_block(ctx) {
1829
1846
  let buttons_1;
1830
1847
  let current;
@@ -1858,7 +1875,7 @@ function create_else_block(ctx) {
1858
1875
  };
1859
1876
  }
1860
1877
 
1861
- // (24:16) {#if buttons.length > 1}
1878
+ // (25:16) {#if buttons.length > 1}
1862
1879
  function create_if_block(ctx) {
1863
1880
  let div;
1864
1881
  let buttons_1;
@@ -1905,7 +1922,7 @@ function create_if_block(ctx) {
1905
1922
  };
1906
1923
  }
1907
1924
 
1908
- // (23:12) {#each sections[key] as buttons}
1925
+ // (24:12) {#each sections[key] as buttons}
1909
1926
  function create_each_block_1(ctx) {
1910
1927
  let current_block_type_index;
1911
1928
  let if_block;
@@ -1978,10 +1995,11 @@ function create_each_block_1(ctx) {
1978
1995
  };
1979
1996
  }
1980
1997
 
1981
- // (21:4) {#each Object.keys(sections) as key}
1998
+ // (22:4) {#each keys(sections) as key}
1982
1999
  function create_each_block$1(ctx) {
1983
2000
  let div;
1984
2001
  let t;
2002
+ let div_class_value;
1985
2003
  let current;
1986
2004
  let each_value_1 = ensure_array_like(/*sections*/ ctx[0][/*key*/ ctx[5]]);
1987
2005
  let each_blocks = [];
@@ -2003,6 +2021,7 @@ function create_each_block$1(ctx) {
2003
2021
  }
2004
2022
 
2005
2023
  t = space();
2024
+ attr(div, "class", div_class_value = "ec-" + /*key*/ ctx[5]);
2006
2025
  },
2007
2026
  m(target, anchor) {
2008
2027
  insert(target, div, anchor);
@@ -2017,7 +2036,7 @@ function create_each_block$1(ctx) {
2017
2036
  current = true;
2018
2037
  },
2019
2038
  p(ctx, dirty) {
2020
- if (dirty & /*$theme, sections, Object*/ 3) {
2039
+ if (dirty & /*$theme, sections*/ 3) {
2021
2040
  each_value_1 = ensure_array_like(/*sections*/ ctx[0][/*key*/ ctx[5]]);
2022
2041
  let i;
2023
2042
 
@@ -2043,6 +2062,10 @@ function create_each_block$1(ctx) {
2043
2062
 
2044
2063
  check_outros();
2045
2064
  }
2065
+
2066
+ if (!current || dirty & /*sections*/ 1 && div_class_value !== (div_class_value = "ec-" + /*key*/ ctx[5])) {
2067
+ attr(div, "class", div_class_value);
2068
+ }
2046
2069
  },
2047
2070
  i(local) {
2048
2071
  if (current) return;
@@ -2076,7 +2099,7 @@ function create_fragment$2(ctx) {
2076
2099
  let nav;
2077
2100
  let nav_class_value;
2078
2101
  let current;
2079
- let each_value = ensure_array_like(Object.keys(/*sections*/ ctx[0]));
2102
+ let each_value = ensure_array_like(keys(/*sections*/ ctx[0]));
2080
2103
  let each_blocks = [];
2081
2104
 
2082
2105
  for (let i = 0; i < each_value.length; i += 1) {
@@ -2109,8 +2132,8 @@ function create_fragment$2(ctx) {
2109
2132
  current = true;
2110
2133
  },
2111
2134
  p(ctx, [dirty]) {
2112
- if (dirty & /*sections, Object, $theme*/ 3) {
2113
- each_value = ensure_array_like(Object.keys(/*sections*/ ctx[0]));
2135
+ if (dirty & /*sections, $theme*/ 3) {
2136
+ each_value = ensure_array_like(keys(/*sections*/ ctx[0]));
2114
2137
  let i;
2115
2138
 
2116
2139
  for (i = 0; i < each_value.length; i += 1) {
@@ -2179,7 +2202,7 @@ function instance$2($$self, $$props, $$invalidate) {
2179
2202
  $$self.$$.update = () => {
2180
2203
  if ($$self.$$.dirty & /*sections, $headerToolbar*/ 17) {
2181
2204
  {
2182
- for (let key of Object.keys(sections)) {
2205
+ for (let key of keys(sections)) {
2183
2206
  $$invalidate(0, sections[key] = $headerToolbar[key].split(' ').map(group => group.split(',')), sections);
2184
2207
  }
2185
2208
  }
@@ -2196,7 +2219,7 @@ class Toolbar extends SvelteComponent {
2196
2219
  }
2197
2220
  }
2198
2221
 
2199
- /* packages/core/src/Auxiliary.svelte generated by Svelte v4.2.16 */
2222
+ /* packages/core/src/Auxiliary.svelte generated by Svelte v4.2.18 */
2200
2223
 
2201
2224
  function get_each_context(ctx, list, i) {
2202
2225
  const child_ctx = ctx.slice();
@@ -2404,7 +2427,7 @@ class Auxiliary extends SvelteComponent {
2404
2427
  }
2405
2428
  }
2406
2429
 
2407
- /* packages/core/src/Calendar.svelte generated by Svelte v4.2.16 */
2430
+ /* packages/core/src/Calendar.svelte generated by Svelte v4.2.18 */
2408
2431
 
2409
2432
  function create_fragment(ctx) {
2410
2433
  let div;
@@ -2459,7 +2482,7 @@ function create_fragment(ctx) {
2459
2482
  current = true;
2460
2483
 
2461
2484
  if (!mounted) {
2462
- dispose = listen(window, "resize", /*recheckScrollable*/ ctx[17]);
2485
+ dispose = listen(window, "resize", /*recheckScrollable*/ ctx[20]);
2463
2486
  mounted = true;
2464
2487
  }
2465
2488
  },
@@ -2535,6 +2558,9 @@ function instance($$self, $$props, $$invalidate) {
2535
2558
  let $_scrollable;
2536
2559
  let $_queue2;
2537
2560
  let $_queue;
2561
+ let $hiddenDays;
2562
+ let $duration;
2563
+ let $date;
2538
2564
  let $_interaction;
2539
2565
  let $_events;
2540
2566
  let $theme;
@@ -2547,15 +2573,18 @@ function instance($$self, $$props, $$invalidate) {
2547
2573
  let component = get_current_component();
2548
2574
  let state = new State(plugins, options);
2549
2575
  setContext('state', state);
2550
- let { _viewComponent, _bodyEl, _interaction, _iClass, _events, _queue, _queue2, _tasks, _scrollable, height, theme, view } = state;
2576
+ let { _viewComponent, _bodyEl, _interaction, _iClass, _events, _queue, _queue2, _tasks, _scrollable, date, duration, hiddenDays, height, theme, view } = state;
2551
2577
  component_subscribe($$self, _viewComponent, value => $$invalidate(5, $_viewComponent = value));
2552
- component_subscribe($$self, _bodyEl, value => $$invalidate(32, $_bodyEl = value));
2553
- component_subscribe($$self, _interaction, value => $$invalidate(35, $_interaction = value));
2578
+ component_subscribe($$self, _bodyEl, value => $$invalidate(37, $_bodyEl = value));
2579
+ component_subscribe($$self, _interaction, value => $$invalidate(43, $_interaction = value));
2554
2580
  component_subscribe($$self, _iClass, value => $$invalidate(2, $_iClass = value));
2555
- component_subscribe($$self, _events, value => $$invalidate(36, $_events = value));
2556
- component_subscribe($$self, _queue, value => $$invalidate(34, $_queue = value));
2557
- component_subscribe($$self, _queue2, value => $$invalidate(33, $_queue2 = value));
2581
+ component_subscribe($$self, _events, value => $$invalidate(44, $_events = value));
2582
+ component_subscribe($$self, _queue, value => $$invalidate(39, $_queue = value));
2583
+ component_subscribe($$self, _queue2, value => $$invalidate(38, $_queue2 = value));
2558
2584
  component_subscribe($$self, _scrollable, value => $$invalidate(0, $_scrollable = value));
2585
+ component_subscribe($$self, date, value => $$invalidate(42, $date = value));
2586
+ component_subscribe($$self, duration, value => $$invalidate(41, $duration = value));
2587
+ component_subscribe($$self, hiddenDays, value => $$invalidate(40, $hiddenDays = value));
2559
2588
  component_subscribe($$self, height, value => $$invalidate(3, $height = value));
2560
2589
  component_subscribe($$self, theme, value => $$invalidate(1, $theme = value));
2561
2590
  component_subscribe($$self, view, value => $$invalidate(4, $view = value));
@@ -2626,10 +2655,7 @@ function instance($$self, $$props, $$invalidate) {
2626
2655
  }
2627
2656
 
2628
2657
  function unselect() {
2629
- if ($_interaction.action) {
2630
- $_interaction.action.unselect();
2631
- }
2632
-
2658
+ $_interaction.action?.unselect();
2633
2659
  return this;
2634
2660
  }
2635
2661
 
@@ -2642,6 +2668,16 @@ function instance($$self, $$props, $$invalidate) {
2642
2668
  destroy_component(component, true);
2643
2669
  }
2644
2670
 
2671
+ function next() {
2672
+ set_store_value(date, $date = nextDate($date, $duration), $date);
2673
+ return this;
2674
+ }
2675
+
2676
+ function prev() {
2677
+ set_store_value(date, $date = prevDate($date, $duration, $hiddenDays), $date);
2678
+ return this;
2679
+ }
2680
+
2645
2681
  beforeUpdate(() => {
2646
2682
  flushDebounce($_queue);
2647
2683
  });
@@ -2658,12 +2694,12 @@ function instance($$self, $$props, $$invalidate) {
2658
2694
  }
2659
2695
 
2660
2696
  $$self.$$set = $$props => {
2661
- if ('plugins' in $$props) $$invalidate(18, plugins = $$props.plugins);
2662
- if ('options' in $$props) $$invalidate(19, options = $$props.options);
2697
+ if ('plugins' in $$props) $$invalidate(21, plugins = $$props.plugins);
2698
+ if ('options' in $$props) $$invalidate(22, options = $$props.options);
2663
2699
  };
2664
2700
 
2665
2701
  $$self.$$.update = () => {
2666
- if ($$self.$$.dirty[0] & /*options*/ 524288) {
2702
+ if ($$self.$$.dirty[0] & /*options*/ 4194304) {
2667
2703
  for (let [name, value] of diff(options, prevOptions)) {
2668
2704
  setOption(name, value);
2669
2705
  }
@@ -2685,6 +2721,9 @@ function instance($$self, $$props, $$invalidate) {
2685
2721
  _queue,
2686
2722
  _queue2,
2687
2723
  _scrollable,
2724
+ date,
2725
+ duration,
2726
+ hiddenDays,
2688
2727
  height,
2689
2728
  theme,
2690
2729
  view,
@@ -2702,7 +2741,9 @@ function instance($$self, $$props, $$invalidate) {
2702
2741
  getView,
2703
2742
  unselect,
2704
2743
  dateFromPoint,
2705
- destroy
2744
+ destroy,
2745
+ next,
2746
+ prev
2706
2747
  ];
2707
2748
  }
2708
2749
 
@@ -2717,20 +2758,22 @@ class Calendar extends SvelteComponent {
2717
2758
  create_fragment,
2718
2759
  safe_not_equal,
2719
2760
  {
2720
- plugins: 18,
2721
- options: 19,
2722
- setOption: 20,
2723
- getOption: 21,
2724
- refetchEvents: 22,
2725
- getEvents: 23,
2726
- getEventById: 24,
2727
- addEvent: 25,
2728
- updateEvent: 26,
2729
- removeEventById: 27,
2730
- getView: 28,
2731
- unselect: 29,
2732
- dateFromPoint: 30,
2733
- destroy: 31
2761
+ plugins: 21,
2762
+ options: 22,
2763
+ setOption: 23,
2764
+ getOption: 24,
2765
+ refetchEvents: 25,
2766
+ getEvents: 26,
2767
+ getEventById: 27,
2768
+ addEvent: 28,
2769
+ updateEvent: 29,
2770
+ removeEventById: 30,
2771
+ getView: 31,
2772
+ unselect: 32,
2773
+ dateFromPoint: 33,
2774
+ destroy: 34,
2775
+ next: 35,
2776
+ prev: 36
2734
2777
  },
2735
2778
  null,
2736
2779
  [-1, -1]
@@ -2738,52 +2781,60 @@ class Calendar extends SvelteComponent {
2738
2781
  }
2739
2782
 
2740
2783
  get setOption() {
2741
- return this.$$.ctx[20];
2784
+ return this.$$.ctx[23];
2742
2785
  }
2743
2786
 
2744
2787
  get getOption() {
2745
- return this.$$.ctx[21];
2788
+ return this.$$.ctx[24];
2746
2789
  }
2747
2790
 
2748
2791
  get refetchEvents() {
2749
- return this.$$.ctx[22];
2792
+ return this.$$.ctx[25];
2750
2793
  }
2751
2794
 
2752
2795
  get getEvents() {
2753
- return this.$$.ctx[23];
2796
+ return this.$$.ctx[26];
2754
2797
  }
2755
2798
 
2756
2799
  get getEventById() {
2757
- return this.$$.ctx[24];
2800
+ return this.$$.ctx[27];
2758
2801
  }
2759
2802
 
2760
2803
  get addEvent() {
2761
- return this.$$.ctx[25];
2804
+ return this.$$.ctx[28];
2762
2805
  }
2763
2806
 
2764
2807
  get updateEvent() {
2765
- return this.$$.ctx[26];
2808
+ return this.$$.ctx[29];
2766
2809
  }
2767
2810
 
2768
2811
  get removeEventById() {
2769
- return this.$$.ctx[27];
2812
+ return this.$$.ctx[30];
2770
2813
  }
2771
2814
 
2772
2815
  get getView() {
2773
- return this.$$.ctx[28];
2816
+ return this.$$.ctx[31];
2774
2817
  }
2775
2818
 
2776
2819
  get unselect() {
2777
- return this.$$.ctx[29];
2820
+ return this.$$.ctx[32];
2778
2821
  }
2779
2822
 
2780
2823
  get dateFromPoint() {
2781
- return this.$$.ctx[30];
2824
+ return this.$$.ctx[33];
2782
2825
  }
2783
2826
 
2784
2827
  get destroy() {
2785
- return this.$$.ctx[31];
2828
+ return this.$$.ctx[34];
2829
+ }
2830
+
2831
+ get next() {
2832
+ return this.$$.ctx[35];
2833
+ }
2834
+
2835
+ get prev() {
2836
+ return this.$$.ctx[36];
2786
2837
  }
2787
2838
  }
2788
2839
 
2789
- export { DAY_IN_SECONDS, addDay, addDuration, ancestor, assign, bgEvent, btnTextDay, btnTextMonth, btnTextWeek, btnTextYear, ceil, cloneDate, cloneEvent, copyTime, createDate, createDuration, createElement, createEventChunk, createEventClasses, createEventContent, createEventSources, createEvents, createResources, createSlotTimeLimits, createTimes, createView, datesEqual, debounce, Calendar as default, eventIntersects, floor, flushDebounce, getElementWithPayload, getPayload, ghostEvent, hasPayload, hasYScroll, height, helperEvent, intl, intlRange, keyEnter, keys, listView, max, min, nextClosestDay, noTimePart, outsideEvent, pointerEvent, prepareEventChunks, prevClosestDay, previewEvent, rect, repositionEvent, runReposition, setContent, setMidnight, setPayload, sortEventChunks, subtractDay, subtractDuration, symbol, task, themeView, timelineView, toEventWithLocalDates, toISOString, toLocalDate, toSeconds, toViewWithLocalDates, viewResources };
2840
+ export { DAY_IN_SECONDS, addDay, addDuration, ancestor, assign, bgEvent, btnTextDay, btnTextMonth, btnTextWeek, btnTextYear, ceil, cloneDate, cloneEvent, copyTime, createDate, createDuration, createElement, createEventChunk, createEventClasses, createEventContent, createEventSources, createEvents, createResources, createSlotTimeLimits, createTimes, createView, datesEqual, debounce, Calendar as default, eventIntersects, floor, flushDebounce, getElementWithPayload, getPayload, ghostEvent, hasPayload, hasYScroll, height, helperEvent, intl, intlRange, keyEnter, keys, listView, max, min, nextClosestDay, nextDate, noTimePart, outsideEvent, pointerEvent, prepareEventChunks, prevClosestDay, prevDate, previewEvent, rect, repositionEvent, runReposition, setContent, setMidnight, setPayload, sortEventChunks, subtractDay, subtractDuration, symbol, task, themeView, timelineView, toEventWithLocalDates, toISOString, toLocalDate, toSeconds, toViewWithLocalDates, viewResources };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event-calendar/core",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "title": "Event Calendar Core package",
5
5
  "description": "Full-sized drag & drop event calendar with resource & timeline views",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
- import {createDate, cloneDate, subtractDay, addDuration, setContent, subtractDuration, setMidnight} from './lib.js';
3
+ import {createDate, cloneDate, setContent, setMidnight, nextDate, prevDate} from './lib.js';
4
4
 
5
5
  export let buttons;
6
6
 
@@ -11,17 +11,11 @@
11
11
  $: isToday = today >= $_currentRange.start && today < $_currentRange.end || null;
12
12
 
13
13
  function prev() {
14
- let d = subtractDuration($date, $duration);
15
- if ($hiddenDays.length && $hiddenDays.length < 7) {
16
- while ($hiddenDays.includes(d.getUTCDay())) {
17
- subtractDay(d);
18
- }
19
- }
20
- $date = d;
14
+ $date = prevDate($date, $duration, $hiddenDays);
21
15
  }
22
16
 
23
17
  function next() {
24
- $date = addDuration($date, $duration);
18
+ $date = nextDate($date, $duration);
25
19
  }
26
20
  </script>
27
21
 
@@ -18,7 +18,7 @@
18
18
  flushDebounce,
19
19
  hasYScroll,
20
20
  listView,
21
- task
21
+ task, prevDate, nextDate
22
22
  } from './lib.js';
23
23
 
24
24
  export let plugins = [];
@@ -29,7 +29,8 @@
29
29
  let state = new State(plugins, options);
30
30
  setContext('state', state);
31
31
 
32
- let {_viewComponent, _bodyEl, _interaction, _iClass, _events, _queue, _queue2, _tasks, _scrollable, height, theme, view} = state;
32
+ let {_viewComponent, _bodyEl, _interaction, _iClass, _events, _queue, _queue2, _tasks, _scrollable,
33
+ date, duration, hiddenDays, height, theme, view} = state;
33
34
 
34
35
  // Reactively update options that did change
35
36
  let prevOptions = {...options};
@@ -96,9 +97,7 @@
96
97
  }
97
98
 
98
99
  export function unselect() {
99
- if ($_interaction.action) {
100
- $_interaction.action.unselect();
101
- }
100
+ $_interaction.action?.unselect();
102
101
  return this;
103
102
  }
104
103
 
@@ -111,6 +110,16 @@
111
110
  destroy_component(component, true);
112
111
  }
113
112
 
113
+ export function next() {
114
+ $date = nextDate($date, $duration);
115
+ return this;
116
+ }
117
+
118
+ export function prev() {
119
+ $date = prevDate($date, $duration, $hiddenDays);
120
+ return this;
121
+ }
122
+
114
123
  beforeUpdate(() => {
115
124
  flushDebounce($_queue);
116
125
  });
@@ -1,5 +1,6 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
+ import {keys} from './lib.js';
3
4
  import Buttons from './Buttons.svelte';
4
5
 
5
6
  let {headerToolbar, theme} = getContext('state');
@@ -11,15 +12,15 @@
11
12
  };
12
13
 
13
14
  $: {
14
- for (let key of Object.keys(sections)) {
15
+ for (let key of keys(sections)) {
15
16
  sections[key] = $headerToolbar[key].split(' ').map(group => group.split(','));
16
17
  }
17
18
  }
18
19
  </script>
19
20
 
20
21
  <nav class="{$theme.toolbar}">
21
- {#each Object.keys(sections) as key}
22
- <div>
22
+ {#each keys(sections) as key}
23
+ <div class="ec-{key}">
23
24
  {#each sections[key] as buttons}
24
25
  {#if buttons.length > 1}
25
26
  <div class="{$theme.buttonGroup}">
package/src/lib/date.js CHANGED
@@ -130,6 +130,27 @@ export function toSeconds(duration, defaultValue = 0) {
130
130
  return duration?.seconds ?? defaultValue;
131
131
  }
132
132
 
133
+ /**
134
+ * Move the date forward (when pressing the next button)
135
+ */
136
+ export function nextDate(date, duration) {
137
+ addDuration(date, duration);
138
+ return date;
139
+ }
140
+
141
+ /**
142
+ * Move the date backward (when pressing the prev button)
143
+ */
144
+ export function prevDate(date, duration, hiddenDays) {
145
+ subtractDuration(date, duration);
146
+ if (hiddenDays.length && hiddenDays.length < 7) {
147
+ while (hiddenDays.includes(date.getUTCDay())) {
148
+ subtractDay(date);
149
+ }
150
+ }
151
+ return date;
152
+ }
153
+
133
154
  /**
134
155
  * Private functions
135
156
  */
package/src/lib/times.js CHANGED
@@ -3,7 +3,7 @@ import {addDuration, cloneDate, createDuration, DAY_IN_SECONDS, toISOString, toS
3
3
  import {max as maxFn, min as minFn} from './utils.js';
4
4
  import {bgEvent} from './events.js';
5
5
 
6
- export function createTimes(date, $slotDuration, $_slotTimeLimits, $_intlSlotLabel, $_intlDayHeaderAL) {
6
+ export function createTimes(date, $slotDuration, $_slotTimeLimits, $_intlSlotLabel) {
7
7
  date = cloneDate(date);
8
8
  let compact = $slotDuration.seconds < 3600;
9
9
  let times = [];
@@ -15,8 +15,7 @@ export function createTimes(date, $slotDuration, $_slotTimeLimits, $_intlSlotLab
15
15
  times.push([
16
16
  toISOString(date),
17
17
  $_intlSlotLabel.format(date),
18
- times.length && (i || !compact),
19
- $_intlDayHeaderAL && $_intlDayHeaderAL.format(date)
18
+ times.length && (i || !compact)
20
19
  ]);
21
20
  addDuration(date, $slotDuration);
22
21
  i = 1 - i;
@@ -25,7 +25,7 @@ export function createOptions(plugins) {
25
25
  day: 'numeric'
26
26
  },
27
27
  dayHeaderAriaLabelFormat: {
28
- dateStyle: 'long'
28
+ dateStyle: 'full'
29
29
  },
30
30
  displayEventEnd: true,
31
31
  duration: {weeks: 1},
@@ -74,7 +74,7 @@ export function createOptions(plugins) {
74
74
  },
75
75
  slotMaxTime: '24:00:00',
76
76
  slotMinTime: '00:00:00',
77
- slotWidth: 52,
77
+ slotWidth: 72,
78
78
  theme: {
79
79
  allDay: 'ec-all-day',
80
80
  active: 'ec-active',
@@ -5,6 +5,7 @@ import {
5
5
  activeRange,
6
6
  currentRange,
7
7
  dayGrid,
8
+ monthView,
8
9
  events,
9
10
  now,
10
11
  today,
@@ -37,6 +38,7 @@ export default class {
37
38
  this._tasks = new Map(); // timeout IDs for tasks
38
39
  this._auxiliary = writable([]); // auxiliary components
39
40
  this._dayGrid = dayGrid(this);
41
+ this._monthView = monthView(this);
40
42
  this._currentRange = currentRange(this);
41
43
  this._activeRange = activeRange(this);
42
44
  this._fetchedRange = writable({start: undefined, end: undefined});
@@ -22,6 +22,10 @@ export function dayGrid(state) {
22
22
  return derived(state.view, $view => $view?.startsWith('dayGrid'));
23
23
  }
24
24
 
25
+ export function monthView(state) {
26
+ return derived(state.view, $view => $view?.includes('Month'));
27
+ }
28
+
25
29
  export function activeRange(state) {
26
30
  return derived(
27
31
  [state._currentRange, state.firstDay, state.slotMaxTime, state._dayGrid],
@@ -48,10 +52,10 @@ export function activeRange(state) {
48
52
 
49
53
  export function currentRange(state) {
50
54
  return derived(
51
- [state.date, state.duration, state.firstDay, state._dayGrid],
52
- ([$date, $duration, $firstDay, $_dayGrid]) => {
55
+ [state.date, state.duration, state.firstDay, state._monthView],
56
+ ([$date, $duration, $firstDay, $_monthView]) => {
53
57
  let start = cloneDate($date), end;
54
- if ($_dayGrid) {
58
+ if ($_monthView) {
55
59
  start.setUTCDate(1);
56
60
  } else if ($duration.inWeeks) {
57
61
  // First day of week
@@ -140,7 +140,6 @@
140
140
  .ec-body,
141
141
  .ec-days,
142
142
  .ec-day,
143
- .ec-times,
144
143
  .ec-day-head {
145
144
  border: 1px solid var(--ec-border-color);
146
145
  }
@@ -64,24 +64,26 @@
64
64
 
65
65
  .ec-times {
66
66
  display: flex;
67
- border-style: solid none none;
67
+ border-top: 1px solid var(--ec-border-color);;
68
68
  }
69
69
 
70
70
  .ec-time {
71
71
  border-left: 1px solid var(--ec-border-color);
72
72
  box-sizing: border-box;
73
+ font-size: .95em;
73
74
  min-height: 24px;
74
75
  overflow: hidden;
75
76
  text-overflow: ellipsis;
76
77
  }
77
78
 
78
79
  .ec-time, .ec-line {
79
- width: 52px;
80
+ width: 72px;
80
81
  }
81
82
 
82
83
  .ec-events {
83
84
  position: relative;
84
85
  height: 100%;
86
+ margin: 0;
85
87
  }
86
88
 
87
89
  .ec-event {