@svar-ui/svelte-calendar 2.6.0 → 2.7.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/dist/components/Calendar.svelte +13 -4
- package/dist/components/Calendar.svelte.d.ts +50 -19
- package/dist/components/ContextMenu.svelte +13 -5
- package/dist/components/Editor.svelte +29 -34
- package/dist/components/EventDatesForm.svelte +121 -0
- package/dist/components/EventDatesForm.svelte.d.ts +15 -0
- package/dist/components/Layout.svelte +18 -5
- package/dist/components/Layout.svelte.d.ts +2 -0
- package/dist/components/Navigation.svelte +20 -12
- package/dist/components/Navigation.svelte.d.ts +1 -0
- package/dist/components/Render/BarSection.svelte +3 -0
- package/dist/components/Render/EventProjection.svelte +36 -0
- package/dist/components/Render/EventProjection.svelte.d.ts +9 -0
- package/dist/components/Render/GridSection.svelte +5 -2
- package/dist/components/Render/GridSection.svelte.d.ts +2 -1
- package/dist/components/Render/ScrollableSection.svelte +22 -3
- package/dist/components/Render/ScrollableSection.svelte.d.ts +1 -0
- package/dist/components/Render/SectionContent.svelte +1 -0
- package/dist/components/Render/Sections.svelte +46 -9
- package/dist/components/Render/Sections.svelte.d.ts +1 -0
- package/dist/components/Render/YearSection.svelte +8 -1
- package/dist/components/Render/resolveEventPosition.d.ts +5 -0
- package/dist/components/Render/resolveEventPosition.js +35 -0
- package/dist/components/pro_RecurringForm.svelte +346 -0
- package/dist/components/pro_RecurringForm.svelte.d.ts +15 -0
- package/dist/components/pro_rrule-form.d.ts +23 -0
- package/dist/components/pro_rrule-form.js +121 -0
- package/dist/components/{Render/useEventOverlay.svelte.d.ts → useEventOverlay.svelte.d.ts} +1 -1
- package/dist/components/{Render/useEventOverlay.svelte.js → useEventOverlay.svelte.js} +1 -1
- package/dist/context.tx +0 -0
- package/dist/defaults.d.ts +18 -0
- package/dist/defaults.js +15 -0
- package/dist/directives/clickevent.d.ts +1 -0
- package/dist/directives/clickevent.js +11 -8
- package/dist/directives/drag.js +11 -7
- package/dist/directives/dragresize.js +6 -3
- package/dist/helpers/pro_export.d.ts +5 -0
- package/dist/helpers/pro_export.js +22 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -2
- package/dist/pro_export/Calendar.svelte +30 -0
- package/dist/pro_export/Calendar.svelte.d.ts +16 -0
- package/dist/pro_export/Event.svelte +5 -0
- package/dist/pro_export/Event.svelte.d.ts +11 -0
- package/dist/pro_export.d.ts +3 -0
- package/dist/pro_export.js +15 -0
- package/dist/themes/Print.svelte +89 -0
- package/dist/themes/Print.svelte.d.ts +13 -0
- package/dist/themes/PrintBW.svelte +111 -0
- package/dist/themes/PrintBW.svelte.d.ts +13 -0
- package/dist/{components/types.d.ts → types.d.ts} +5 -0
- package/package.json +17 -17
- package/readme.md +2 -2
- package/dist/Demo.svelte +0 -7
- package/dist/Demo.svelte.d.ts +0 -26
- package/dist/components/editorItems.d.ts +0 -15
- package/dist/components/editorItems.js +0 -20
- package/dist/init.d.ts +0 -1
- package/dist/init.js +0 -5
- /package/dist/{components/types.js → types.js} +0 -0
|
@@ -13,7 +13,7 @@ let { events, init, view = "day", date, views = [
|
|
|
13
13
|
"day",
|
|
14
14
|
"week",
|
|
15
15
|
"month"
|
|
16
|
-
], toolbar, cellCss, eventCss, eventContent, recurring = false, readonly = false, children, tooltip, eventPopup, ...restProps } = $props();
|
|
16
|
+
], toolbar, cellCss, eventCss, eventContent, recurring = false, history = false, readonly = false, children, tooltip, eventPopup, eventProjection, ...restProps } = $props();
|
|
17
17
|
// uses same logic as the Locale component
|
|
18
18
|
const words = {
|
|
19
19
|
...coreEn,
|
|
@@ -34,7 +34,8 @@ const fmt = (format) => {
|
|
|
34
34
|
const dataStore = new CalendarStore(writable, {
|
|
35
35
|
recurring,
|
|
36
36
|
weekStart: rawLocale?.calendar?.weekStart ?? 1,
|
|
37
|
-
dateFormat: fmt
|
|
37
|
+
dateFormat: fmt,
|
|
38
|
+
history
|
|
38
39
|
});
|
|
39
40
|
// define event route
|
|
40
41
|
let firstInRoute = dataStore.in;
|
|
@@ -75,12 +76,17 @@ const stateStore = {
|
|
|
75
76
|
getReactiveState,
|
|
76
77
|
exec,
|
|
77
78
|
getEvent,
|
|
78
|
-
fmt
|
|
79
|
+
fmt,
|
|
80
|
+
getBrandmark: () => dataStore.getBrandmark()
|
|
79
81
|
};
|
|
80
82
|
setContext("calendar-api", stateStore);
|
|
81
83
|
let init_once = true;
|
|
84
|
+
let lastOptions = null;
|
|
82
85
|
const reinitStore = () => {
|
|
83
|
-
|
|
86
|
+
if (lastOptions !== viewOptions) {
|
|
87
|
+
lastOptions = viewOptions;
|
|
88
|
+
dataStore.configureViews(viewOptions);
|
|
89
|
+
}
|
|
84
90
|
dataStore.init({
|
|
85
91
|
currentView: view,
|
|
86
92
|
currentDate: date,
|
|
@@ -89,6 +95,7 @@ const reinitStore = () => {
|
|
|
89
95
|
if (init_once && init) {
|
|
90
96
|
init(api);
|
|
91
97
|
init_once = false;
|
|
98
|
+
dataStore.postInit();
|
|
92
99
|
}
|
|
93
100
|
};
|
|
94
101
|
reinitStore();
|
|
@@ -107,4 +114,6 @@ $effect(reinitStore);
|
|
|
107
114
|
{tooltip}
|
|
108
115
|
{eventPopup}
|
|
109
116
|
{readonly}
|
|
117
|
+
{history}
|
|
118
|
+
{eventProjection}
|
|
110
119
|
/>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
2
|
import { CalendarStore } from "@svar-ui/calendar-store";
|
|
3
3
|
import type { ViewConfig } from "@svar-ui/calendar-store";
|
|
4
|
-
import type { CalendarInstanceApi } from "
|
|
5
|
-
import type { ToolbarItem, CellCss, EventCss } from "@svar-ui/calendar-store";
|
|
4
|
+
import type { CalendarInstanceApi } from "../types.js";
|
|
5
|
+
import type { ToolbarItem, CellCss, EventCss, EventProjection } from "@svar-ui/calendar-store";
|
|
6
6
|
type Props = {
|
|
7
7
|
events: any;
|
|
8
8
|
init?: (api: CalendarInstanceApi) => void;
|
|
@@ -18,9 +18,12 @@ type Props = {
|
|
|
18
18
|
eventContent?: any;
|
|
19
19
|
date?: Date;
|
|
20
20
|
recurring?: boolean;
|
|
21
|
+
history?: boolean;
|
|
21
22
|
children?: Snippet;
|
|
22
23
|
tooltip?: any;
|
|
23
24
|
eventPopup?: any;
|
|
25
|
+
eventProjection?: EventProjection | null;
|
|
26
|
+
[key: `on${string}`]: ((ev: any) => void) | undefined;
|
|
24
27
|
};
|
|
25
28
|
declare const Calendar: import("svelte").Component<Props, {
|
|
26
29
|
getState: () => import("@svar-ui/calendar-store").State;
|
|
@@ -35,7 +38,11 @@ declare const Calendar: import("svelte").Component<Props, {
|
|
|
35
38
|
events: import("@svar-ui/lib-state").IPublicWritable<import("@svar-ui/calendar-store").EventsStore>;
|
|
36
39
|
viewData: import("@svar-ui/lib-state").IPublicWritable<any>;
|
|
37
40
|
filters: import("@svar-ui/lib-state").IPublicWritable<Map<string, (obj: any) => boolean>>;
|
|
38
|
-
editorData: import("@svar-ui/lib-state").IPublicWritable<import("@svar-ui/calendar-store").
|
|
41
|
+
editorData: import("@svar-ui/lib-state").IPublicWritable<import("@svar-ui/calendar-store").EditorData | null>;
|
|
42
|
+
history: import("@svar-ui/lib-state").IPublicWritable<{
|
|
43
|
+
undo: number;
|
|
44
|
+
redo: number;
|
|
45
|
+
}>;
|
|
39
46
|
_view: import("@svar-ui/lib-state").IPublicWritable<import("@svar-ui/calendar-store").ViewModel>;
|
|
40
47
|
};
|
|
41
48
|
getStores: () => {
|
|
@@ -52,23 +59,29 @@ declare const Calendar: import("svelte").Component<Props, {
|
|
|
52
59
|
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
53
60
|
edit?: boolean;
|
|
54
61
|
id?: import("@svar-ui/calendar-store").EventID;
|
|
62
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
55
63
|
} | {
|
|
56
64
|
id: import("@svar-ui/calendar-store").EventID;
|
|
65
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
57
66
|
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
58
67
|
mode?: "single" | "following";
|
|
59
|
-
originalDate?: string;
|
|
60
68
|
} | {
|
|
61
69
|
id: import("@svar-ui/calendar-store").EventID;
|
|
70
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
71
|
+
cascade?: boolean;
|
|
62
72
|
} | {
|
|
63
73
|
id: import("@svar-ui/calendar-store").EventID | null;
|
|
74
|
+
rawId?: import("@svar-ui/calendar-store").EventID | null;
|
|
75
|
+
mode?: import("@svar-ui/calendar-store").RecurringEditMode | null;
|
|
64
76
|
} | {
|
|
65
77
|
id: import("@svar-ui/calendar-store").EventID;
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
79
|
+
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
80
|
+
mode?: "single" | "following";
|
|
68
81
|
} | {
|
|
69
82
|
filter?: ((obj: any) => boolean) | null;
|
|
70
83
|
tag?: string;
|
|
71
|
-
}) => Promise<{
|
|
84
|
+
} | import("@svar-ui/calendar-store").RequestDataAction | import("@svar-ui/calendar-store").ProvideDataAction) => Promise<{
|
|
72
85
|
date?: Date;
|
|
73
86
|
view?: string;
|
|
74
87
|
} | {
|
|
@@ -77,23 +90,29 @@ declare const Calendar: import("svelte").Component<Props, {
|
|
|
77
90
|
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
78
91
|
edit?: boolean;
|
|
79
92
|
id?: import("@svar-ui/calendar-store").EventID;
|
|
93
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
80
94
|
} | {
|
|
81
95
|
id: import("@svar-ui/calendar-store").EventID;
|
|
96
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
82
97
|
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
83
98
|
mode?: "single" | "following";
|
|
84
|
-
originalDate?: string;
|
|
85
99
|
} | {
|
|
86
100
|
id: import("@svar-ui/calendar-store").EventID;
|
|
101
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
102
|
+
cascade?: boolean;
|
|
87
103
|
} | {
|
|
88
104
|
id: import("@svar-ui/calendar-store").EventID | null;
|
|
105
|
+
rawId?: import("@svar-ui/calendar-store").EventID | null;
|
|
106
|
+
mode?: import("@svar-ui/calendar-store").RecurringEditMode | null;
|
|
89
107
|
} | {
|
|
90
108
|
id: import("@svar-ui/calendar-store").EventID;
|
|
91
|
-
|
|
92
|
-
|
|
109
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
110
|
+
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
111
|
+
mode?: "single" | "following";
|
|
93
112
|
} | {
|
|
94
113
|
filter?: ((obj: any) => boolean) | null;
|
|
95
114
|
tag?: string;
|
|
96
|
-
}>;
|
|
115
|
+
} | import("@svar-ui/calendar-store").RequestDataAction | import("@svar-ui/calendar-store").ProvideDataAction>;
|
|
97
116
|
setNext: (ev: any) => any;
|
|
98
117
|
intercept: (name: keyof import("@svar-ui/calendar-store").StoreActions, handler: (v: {
|
|
99
118
|
date?: Date;
|
|
@@ -104,23 +123,29 @@ declare const Calendar: import("svelte").Component<Props, {
|
|
|
104
123
|
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
105
124
|
edit?: boolean;
|
|
106
125
|
id?: import("@svar-ui/calendar-store").EventID;
|
|
126
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
107
127
|
} | {
|
|
108
128
|
id: import("@svar-ui/calendar-store").EventID;
|
|
129
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
109
130
|
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
110
131
|
mode?: "single" | "following";
|
|
111
|
-
originalDate?: string;
|
|
112
132
|
} | {
|
|
113
133
|
id: import("@svar-ui/calendar-store").EventID;
|
|
134
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
135
|
+
cascade?: boolean;
|
|
114
136
|
} | {
|
|
115
137
|
id: import("@svar-ui/calendar-store").EventID | null;
|
|
138
|
+
rawId?: import("@svar-ui/calendar-store").EventID | null;
|
|
139
|
+
mode?: import("@svar-ui/calendar-store").RecurringEditMode | null;
|
|
116
140
|
} | {
|
|
117
141
|
id: import("@svar-ui/calendar-store").EventID;
|
|
118
|
-
|
|
119
|
-
|
|
142
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
143
|
+
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
144
|
+
mode?: "single" | "following";
|
|
120
145
|
} | {
|
|
121
146
|
filter?: ((obj: any) => boolean) | null;
|
|
122
147
|
tag?: string;
|
|
123
|
-
}) => void | boolean | Promise<boolean>, config?: import("@svar-ui/lib-state").IEventConfig) => void;
|
|
148
|
+
} | import("@svar-ui/calendar-store").RequestDataAction | import("@svar-ui/calendar-store").ProvideDataAction) => void | boolean | Promise<boolean>, config?: import("@svar-ui/lib-state").IEventConfig) => void;
|
|
124
149
|
on: (name: keyof import("@svar-ui/calendar-store").StoreActions, handler: (v: {
|
|
125
150
|
date?: Date;
|
|
126
151
|
view?: string;
|
|
@@ -130,23 +155,29 @@ declare const Calendar: import("svelte").Component<Props, {
|
|
|
130
155
|
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
131
156
|
edit?: boolean;
|
|
132
157
|
id?: import("@svar-ui/calendar-store").EventID;
|
|
158
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
133
159
|
} | {
|
|
134
160
|
id: import("@svar-ui/calendar-store").EventID;
|
|
161
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
135
162
|
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
136
163
|
mode?: "single" | "following";
|
|
137
|
-
originalDate?: string;
|
|
138
164
|
} | {
|
|
139
165
|
id: import("@svar-ui/calendar-store").EventID;
|
|
166
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
167
|
+
cascade?: boolean;
|
|
140
168
|
} | {
|
|
141
169
|
id: import("@svar-ui/calendar-store").EventID | null;
|
|
170
|
+
rawId?: import("@svar-ui/calendar-store").EventID | null;
|
|
171
|
+
mode?: import("@svar-ui/calendar-store").RecurringEditMode | null;
|
|
142
172
|
} | {
|
|
143
173
|
id: import("@svar-ui/calendar-store").EventID;
|
|
144
|
-
|
|
145
|
-
|
|
174
|
+
rawId?: import("@svar-ui/calendar-store").EventID;
|
|
175
|
+
event: Partial<import("@svar-ui/calendar-store").CalendarEvent>;
|
|
176
|
+
mode?: "single" | "following";
|
|
146
177
|
} | {
|
|
147
178
|
filter?: ((obj: any) => boolean) | null;
|
|
148
179
|
tag?: string;
|
|
149
|
-
}) => void | boolean | Promise<boolean>, config?: import("@svar-ui/lib-state").IEventConfig) => void;
|
|
180
|
+
} | import("@svar-ui/calendar-store").RequestDataAction | import("@svar-ui/calendar-store").ProvideDataAction) => void | boolean | Promise<boolean>, config?: import("@svar-ui/lib-state").IEventConfig) => void;
|
|
150
181
|
detach: (tag: number | string | symbol) => void;
|
|
151
182
|
}, "">;
|
|
152
183
|
type Calendar = ReturnType<typeof Calendar>;
|
|
@@ -6,6 +6,7 @@ import { en as coreEn } from "@svar-ui/core-locales";
|
|
|
6
6
|
import { getMenuOptions } from "@svar-ui/calendar-store";
|
|
7
7
|
let { options = [], api = null, resolver = null, filter = null, at = "point", children, onclick, css } = $props();
|
|
8
8
|
let activeId = null;
|
|
9
|
+
let rawId = null;
|
|
9
10
|
// set locale
|
|
10
11
|
let l = getContext("wx-i18n");
|
|
11
12
|
if (!l) {
|
|
@@ -29,15 +30,16 @@ function getOptions() {
|
|
|
29
30
|
const base = options.length ? options : getMenuOptions();
|
|
30
31
|
return applyLocale(base);
|
|
31
32
|
}
|
|
32
|
-
function itemResolver(
|
|
33
|
-
if (!
|
|
34
|
-
const event = api.getEvent(
|
|
33
|
+
function itemResolver(id, ev) {
|
|
34
|
+
if (!id || !api) return null;
|
|
35
|
+
const event = api.getEvent(id);
|
|
35
36
|
if (!event) return null;
|
|
36
37
|
if (resolver) {
|
|
37
38
|
const result = resolver(event, ev);
|
|
38
39
|
if (!result) return null;
|
|
39
40
|
}
|
|
40
41
|
activeId = event.id;
|
|
42
|
+
rawId = id;
|
|
41
43
|
return event;
|
|
42
44
|
}
|
|
43
45
|
function menuAction(ev) {
|
|
@@ -45,9 +47,15 @@ function menuAction(ev) {
|
|
|
45
47
|
if (!action) return;
|
|
46
48
|
const id = typeof activeId === "object" ? activeId.id : activeId;
|
|
47
49
|
if (action.id === "edit-event") {
|
|
48
|
-
api.exec("select-event", {
|
|
50
|
+
api.exec("select-event", {
|
|
51
|
+
id,
|
|
52
|
+
rawId
|
|
53
|
+
});
|
|
49
54
|
} else if (action.id === "delete-event") {
|
|
50
|
-
api.exec("delete-event", {
|
|
55
|
+
api.exec("delete-event", {
|
|
56
|
+
id,
|
|
57
|
+
rawId
|
|
58
|
+
});
|
|
51
59
|
}
|
|
52
60
|
onclick?.(ev);
|
|
53
61
|
}
|
|
@@ -4,9 +4,11 @@ import { locale } from "@svar-ui/lib-dom";
|
|
|
4
4
|
import { en } from "@svar-ui/calendar-locales";
|
|
5
5
|
import { en as coreEn } from "@svar-ui/core-locales";
|
|
6
6
|
import DateTimePicker from "./DateTimePicker.svelte";
|
|
7
|
-
import
|
|
7
|
+
import EventDatesForm from "./EventDatesForm.svelte";
|
|
8
|
+
import { getEditorItems } from "../defaults.js";
|
|
8
9
|
registerEditorItem("date-time-picker", DateTimePicker);
|
|
9
|
-
|
|
10
|
+
registerEditorItem("event-dates", EventDatesForm);
|
|
11
|
+
let { api, values, items, placement, layout = "default", focus = true, css = "", topBar, autoSave = true, onchange, onsave, onaction, ...editorProps } = $props();
|
|
10
12
|
// svelte-ignore state_referenced_locally
|
|
11
13
|
void values;
|
|
12
14
|
// svelte-ignore state_referenced_locally
|
|
@@ -30,9 +32,10 @@ function applyLocale(list) {
|
|
|
30
32
|
return next;
|
|
31
33
|
});
|
|
32
34
|
}
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const
|
|
35
|
+
const calendarCtx = getContext("calendar-api");
|
|
36
|
+
const finalPlacement = $derived(placement ?? (calendarCtx?.isCompact() ? "fullscreen" : "sidebar"));
|
|
37
|
+
const useRecurringForm = $derived(!!$editorData?.recurring && ($editorData?.recurringMode ?? "series") !== "single");
|
|
38
|
+
const cItems = $derived(applyLocale(items ?? getEditorItems(useRecurringForm)));
|
|
36
39
|
const defaultTopBar = { items: [
|
|
37
40
|
{
|
|
38
41
|
comp: "icon",
|
|
@@ -49,49 +52,44 @@ const defaultTopBar = { items: [
|
|
|
49
52
|
}
|
|
50
53
|
] };
|
|
51
54
|
const editorTopBar = $derived(topBar === undefined ? defaultTopBar : topBar);
|
|
52
|
-
const editorCss = $derived([
|
|
53
|
-
"wx-editor-calendar",
|
|
54
|
-
allDay ? "wx-editor-all-day" : "",
|
|
55
|
-
css
|
|
56
|
-
].filter(Boolean).join(" "));
|
|
55
|
+
const editorCss = $derived(["wx-editor-calendar", css].filter(Boolean).join(" "));
|
|
57
56
|
function handleSave(ev) {
|
|
58
57
|
onsave?.(ev);
|
|
59
58
|
const data = $editorData;
|
|
60
59
|
if (!data) return;
|
|
60
|
+
const mode = data.recurringMode ?? "series";
|
|
61
|
+
// a series save must not carry the clicked occurrence's context in
|
|
62
|
+
// rawId, or the store would treat it as a single-occurrence edit
|
|
61
63
|
api.exec("update-event", {
|
|
62
64
|
id: data.id,
|
|
63
|
-
|
|
65
|
+
rawId: mode === "series" ? data.id : data.rawId,
|
|
66
|
+
event: { ...ev.values },
|
|
67
|
+
...data.recurringOriginalDate && mode !== "series" ? { mode } : {}
|
|
64
68
|
});
|
|
65
69
|
}
|
|
66
|
-
function sameDay(a, b) {
|
|
67
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
68
|
-
}
|
|
69
70
|
function handleChange(ev) {
|
|
70
|
-
const { key, value, update } = ev;
|
|
71
|
-
const prev = $editorData;
|
|
72
|
-
generation++;
|
|
73
|
-
if (prev && key === "start" && !update.allDay) {
|
|
74
|
-
const oldStart = prev.start;
|
|
75
|
-
const oldEnd = prev.end;
|
|
76
|
-
if (oldStart instanceof Date && oldEnd instanceof Date && sameDay(oldStart, oldEnd) && value instanceof Date) {
|
|
77
|
-
const newEnd = new Date(oldEnd);
|
|
78
|
-
newEnd.setFullYear(value.getFullYear(), value.getMonth(), value.getDate());
|
|
79
|
-
update.end = newEnd;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
71
|
onchange?.(ev);
|
|
83
72
|
}
|
|
84
73
|
function handleDelete() {
|
|
85
74
|
const data = $editorData;
|
|
86
75
|
if (!data) return;
|
|
87
|
-
api.exec("delete-event", {
|
|
88
|
-
|
|
76
|
+
api.exec("delete-event", {
|
|
77
|
+
id: data.id,
|
|
78
|
+
rawId: data.rawId
|
|
79
|
+
});
|
|
80
|
+
api.exec("select-event", {
|
|
81
|
+
id: null,
|
|
82
|
+
rawId: null
|
|
83
|
+
});
|
|
89
84
|
}
|
|
90
85
|
function handleAction(ev) {
|
|
91
86
|
onaction?.(ev);
|
|
92
87
|
const { item } = ev;
|
|
93
88
|
if (item.id === "close" && !!item.comp) {
|
|
94
|
-
api.exec("select-event", {
|
|
89
|
+
api.exec("select-event", {
|
|
90
|
+
id: null,
|
|
91
|
+
rawId: null
|
|
92
|
+
});
|
|
95
93
|
}
|
|
96
94
|
}
|
|
97
95
|
</script>
|
|
@@ -106,9 +104,9 @@ function handleAction(ev) {
|
|
|
106
104
|
onchange={handleChange}
|
|
107
105
|
onaction={handleAction}
|
|
108
106
|
onsave={handleSave}
|
|
109
|
-
{
|
|
107
|
+
placement={finalPlacement}
|
|
110
108
|
{layout}
|
|
111
|
-
values={$editorData}
|
|
109
|
+
values={$editorData.values}
|
|
112
110
|
css={editorCss}
|
|
113
111
|
/>
|
|
114
112
|
{/if}
|
|
@@ -117,7 +115,4 @@ function handleAction(ev) {
|
|
|
117
115
|
:global(.wx-sidearea .wx-editor-calendar) {
|
|
118
116
|
width: 450px;
|
|
119
117
|
}
|
|
120
|
-
:global(.wx-editor-calendar.wx-editor-all-day .wx-timepicker) {
|
|
121
|
-
visibility: hidden;
|
|
122
|
-
}
|
|
123
118
|
</style>
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<script lang="ts">import { getContext, setContext } from "svelte";
|
|
2
|
+
import { Checkbox, DatePicker, TimePicker } from "@svar-ui/svelte-core";
|
|
3
|
+
const locale = getContext("wx-i18n");
|
|
4
|
+
const _ = locale ? locale.getGroup("eventCalendar") : (v) => v;
|
|
5
|
+
let { value, error, onchange } = $props();
|
|
6
|
+
setContext("wx-input-id", "");
|
|
7
|
+
function sameDay(a, b) {
|
|
8
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
9
|
+
}
|
|
10
|
+
function update(part) {
|
|
11
|
+
onchange({ value: {
|
|
12
|
+
...value,
|
|
13
|
+
...part
|
|
14
|
+
} });
|
|
15
|
+
}
|
|
16
|
+
function pickDate(key, day) {
|
|
17
|
+
if (!day) return;
|
|
18
|
+
const current = value[key];
|
|
19
|
+
const next = new Date(day);
|
|
20
|
+
if (current) {
|
|
21
|
+
next.setHours(current.getHours(), current.getMinutes(), 0, 0);
|
|
22
|
+
}
|
|
23
|
+
if (key === "start" && sameDay(value.start, value.end)) {
|
|
24
|
+
const end = new Date(value.end);
|
|
25
|
+
end.setFullYear(next.getFullYear(), next.getMonth(), next.getDate());
|
|
26
|
+
update({
|
|
27
|
+
start: next,
|
|
28
|
+
end
|
|
29
|
+
});
|
|
30
|
+
} else {
|
|
31
|
+
update({ [key]: next });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function pickTime(key, time) {
|
|
35
|
+
const next = new Date(value[key]);
|
|
36
|
+
next.setHours(time.getHours(), time.getMinutes(), 0, 0);
|
|
37
|
+
update({ [key]: next });
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<div class="wx-event-dates" class:wx-error={!!error}>
|
|
42
|
+
<div class="wx-date-row">
|
|
43
|
+
<span class="wx-date-label">{_("Start date")}</span>
|
|
44
|
+
<div class="wx-date-control">
|
|
45
|
+
<DatePicker
|
|
46
|
+
value={value.start}
|
|
47
|
+
buttons={false}
|
|
48
|
+
onchange={ev => pickDate("start", ev.value)}
|
|
49
|
+
/>
|
|
50
|
+
</div>
|
|
51
|
+
{#if !value.allDay}
|
|
52
|
+
<div class="wx-time-control">
|
|
53
|
+
<TimePicker
|
|
54
|
+
value={value.start}
|
|
55
|
+
onchange={ev => pickTime("start", ev.value)}
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
{/if}
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="wx-date-row">
|
|
62
|
+
<span class="wx-date-label">{_("End date")}</span>
|
|
63
|
+
<div class="wx-date-control">
|
|
64
|
+
<DatePicker
|
|
65
|
+
value={value.end}
|
|
66
|
+
buttons={false}
|
|
67
|
+
onchange={ev => pickDate("end", ev.value)}
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
{#if !value.allDay}
|
|
71
|
+
<div class="wx-time-control">
|
|
72
|
+
<TimePicker
|
|
73
|
+
value={value.end}
|
|
74
|
+
onchange={ev => pickTime("end", ev.value)}
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
{/if}
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div class="wx-date-row">
|
|
81
|
+
<span class="wx-date-label"></span>
|
|
82
|
+
<Checkbox
|
|
83
|
+
label={_("All day")}
|
|
84
|
+
value={!!value.allDay}
|
|
85
|
+
onchange={ev => update({ allDay: ev.value })}
|
|
86
|
+
/>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<style>
|
|
91
|
+
.wx-event-dates {
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-direction: column;
|
|
94
|
+
gap: var(--wx-padding);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.wx-date-row {
|
|
98
|
+
display: flex;
|
|
99
|
+
align-items: center;
|
|
100
|
+
gap: var(--wx-padding);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.wx-date-label {
|
|
104
|
+
flex: none;
|
|
105
|
+
width: 72px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.wx-date-control {
|
|
109
|
+
flex: 1;
|
|
110
|
+
min-width: 0;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.wx-time-control {
|
|
114
|
+
flex: none;
|
|
115
|
+
width: 96px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.wx-error :global(.wx-input) {
|
|
119
|
+
border-color: var(--wx-color-danger);
|
|
120
|
+
}
|
|
121
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type Value = {
|
|
2
|
+
start: Date;
|
|
3
|
+
end: Date;
|
|
4
|
+
allDay?: boolean;
|
|
5
|
+
};
|
|
6
|
+
type $$ComponentProps = {
|
|
7
|
+
value: Value;
|
|
8
|
+
error?: unknown;
|
|
9
|
+
onchange: (ev: {
|
|
10
|
+
value: Value;
|
|
11
|
+
}) => void;
|
|
12
|
+
};
|
|
13
|
+
declare const EventDatesForm: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
14
|
+
type EventDatesForm = ReturnType<typeof EventDatesForm>;
|
|
15
|
+
export default EventDatesForm;
|
|
@@ -2,24 +2,37 @@
|
|
|
2
2
|
import Navigation from "./Navigation.svelte";
|
|
3
3
|
import Sections from "./Render/Sections.svelte";
|
|
4
4
|
import ScrollableSection from "./Render/ScrollableSection.svelte";
|
|
5
|
+
const COMPACT_WIDTH = 480;
|
|
5
6
|
const _ = getContext("wx-i18n").getGroup("eventCalendar");
|
|
6
|
-
const { store, views, toolbar, cellCss, eventCss, eventContent, children, tooltip, eventPopup, brandmark, readonly = false } = $props();
|
|
7
|
+
const { store, views, toolbar, cellCss, eventCss, eventContent, children, tooltip, eventPopup, brandmark, readonly = false, history = false, eventProjection } = $props();
|
|
7
8
|
// svelte-ignore state_referenced_locally
|
|
8
9
|
const { viewData, currentView, _view } = store.getReactiveState();
|
|
9
10
|
const renderMode = $derived($_view?.render);
|
|
11
|
+
let isCompact = false;
|
|
12
|
+
// svelte-ignore state_referenced_locally
|
|
13
|
+
store.isCompact = () => isCompact;
|
|
14
|
+
function observeSize(node) {
|
|
15
|
+
store.getRootNode = () => node;
|
|
16
|
+
const observer = new ResizeObserver((entries) => {
|
|
17
|
+
isCompact = entries[0].contentRect.width < COMPACT_WIDTH;
|
|
18
|
+
node.classList.toggle("wx-calendar--compact", isCompact);
|
|
19
|
+
});
|
|
20
|
+
observer.observe(node);
|
|
21
|
+
return { destroy: () => observer.disconnect() };
|
|
22
|
+
}
|
|
10
23
|
</script>
|
|
11
24
|
|
|
12
25
|
{#snippet viewContent()}
|
|
13
26
|
{#if renderMode === "scrollable"}
|
|
14
|
-
<ScrollableSection data={$viewData} {cellCss} {eventCss} {eventContent} view={$currentView} {tooltip} {eventPopup} {readonly} />
|
|
27
|
+
<ScrollableSection data={$viewData} {cellCss} {eventCss} {eventContent} view={$currentView} {tooltip} {eventPopup} {readonly} {eventProjection} />
|
|
15
28
|
{:else}
|
|
16
|
-
<Sections data={$viewData} {cellCss} {eventCss} {eventContent} view={$currentView} {tooltip} {eventPopup} {readonly} />
|
|
29
|
+
<Sections data={$viewData} {cellCss} {eventCss} {eventContent} view={$currentView} {tooltip} {eventPopup} {readonly} {eventProjection} />
|
|
17
30
|
{/if}
|
|
18
31
|
{/snippet}
|
|
19
32
|
|
|
20
|
-
<div class="wx-calendar" role="region" aria-label={_("Calendar")}>
|
|
33
|
+
<div class="wx-calendar" role="region" aria-label={_("Calendar")} use:observeSize>
|
|
21
34
|
{#if toolbar !== null}
|
|
22
|
-
<Navigation {views} toolbar={toolbar} {readonly} />
|
|
35
|
+
<Navigation {views} toolbar={toolbar} {readonly} {history} />
|
|
23
36
|
{/if}
|
|
24
37
|
{#if children}
|
|
25
38
|
<div class="wx-calendar-content">
|
|
@@ -15,6 +15,8 @@ type $$ComponentProps = {
|
|
|
15
15
|
eventPopup?: any;
|
|
16
16
|
brandmark?: Brandmark;
|
|
17
17
|
readonly?: boolean;
|
|
18
|
+
history?: boolean;
|
|
19
|
+
eventProjection?: any;
|
|
18
20
|
};
|
|
19
21
|
declare const Layout: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
20
22
|
type Layout = ReturnType<typeof Layout>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">import { getContext } from "svelte";
|
|
2
|
-
import { Toolbar, registerToolbarItem } from "@svar-ui/svelte-toolbar";
|
|
2
|
+
import { Toolbar, registerToolbarItem, ButtonList } from "@svar-ui/svelte-toolbar";
|
|
3
3
|
import { RichSelect, Segmented } from "@svar-ui/svelte-core";
|
|
4
4
|
import { getToolbarItems } from "@svar-ui/calendar-store";
|
|
5
5
|
import DateNav from "./DateNav.svelte";
|
|
@@ -8,36 +8,42 @@ import DateLabel from "./DateLabel.svelte";
|
|
|
8
8
|
import MenuButton from "./MenuButton.svelte";
|
|
9
9
|
import AddEventButton from "./AddEventButton.svelte";
|
|
10
10
|
registerToolbarItem("richselect", RichSelect);
|
|
11
|
+
registerToolbarItem("richselect-navigation", RichSelect);
|
|
12
|
+
registerToolbarItem("richselect-navigation", ButtonList, { menu: true });
|
|
11
13
|
registerToolbarItem("segmented", Segmented);
|
|
14
|
+
registerToolbarItem("segmented-navigation", Segmented);
|
|
15
|
+
registerToolbarItem("segmented-navigation", ButtonList, { menu: true });
|
|
16
|
+
registerToolbarItem("segmented", ButtonList, { menu: true });
|
|
12
17
|
registerToolbarItem("dateNav", DateNav);
|
|
13
18
|
registerToolbarItem("todayButton", TodayButton);
|
|
14
19
|
registerToolbarItem("dateLabel", DateLabel);
|
|
15
20
|
registerToolbarItem("menuButton", MenuButton);
|
|
16
21
|
registerToolbarItem("addEventButton", AddEventButton);
|
|
17
22
|
const store = getContext("calendar-api");
|
|
18
|
-
const { views, toolbar =
|
|
19
|
-
const
|
|
23
|
+
const { views, toolbar, readonly = false, history = false } = $props();
|
|
24
|
+
const reactiveState = store.getReactiveState();
|
|
25
|
+
const { currentView } = reactiveState;
|
|
20
26
|
const _ = getContext("wx-i18n").getGroup("eventCalendar");
|
|
21
27
|
const items = $derived.by(() => {
|
|
22
|
-
const base = toolbar
|
|
28
|
+
const base = toolbar ? toolbar.items : getToolbarItems({ history });
|
|
23
29
|
const viewOptions = views.map((v) => ({
|
|
24
30
|
id: v.id,
|
|
25
31
|
label: _(v.label || v.id.charAt(0).toUpperCase() + v.id.slice(1))
|
|
26
32
|
}));
|
|
27
33
|
const res = [...base ?? []].map((item) => {
|
|
28
|
-
|
|
34
|
+
let next = item;
|
|
35
|
+
if (next.id === "modes") {
|
|
29
36
|
if (viewOptions.length > 1) {
|
|
30
37
|
return {
|
|
31
|
-
...
|
|
38
|
+
...next,
|
|
32
39
|
value: $currentView,
|
|
33
40
|
options: viewOptions
|
|
34
41
|
};
|
|
35
42
|
} else {
|
|
36
43
|
return null;
|
|
37
44
|
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return item;
|
|
45
|
+
} else if (!readonly) {} else if (next.comp === "addEventButton" || next.id === "undo" || next.id === "redo") return null;
|
|
46
|
+
return next;
|
|
41
47
|
}).filter(Boolean);
|
|
42
48
|
return res;
|
|
43
49
|
});
|
|
@@ -48,9 +54,11 @@ const onchange = ({ item, value }) => {
|
|
|
48
54
|
};
|
|
49
55
|
</script>
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
|
|
57
|
+
{#if items.length}
|
|
58
|
+
<div class="wx-navigation" role="navigation" aria-label={_("Calendar controls")}>
|
|
59
|
+
<Toolbar {items} {onchange} css={toolbar?.css}></Toolbar>
|
|
60
|
+
</div>
|
|
61
|
+
{/if}
|
|
54
62
|
|
|
55
63
|
<style>
|
|
56
64
|
.wx-navigation {
|
|
@@ -73,6 +73,9 @@ function css(p) {
|
|
|
73
73
|
box-shadow: none;
|
|
74
74
|
border-radius: 0;
|
|
75
75
|
}
|
|
76
|
+
.wx-bar-single-day:global(.wx-dragging) {
|
|
77
|
+
background-color: var(--wx-background);
|
|
78
|
+
}
|
|
76
79
|
.wx-bar-single-day:hover {
|
|
77
80
|
background-color: var(--wx-color-secondary-hover);
|
|
78
81
|
box-shadow: none;
|