joplin-plugin-my-calendar 1.2.7 → 1.3.1
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/CHANGELOG.md +14 -0
- package/README.md +17 -7
- package/dist/index.js +0 -7
- package/dist/manifest.json +2 -2
- package/dist/ui/calendar.js +146 -23
- package/dist/ui/mycalendar.css +179 -69
- package/manifest.json +2 -2
- package/package.json +1 -1
- package/publish/com.volodymyroliinyk.joplin.plugin.my-calendar.jpl +0 -0
- package/publish/com.volodymyroliinyk.joplin.plugin.my-calendar.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [1.3.1](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/compare/v1.3.0...v1.3.1) (2026-02-04)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### 🐛 Bug Fixes
|
|
9
|
+
|
|
10
|
+
* eliminate UI flickering and improve mobile initialization ([01d378f](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/01d378f198a416777414c2c4d92627f9b903f58c))
|
|
11
|
+
|
|
12
|
+
## [1.3.0](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/compare/v1.2.7...v1.3.0) (2026-02-04)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### ✨ Features
|
|
16
|
+
|
|
17
|
+
* ui enhancements ([af04211](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/af04211e1efcb8816ebd3decec7da11a74048118))
|
|
18
|
+
|
|
5
19
|
### [1.2.7](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/compare/v1.2.6...v1.2.7) (2026-02-02)
|
|
6
20
|
|
|
7
21
|
|
package/README.md
CHANGED
|
@@ -18,6 +18,8 @@ note-taking app.
|
|
|
18
18
|
## 🌟 Key Features
|
|
19
19
|
|
|
20
20
|
- **Monthly Calendar Grid**: Navigate through months, view event bars, and see your schedule at a glance.
|
|
21
|
+
- **Quick Month-Year Navigation**: Click the month/year header to open a picker and jump instantly to any date in the
|
|
22
|
+
past or future.
|
|
21
23
|
- **Smart Day View**: Click any day to see a detailed list of scheduled events.
|
|
22
24
|
- **Notes as Events**: Any note can become a calendar event simply by adding a small Markdown block.
|
|
23
25
|
- **ICS Import**: Import standard `*.ics` files (from Google Calendar, Outlook, Apple, etc.) directly into your Joplin
|
|
@@ -64,8 +66,8 @@ You don't need to import files to use the calendar. Simply add the following blo
|
|
|
64
66
|
~~~markdown
|
|
65
67
|
```mycalendar-event
|
|
66
68
|
title: Meeting with Team
|
|
67
|
-
start:
|
|
68
|
-
end:
|
|
69
|
+
start: 2026-02-04 10:00+02:00
|
|
70
|
+
end: 2026-02-04 11:30+02:00
|
|
69
71
|
color: #3498db
|
|
70
72
|
location: Conference Room B
|
|
71
73
|
```
|
|
@@ -128,14 +130,14 @@ The calendar supports several ways to specify the time and timezone of your even
|
|
|
128
130
|
Explicitly define the time and its relation to UTC. This time will be automatically converted to your current
|
|
129
131
|
device's timezone.
|
|
130
132
|
```text
|
|
131
|
-
start:
|
|
133
|
+
start: 2026-02-04 10:00+02:00
|
|
132
134
|
```
|
|
133
135
|
|
|
134
136
|
2. **With `tz` Property (IANA)**
|
|
135
137
|
Specify the time and the exact IANA Timezone name. The plugin will handle the conversion based on daylight saving
|
|
136
138
|
rules.
|
|
137
139
|
```text
|
|
138
|
-
start:
|
|
140
|
+
start: 2026-02-04 10:00
|
|
139
141
|
tz: America/Toronto
|
|
140
142
|
```
|
|
141
143
|
|
|
@@ -143,7 +145,7 @@ The calendar supports several ways to specify the time and timezone of your even
|
|
|
143
145
|
If no offset or `tz` is provided, the time is considered "floating" and will be shown exactly as written, regardless
|
|
144
146
|
of the device's timezone settings.
|
|
145
147
|
```text
|
|
146
|
-
start:
|
|
148
|
+
start: 2026-02-04 10:00
|
|
147
149
|
```
|
|
148
150
|
|
|
149
151
|
---
|
|
@@ -189,10 +191,10 @@ Customize your experience in the Joplin Settings (`Tools` > `Options` > `My Cale
|
|
|
189
191
|
|
|
190
192
|
## 👨💻 Development
|
|
191
193
|
|
|
192
|
-
### Commands
|
|
194
|
+
### Commands
|
|
193
195
|
|
|
194
196
|
- `npm run build;`: Compile the project.
|
|
195
|
-
- `npm
|
|
197
|
+
- `npm pack;`: Create the `.jpl` distribution file.
|
|
196
198
|
- `npm test;`: Run the extensive test suite (250+ cases).
|
|
197
199
|
- `npm run lint;`: Check code style and common patterns.
|
|
198
200
|
- `pkill -f jest || true;pkill -f node || true;rm -rf node_modules/.cache;rm -rf ~/.cache/jest;npx jest --clearCache;`:
|
|
@@ -218,6 +220,14 @@ Automates the entire release workflow: bumps version, syncs manifest, tags, push
|
|
|
218
220
|
bash ./scripts/release.sh [patch|minor|major];
|
|
219
221
|
```
|
|
220
222
|
|
|
223
|
+
#### `scripts/update-demo-ics.py`
|
|
224
|
+
|
|
225
|
+
Automatically shifts dates in the demo ICS file to start from today. Useful for refreshing screenshots.
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
./scripts/update-demo-ics.py;
|
|
229
|
+
```
|
|
230
|
+
|
|
221
231
|
### Development Workflow
|
|
222
232
|
|
|
223
233
|
For a detailed guide on branch naming, commit message formats, and the release process, please see the *
|
package/dist/index.js
CHANGED
|
@@ -877,12 +877,6 @@ function registerUiMessageHandlers(joplin, panelId) {
|
|
|
877
877
|
}
|
|
878
878
|
if (msg.name === 'uiReady') {
|
|
879
879
|
yield (0, uiSettings_1.pushUiSettings)(joplin, panelId);
|
|
880
|
-
// Force a redraw so weekStart takes effect immediately.
|
|
881
|
-
// const pm = joplin?.views?.panels?.postMessage;
|
|
882
|
-
// if (typeof pm === 'function') {
|
|
883
|
-
// await pm(panelId, {name: 'redrawMonth'});
|
|
884
|
-
// }
|
|
885
|
-
yield safePostMessage(joplin, panelId, { name: 'redrawMonth' });
|
|
886
880
|
return;
|
|
887
881
|
}
|
|
888
882
|
}));
|
|
@@ -2439,7 +2433,6 @@ function registerCalendarPanelController(joplin, panel, helpers) {
|
|
|
2439
2433
|
switch (msg.name) {
|
|
2440
2434
|
case 'uiReady': {
|
|
2441
2435
|
yield (0, uiSettings_1.pushUiSettings)(joplin, panel);
|
|
2442
|
-
yield post({ name: 'redrawMonth' });
|
|
2443
2436
|
return;
|
|
2444
2437
|
}
|
|
2445
2438
|
case 'requestRangeEvents': {
|
package/dist/manifest.json
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"id": "com.volodymyroliinyk.joplin.plugin.my-calendar",
|
|
4
4
|
"app_min_version": "3.3",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.3.1",
|
|
6
6
|
"name": "My Calendar",
|
|
7
|
-
"description": "Calendar
|
|
7
|
+
"description": "Calendar plugin for Joplin",
|
|
8
8
|
"author": "Volodymyr Oliinyk",
|
|
9
9
|
"homepage_url": "https://github.com/volodymyroliinyk/joplin-plugin-my-calendar",
|
|
10
10
|
"repository_url": "https://github.com/volodymyroliinyk/joplin-plugin-my-calendar",
|
package/dist/ui/calendar.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
(function () {
|
|
4
4
|
// Ensure a single shared settings object across all UI scripts.
|
|
5
5
|
window.__mcUiSettings = window.__mcUiSettings || {
|
|
6
|
-
weekStart: undefined
|
|
7
|
-
debug:
|
|
8
|
-
dayEventsRefreshMinutes:
|
|
6
|
+
weekStart: 'monday', // Default to Monday instead of undefined
|
|
7
|
+
debug: false,
|
|
8
|
+
dayEventsRefreshMinutes: 1,
|
|
9
9
|
showEventTimeline: true,
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -244,6 +244,9 @@
|
|
|
244
244
|
let current = startOfMonthLocal(new Date());
|
|
245
245
|
let selectedDayUtc = localMidnightTs(new Date());
|
|
246
246
|
|
|
247
|
+
let isPickerOpen = false;
|
|
248
|
+
let pickerYear = null;
|
|
249
|
+
|
|
247
250
|
// Events received for the current range of calendar grid (42 days)
|
|
248
251
|
let gridEvents = [];
|
|
249
252
|
|
|
@@ -272,9 +275,10 @@
|
|
|
272
275
|
// Ensure immediate behavior on settings toggle without requiring a full re-render.
|
|
273
276
|
if (hidden) {
|
|
274
277
|
ul.querySelectorAll('.mc-event-timeline').forEach((el) => el.remove());
|
|
278
|
+
ul.querySelectorAll('.mc-events-timeline-now-line-wrap').forEach((el) => el.remove());
|
|
275
279
|
}
|
|
276
280
|
}
|
|
277
|
-
|
|
281
|
+
|
|
278
282
|
function markPastDayEvents() {
|
|
279
283
|
const ul = document.getElementById('mc-events-list');
|
|
280
284
|
if (!ul) return;
|
|
@@ -357,15 +361,16 @@
|
|
|
357
361
|
const inDay = now >= dayStartUtc && now < (dayStartUtc + DAY);
|
|
358
362
|
const pct = Math.max(0, Math.min(100, ((now - dayStartUtc) / DAY) * 100));
|
|
359
363
|
|
|
360
|
-
ul.
|
|
361
|
-
|
|
364
|
+
const line = ul.querySelector('.mc-events-timeline-now-line');
|
|
365
|
+
if (line) {
|
|
366
|
+
const el = /** @type {HTMLElement} */ (line);
|
|
362
367
|
if (!inDay) {
|
|
363
368
|
el.style.display = 'none';
|
|
364
|
-
|
|
369
|
+
} else {
|
|
370
|
+
el.style.display = 'block';
|
|
371
|
+
el.style.left = pct + '%';
|
|
365
372
|
}
|
|
366
|
-
|
|
367
|
-
el.style.left = pct + '%';
|
|
368
|
-
});
|
|
373
|
+
}
|
|
369
374
|
}
|
|
370
375
|
|
|
371
376
|
function scheduleDayNowTimelineTick() {
|
|
@@ -402,7 +407,10 @@
|
|
|
402
407
|
clearTimeout(_uiReadyDebounce);
|
|
403
408
|
_uiReadyDebounce = setTimeout(() => {
|
|
404
409
|
try {
|
|
410
|
+
log('sending uiReady again (visibility/focus)');
|
|
405
411
|
window.webviewApi?.postMessage?.({name: 'uiReady'});
|
|
412
|
+
// Also trigger a redraw to ensure UI is not stuck
|
|
413
|
+
drawMonth();
|
|
406
414
|
} catch (_err) {
|
|
407
415
|
// ignore
|
|
408
416
|
}
|
|
@@ -564,7 +572,7 @@
|
|
|
564
572
|
const firstSettingsArrived = !__mcHasUiSettings;
|
|
565
573
|
__mcHasUiSettings = true;
|
|
566
574
|
|
|
567
|
-
if (
|
|
575
|
+
if (weekStartChanged || (firstSettingsArrived && !gridEvents.length)) {
|
|
568
576
|
drawMonth();
|
|
569
577
|
}
|
|
570
578
|
},
|
|
@@ -591,6 +599,11 @@
|
|
|
591
599
|
log('got rangeEvents:', (msg.events || []).length);
|
|
592
600
|
gridEvents = msg.events || [];
|
|
593
601
|
|
|
602
|
+
if (rangeRequestTimer) {
|
|
603
|
+
clearTimeout(rangeRequestTimer);
|
|
604
|
+
rangeRequestTimer = null;
|
|
605
|
+
}
|
|
606
|
+
|
|
594
607
|
setGridLoading(false);
|
|
595
608
|
|
|
596
609
|
paintGrid();
|
|
@@ -629,6 +642,83 @@
|
|
|
629
642
|
return b;
|
|
630
643
|
}
|
|
631
644
|
|
|
645
|
+
function renderMonthYearPicker() {
|
|
646
|
+
const dropdown = document.createElement('div');
|
|
647
|
+
dropdown.className = 'mc-picker-dropdown';
|
|
648
|
+
dropdown.addEventListener('click', (e) => e.stopPropagation());
|
|
649
|
+
|
|
650
|
+
if (pickerYear === null) {
|
|
651
|
+
pickerYear = current.getFullYear();
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
const yearRow = document.createElement('div');
|
|
655
|
+
yearRow.className = 'mc-picker-year-row';
|
|
656
|
+
|
|
657
|
+
const btnPrevYear = button('‹', 'Previous year', () => {
|
|
658
|
+
pickerYear--;
|
|
659
|
+
renderToolbar();
|
|
660
|
+
});
|
|
661
|
+
const yearLabel = document.createElement('div');
|
|
662
|
+
yearLabel.className = 'mc-picker-year';
|
|
663
|
+
yearLabel.textContent = String(pickerYear);
|
|
664
|
+
const btnNextYear = button('›', 'Next year', () => {
|
|
665
|
+
pickerYear++;
|
|
666
|
+
renderToolbar();
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
yearRow.appendChild(btnPrevYear);
|
|
670
|
+
yearRow.appendChild(yearLabel);
|
|
671
|
+
yearRow.appendChild(btnNextYear);
|
|
672
|
+
dropdown.appendChild(yearRow);
|
|
673
|
+
|
|
674
|
+
const monthsGrid = document.createElement('div');
|
|
675
|
+
monthsGrid.className = 'mc-picker-months';
|
|
676
|
+
|
|
677
|
+
const monthNames = [];
|
|
678
|
+
for (let m = 0; m < 12; m++) {
|
|
679
|
+
const d = new Date(2000, m, 1);
|
|
680
|
+
monthNames.push(d.toLocaleString(undefined, {month: 'short'}));
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
monthNames.forEach((name, idx) => {
|
|
684
|
+
const mBtn = document.createElement('div');
|
|
685
|
+
mBtn.className = 'mc-picker-month';
|
|
686
|
+
if (idx === current.getMonth() && pickerYear === current.getFullYear()) {
|
|
687
|
+
mBtn.classList.add('mc-active');
|
|
688
|
+
}
|
|
689
|
+
mBtn.textContent = name;
|
|
690
|
+
mBtn.addEventListener('click', () => {
|
|
691
|
+
current = new Date(pickerYear, idx, 1);
|
|
692
|
+
isPickerOpen = false;
|
|
693
|
+
pickerYear = null;
|
|
694
|
+
drawMonth();
|
|
695
|
+
});
|
|
696
|
+
monthsGrid.appendChild(mBtn);
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
dropdown.appendChild(monthsGrid);
|
|
700
|
+
|
|
701
|
+
// const footer = document.createElement('div');
|
|
702
|
+
// footer.style.display = 'flex';
|
|
703
|
+
// footer.style.justifyContent = 'center';
|
|
704
|
+
// footer.style.marginTop = '8px';
|
|
705
|
+
// footer.style.paddingTop = '8px';
|
|
706
|
+
// footer.style.borderTop = '1px solid var(--joplin-divider-color)';
|
|
707
|
+
//
|
|
708
|
+
// const btnTodayPicker = button('Go to Today', 'Go to current month', () => {
|
|
709
|
+
// current = startOfMonthLocal(new Date());
|
|
710
|
+
// selectedDayUtc = localMidnightTs(new Date());
|
|
711
|
+
// isPickerOpen = false;
|
|
712
|
+
// pickerYear = null;
|
|
713
|
+
// drawMonth();
|
|
714
|
+
// });
|
|
715
|
+
// btnTodayPicker.style.width = '100%';
|
|
716
|
+
// footer.appendChild(btnTodayPicker);
|
|
717
|
+
// dropdown.appendChild(footer);
|
|
718
|
+
|
|
719
|
+
return dropdown;
|
|
720
|
+
}
|
|
721
|
+
|
|
632
722
|
function renderToolbar() {
|
|
633
723
|
const root = $toolbar();
|
|
634
724
|
if (!root) return;
|
|
@@ -637,15 +727,18 @@
|
|
|
637
727
|
wrap.className = 'mc-toolbar-inner';
|
|
638
728
|
|
|
639
729
|
const btnPrev = button('‹', 'Previous month', () => {
|
|
730
|
+
isPickerOpen = false;
|
|
640
731
|
current = addMonthsLocal(current, -1);
|
|
641
732
|
drawMonth();
|
|
642
733
|
});
|
|
643
734
|
const btnToday = button('Today', 'Today', () => {
|
|
735
|
+
isPickerOpen = false;
|
|
644
736
|
current = startOfMonthLocal(new Date());
|
|
645
737
|
selectedDayUtc = localMidnightTs(new Date());
|
|
646
738
|
drawMonth();
|
|
647
739
|
});
|
|
648
740
|
const btnNext = button('›', 'Next month', () => {
|
|
741
|
+
isPickerOpen = false;
|
|
649
742
|
current = addMonthsLocal(current, +1);
|
|
650
743
|
drawMonth();
|
|
651
744
|
});
|
|
@@ -653,20 +746,40 @@
|
|
|
653
746
|
// Month YYYY title.
|
|
654
747
|
const title = document.createElement('div');
|
|
655
748
|
title.className = 'mc-title';
|
|
656
|
-
title.
|
|
749
|
+
title.id = 'mc-picker-trigger';
|
|
750
|
+
title.innerHTML = `${monthLabel(current)} <span class="mc-picker-arrow">▾</span>`;
|
|
751
|
+
title.addEventListener('click', (e) => {
|
|
752
|
+
e.stopPropagation();
|
|
753
|
+
isPickerOpen = !isPickerOpen;
|
|
754
|
+
if (isPickerOpen) {
|
|
755
|
+
pickerYear = current.getFullYear();
|
|
756
|
+
}
|
|
757
|
+
renderToolbar();
|
|
758
|
+
});
|
|
657
759
|
|
|
658
760
|
wrap.appendChild(btnPrev);
|
|
659
761
|
wrap.appendChild(btnToday);
|
|
660
762
|
wrap.appendChild(btnNext);
|
|
661
763
|
wrap.appendChild(title);
|
|
764
|
+
|
|
765
|
+
if (isPickerOpen) {
|
|
766
|
+
const picker = renderMonthYearPicker();
|
|
767
|
+
title.appendChild(picker);
|
|
768
|
+
}
|
|
769
|
+
|
|
662
770
|
root.appendChild(wrap);
|
|
663
771
|
}
|
|
664
772
|
|
|
665
|
-
|
|
666
|
-
if (
|
|
667
|
-
|
|
668
|
-
|
|
773
|
+
document.addEventListener('click', () => {
|
|
774
|
+
if (isPickerOpen) {
|
|
775
|
+
isPickerOpen = false;
|
|
776
|
+
renderToolbar();
|
|
669
777
|
}
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
function drawMonth() {
|
|
781
|
+
// We no longer skip if weekStart is missing; getWeekdayMeta/startOfCalendarGridLocal have defaults.
|
|
782
|
+
// This ensures the loader and toolbar are visible immediately.
|
|
670
783
|
renderToolbar();
|
|
671
784
|
renderGridSkeleton();
|
|
672
785
|
|
|
@@ -932,6 +1045,15 @@
|
|
|
932
1045
|
return;
|
|
933
1046
|
}
|
|
934
1047
|
|
|
1048
|
+
if (uiSettings.showEventTimeline !== false) {
|
|
1049
|
+
const wrap = document.createElement('div');
|
|
1050
|
+
wrap.className = 'mc-events-timeline-now-line-wrap';
|
|
1051
|
+
const line = document.createElement('div');
|
|
1052
|
+
line.className = 'mc-events-timeline-now-line';
|
|
1053
|
+
wrap.appendChild(line);
|
|
1054
|
+
ul.appendChild(wrap);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
935
1057
|
for (const item of daySlices) {
|
|
936
1058
|
const ev = item.ev;
|
|
937
1059
|
const slice = item.slice;
|
|
@@ -955,7 +1077,7 @@
|
|
|
955
1077
|
li.appendChild(title);
|
|
956
1078
|
li.appendChild(t);
|
|
957
1079
|
|
|
958
|
-
// 24h timeline under the event (segment = event slice
|
|
1080
|
+
// 24h timeline under the event (segment = event slice)
|
|
959
1081
|
if (uiSettings.showEventTimeline !== false) {
|
|
960
1082
|
const timeline = document.createElement('div');
|
|
961
1083
|
timeline.className = 'mc-event-timeline';
|
|
@@ -972,11 +1094,7 @@
|
|
|
972
1094
|
seg.style.left = left + '%';
|
|
973
1095
|
seg.style.width = Math.max(0, (right - left)) + '%';
|
|
974
1096
|
|
|
975
|
-
const nowDot = document.createElement('div');
|
|
976
|
-
nowDot.className = 'mc-event-timeline-now';
|
|
977
|
-
|
|
978
1097
|
timeline.appendChild(seg);
|
|
979
|
-
timeline.appendChild(nowDot);
|
|
980
1098
|
li.appendChild(timeline);
|
|
981
1099
|
}
|
|
982
1100
|
|
|
@@ -1001,10 +1119,15 @@
|
|
|
1001
1119
|
}
|
|
1002
1120
|
|
|
1003
1121
|
// Launch
|
|
1004
|
-
// Ensure backend handshake is not lost on first start
|
|
1122
|
+
// Ensure backend handshake is not lost on first start.
|
|
1123
|
+
// We only show the preliminary skeleton state here to avoid total empty screen.
|
|
1124
|
+
renderToolbar();
|
|
1125
|
+
renderGridSkeleton();
|
|
1126
|
+
setGridLoading(true);
|
|
1127
|
+
|
|
1005
1128
|
ensureBackendReady(() => {
|
|
1129
|
+
// Handshake will trigger uiSettings, which will then trigger full drawMonth()
|
|
1006
1130
|
});
|
|
1007
|
-
drawMonth();
|
|
1008
1131
|
|
|
1009
1132
|
log('init done');
|
|
1010
1133
|
} catch (e) {
|
package/dist/ui/mycalendar.css
CHANGED
|
@@ -1,35 +1,42 @@
|
|
|
1
1
|
/* src/ui/mycalendar.css */
|
|
2
2
|
|
|
3
|
-
html,
|
|
3
|
+
html,
|
|
4
|
+
body {
|
|
4
5
|
height: 100%;
|
|
5
6
|
margin: 0;
|
|
6
7
|
overflow: auto;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
/* TODO:[1]: parent --scrollbar-size is invisible inside of iframe, and size is 7px always. How to solve that? */
|
|
10
|
-
body::-webkit-scrollbar,
|
|
11
|
+
body::-webkit-scrollbar,
|
|
12
|
+
select::-webkit-scrollbar {
|
|
11
13
|
width: var(--scrollbar-size, 7px);
|
|
12
14
|
height: var(--scrollbar-size, 7px);
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
body::-webkit-scrollbar-corner,
|
|
17
|
+
body::-webkit-scrollbar-corner,
|
|
18
|
+
select::-webkit-scrollbar-corner {
|
|
16
19
|
background: none;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
body::-webkit-scrollbar-track,
|
|
22
|
+
body::-webkit-scrollbar-track,
|
|
23
|
+
select::-webkit-scrollbar-track {
|
|
20
24
|
border: none;
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
body::-webkit-scrollbar-thumb,
|
|
27
|
+
body::-webkit-scrollbar-thumb,
|
|
28
|
+
select::-webkit-scrollbar-thumb {
|
|
24
29
|
background: var(--scrollbar-thumb-color);
|
|
25
30
|
border-radius: calc(var(--scrollbar-size, 7px) * 0.7);
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
body::-webkit-scrollbar-track:hover,
|
|
33
|
+
body::-webkit-scrollbar-track:hover,
|
|
34
|
+
select::-webkit-scrollbar-track:hover {
|
|
29
35
|
background: rgba(0, 0, 0, 0.1);
|
|
30
36
|
}
|
|
31
37
|
|
|
32
|
-
body::-webkit-scrollbar-thumb:hover,
|
|
38
|
+
body::-webkit-scrollbar-thumb:hover,
|
|
39
|
+
select::-webkit-scrollbar-thumb:hover {
|
|
33
40
|
background: var(--scrollbar-thumb-color-hover);
|
|
34
41
|
}
|
|
35
42
|
|
|
@@ -37,6 +44,7 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
37
44
|
--scrollbar-thumb-color: var(--joplin-scrollbar-thumb-color);
|
|
38
45
|
--scrollbar-thumb-color-hover: var(--joplin-scrollbar-thumb-color-hover);
|
|
39
46
|
--mc-default-event-color: #1470d9;
|
|
47
|
+
--mc-default-current-time-v-line-color: #ffa334;
|
|
40
48
|
--mc-past-opacity: 0.45;
|
|
41
49
|
/* Subtle weekend highlight (theme-aware) */
|
|
42
50
|
--mc-weekend-head-bg: color-mix(in srgb, var(--joplin-background-color3) 70%, transparent);
|
|
@@ -44,11 +52,6 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
44
52
|
|
|
45
53
|
}
|
|
46
54
|
|
|
47
|
-
/*#joplin-plugin-content-root {*/
|
|
48
|
-
/* min-width: 315px;*/
|
|
49
|
-
/*}*/
|
|
50
|
-
|
|
51
|
-
|
|
52
55
|
/* Outer container that will actually scroll */
|
|
53
56
|
#mc-cal-scroll {
|
|
54
57
|
height: 100%;
|
|
@@ -94,6 +97,102 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
94
97
|
flex: 1;
|
|
95
98
|
}
|
|
96
99
|
|
|
100
|
+
.mc-toolbar-inner .mc-title {
|
|
101
|
+
margin-left: 4px;
|
|
102
|
+
font-weight: 700;
|
|
103
|
+
flex: 1;
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
display: flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
gap: 4px;
|
|
108
|
+
padding: 4px 8px;
|
|
109
|
+
border-radius: 4px;
|
|
110
|
+
transition: background 0.1s;
|
|
111
|
+
user-select: none;
|
|
112
|
+
position: relative;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.mc-toolbar-inner .mc-title:hover {
|
|
116
|
+
background: var(--joplin-background-color3);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.mc-btn.mc-calendar-nav-btn:hover {
|
|
120
|
+
background: var(--joplin-background-color3);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.mc-picker-dropdown {
|
|
124
|
+
position: absolute;
|
|
125
|
+
top: calc(100% + 4px);
|
|
126
|
+
right: 0;
|
|
127
|
+
background: var(--joplin-background-color);
|
|
128
|
+
border: 1px solid var(--joplin-divider-color);
|
|
129
|
+
border-radius: 8px;
|
|
130
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
131
|
+
z-index: 1000;
|
|
132
|
+
padding: 8px;
|
|
133
|
+
min-width: 200px;
|
|
134
|
+
display: flex;
|
|
135
|
+
flex-direction: column;
|
|
136
|
+
gap: 8px;
|
|
137
|
+
animation: mc-fade-in 0.15s ease-out;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@keyframes mc-fade-in {
|
|
141
|
+
from {
|
|
142
|
+
opacity: 0;
|
|
143
|
+
transform: translateY(-4px);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
to {
|
|
147
|
+
opacity: 1;
|
|
148
|
+
transform: translateY(0);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.mc-picker-year-row {
|
|
153
|
+
display: flex;
|
|
154
|
+
align-items: center;
|
|
155
|
+
justify-content: space-between;
|
|
156
|
+
gap: 4px;
|
|
157
|
+
border-bottom: 1px solid var(--joplin-divider-color);
|
|
158
|
+
padding-bottom: 8px;
|
|
159
|
+
margin-bottom: 4px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.mc-picker-year {
|
|
163
|
+
font-size: 14px;
|
|
164
|
+
font-weight: bold;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.mc-picker-months {
|
|
168
|
+
display: grid;
|
|
169
|
+
grid-template-columns: repeat(3, 1fr);
|
|
170
|
+
gap: 4px;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.mc-picker-month {
|
|
174
|
+
padding: 6px;
|
|
175
|
+
font-size: 12px;
|
|
176
|
+
text-align: center;
|
|
177
|
+
border-radius: 4px;
|
|
178
|
+
cursor: pointer;
|
|
179
|
+
transition: background 0.1s;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.mc-picker-month:hover {
|
|
183
|
+
background: var(--joplin-background-color3);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.mc-picker-month.mc-active {
|
|
187
|
+
background: var(--joplin-background-color3);
|
|
188
|
+
color: var(--joplin-color);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.mc-picker-arrow {
|
|
192
|
+
font-size: 10px;
|
|
193
|
+
opacity: 0.6;
|
|
194
|
+
}
|
|
195
|
+
|
|
97
196
|
#mc-grid {
|
|
98
197
|
border: 1px solid var(--joplin-divider-color);
|
|
99
198
|
border-radius: 8px;
|
|
@@ -105,7 +204,8 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
105
204
|
#mc-grid .mc-grid-loader {
|
|
106
205
|
position: absolute;
|
|
107
206
|
inset: 0;
|
|
108
|
-
display: none;
|
|
207
|
+
display: none;
|
|
208
|
+
/* shown via .mc-loading */
|
|
109
209
|
align-items: center;
|
|
110
210
|
justify-content: center;
|
|
111
211
|
background: color-mix(in srgb, var(--joplin-background-color) 70%, transparent);
|
|
@@ -142,7 +242,8 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
142
242
|
}
|
|
143
243
|
}
|
|
144
244
|
|
|
145
|
-
.mc-grid-head,
|
|
245
|
+
.mc-grid-head,
|
|
246
|
+
.mc-grid-body {
|
|
146
247
|
display: grid;
|
|
147
248
|
grid-template-columns: repeat(7, 1fr);
|
|
148
249
|
gap: 4px;
|
|
@@ -208,8 +309,20 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
208
309
|
.mc-grid-body .mc-cell {
|
|
209
310
|
min-width: 0;
|
|
210
311
|
padding: var(--mc-cell-pad-y) var(--mc-cell-pad-x);
|
|
312
|
+
border-right: 1px solid var(--joplin-divider-color);
|
|
313
|
+
border-top: 1px solid var(--joplin-divider-color);
|
|
314
|
+
overflow: hidden;
|
|
211
315
|
}
|
|
212
316
|
|
|
317
|
+
.mc-grid-body .mc-cell.mc-weekend {
|
|
318
|
+
background: var(--mc-weekend-cell-bg);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.mc-grid-body .mc-cell:nth-child(7n) {
|
|
322
|
+
border-right: none;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
|
|
213
326
|
/* Scale typography inside cells */
|
|
214
327
|
.mc-daynum {
|
|
215
328
|
font-size: var(--mc-daynum-font);
|
|
@@ -258,24 +371,6 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
258
371
|
|
|
259
372
|
/*****/
|
|
260
373
|
|
|
261
|
-
.mc-grid-body .mc-cell {
|
|
262
|
-
/*position: relative;*/
|
|
263
|
-
/*min-height: 50px;*/
|
|
264
|
-
border-right: 1px solid var(--joplin-divider-color);
|
|
265
|
-
border-top: 1px solid var(--joplin-divider-color);
|
|
266
|
-
padding: 4px 6px;
|
|
267
|
-
overflow: hidden;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/* Highlight weekends inside the current month only (keep .mc-out styling as-is) */
|
|
271
|
-
.mc-grid-body .mc-cell.mc-weekend:not(.mc-out) {
|
|
272
|
-
background: var(--mc-weekend-cell-bg);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.mc-grid-body .mc-cell:nth-child(7n) {
|
|
276
|
-
border-right: none;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
374
|
.mc-daynum {
|
|
280
375
|
font-size: 12px;
|
|
281
376
|
opacity: 0.8;
|
|
@@ -297,7 +392,7 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
297
392
|
}
|
|
298
393
|
|
|
299
394
|
.mc-out {
|
|
300
|
-
|
|
395
|
+
opacity: 0.6;
|
|
301
396
|
}
|
|
302
397
|
|
|
303
398
|
.mc-today {
|
|
@@ -309,16 +404,6 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
309
404
|
box-shadow: inset 0 0 0 2px var(--joplin-color);
|
|
310
405
|
}
|
|
311
406
|
|
|
312
|
-
/* Past days in the month grid */
|
|
313
|
-
.mc-cell.mc-past {
|
|
314
|
-
opacity: var(--mc-past-opacity);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/* Keep selection slightly more readable even if the day is in the past */
|
|
318
|
-
.mc-cell.mc-past.mc-selected {
|
|
319
|
-
opacity: 0.7;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
407
|
.mc-events-header {
|
|
323
408
|
display: flex;
|
|
324
409
|
align-items: center;
|
|
@@ -332,13 +417,15 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
332
417
|
white-space: nowrap;
|
|
333
418
|
}
|
|
334
419
|
|
|
335
|
-
#mc-events,
|
|
420
|
+
#mc-events,
|
|
421
|
+
#mc-import {
|
|
336
422
|
border: 1px solid var(--joplin-divider-color);
|
|
337
423
|
border-radius: 8px;
|
|
338
424
|
overflow: hidden;
|
|
339
425
|
}
|
|
340
426
|
|
|
341
|
-
.mc-events-header,
|
|
427
|
+
.mc-events-header,
|
|
428
|
+
.mc-import-header {
|
|
342
429
|
background: var(--joplin-background-color3);
|
|
343
430
|
padding: 6px 10px;
|
|
344
431
|
font-size: 12px;
|
|
@@ -349,6 +436,7 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
349
436
|
list-style: none;
|
|
350
437
|
margin: 0;
|
|
351
438
|
padding: 8px 6px;
|
|
439
|
+
position: relative;
|
|
352
440
|
}
|
|
353
441
|
|
|
354
442
|
.mc-event {
|
|
@@ -358,6 +446,8 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
358
446
|
padding: 6px;
|
|
359
447
|
border-radius: 6px;
|
|
360
448
|
cursor: pointer;
|
|
449
|
+
position: relative;
|
|
450
|
+
z-index: 2;
|
|
361
451
|
}
|
|
362
452
|
|
|
363
453
|
.mc-event:hover {
|
|
@@ -384,7 +474,6 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
384
474
|
|
|
385
475
|
/* The container of strips in the cell */
|
|
386
476
|
.mc-bars {
|
|
387
|
-
/*position: absolute;*/
|
|
388
477
|
left: 4px;
|
|
389
478
|
right: 4px;
|
|
390
479
|
bottom: 6px;
|
|
@@ -404,17 +493,16 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
404
493
|
|
|
405
494
|
/* Badge-chiller is up to the right */
|
|
406
495
|
.mc-count {
|
|
407
|
-
/*position: absolute;*/
|
|
408
496
|
top: 2px;
|
|
409
497
|
right: 4px;
|
|
410
498
|
font-size: 14px;
|
|
411
499
|
font-weight: bold;
|
|
412
500
|
text-align: center;
|
|
413
501
|
line-height: 1;
|
|
414
|
-
padding:
|
|
415
|
-
border-radius:
|
|
502
|
+
padding: 3px 4px;
|
|
503
|
+
border-radius: 4px;
|
|
416
504
|
background: var(--joplin-background-color3);
|
|
417
|
-
border:
|
|
505
|
+
border: 0px solid var(--joplin-divider-color);
|
|
418
506
|
opacity: 0.85;
|
|
419
507
|
z-index: 3;
|
|
420
508
|
}
|
|
@@ -424,8 +512,10 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
424
512
|
}
|
|
425
513
|
|
|
426
514
|
.mc-calendar-nav-btn {
|
|
427
|
-
color: var(--joplin-color) !important;
|
|
428
|
-
|
|
515
|
+
color: var(--joplin-color) !important;
|
|
516
|
+
/* make the text white */
|
|
517
|
+
background: transparent;
|
|
518
|
+
/* The background is transparent */
|
|
429
519
|
border: none;
|
|
430
520
|
font-size: 12px;
|
|
431
521
|
font-weight: 700;
|
|
@@ -433,7 +523,8 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
433
523
|
}
|
|
434
524
|
|
|
435
525
|
.mc-calendar-nav-btn:hover {
|
|
436
|
-
color: var(--joplin-color) !important;
|
|
526
|
+
color: var(--joplin-color) !important;
|
|
527
|
+
/* lighter when creeping */
|
|
437
528
|
}
|
|
438
529
|
|
|
439
530
|
/* --- Events panel layout: list scroll + import at bottom --- */
|
|
@@ -450,7 +541,8 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
450
541
|
#mc-ics-import-form .mc-grid-loader {
|
|
451
542
|
position: absolute;
|
|
452
543
|
inset: 0;
|
|
453
|
-
display: none;
|
|
544
|
+
display: none;
|
|
545
|
+
/* shown via .mc-loading */
|
|
454
546
|
align-items: center;
|
|
455
547
|
justify-content: center;
|
|
456
548
|
background: color-mix(in srgb, var(--joplin-background-color) 70%, transparent);
|
|
@@ -489,8 +581,10 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
489
581
|
/* Container to be scrolled */
|
|
490
582
|
#mc-import-body {
|
|
491
583
|
margin: 0;
|
|
492
|
-
max-height: 260px;
|
|
493
|
-
|
|
584
|
+
max-height: 260px;
|
|
585
|
+
/* choose the height that suits you */
|
|
586
|
+
padding: 8px 6px;
|
|
587
|
+
/* so that the scroll does not "stick" to the content */
|
|
494
588
|
}
|
|
495
589
|
|
|
496
590
|
/* Very important for <input type="file"> in flex-line: otherwise it can inflate the width */
|
|
@@ -545,7 +639,6 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
545
639
|
position: relative;
|
|
546
640
|
flex: 0 0 100%;
|
|
547
641
|
height: 2px;
|
|
548
|
-
/*margin-top: 4px;*/
|
|
549
642
|
border-radius: 999px;
|
|
550
643
|
background: color-mix(in srgb, var(--joplin-color) 18%, transparent);
|
|
551
644
|
overflow: hidden;
|
|
@@ -560,16 +653,28 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
560
653
|
opacity: 0.9;
|
|
561
654
|
}
|
|
562
655
|
|
|
563
|
-
/*
|
|
564
|
-
.mc-
|
|
656
|
+
/* shared vertical line “now” */
|
|
657
|
+
.mc-events-timeline-now-line-wrap {
|
|
565
658
|
position: absolute;
|
|
566
|
-
top:
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
659
|
+
top: 0;
|
|
660
|
+
bottom: 0;
|
|
661
|
+
left: 12px;
|
|
662
|
+
/* 6px (ul padding) + 6px (li padding) */
|
|
663
|
+
right: 12px;
|
|
664
|
+
pointer-events: none;
|
|
665
|
+
z-index: 1;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
.mc-events-timeline-now-line {
|
|
669
|
+
position: absolute;
|
|
670
|
+
top: 0;
|
|
671
|
+
bottom: 0;
|
|
672
|
+
width: 1px;
|
|
673
|
+
background: color-mix(in srgb, var(--mc-default-current-time-v-line-color) 40%, transparent);
|
|
674
|
+
box-shadow: 0 0 2px color-mix(in srgb, var(--mc-default-current-time-v-line-color) 20%, transparent);
|
|
675
|
+
z-index: 1;
|
|
676
|
+
display: none;
|
|
677
|
+
/* shown via JS when inDay */
|
|
573
678
|
}
|
|
574
679
|
|
|
575
680
|
/* slightly mute the timeline for past events */
|
|
@@ -689,7 +794,7 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
689
794
|
gap: 2px;
|
|
690
795
|
}
|
|
691
796
|
|
|
692
|
-
.mc-cell {
|
|
797
|
+
.mc-grid-body .mc-cell {
|
|
693
798
|
padding: 6px;
|
|
694
799
|
}
|
|
695
800
|
|
|
@@ -697,7 +802,8 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
697
802
|
font-size: 12px;
|
|
698
803
|
}
|
|
699
804
|
|
|
700
|
-
.mc-events-header,
|
|
805
|
+
.mc-events-header,
|
|
806
|
+
.mc-import-header {
|
|
701
807
|
font-weight: normal;
|
|
702
808
|
font-size: 12px;
|
|
703
809
|
}
|
|
@@ -721,4 +827,8 @@ body::-webkit-scrollbar-thumb:hover, select::-webkit-scrollbar-thumb:hover {
|
|
|
721
827
|
.mc-grid-head-cell.mc-weekend {
|
|
722
828
|
background: var(--mc-weekend-head-bg);
|
|
723
829
|
}
|
|
724
|
-
|
|
830
|
+
|
|
831
|
+
.mc-count {
|
|
832
|
+
padding: 2px 4px;
|
|
833
|
+
}
|
|
834
|
+
}
|
package/manifest.json
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"id": "com.volodymyroliinyk.joplin.plugin.my-calendar",
|
|
4
4
|
"app_min_version": "3.3",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.3.1",
|
|
6
6
|
"name": "My Calendar",
|
|
7
|
-
"description": "Calendar
|
|
7
|
+
"description": "Calendar plugin for Joplin",
|
|
8
8
|
"author": "Volodymyr Oliinyk",
|
|
9
9
|
"homepage_url": "https://github.com/volodymyroliinyk/joplin-plugin-my-calendar",
|
|
10
10
|
"repository_url": "https://github.com/volodymyroliinyk/joplin-plugin-my-calendar",
|
package/package.json
CHANGED
|
Binary file
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"id": "com.volodymyroliinyk.joplin.plugin.my-calendar",
|
|
4
4
|
"app_min_version": "3.3",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.3.1",
|
|
6
6
|
"name": "My Calendar",
|
|
7
|
-
"description": "Calendar
|
|
7
|
+
"description": "Calendar plugin for Joplin",
|
|
8
8
|
"author": "Volodymyr Oliinyk",
|
|
9
9
|
"homepage_url": "https://github.com/volodymyroliinyk/joplin-plugin-my-calendar",
|
|
10
10
|
"repository_url": "https://github.com/volodymyroliinyk/joplin-plugin-my-calendar",
|