ublo-lib 1.13.4 → 1.14.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.
@@ -0,0 +1,150 @@
1
+ import * as React from "react";
2
+ import { useUbloContext } from "ublo/with-ublo";
3
+ import Input from "dt-design-system/es/input";
4
+ import css from "./calendar-caption.module.css";
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+ const defaultColors = ["#234d5c", "#5F2EEA", "#0038FF", "#4ec3df", "#24C678", "#FFB648", "#F26464", "#FF005C", "#7C7B7B", "#222222"];
8
+ export default function CalendarCaption({
9
+ presets,
10
+ setPresets
11
+ }) {
12
+ const {
13
+ cmsMode
14
+ } = useUbloContext();
15
+ const initialColors = presets.colors ? Object.keys(presets.colors).map(key => presets.colors[key].backgroundColor) : defaultColors;
16
+ const [colors, setColors] = React.useState(initialColors);
17
+ const initialTextColors = presets.colors ? Object.keys(presets.colors).map(key => presets.colors[key].textColor) : [...new Array(colors.length)].fill("#ffffff");
18
+ const [textColors, setTextColors] = React.useState(initialTextColors);
19
+ const initialValues = presets.colors ? Object.keys(presets.colors).map(color => presets.colors[color].text) : [...new Array(colors.length)].fill("");
20
+ const [values, setValues] = React.useState(initialValues);
21
+ const isEditing = cmsMode === "editing";
22
+ React.useEffect(() => {
23
+ if (isEditing) {
24
+ const newPresets = {
25
+ colors: colors.reduce((acc, color, index) => {
26
+ return {
27
+ ...acc,
28
+ [index]: {
29
+ text: values[index],
30
+ backgroundColor: color,
31
+ textColor: textColors[index]
32
+ }
33
+ };
34
+ }, {})
35
+ };
36
+ setPresets(currentPresets => {
37
+ return {
38
+ ...currentPresets,
39
+ ...newPresets
40
+ };
41
+ });
42
+ }
43
+ }, [colors, isEditing, setPresets, textColors, values]);
44
+ return isEditing ? _jsx(Editor, {
45
+ colors: colors,
46
+ setColors: setColors,
47
+ values: values,
48
+ setValues: setValues,
49
+ textColors: textColors,
50
+ setTextColors: setTextColors
51
+ }) : _jsx(Caption, {
52
+ colors: colors,
53
+ values: values,
54
+ textColors: textColors
55
+ });
56
+ }
57
+ function Editor({
58
+ colors,
59
+ setColors,
60
+ values,
61
+ setValues,
62
+ textColors,
63
+ setTextColors
64
+ }) {
65
+ return _jsxs("div", {
66
+ className: css.root,
67
+ children: [colors.map((color, index) => {
68
+ const updateValue = value => {
69
+ setValues(prev => {
70
+ const newValues = [...prev];
71
+ newValues[index] = value;
72
+ return newValues;
73
+ });
74
+ };
75
+ const updateColor = e => {
76
+ const color = e.target.value;
77
+ setColors(prev => {
78
+ const newColors = [...prev];
79
+ newColors[index] = color;
80
+ return newColors;
81
+ });
82
+ };
83
+ const updateTextColor = e => {
84
+ const color = e.target.value;
85
+ setTextColors(prev => {
86
+ const newTextColors = [...prev];
87
+ newTextColors[index] = color;
88
+ return newTextColors;
89
+ });
90
+ };
91
+ return _jsxs("div", {
92
+ className: css.row,
93
+ children: [_jsx(Input, {
94
+ className: css.color,
95
+ style: {
96
+ color: textColors[index],
97
+ backgroundColor: color
98
+ },
99
+ placeholder: "Horaires",
100
+ onValueChange: updateValue,
101
+ value: values[index],
102
+ compact: true
103
+ }), _jsx("input", {
104
+ className: css.colorPicker,
105
+ type: "color",
106
+ value: color,
107
+ onChange: updateColor
108
+ }), _jsx("input", {
109
+ className: css.textColorPicker,
110
+ type: "color",
111
+ value: textColors[index],
112
+ onChange: updateTextColor,
113
+ list: "textColors"
114
+ }), _jsx("span", {
115
+ className: css.textPickerLabel,
116
+ children: "A"
117
+ })]
118
+ }, `${color}-${index}`);
119
+ }), _jsxs("datalist", {
120
+ id: "textColors",
121
+ children: [_jsx("option", {
122
+ children: "#000000"
123
+ }), _jsx("option", {
124
+ children: "#ffffff"
125
+ })]
126
+ })]
127
+ });
128
+ }
129
+ function Caption({
130
+ colors,
131
+ values,
132
+ textColors
133
+ }) {
134
+ return _jsx("div", {
135
+ className: css.root,
136
+ children: colors.map((color, index) => {
137
+ return _jsx("div", {
138
+ className: css.row,
139
+ children: _jsx("div", {
140
+ className: css.color,
141
+ style: {
142
+ color: textColors[index],
143
+ backgroundColor: color
144
+ },
145
+ children: values[index]
146
+ })
147
+ }, `${color}-${index}`);
148
+ })
149
+ });
150
+ }
@@ -0,0 +1,76 @@
1
+ .root {
2
+ flex: 0 0 auto;
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 3px;
6
+ }
7
+
8
+ .row {
9
+ position: relative;
10
+ display: flex;
11
+ align-items: center;
12
+ gap: 3px;
13
+ }
14
+
15
+ .color {
16
+ width: 140px;
17
+ height: 30px;
18
+ }
19
+
20
+ .color input::placeholder {
21
+ color: inherit;
22
+ }
23
+
24
+ div.color {
25
+ flex: 1 1 100%;
26
+ width: auto;
27
+ min-width: 140px;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ padding: 3px 8px;
32
+ text-align: center;
33
+ border-radius: var(--ds-radius-100, 4px);
34
+ }
35
+
36
+ div.color:empty {
37
+ display: none;
38
+ }
39
+
40
+ .color:has(input:focus) {
41
+ z-index: 2;
42
+ }
43
+
44
+ .colorPicker,
45
+ .textColorPicker {
46
+ flex: 0 0 30px;
47
+ width: 30px;
48
+ height: 30px;
49
+ padding: 0;
50
+ border: 0;
51
+ background-color: transparent;
52
+ cursor: pointer;
53
+ border-radius: var(--ds-radius-100, 4px);
54
+ }
55
+
56
+ .textColorPicker {
57
+ flex: 0 0 60px;
58
+ width: 60px;
59
+ appearance: none;
60
+ }
61
+
62
+ .colorPicker:focus {
63
+ z-index: 3;
64
+ }
65
+
66
+ .textPickerLabel {
67
+ position: absolute;
68
+ top: 6px;
69
+ right: 33px;
70
+ font-family: "Times New Roman", Times, serif;
71
+ font-size: 14px;
72
+ font-weight: 700;
73
+ color: rgb(255, 255, 255);
74
+ mix-blend-mode: difference;
75
+ pointer-events: none;
76
+ }
@@ -0,0 +1,84 @@
1
+ import * as React from "react";
2
+ import classnames from "classnames";
3
+ import { useUbloContext } from "ublo/with-ublo";
4
+ import * as Ripple from "dt-design-system/es/ripple";
5
+ import * as Utils from "./utils";
6
+ import css from "./calendar-date.module.css";
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ export default React.memo(CalendarDate);
9
+ function CalendarDate({
10
+ date,
11
+ month,
12
+ year,
13
+ minDate,
14
+ presets,
15
+ selecting,
16
+ setSelecting,
17
+ hoveredDates,
18
+ setHoveredDates
19
+ }) {
20
+ const {
21
+ cmsMode
22
+ } = useUbloContext();
23
+ const {
24
+ colors,
25
+ dates = {}
26
+ } = presets;
27
+ const isEditing = cmsMode === "editing";
28
+ const dateString = date.join("-");
29
+ const _date = new Date(dateString);
30
+ _date.setHours(0, 0, 0, 0);
31
+ const datesKeys = Object.keys(dates);
32
+ const isInPresets = datesKeys.includes(dateString);
33
+ const dateStyles = isInPresets ? {
34
+ color: colors[dates[dateString]].textColor,
35
+ backgroundColor: colors[dates[dateString]].backgroundColor
36
+ } : undefined;
37
+ const dateTooltip = isInPresets && !isEditing ? colors[dates[dateString]].text : undefined;
38
+ const isToday = Utils.isSameDay(_date);
39
+ const inMonth = month && year && Utils.isSameMonth(_date, new Date([Utils.zeroPad(year, 2), Utils.zeroPad(month, 2), "01"].join("-")));
40
+ const isDisabled = minDate && _date < minDate;
41
+ const createRipple = e => {
42
+ Ripple.create(e);
43
+ };
44
+ const startSelecting = e => {
45
+ if (isDisabled) return;
46
+ createRipple(e);
47
+ if (!isEditing) return;
48
+ setSelecting(true);
49
+ setHoveredDates([_date]);
50
+ };
51
+ const stopSelecting = () => {
52
+ if (!isEditing) return;
53
+ setSelecting(false);
54
+ };
55
+ const computeSelection = () => {
56
+ if (isDisabled || !isEditing || !selecting) return;
57
+ let startDate = hoveredDates[0];
58
+ const endDate = _date;
59
+ const isBefore = startDate.getTime() > endDate.getTime();
60
+ if (isBefore) {
61
+ startDate = hoveredDates[hoveredDates.length - 1];
62
+ }
63
+ const dates = Utils.getDateInterval(startDate, endDate, isBefore);
64
+ setHoveredDates(dates);
65
+ };
66
+ const classes = classnames(css.date, {
67
+ [css.dateToday]: isToday,
68
+ [css.dateNotInMonth]: !inMonth,
69
+ [css.dateDisabled]: isDisabled,
70
+ [css.dateHovered]: !!hoveredDates.find(item => {
71
+ return item.getTime() === _date.getTime();
72
+ })
73
+ });
74
+ return _jsx("button", {
75
+ className: classes,
76
+ tabIndex: isDisabled ? -1 : 0,
77
+ onMouseDown: startSelecting,
78
+ onMouseEnter: computeSelection,
79
+ onMouseUp: stopSelecting,
80
+ style: dateStyles,
81
+ "data-tooltip": dateTooltip,
82
+ children: _date.getDate()
83
+ });
84
+ }
@@ -0,0 +1,52 @@
1
+ .date {
2
+ position: relative;
3
+ width: 100%;
4
+ margin: 0;
5
+ padding: 8px 6px;
6
+ box-sizing: border-box;
7
+ font-size: 14px;
8
+ text-align: center;
9
+ color: var(--ds-grey-700, #262626);
10
+ background-color: transparent;
11
+ border: 0;
12
+ border-radius: var(--ds-radius-200, 8px);
13
+ cursor: pointer;
14
+ user-select: none;
15
+ outline: none;
16
+ transition: color 160ms
17
+ var(--ds-transition-easing, cubic-bezier(0.4, 0.1, 0.2, 0.9)),
18
+ background-color 160ms
19
+ var(--ds-transition-easing, cubic-bezier(0.4, 0.1, 0.2, 0.9)),
20
+ border-radius 160ms
21
+ var(--ds-transition-easing, cubic-bezier(0.4, 0.1, 0.2, 0.9));
22
+ }
23
+
24
+ .date:focus-visible {
25
+ outline: var(--ds-focus-ring-width, 2px) solid
26
+ var(--ds-focus-ring-color, var(--ds-blue-400, #0038ff));
27
+ outline-offset: var(--ds-focus-ring-offset, 2px);
28
+ }
29
+
30
+ .dateToday {
31
+ font-weight: 700;
32
+ }
33
+
34
+ .dateHovered {
35
+ color: var(--ds-white, #fff) !important;
36
+ background-color: var(--ds-secondary, var(--ds-blue-400, #0038ff)) !important;
37
+ }
38
+
39
+ .dateDisabled,
40
+ .dateDisabled.dateNotInMonth {
41
+ opacity: 0.25;
42
+ transform: translateZ(0);
43
+ cursor: not-allowed;
44
+ }
45
+
46
+ .dateNotInMonth {
47
+ opacity: 0.5;
48
+ }
49
+
50
+ .date:not(.dateDisabled, .dateHovered):hover {
51
+ background-color: var(--ds-grey-200, #ededed);
52
+ }
@@ -0,0 +1,89 @@
1
+ import * as React from "react";
2
+ import Button from "dt-design-system/es/button";
3
+ import * as Icons from "dt-design-system/es/icons";
4
+ import css from "./calendar-editor.module.css";
5
+ import * as Utils from "./utils";
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ import { jsxs as _jsxs } from "react/jsx-runtime";
8
+ export default function CalendarEditor({
9
+ presets,
10
+ setPresets,
11
+ hoveredDates,
12
+ closeEditor
13
+ }) {
14
+ const {
15
+ colors,
16
+ dates = {}
17
+ } = presets;
18
+ const formatedHoveredDates = hoveredDates.map(date => {
19
+ return Utils.formatDate(date);
20
+ });
21
+ const updateDates = colorIndex => () => {
22
+ const newDates = formatedHoveredDates.reduce((acc, date) => {
23
+ if (!colorIndex) return acc;
24
+ return {
25
+ ...acc,
26
+ [date]: colorIndex
27
+ };
28
+ }, {});
29
+ const newPresets = {
30
+ dates: {
31
+ ...dates,
32
+ ...newDates
33
+ }
34
+ };
35
+ if (!colorIndex) {
36
+ for (const date of formatedHoveredDates) {
37
+ delete newPresets.dates[date];
38
+ }
39
+ }
40
+ Object.keys(dates).forEach(key => {
41
+ const now = new Date();
42
+ const date = new Date(key);
43
+ if (date < now) {
44
+ delete newPresets.dates[key];
45
+ }
46
+ });
47
+ setPresets(currentPresets => {
48
+ return {
49
+ ...currentPresets,
50
+ ...newPresets
51
+ };
52
+ });
53
+ closeEditor();
54
+ };
55
+ return _jsxs("div", {
56
+ className: css.editor,
57
+ children: [_jsx(Button, {
58
+ variant: "transparent",
59
+ className: css.close,
60
+ onClick: closeEditor,
61
+ children: _jsx(Icons.Cross, {})
62
+ }), _jsxs("div", {
63
+ className: css.inner,
64
+ children: [_jsx(Button, {
65
+ variant: "transparent",
66
+ className: css.cleanup,
67
+ onClick: updateDates(),
68
+ children: "Aucun"
69
+ }), Object.keys(colors).map(key => {
70
+ const {
71
+ text,
72
+ backgroundColor,
73
+ textColor
74
+ } = colors[key];
75
+ if (!text) return null;
76
+ return _jsx(Button, {
77
+ variant: "secondary",
78
+ className: css.color,
79
+ style: {
80
+ color: textColor,
81
+ backgroundColor
82
+ },
83
+ onClick: updateDates(key),
84
+ children: text
85
+ }, key);
86
+ })]
87
+ })]
88
+ });
89
+ }
@@ -0,0 +1,38 @@
1
+ .editor {
2
+ position: absolute;
3
+ top: 0;
4
+ left: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ background-color: rgba(0, 0, 0, 0.75);
11
+ backdrop-filter: blur(var(--ds-blur, 8px));
12
+ padding: 20px;
13
+ border-radius: inherit;
14
+ z-index: 2;
15
+ }
16
+
17
+ .close {
18
+ position: absolute;
19
+ top: 8px;
20
+ right: 8px;
21
+ color: var(--ds-grey-000, #ffffff);
22
+ }
23
+
24
+ .inner {
25
+ width: 380px;
26
+ max-width: 100%;
27
+ display: flex;
28
+ align-items: flex-start;
29
+ flex-wrap: wrap;
30
+ gap: 4px;
31
+ padding: 16px;
32
+ background-color: var(--ds-grey-000, #ffffff);
33
+ border-radius: inherit;
34
+ }
35
+
36
+ .color {
37
+ flex: 1 1 auto;
38
+ }
@@ -0,0 +1,30 @@
1
+ import * as React from "react";
2
+ import Button from "dt-design-system/es/button";
3
+ import * as Icons from "dt-design-system/es/icons";
4
+ import css from "./calendar-header.module.css";
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+ export default function Header({
8
+ goToPreviousMonth,
9
+ goToNextMonth,
10
+ monthName,
11
+ year,
12
+ pastMonthDisabled
13
+ }) {
14
+ return _jsxs("div", {
15
+ className: css.header,
16
+ children: [_jsx(Button, {
17
+ className: css.control,
18
+ onClick: goToPreviousMonth,
19
+ disabled: !!pastMonthDisabled,
20
+ children: _jsx(Icons.ChevronLeft, {})
21
+ }), _jsxs("div", {
22
+ className: css.title,
23
+ children: [monthName, " ", year]
24
+ }), _jsx(Button, {
25
+ className: css.control,
26
+ onClick: goToNextMonth,
27
+ children: _jsx(Icons.ChevronRight, {})
28
+ })]
29
+ });
30
+ }
@@ -0,0 +1,20 @@
1
+ .header {
2
+ display: flex;
3
+ align-items: center;
4
+ }
5
+
6
+ button.control {
7
+ color: var(--ds-grey-600, #484848);
8
+ background-color: transparent;
9
+ }
10
+
11
+ .title {
12
+ margin: 0 auto;
13
+ color: var(--ds-grey-600, #484848);
14
+ font-weight: 700;
15
+ background-color: transparent;
16
+ }
17
+
18
+ button.control:not(:disabled):hover {
19
+ background-color: var(--ds-grey-100, #f8f8f8);
20
+ }
@@ -0,0 +1,127 @@
1
+ import * as React from "react";
2
+ import classnames from "classnames";
3
+ import Header from "./calendar-header";
4
+ import CalendarDate from "./calendar-date";
5
+ import CalendarEditor from "./calendar-editor";
6
+ import CalendarCaption from "./calendar-caption";
7
+ import * as Data from "./data";
8
+ import * as Utils from "./utils";
9
+ import css from "./calendar.module.css";
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { jsxs as _jsxs } from "react/jsx-runtime";
12
+ export default React.forwardRef(Calendar);
13
+ function Calendar({
14
+ lang = "fr",
15
+ format,
16
+ className
17
+ }, ref) {
18
+ const locale = lang || (typeof navigator !== "undefined" && navigator.language) === "fr" ? "fr" : "en";
19
+ const [presets, setPresets] = React.useState(format.presets);
20
+ React.useEffect(() => {
21
+ format.element.dataset.presets = JSON.stringify(presets);
22
+ }, [format, presets]);
23
+ const now = new Date();
24
+ const minDate = now;
25
+ if (minDate) minDate.setHours(0, 0, 0, 0);
26
+ const defaultMonth = Date.THIS_MONTH;
27
+ const currentMonth = getMonthFromPresets(presets?.dates);
28
+ const currentYear = Data.THIS_YEAR;
29
+ const [month, setMonth] = React.useState(currentMonth);
30
+ const [year, setYear] = React.useState(currentYear);
31
+ const [selecting, setSelecting] = React.useState(false);
32
+ const [hoveredDates, setHoveredDates] = React.useState([]);
33
+ const showAssociationEditor = !selecting && hoveredDates.length > 0;
34
+ const closeEditor = () => {
35
+ setSelecting(false);
36
+ setHoveredDates([]);
37
+ };
38
+ const resetSelection = () => {
39
+ if (!selecting) return;
40
+ setSelecting(false);
41
+ setHoveredDates([]);
42
+ };
43
+ const pastMonthDisabled = minDate && month <= minDate.getMonth() + 1 && year <= minDate.getFullYear() || minDate && month <= defaultMonth && year <= currentYear;
44
+ const i18nMonths = Data.MONTHS[locale];
45
+ const monthName = i18nMonths[Object.keys(i18nMonths)[month - 1]];
46
+ const i18nWeekDays = Data.WEEK_DAYS[locale];
47
+ const days = Object.keys(i18nWeekDays);
48
+ const calendarDates = Data.calendar(month, year);
49
+ const goToPreviousMonth = () => {
50
+ const {
51
+ month: newMonth,
52
+ year: newYear
53
+ } = Utils.getPreviousMonth(month, year);
54
+ setMonth(newMonth);
55
+ setYear(newYear);
56
+ };
57
+ const goToNextMonth = () => {
58
+ const {
59
+ month: newMonth,
60
+ year: newYear
61
+ } = Utils.getNextMonth(month, year);
62
+ setMonth(newMonth);
63
+ setYear(newYear);
64
+ };
65
+ const classes = classnames(css.root, className);
66
+ return _jsx("div", {
67
+ ref: ref,
68
+ className: classes,
69
+ "data-cms-remove": "",
70
+ children: _jsxs("div", {
71
+ className: css.outer,
72
+ children: [_jsxs("div", {
73
+ className: css.calendar,
74
+ children: [_jsxs("div", {
75
+ className: css.inner,
76
+ children: [_jsx(Header, {
77
+ goToPreviousMonth: goToPreviousMonth,
78
+ goToNextMonth: goToNextMonth,
79
+ monthName: monthName,
80
+ year: year,
81
+ pastMonthDisabled: pastMonthDisabled
82
+ }), _jsx("div", {
83
+ className: css.days,
84
+ children: days.map((day, i) => _jsx("div", {
85
+ className: css.day,
86
+ children: i18nWeekDays[day]
87
+ }, `${day}-${i}`))
88
+ }), _jsx("div", {
89
+ className: css.dates,
90
+ onMouseLeave: resetSelection,
91
+ children: calendarDates.map((date, i) => _jsx(CalendarDate, {
92
+ date: date,
93
+ month: month,
94
+ year: year,
95
+ minDate: minDate,
96
+ presets: presets,
97
+ setPresets: setPresets,
98
+ selecting: selecting,
99
+ setSelecting: setSelecting,
100
+ hoveredDates: hoveredDates,
101
+ setHoveredDates: setHoveredDates
102
+ }, i))
103
+ })]
104
+ }), showAssociationEditor && _jsx(CalendarEditor, {
105
+ presets: presets,
106
+ setPresets: setPresets,
107
+ hoveredDates: hoveredDates,
108
+ closeEditor: closeEditor
109
+ })]
110
+ }), _jsx(CalendarCaption, {
111
+ presets: presets,
112
+ setPresets: setPresets
113
+ })]
114
+ })
115
+ });
116
+ }
117
+ function getMonthFromPresets(dates = {}) {
118
+ const keys = Object.keys(dates);
119
+ if (keys.length === 0) return Data.THIS_MONTH;
120
+ const sortedKeys = keys.sort((a, b) => {
121
+ const dateA = new Date(a);
122
+ const dateB = new Date(b);
123
+ return dateA.getTime() - dateB.getTime();
124
+ });
125
+ const firstDate = new Date(sortedKeys[0]);
126
+ return firstDate.getMonth() + 1;
127
+ }
@@ -0,0 +1,80 @@
1
+ .root {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ }
6
+
7
+ .outer {
8
+ position: relative;
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ gap: 10px;
13
+ }
14
+
15
+ :global(body:not(.cms--editing) [data-caption-position="haut"]) .outer {
16
+ flex-direction: column;
17
+ }
18
+
19
+ :global(body:not(.cms--editing) [data-caption-position="haut"]) .outer {
20
+ flex-direction: column-reverse;
21
+ }
22
+
23
+ :global(body:not(.cms--editing) [data-caption-position="gauche"]) .outer {
24
+ flex-direction: row-reverse;
25
+ }
26
+
27
+ .calendar {
28
+ width: min-content;
29
+ padding: 6px;
30
+ box-sizing: border-box;
31
+ font-family: var(--ds-sans-serif-font, Montserrat, sans-serif);
32
+ background-color: var(--ds-grey-000, #fff);
33
+ border: 1px solid var(--ds-grey-100, #ebebeb);
34
+ border-radius: var(--ds-date-picker-radius, var(--ds-radius-200, 8px));
35
+ }
36
+
37
+ @media (min-width: 350px) {
38
+ .calendar {
39
+ padding: 14px;
40
+ }
41
+ }
42
+
43
+ .inner {
44
+ position: relative;
45
+ display: flex;
46
+ flex-direction: column;
47
+ gap: 10px;
48
+ }
49
+
50
+ .dates,
51
+ .days {
52
+ display: grid;
53
+ grid-template-columns: repeat(7, minmax(36px, 1fr));
54
+ gap: 3px;
55
+ }
56
+
57
+ @media (min-width: 350px) {
58
+ .dates,
59
+ .days {
60
+ grid-template-columns: repeat(7, minmax(40px, 1fr));
61
+ }
62
+ }
63
+
64
+ .days {
65
+ height: 34px;
66
+ align-items: center;
67
+ margin-bottom: 3px;
68
+ background-color: var(--ds-grey-100, #f8f8f8);
69
+ border-radius: var(--ds-radius-200, 8px);
70
+ }
71
+
72
+ .day {
73
+ color: var(--ds-grey-500, #7c7b7b);
74
+ font-size: 15px;
75
+ text-align: center;
76
+ font-weight: 700;
77
+ text-transform: uppercase;
78
+ transition: color 160ms
79
+ var(--ds-transition-easing, cubic-bezier(0.4, 0.1, 0.2, 0.9));
80
+ }
@@ -0,0 +1,112 @@
1
+ import * as Utils from "./utils";
2
+ export const THIS_YEAR = new Date().getFullYear();
3
+ export const THIS_MONTH = new Date().getMonth() + 1;
4
+ export const MONTHS = {
5
+ fr: {
6
+ january: "Janvier",
7
+ february: "Février",
8
+ march: "Mars",
9
+ april: "Avril",
10
+ may: "Mai",
11
+ june: "Juin",
12
+ july: "Juillet",
13
+ august: "Aout",
14
+ september: "Septembre",
15
+ october: "Octobre",
16
+ november: "Novembre",
17
+ december: "Décembre"
18
+ },
19
+ en: {
20
+ january: "January",
21
+ february: "February",
22
+ march: "March",
23
+ april: "April",
24
+ may: "May",
25
+ june: "June",
26
+ july: "July",
27
+ august: "August",
28
+ september: "September",
29
+ october: "October",
30
+ november: "November",
31
+ december: "December"
32
+ }
33
+ };
34
+ export const SHORT_MONTHS = {
35
+ fr: {
36
+ january: "Jan",
37
+ february: "Fév",
38
+ march: "Mar",
39
+ april: "Avr",
40
+ may: "Mai",
41
+ june: "Juin",
42
+ july: "Juil",
43
+ august: "Aou",
44
+ september: "Sept",
45
+ october: "Oct",
46
+ november: "Nov",
47
+ december: "Déc"
48
+ },
49
+ en: {
50
+ january: "Jan",
51
+ february: "Feb",
52
+ march: "Mar",
53
+ april: "Apr",
54
+ may: "May",
55
+ june: "Jun",
56
+ july: "Jul",
57
+ august: "Aug",
58
+ september: "Sept",
59
+ october: "Oct",
60
+ november: "Nov",
61
+ december: "Dec"
62
+ }
63
+ };
64
+ export const WEEK_DAYS = {
65
+ fr: {
66
+ monday: "L",
67
+ tuesday: "M",
68
+ wednesday: "M",
69
+ thursday: "J",
70
+ friday: "V",
71
+ saturday: "S",
72
+ sunday: "D"
73
+ },
74
+ en: {
75
+ monday: "M",
76
+ tuesday: "T",
77
+ wednesday: "W",
78
+ thursday: "T",
79
+ friday: "F",
80
+ saturday: "S",
81
+ sunday: "S"
82
+ }
83
+ };
84
+ export const CALENDAR_WEEKS = 6;
85
+ export function calendar(month = THIS_MONTH, year = THIS_YEAR) {
86
+ const monthDays = Utils.getMonthDays(month, year);
87
+ const monthFirstDay = Utils.getMonthFirstDay(month, year);
88
+ const daysFromPrevMonth = monthFirstDay === 0 ? 6 : monthFirstDay - 1;
89
+ const daysFromNextMonth = CALENDAR_WEEKS * 7 - (daysFromPrevMonth + monthDays);
90
+ const {
91
+ month: prevMonth,
92
+ year: prevMonthYear
93
+ } = Utils.getPreviousMonth(month, year);
94
+ const {
95
+ month: nextMonth,
96
+ year: nextMonthYear
97
+ } = Utils.getNextMonth(month, year);
98
+ const prevMonthDays = Utils.getMonthDays(prevMonth, prevMonthYear);
99
+ const prevMonthDates = [...new Array(daysFromPrevMonth)].map((_, i) => {
100
+ const day = i + 1 + (prevMonthDays - daysFromPrevMonth);
101
+ return [prevMonthYear, Utils.zeroPad(prevMonth, 2), Utils.zeroPad(day, 2)];
102
+ });
103
+ const thisMonthDates = [...new Array(monthDays)].map((_, i) => {
104
+ const day = i + 1;
105
+ return [year, Utils.zeroPad(month, 2), Utils.zeroPad(day, 2)];
106
+ });
107
+ const nextMonthDates = [...new Array(daysFromNextMonth)].map((_, i) => {
108
+ const day = i + 1;
109
+ return [nextMonthYear, Utils.zeroPad(nextMonth, 2), Utils.zeroPad(day, 2)];
110
+ });
111
+ return [...prevMonthDates, ...thisMonthDates, ...nextMonthDates];
112
+ }
@@ -0,0 +1,56 @@
1
+ import * as React from "react";
2
+ import * as ReactDOM from "react-dom";
3
+ import dynamic from "next/dynamic";
4
+ import { useUbloContext } from "ublo/with-ublo";
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ const Calendar = dynamic(() => import("./calendar"), {
7
+ ssr: false
8
+ });
9
+ export default function EditableCalendar() {
10
+ const {
11
+ lang,
12
+ path
13
+ } = useUbloContext();
14
+ const [formats, setFormats] = React.useState([]);
15
+ const refreshFormats = React.useCallback(() => {
16
+ setFormats([]);
17
+ const elements = document.querySelectorAll("section.editable-calendar");
18
+ if (elements.length) {
19
+ const formats = Array.from(elements).map(element => {
20
+ const storedPresets = element.dataset.presets;
21
+ const presets = storedPresets ? JSON.parse(storedPresets) : {};
22
+ return {
23
+ element,
24
+ presets
25
+ };
26
+ });
27
+ setFormats(formats);
28
+ }
29
+ }, []);
30
+ React.useEffect(() => {
31
+ refreshFormats();
32
+ }, [lang, path, refreshFormats]);
33
+ React.useEffect(() => {
34
+ const zones = Array.from(document.querySelectorAll(".cms"));
35
+ zones.forEach(zone => {
36
+ zone.addEventListener("ublo-section-created", refreshFormats);
37
+ zone.addEventListener("ublo-section-pasted", refreshFormats);
38
+ });
39
+ window.addEventListener("ublo-content-saved", reloadWindow);
40
+ return () => {
41
+ window.addEventListener("ublo-content-saved", reloadWindow);
42
+ zones.forEach(zone => {
43
+ zone.removeEventListener("ublo-section-created", refreshFormats);
44
+ zone.removeEventListener("ublo-section-pasted", refreshFormats);
45
+ });
46
+ };
47
+ }, [refreshFormats]);
48
+ if (!formats.length) return null;
49
+ return formats.map(format => ReactDOM.createPortal(_jsx(Calendar, {
50
+ lang: lang,
51
+ format: format
52
+ }), format.element));
53
+ }
54
+ function reloadWindow() {
55
+ window.location.reload();
56
+ }
@@ -0,0 +1,76 @@
1
+ import * as Data from "./data";
2
+ export function zeroPad(value, length) {
3
+ return `${value}`.padStart(length, "0");
4
+ }
5
+ export function formatDate(date) {
6
+ const d = new Date(date);
7
+ const day = zeroPad(d.getDate(), 2);
8
+ const month = zeroPad(d.getMonth() + 1, 2);
9
+ const year = d.getFullYear();
10
+ return `${year}-${month}-${day}`;
11
+ }
12
+ export function getYearsRange(start, end) {
13
+ return Array(end - start + 1).fill(undefined).map((_, i) => start + i);
14
+ }
15
+ export function getMonthDays(month = Data.THIS_MONTH, year = Data.THIS_YEAR) {
16
+ const months30 = [4, 6, 9, 11];
17
+ const leapYear = year % 4 === 0;
18
+ return month === 2 ? leapYear ? 29 : 28 : months30.includes(month) ? 30 : 31;
19
+ }
20
+ export function getMonthFirstDay(month = Data.THIS_MONTH, year = Data.THIS_YEAR) {
21
+ return new Date(`${year}-${zeroPad(month, 2)}-01`).getDay();
22
+ }
23
+ export function isDate(date) {
24
+ const isDate = Object.prototype.toString.call(date) === "[object Date]";
25
+ const isValidDate = date && !Number.isNaN(date.valueOf());
26
+ return isDate && isValidDate;
27
+ }
28
+ export function isSameMonth(date, basedate = new Date()) {
29
+ if (!(isDate(date) && isDate(basedate))) return false;
30
+ const basedateMonth = basedate.getMonth() + 1;
31
+ const basedateYear = basedate.getFullYear();
32
+ const dateMonth = date.getMonth() + 1;
33
+ const dateYear = date.getFullYear();
34
+ return basedateMonth === dateMonth && basedateYear === dateYear;
35
+ }
36
+ export function isSameDay(date, basedate = new Date()) {
37
+ if (!(isDate(date) && isDate(basedate))) return false;
38
+ const basedateDate = basedate.getDate();
39
+ const basedateMonth = basedate.getMonth() + 1;
40
+ const basedateYear = basedate.getFullYear();
41
+ const dateDate = date.getDate();
42
+ const dateMonth = date.getMonth() + 1;
43
+ const dateYear = date.getFullYear();
44
+ return basedateDate === dateDate && basedateMonth === dateMonth && basedateYear === dateYear;
45
+ }
46
+ export function getPreviousMonth(month, year) {
47
+ const prevMonth = month > 1 ? month - 1 : 12;
48
+ const prevMonthYear = month > 1 ? year : year - 1;
49
+ return {
50
+ month: prevMonth,
51
+ year: prevMonthYear
52
+ };
53
+ }
54
+ export function getNextMonth(month, year) {
55
+ const nextMonth = month < 12 ? month + 1 : 1;
56
+ const nextMonthYear = month < 12 ? year : year + 1;
57
+ return {
58
+ month: nextMonth,
59
+ year: nextMonthYear
60
+ };
61
+ }
62
+ export function addDays(_date, days) {
63
+ const date = new Date(_date);
64
+ date.setDate(date.getDate() + days);
65
+ return date;
66
+ }
67
+ export function getDateInterval(startDate, endDate, reverse) {
68
+ const dates = [];
69
+ let currentDate = reverse ? endDate : startDate;
70
+ const stopDate = reverse ? startDate : endDate;
71
+ while (currentDate <= stopDate) {
72
+ dates.push(currentDate);
73
+ currentDate = addDays(currentDate, 1);
74
+ }
75
+ return dates;
76
+ }
@@ -94,11 +94,11 @@ export default function EditForm({
94
94
  onClick: removeMarker,
95
95
  compact: true,
96
96
  children: [_jsx(Icons.Bin, {}), "Supprimer ce point"]
97
- }), _jsx(Button, {
97
+ }), _jsxs(Button, {
98
98
  variant: "success",
99
99
  onClick: closeMarker,
100
100
  compact: true,
101
- children: _jsx(Icons.Check, {})
101
+ children: ["Valider", _jsx(Icons.Check, {})]
102
102
  })]
103
103
  })]
104
104
  });
@@ -73,7 +73,7 @@ const renderField = (lang, label, classes, name, field, data, setData) => {
73
73
  newData[name].validator = isValid;
74
74
  }
75
75
  };
76
- const formatedOptions = [{
76
+ const formatedOptions = type === "select" ? [{
77
77
  label: Messages.get(lang, "select"),
78
78
  value: ""
79
79
  }].concat(optionsToDisplay.map(option => {
@@ -81,7 +81,7 @@ const renderField = (lang, label, classes, name, field, data, setData) => {
81
81
  label: option.label?.[lang],
82
82
  value: option.value ?? option.label?.[lang]
83
83
  };
84
- }));
84
+ })) : undefined;
85
85
  return _jsx(Tag, {
86
86
  onValueChange: onChange,
87
87
  options: formatedOptions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ublo-lib",
3
- "version": "1.13.4",
3
+ "version": "1.14.0",
4
4
  "peerDependencies": {
5
5
  "dt-design-system": "^2.1.0",
6
6
  "leaflet": "^1.9.1",