@sentropic/design-system-vue 0.8.0 → 0.9.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/Autosave.d.ts +92 -0
- package/dist/Autosave.d.ts.map +1 -0
- package/dist/Autosave.js +137 -0
- package/dist/Autosave.js.map +1 -0
- package/dist/Calendar.d.ts +135 -0
- package/dist/Calendar.d.ts.map +1 -0
- package/dist/Calendar.js +274 -0
- package/dist/Calendar.js.map +1 -0
- package/dist/Rating.d.ts +110 -0
- package/dist/Rating.d.ts.map +1 -0
- package/dist/Rating.js +154 -0
- package/dist/Rating.js.map +1 -0
- package/dist/SlideIndicator.d.ts +87 -0
- package/dist/SlideIndicator.d.ts.map +1 -0
- package/dist/SlideIndicator.js +73 -0
- package/dist/SlideIndicator.js.map +1 -0
- package/dist/TimePicker.d.ts +130 -0
- package/dist/TimePicker.d.ts.map +1 -0
- package/dist/TimePicker.js +179 -0
- package/dist/TimePicker.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/styles.css +449 -0
- package/package.json +1 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export type AutosaveStatus = "idle" | "saving" | "saved" | "error";
|
|
2
|
+
export type AutosaveLabels = {
|
|
3
|
+
idle?: string;
|
|
4
|
+
saving?: string;
|
|
5
|
+
saved?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
};
|
|
8
|
+
export type AutosaveProps = {
|
|
9
|
+
status?: AutosaveStatus;
|
|
10
|
+
/** Horodatage de la dernière sauvegarde réussie. */
|
|
11
|
+
lastSaved?: string | Date;
|
|
12
|
+
/** Affiche un bouton « Réessayer » sur le statut `error`. */
|
|
13
|
+
onRetry?: () => void;
|
|
14
|
+
/** Surcharge des libellés par statut. */
|
|
15
|
+
labels?: AutosaveLabels;
|
|
16
|
+
/** Étiquette du bouton de relance. */
|
|
17
|
+
retryLabel?: string;
|
|
18
|
+
locale?: string;
|
|
19
|
+
class?: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const Autosave: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
22
|
+
status: {
|
|
23
|
+
type: () => AutosaveStatus;
|
|
24
|
+
default: string;
|
|
25
|
+
};
|
|
26
|
+
lastSaved: {
|
|
27
|
+
type: () => string | Date;
|
|
28
|
+
default: undefined;
|
|
29
|
+
};
|
|
30
|
+
onRetry: {
|
|
31
|
+
type: () => () => void;
|
|
32
|
+
default: undefined;
|
|
33
|
+
};
|
|
34
|
+
labels: {
|
|
35
|
+
type: () => AutosaveLabels;
|
|
36
|
+
default: undefined;
|
|
37
|
+
};
|
|
38
|
+
retryLabel: {
|
|
39
|
+
type: StringConstructor;
|
|
40
|
+
default: undefined;
|
|
41
|
+
};
|
|
42
|
+
locale: {
|
|
43
|
+
type: StringConstructor;
|
|
44
|
+
default: string;
|
|
45
|
+
};
|
|
46
|
+
class: {
|
|
47
|
+
type: StringConstructor;
|
|
48
|
+
default: undefined;
|
|
49
|
+
};
|
|
50
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
51
|
+
[key: string]: any;
|
|
52
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "retry"[], "retry", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
53
|
+
status: {
|
|
54
|
+
type: () => AutosaveStatus;
|
|
55
|
+
default: string;
|
|
56
|
+
};
|
|
57
|
+
lastSaved: {
|
|
58
|
+
type: () => string | Date;
|
|
59
|
+
default: undefined;
|
|
60
|
+
};
|
|
61
|
+
onRetry: {
|
|
62
|
+
type: () => () => void;
|
|
63
|
+
default: undefined;
|
|
64
|
+
};
|
|
65
|
+
labels: {
|
|
66
|
+
type: () => AutosaveLabels;
|
|
67
|
+
default: undefined;
|
|
68
|
+
};
|
|
69
|
+
retryLabel: {
|
|
70
|
+
type: StringConstructor;
|
|
71
|
+
default: undefined;
|
|
72
|
+
};
|
|
73
|
+
locale: {
|
|
74
|
+
type: StringConstructor;
|
|
75
|
+
default: string;
|
|
76
|
+
};
|
|
77
|
+
class: {
|
|
78
|
+
type: StringConstructor;
|
|
79
|
+
default: undefined;
|
|
80
|
+
};
|
|
81
|
+
}>> & Readonly<{
|
|
82
|
+
onRetry?: ((...args: any[]) => any) | undefined;
|
|
83
|
+
}>, {
|
|
84
|
+
class: string;
|
|
85
|
+
status: AutosaveStatus;
|
|
86
|
+
lastSaved: string | Date;
|
|
87
|
+
onRetry: () => void;
|
|
88
|
+
labels: AutosaveLabels;
|
|
89
|
+
retryLabel: string;
|
|
90
|
+
locale: string;
|
|
91
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
92
|
+
//# sourceMappingURL=Autosave.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Autosave.d.ts","sourceRoot":"","sources":["../src/Autosave.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnE,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,yCAAyC;IACzC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA+DF,eAAO,MAAM,QAAQ;;cAGS,MAAM,cAAc;;;;cACE,MAAM,MAAM,GAAG,IAAI;;;;cAC3B,MAAM,MAAM,IAAI;;;;cAC9B,MAAM,cAAc;;;;;;;;;;;;;;;;;;;cAHpB,MAAM,cAAc;;;;cACE,MAAM,MAAM,GAAG,IAAI;;;;cAC3B,MAAM,MAAM,IAAI;;;;cAC9B,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;mBADM,IAAI;;;;4EA4F1D,CAAC"}
|
package/dist/Autosave.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { defineComponent, h } from "vue";
|
|
2
|
+
import { classNames } from "./classNames.js";
|
|
3
|
+
function LoaderCircleIcon(size) {
|
|
4
|
+
return h("svg", {
|
|
5
|
+
width: size,
|
|
6
|
+
height: size,
|
|
7
|
+
viewBox: "0 0 24 24",
|
|
8
|
+
fill: "none",
|
|
9
|
+
stroke: "currentColor",
|
|
10
|
+
"stroke-width": 2,
|
|
11
|
+
"stroke-linecap": "round",
|
|
12
|
+
"stroke-linejoin": "round",
|
|
13
|
+
"aria-hidden": "true",
|
|
14
|
+
}, [h("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })]);
|
|
15
|
+
}
|
|
16
|
+
function CircleCheckIcon(size) {
|
|
17
|
+
return h("svg", {
|
|
18
|
+
width: size,
|
|
19
|
+
height: size,
|
|
20
|
+
viewBox: "0 0 24 24",
|
|
21
|
+
fill: "none",
|
|
22
|
+
stroke: "currentColor",
|
|
23
|
+
"stroke-width": 2,
|
|
24
|
+
"stroke-linecap": "round",
|
|
25
|
+
"stroke-linejoin": "round",
|
|
26
|
+
"aria-hidden": "true",
|
|
27
|
+
}, [
|
|
28
|
+
h("circle", { cx: "12", cy: "12", r: "10" }),
|
|
29
|
+
h("path", { d: "m9 12 2 2 4-4" }),
|
|
30
|
+
]);
|
|
31
|
+
}
|
|
32
|
+
function CircleAlertIcon(size) {
|
|
33
|
+
return h("svg", {
|
|
34
|
+
width: size,
|
|
35
|
+
height: size,
|
|
36
|
+
viewBox: "0 0 24 24",
|
|
37
|
+
fill: "none",
|
|
38
|
+
stroke: "currentColor",
|
|
39
|
+
"stroke-width": 2,
|
|
40
|
+
"stroke-linecap": "round",
|
|
41
|
+
"stroke-linejoin": "round",
|
|
42
|
+
"aria-hidden": "true",
|
|
43
|
+
}, [
|
|
44
|
+
h("circle", { cx: "12", cy: "12", r: "10" }),
|
|
45
|
+
h("line", { x1: "12", x2: "12", y1: "8", y2: "12" }),
|
|
46
|
+
h("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" }),
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
export const Autosave = defineComponent({
|
|
50
|
+
name: "Autosave",
|
|
51
|
+
props: {
|
|
52
|
+
status: { type: String, default: "idle" },
|
|
53
|
+
lastSaved: { type: [String, Date], default: undefined },
|
|
54
|
+
onRetry: { type: Function, default: undefined },
|
|
55
|
+
labels: { type: Object, default: undefined },
|
|
56
|
+
retryLabel: { type: String, default: undefined },
|
|
57
|
+
locale: { type: String, default: "fr-FR" },
|
|
58
|
+
class: { type: String, default: undefined },
|
|
59
|
+
},
|
|
60
|
+
emits: ["retry"],
|
|
61
|
+
setup(props, { emit, attrs }) {
|
|
62
|
+
return () => {
|
|
63
|
+
const status = props.status;
|
|
64
|
+
const locale = props.locale;
|
|
65
|
+
const isFr = (locale ?? "fr-FR").toLowerCase().startsWith("fr");
|
|
66
|
+
const DEFAULT_LABELS = isFr
|
|
67
|
+
? {
|
|
68
|
+
idle: "Modifications enregistrées",
|
|
69
|
+
saving: "Enregistrement…",
|
|
70
|
+
saved: "Enregistré",
|
|
71
|
+
error: "Échec de l'enregistrement",
|
|
72
|
+
}
|
|
73
|
+
: {
|
|
74
|
+
idle: "All changes saved",
|
|
75
|
+
saving: "Saving…",
|
|
76
|
+
saved: "Saved",
|
|
77
|
+
error: "Failed to save",
|
|
78
|
+
};
|
|
79
|
+
const resolvedRetryLabel = props.retryLabel ?? (isFr ? "Réessayer" : "Retry");
|
|
80
|
+
const statusLabel = props.labels?.[status] ?? DEFAULT_LABELS[status];
|
|
81
|
+
const role = status === "error" ? "alert" : "status";
|
|
82
|
+
// Heure relative de la dernière sauvegarde (rendu uniquement sur idle/saved).
|
|
83
|
+
const relativeTime = (() => {
|
|
84
|
+
if (!props.lastSaved)
|
|
85
|
+
return "";
|
|
86
|
+
const date = props.lastSaved instanceof Date ? props.lastSaved : new Date(props.lastSaved);
|
|
87
|
+
if (Number.isNaN(date.getTime()))
|
|
88
|
+
return "";
|
|
89
|
+
const diffMs = Date.now() - date.getTime();
|
|
90
|
+
const diffSec = Math.round(diffMs / 1000);
|
|
91
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
|
|
92
|
+
if (Math.abs(diffSec) < 60)
|
|
93
|
+
return rtf.format(-diffSec, "second");
|
|
94
|
+
const diffMin = Math.round(diffSec / 60);
|
|
95
|
+
if (Math.abs(diffMin) < 60)
|
|
96
|
+
return rtf.format(-diffMin, "minute");
|
|
97
|
+
const diffHour = Math.round(diffMin / 60);
|
|
98
|
+
if (Math.abs(diffHour) < 24)
|
|
99
|
+
return rtf.format(-diffHour, "hour");
|
|
100
|
+
const diffDay = Math.round(diffHour / 24);
|
|
101
|
+
return rtf.format(-diffDay, "day");
|
|
102
|
+
})();
|
|
103
|
+
const showRelative = (status === "saved" || status === "idle") && relativeTime !== "";
|
|
104
|
+
const icon = status === "saving"
|
|
105
|
+
? h("span", { class: "st-autosave__spinner" }, [LoaderCircleIcon(16)])
|
|
106
|
+
: status === "saved"
|
|
107
|
+
? CircleCheckIcon(16)
|
|
108
|
+
: status === "error"
|
|
109
|
+
? CircleAlertIcon(16)
|
|
110
|
+
: null;
|
|
111
|
+
const triggerRetry = () => {
|
|
112
|
+
emit("retry");
|
|
113
|
+
props.onRetry?.();
|
|
114
|
+
};
|
|
115
|
+
return h("div", {
|
|
116
|
+
...attrs,
|
|
117
|
+
class: classNames("st-autosave", `st-autosave--${status}`, props.class),
|
|
118
|
+
role,
|
|
119
|
+
"aria-live": "polite",
|
|
120
|
+
}, [
|
|
121
|
+
h("span", { class: "st-autosave__icon", "aria-hidden": "true" }, [icon]),
|
|
122
|
+
h("span", { class: "st-autosave__label" }, statusLabel),
|
|
123
|
+
showRelative
|
|
124
|
+
? h("span", { class: "st-autosave__time" }, relativeTime)
|
|
125
|
+
: null,
|
|
126
|
+
status === "error" && props.onRetry
|
|
127
|
+
? h("button", {
|
|
128
|
+
type: "button",
|
|
129
|
+
class: "st-autosave__retry",
|
|
130
|
+
onClick: triggerRetry,
|
|
131
|
+
}, resolvedRetryLabel)
|
|
132
|
+
: null,
|
|
133
|
+
]);
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
//# sourceMappingURL=Autosave.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Autosave.js","sourceRoot":"","sources":["../src/Autosave.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA2B7C,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,CAAC,CACN,KAAK,EACL;QACE,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,WAAW;QACpB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,cAAc;QACtB,cAAc,EAAE,CAAC;QACjB,gBAAgB,EAAE,OAAO;QACzB,iBAAiB,EAAE,OAAO;QAC1B,aAAa,EAAE,MAAM;KACtB,EACD,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,6BAA6B,EAAE,CAAC,CAAC,CAClD,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,CAAC,CACN,KAAK,EACL;QACE,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,WAAW;QACpB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,cAAc;QACtB,cAAc,EAAE,CAAC;QACjB,gBAAgB,EAAE,OAAO;QACzB,iBAAiB,EAAE,OAAO;QAC1B,aAAa,EAAE,MAAM;KACtB,EACD;QACE,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;QAC5C,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC;KAClC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,CAAC,CACN,KAAK,EACL;QACE,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,WAAW;QACpB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,cAAc;QACtB,cAAc,EAAE,CAAC;QACjB,gBAAgB,EAAE,OAAO;QACzB,iBAAiB,EAAE,OAAO;QAC1B,aAAa,EAAE,MAAM;KACtB,EACD;QACE,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;QAC5C,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACpD,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;KACzD,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,eAAe,CAAC;IACtC,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE;QACL,MAAM,EAAE,EAAE,IAAI,EAAE,MAA8B,EAAE,OAAO,EAAE,MAAM,EAAE;QACjE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,IAAI,CAAmC,EAAE,OAAO,EAAE,SAAS,EAAE;QACzF,OAAO,EAAE,EAAE,IAAI,EAAE,QAAuC,EAAE,OAAO,EAAE,SAAS,EAAE;QAC9E,MAAM,EAAE,EAAE,IAAI,EAAE,MAA8B,EAAE,OAAO,EAAE,SAAS,EAAE;QACpE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE;QAChD,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE;QAC1C,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE;KAC5C;IACD,KAAK,EAAE,CAAC,OAAO,CAAC;IAChB,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QAC1B,OAAO,GAAG,EAAE;YACV,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC5B,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAChE,MAAM,cAAc,GAA6B,IAAI;gBACnD,CAAC,CAAC;oBACE,IAAI,EAAE,4BAA4B;oBAClC,MAAM,EAAE,iBAAiB;oBACzB,KAAK,EAAE,YAAY;oBACnB,KAAK,EAAE,2BAA2B;iBACnC;gBACH,CAAC,CAAC;oBACE,IAAI,EAAE,mBAAmB;oBACzB,MAAM,EAAE,SAAS;oBACjB,KAAK,EAAE,OAAO;oBACd,KAAK,EAAE,gBAAgB;iBACxB,CAAC;YACN,MAAM,kBAAkB,GAAG,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC9E,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;YACrE,MAAM,IAAI,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;YAErD,8EAA8E;YAC9E,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE;gBACzB,IAAI,CAAC,KAAK,CAAC,SAAS;oBAAE,OAAO,EAAE,CAAC;gBAChC,MAAM,IAAI,GACR,KAAK,CAAC,SAAS,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAChF,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBAAE,OAAO,EAAE,CAAC;gBAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;gBAC1C,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;gBACrE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE;oBAAE,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBAClE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;gBACzC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE;oBAAE,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;gBAC1C,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE;oBAAE,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAClE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;gBAC1C,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC,CAAC,EAAE,CAAC;YACL,MAAM,YAAY,GAChB,CAAC,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,YAAY,KAAK,EAAE,CAAC;YAEnE,MAAM,IAAI,GACR,MAAM,KAAK,QAAQ;gBACjB,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC;gBACtE,CAAC,CAAC,MAAM,KAAK,OAAO;oBAClB,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC;oBACrB,CAAC,CAAC,MAAM,KAAK,OAAO;wBAClB,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC;wBACrB,CAAC,CAAC,IAAI,CAAC;YAEf,MAAM,YAAY,GAAG,GAAG,EAAE;gBACxB,IAAI,CAAC,OAAO,CAAC,CAAC;gBACd,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YACpB,CAAC,CAAC;YAEF,OAAO,CAAC,CACN,KAAK,EACL;gBACE,GAAG,KAAK;gBACR,KAAK,EAAE,UAAU,CAAC,aAAa,EAAE,gBAAgB,MAAM,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC;gBACvE,IAAI;gBACJ,WAAW,EAAE,QAAQ;aACtB,EACD;gBACE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;gBACxE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,WAAW,CAAC;gBACvD,YAAY;oBACV,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,YAAY,CAAC;oBACzD,CAAC,CAAC,IAAI;gBACR,MAAM,KAAK,OAAO,IAAI,KAAK,CAAC,OAAO;oBACjC,CAAC,CAAC,CAAC,CACC,QAAQ,EACR;wBACE,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,oBAAoB;wBAC3B,OAAO,EAAE,YAAY;qBACtB,EACD,kBAAkB,CACnB;oBACH,CAAC,CAAC,IAAI;aACT,CACF,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* En mode simple : `string | null` ("YYYY-MM-DD").
|
|
3
|
+
* En mode plage (`range`) : tuple `[start, end]` où chaque borne est
|
|
4
|
+
* "YYYY-MM-DD" ou null.
|
|
5
|
+
*/
|
|
6
|
+
export type CalendarValue = string | null | [string | null, string | null];
|
|
7
|
+
export type CalendarProps = {
|
|
8
|
+
/** Date sélectionnée ("YYYY-MM-DD") ou tuple [start,end] si `range`. */
|
|
9
|
+
value?: CalendarValue;
|
|
10
|
+
/** Appelé avec la nouvelle date (ou le tuple en mode plage). */
|
|
11
|
+
onChange?: (value: CalendarValue) => void;
|
|
12
|
+
/** Borne minimale "YYYY-MM-DD" (inclusive). */
|
|
13
|
+
min?: string;
|
|
14
|
+
/** Borne maximale "YYYY-MM-DD" (inclusive). */
|
|
15
|
+
max?: string;
|
|
16
|
+
/** Sélection d'une plage de deux dates. */
|
|
17
|
+
range?: boolean;
|
|
18
|
+
/** Premier jour de la semaine : 0 = dimanche, 1 = lundi. */
|
|
19
|
+
weekStartsOn?: 0 | 1;
|
|
20
|
+
locale?: string;
|
|
21
|
+
/** Mois affiché ("YYYY-MM"), contrôlable de l'extérieur. */
|
|
22
|
+
month?: string;
|
|
23
|
+
class?: string;
|
|
24
|
+
previousMonthLabel?: string;
|
|
25
|
+
nextMonthLabel?: string;
|
|
26
|
+
};
|
|
27
|
+
export declare const Calendar: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
28
|
+
value: {
|
|
29
|
+
type: () => CalendarValue;
|
|
30
|
+
default: null;
|
|
31
|
+
};
|
|
32
|
+
onChange: {
|
|
33
|
+
type: () => (value: CalendarValue) => void;
|
|
34
|
+
default: undefined;
|
|
35
|
+
};
|
|
36
|
+
min: {
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
default: undefined;
|
|
39
|
+
};
|
|
40
|
+
max: {
|
|
41
|
+
type: StringConstructor;
|
|
42
|
+
default: undefined;
|
|
43
|
+
};
|
|
44
|
+
range: {
|
|
45
|
+
type: BooleanConstructor;
|
|
46
|
+
default: boolean;
|
|
47
|
+
};
|
|
48
|
+
weekStartsOn: {
|
|
49
|
+
type: () => 0 | 1;
|
|
50
|
+
default: number;
|
|
51
|
+
};
|
|
52
|
+
locale: {
|
|
53
|
+
type: StringConstructor;
|
|
54
|
+
default: string;
|
|
55
|
+
};
|
|
56
|
+
month: {
|
|
57
|
+
type: StringConstructor;
|
|
58
|
+
default: undefined;
|
|
59
|
+
};
|
|
60
|
+
class: {
|
|
61
|
+
type: StringConstructor;
|
|
62
|
+
default: undefined;
|
|
63
|
+
};
|
|
64
|
+
previousMonthLabel: {
|
|
65
|
+
type: StringConstructor;
|
|
66
|
+
default: undefined;
|
|
67
|
+
};
|
|
68
|
+
nextMonthLabel: {
|
|
69
|
+
type: StringConstructor;
|
|
70
|
+
default: undefined;
|
|
71
|
+
};
|
|
72
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
73
|
+
[key: string]: any;
|
|
74
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("change" | "update:modelValue")[], "change" | "update:modelValue", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
75
|
+
value: {
|
|
76
|
+
type: () => CalendarValue;
|
|
77
|
+
default: null;
|
|
78
|
+
};
|
|
79
|
+
onChange: {
|
|
80
|
+
type: () => (value: CalendarValue) => void;
|
|
81
|
+
default: undefined;
|
|
82
|
+
};
|
|
83
|
+
min: {
|
|
84
|
+
type: StringConstructor;
|
|
85
|
+
default: undefined;
|
|
86
|
+
};
|
|
87
|
+
max: {
|
|
88
|
+
type: StringConstructor;
|
|
89
|
+
default: undefined;
|
|
90
|
+
};
|
|
91
|
+
range: {
|
|
92
|
+
type: BooleanConstructor;
|
|
93
|
+
default: boolean;
|
|
94
|
+
};
|
|
95
|
+
weekStartsOn: {
|
|
96
|
+
type: () => 0 | 1;
|
|
97
|
+
default: number;
|
|
98
|
+
};
|
|
99
|
+
locale: {
|
|
100
|
+
type: StringConstructor;
|
|
101
|
+
default: string;
|
|
102
|
+
};
|
|
103
|
+
month: {
|
|
104
|
+
type: StringConstructor;
|
|
105
|
+
default: undefined;
|
|
106
|
+
};
|
|
107
|
+
class: {
|
|
108
|
+
type: StringConstructor;
|
|
109
|
+
default: undefined;
|
|
110
|
+
};
|
|
111
|
+
previousMonthLabel: {
|
|
112
|
+
type: StringConstructor;
|
|
113
|
+
default: undefined;
|
|
114
|
+
};
|
|
115
|
+
nextMonthLabel: {
|
|
116
|
+
type: StringConstructor;
|
|
117
|
+
default: undefined;
|
|
118
|
+
};
|
|
119
|
+
}>> & Readonly<{
|
|
120
|
+
onChange?: ((...args: any[]) => any) | undefined;
|
|
121
|
+
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
122
|
+
}>, {
|
|
123
|
+
class: string;
|
|
124
|
+
onChange: (value: CalendarValue) => void;
|
|
125
|
+
min: string;
|
|
126
|
+
max: string;
|
|
127
|
+
locale: string;
|
|
128
|
+
month: string;
|
|
129
|
+
range: boolean;
|
|
130
|
+
value: CalendarValue;
|
|
131
|
+
weekStartsOn: 0 | 1;
|
|
132
|
+
previousMonthLabel: string;
|
|
133
|
+
nextMonthLabel: string;
|
|
134
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
135
|
+
//# sourceMappingURL=Calendar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Calendar.d.ts","sourceRoot":"","sources":["../src/Calendar.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAI3E,MAAM,MAAM,aAAa,GAAG;IAC1B,wEAAwE;IACxE,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAoEF,eAAO,MAAM,QAAQ;;cAI6B,MAAM,aAAa;;;;cAIlC,MAAM,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI;;;;;;;;;;;;;;;;cAMnC,MAAM,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;cAVG,MAAM,aAAa;;;;cAIlC,MAAM,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI;;;;;;;;;;;;;;;;cAMnC,MAAM,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBANE,aAAa,KAAK,IAAI;;;;;;;;;;4EA0QrE,CAAC"}
|
package/dist/Calendar.js
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { defineComponent, h, ref, watch } from "vue";
|
|
2
|
+
import { classNames } from "./classNames.js";
|
|
3
|
+
function calStartOfDay(date) {
|
|
4
|
+
const d = new Date(date);
|
|
5
|
+
d.setHours(0, 0, 0, 0);
|
|
6
|
+
return d;
|
|
7
|
+
}
|
|
8
|
+
function calToISO(date) {
|
|
9
|
+
const y = date.getFullYear();
|
|
10
|
+
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
11
|
+
const d = String(date.getDate()).padStart(2, "0");
|
|
12
|
+
return `${y}-${m}-${d}`;
|
|
13
|
+
}
|
|
14
|
+
function calParseISO(iso) {
|
|
15
|
+
if (!iso)
|
|
16
|
+
return null;
|
|
17
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(iso);
|
|
18
|
+
if (!match)
|
|
19
|
+
return null;
|
|
20
|
+
const d = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
|
|
21
|
+
return Number.isNaN(d.getTime()) ? null : calStartOfDay(d);
|
|
22
|
+
}
|
|
23
|
+
function calIsSameDay(a, b) {
|
|
24
|
+
if (!a || !b)
|
|
25
|
+
return false;
|
|
26
|
+
return (a.getFullYear() === b.getFullYear() &&
|
|
27
|
+
a.getMonth() === b.getMonth() &&
|
|
28
|
+
a.getDate() === b.getDate());
|
|
29
|
+
}
|
|
30
|
+
function ChevronLeftIcon(size) {
|
|
31
|
+
return h("svg", {
|
|
32
|
+
width: size,
|
|
33
|
+
height: size,
|
|
34
|
+
viewBox: "0 0 24 24",
|
|
35
|
+
fill: "none",
|
|
36
|
+
stroke: "currentColor",
|
|
37
|
+
"stroke-width": 2,
|
|
38
|
+
"stroke-linecap": "round",
|
|
39
|
+
"stroke-linejoin": "round",
|
|
40
|
+
"aria-hidden": "true",
|
|
41
|
+
}, [h("polyline", { points: "15 18 9 12 15 6" })]);
|
|
42
|
+
}
|
|
43
|
+
function ChevronRightIcon(size) {
|
|
44
|
+
return h("svg", {
|
|
45
|
+
width: size,
|
|
46
|
+
height: size,
|
|
47
|
+
viewBox: "0 0 24 24",
|
|
48
|
+
fill: "none",
|
|
49
|
+
stroke: "currentColor",
|
|
50
|
+
"stroke-width": 2,
|
|
51
|
+
"stroke-linecap": "round",
|
|
52
|
+
"stroke-linejoin": "round",
|
|
53
|
+
"aria-hidden": "true",
|
|
54
|
+
}, [h("polyline", { points: "9 18 15 12 9 6" })]);
|
|
55
|
+
}
|
|
56
|
+
export const Calendar = defineComponent({
|
|
57
|
+
name: "Calendar",
|
|
58
|
+
props: {
|
|
59
|
+
value: {
|
|
60
|
+
type: [String, Array, Object],
|
|
61
|
+
default: null,
|
|
62
|
+
},
|
|
63
|
+
onChange: {
|
|
64
|
+
type: Function,
|
|
65
|
+
default: undefined,
|
|
66
|
+
},
|
|
67
|
+
min: { type: String, default: undefined },
|
|
68
|
+
max: { type: String, default: undefined },
|
|
69
|
+
range: { type: Boolean, default: false },
|
|
70
|
+
weekStartsOn: { type: Number, default: 1 },
|
|
71
|
+
locale: { type: String, default: "fr-FR" },
|
|
72
|
+
month: { type: String, default: undefined },
|
|
73
|
+
class: { type: String, default: undefined },
|
|
74
|
+
previousMonthLabel: { type: String, default: undefined },
|
|
75
|
+
nextMonthLabel: { type: String, default: undefined },
|
|
76
|
+
},
|
|
77
|
+
emits: ["change", "update:modelValue"],
|
|
78
|
+
setup(props, { emit, attrs }) {
|
|
79
|
+
const internal = ref(props.value ?? null);
|
|
80
|
+
const pickInitialMonth = () => {
|
|
81
|
+
const parsed = calParseISO(props.month ? `${props.month}-01` : undefined);
|
|
82
|
+
if (parsed)
|
|
83
|
+
return parsed;
|
|
84
|
+
const v = props.value ?? internal.value;
|
|
85
|
+
if (!props.range) {
|
|
86
|
+
const single = calParseISO(v);
|
|
87
|
+
if (single)
|
|
88
|
+
return single;
|
|
89
|
+
}
|
|
90
|
+
else if (Array.isArray(v)) {
|
|
91
|
+
const start = calParseISO(v[0]);
|
|
92
|
+
if (start)
|
|
93
|
+
return start;
|
|
94
|
+
}
|
|
95
|
+
return calStartOfDay(new Date());
|
|
96
|
+
};
|
|
97
|
+
const initial = pickInitialMonth();
|
|
98
|
+
const viewYear = ref(initial.getFullYear());
|
|
99
|
+
const viewMonth = ref(initial.getMonth());
|
|
100
|
+
// Resynchronise le mois affiché lorsque la prop `month` change.
|
|
101
|
+
watch(() => props.month, (m) => {
|
|
102
|
+
const parsed = calParseISO(m ? `${m}-01` : undefined);
|
|
103
|
+
if (parsed) {
|
|
104
|
+
viewYear.value = parsed.getFullYear();
|
|
105
|
+
viewMonth.value = parsed.getMonth();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
const previousMonth = () => {
|
|
109
|
+
if (viewMonth.value === 0) {
|
|
110
|
+
viewMonth.value = 11;
|
|
111
|
+
viewYear.value -= 1;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
viewMonth.value -= 1;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const nextMonth = () => {
|
|
118
|
+
if (viewMonth.value === 11) {
|
|
119
|
+
viewMonth.value = 0;
|
|
120
|
+
viewYear.value += 1;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
viewMonth.value += 1;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
return () => {
|
|
127
|
+
const activeValue = props.value ?? internal.value;
|
|
128
|
+
const locale = props.locale;
|
|
129
|
+
const isFr = (locale ?? "fr-FR").toLowerCase().startsWith("fr");
|
|
130
|
+
const resolvedPrevLabel = props.previousMonthLabel ?? (isFr ? "Mois précédent" : "Previous month");
|
|
131
|
+
const resolvedNextLabel = props.nextMonthLabel ?? (isFr ? "Mois suivant" : "Next month");
|
|
132
|
+
const monthFormatter = new Intl.DateTimeFormat(locale, {
|
|
133
|
+
month: "long",
|
|
134
|
+
year: "numeric",
|
|
135
|
+
});
|
|
136
|
+
const weekdayFormatter = new Intl.DateTimeFormat(locale, { weekday: "short" });
|
|
137
|
+
const cellFormatter = new Intl.DateTimeFormat(locale, {
|
|
138
|
+
day: "numeric",
|
|
139
|
+
month: "long",
|
|
140
|
+
year: "numeric",
|
|
141
|
+
});
|
|
142
|
+
const single = props.range ? null : calParseISO(activeValue);
|
|
143
|
+
const rangeStart = props.range && Array.isArray(activeValue) ? calParseISO(activeValue[0]) : null;
|
|
144
|
+
const rangeEnd = props.range && Array.isArray(activeValue) ? calParseISO(activeValue[1]) : null;
|
|
145
|
+
const today = calStartOfDay(new Date());
|
|
146
|
+
// 2024-01-07 est un dimanche : on énumère puis on tourne selon weekStartsOn.
|
|
147
|
+
const sample = new Date(Date.UTC(2024, 0, 7));
|
|
148
|
+
const rawLabels = [];
|
|
149
|
+
for (let i = 0; i < 7; i++) {
|
|
150
|
+
const d = new Date(sample);
|
|
151
|
+
d.setUTCDate(sample.getUTCDate() + i);
|
|
152
|
+
rawLabels.push(weekdayFormatter.format(d));
|
|
153
|
+
}
|
|
154
|
+
const weekdayLabels = [
|
|
155
|
+
...rawLabels.slice(props.weekStartsOn),
|
|
156
|
+
...rawLabels.slice(0, props.weekStartsOn),
|
|
157
|
+
];
|
|
158
|
+
const first = new Date(viewYear.value, viewMonth.value, 1);
|
|
159
|
+
const firstDayIdx = first.getDay();
|
|
160
|
+
const offset = (firstDayIdx - props.weekStartsOn + 7) % 7;
|
|
161
|
+
const start = new Date(viewYear.value, viewMonth.value, 1 - offset);
|
|
162
|
+
const grid = [];
|
|
163
|
+
for (let i = 0; i < 42; i++) {
|
|
164
|
+
const d = new Date(start);
|
|
165
|
+
d.setDate(start.getDate() + i);
|
|
166
|
+
grid.push({ date: calStartOfDay(d), inMonth: d.getMonth() === viewMonth.value });
|
|
167
|
+
}
|
|
168
|
+
const minDate = calParseISO(props.min);
|
|
169
|
+
const maxDate = calParseISO(props.max);
|
|
170
|
+
const isOutOfBounds = (date) => {
|
|
171
|
+
const d = calStartOfDay(date).getTime();
|
|
172
|
+
if (minDate && d < minDate.getTime())
|
|
173
|
+
return true;
|
|
174
|
+
if (maxDate && d > maxDate.getTime())
|
|
175
|
+
return true;
|
|
176
|
+
return false;
|
|
177
|
+
};
|
|
178
|
+
const isSelected = (date) => {
|
|
179
|
+
if (!props.range)
|
|
180
|
+
return calIsSameDay(single, date);
|
|
181
|
+
return calIsSameDay(rangeStart, date) || calIsSameDay(rangeEnd, date);
|
|
182
|
+
};
|
|
183
|
+
const isInRange = (date) => {
|
|
184
|
+
if (!props.range || !rangeStart || !rangeEnd)
|
|
185
|
+
return false;
|
|
186
|
+
const d = calStartOfDay(date).getTime();
|
|
187
|
+
return d > rangeStart.getTime() && d < rangeEnd.getTime();
|
|
188
|
+
};
|
|
189
|
+
const commit = (next) => {
|
|
190
|
+
if (props.value === undefined)
|
|
191
|
+
internal.value = next;
|
|
192
|
+
emit("update:modelValue", next);
|
|
193
|
+
emit("change", next);
|
|
194
|
+
props.onChange?.(next);
|
|
195
|
+
};
|
|
196
|
+
const pickDate = (date) => {
|
|
197
|
+
if (isOutOfBounds(date))
|
|
198
|
+
return;
|
|
199
|
+
const picked = calStartOfDay(date);
|
|
200
|
+
const iso = calToISO(picked);
|
|
201
|
+
if (!props.range) {
|
|
202
|
+
commit(iso);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// Mode plage : (re)démarrage si pas de début, ou si plage déjà complète,
|
|
206
|
+
// ou si la date est antérieure au début courant.
|
|
207
|
+
if (!rangeStart || (rangeStart && rangeEnd) || picked.getTime() < rangeStart.getTime()) {
|
|
208
|
+
commit([iso, null]);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
commit([calToISO(rangeStart), iso]);
|
|
212
|
+
};
|
|
213
|
+
const monthLabel = monthFormatter.format(new Date(viewYear.value, viewMonth.value, 1));
|
|
214
|
+
return h("div", { ...attrs, class: classNames("st-calendar", props.class) }, [
|
|
215
|
+
h("div", { class: "st-calendar__nav" }, [
|
|
216
|
+
h("button", {
|
|
217
|
+
type: "button",
|
|
218
|
+
class: "st-calendar__navBtn",
|
|
219
|
+
"aria-label": resolvedPrevLabel,
|
|
220
|
+
onClick: previousMonth,
|
|
221
|
+
}, [ChevronLeftIcon(18)]),
|
|
222
|
+
h("span", { class: "st-calendar__monthLabel", "aria-live": "polite" }, monthLabel),
|
|
223
|
+
h("button", {
|
|
224
|
+
type: "button",
|
|
225
|
+
class: "st-calendar__navBtn",
|
|
226
|
+
"aria-label": resolvedNextLabel,
|
|
227
|
+
onClick: nextMonth,
|
|
228
|
+
}, [ChevronRightIcon(18)]),
|
|
229
|
+
]),
|
|
230
|
+
h("div", {
|
|
231
|
+
class: "st-calendar__grid",
|
|
232
|
+
role: "grid",
|
|
233
|
+
tabindex: -1,
|
|
234
|
+
"aria-label": monthLabel,
|
|
235
|
+
onKeydown: (event) => {
|
|
236
|
+
if (event.key === "PageUp") {
|
|
237
|
+
event.preventDefault();
|
|
238
|
+
previousMonth();
|
|
239
|
+
}
|
|
240
|
+
else if (event.key === "PageDown") {
|
|
241
|
+
event.preventDefault();
|
|
242
|
+
nextMonth();
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
}, [
|
|
246
|
+
h("div", { class: "st-calendar__weekdays", role: "row" }, weekdayLabels.map((wd, i) => h("span", {
|
|
247
|
+
key: `${wd}-${i}`,
|
|
248
|
+
class: "st-calendar__weekday",
|
|
249
|
+
role: "columnheader",
|
|
250
|
+
}, wd))),
|
|
251
|
+
h("div", { class: "st-calendar__days" }, grid.map((cell, i) => {
|
|
252
|
+
const oob = isOutOfBounds(cell.date);
|
|
253
|
+
const selected = isSelected(cell.date);
|
|
254
|
+
const inRange = isInRange(cell.date);
|
|
255
|
+
const isToday = calIsSameDay(cell.date, today);
|
|
256
|
+
return h("button", {
|
|
257
|
+
key: i,
|
|
258
|
+
type: "button",
|
|
259
|
+
class: classNames("st-calendar__day", !cell.inMonth && "st-calendar__day--outside", selected && "st-calendar__day--selected", inRange && "st-calendar__day--inRange", isToday && "st-calendar__day--today"),
|
|
260
|
+
role: "gridcell",
|
|
261
|
+
"aria-label": cellFormatter.format(cell.date),
|
|
262
|
+
"aria-selected": selected ? "true" : "false",
|
|
263
|
+
"aria-current": isToday ? "date" : undefined,
|
|
264
|
+
"aria-disabled": oob ? "true" : undefined,
|
|
265
|
+
disabled: oob,
|
|
266
|
+
onClick: () => pickDate(cell.date),
|
|
267
|
+
}, String(cell.date.getDate()));
|
|
268
|
+
})),
|
|
269
|
+
]),
|
|
270
|
+
]);
|
|
271
|
+
};
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
//# sourceMappingURL=Calendar.js.map
|