ublo-lib 1.0.0 → 1.0.3
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/es/{esf/components/contact-form → common/components/gesco-contact-form}/api.js +0 -0
- package/es/{esf/components/contact-form → common/components/gesco-contact-form}/data.js +0 -0
- package/es/{esf/components/contact-form/contact-form.js → common/components/gesco-contact-form/gesco-contact-form.js} +0 -0
- package/es/{esf/components/contact-form/contact-form.module.css → common/components/gesco-contact-form/gesco-contact-form.module.css} +0 -0
- package/es/common/components/gesco-contact-form/index.js +2 -0
- package/es/{esf/components/contact-form → common/components/gesco-contact-form}/messages.js +0 -0
- package/es/{esf/components/contact-form → common/components/gesco-contact-form}/validation.js +0 -0
- package/es/common/components/search-bar/hooks/use-constant.js +15 -0
- package/es/common/components/search-bar/hooks/use-debounced-search.js +18 -0
- package/es/common/components/search-bar/hooks/use-search.js +3 -0
- package/es/common/components/search-bar/icons.js +25 -0
- package/es/common/components/search-bar/index.js +2 -0
- package/es/common/components/search-bar/messages.js +15 -0
- package/es/common/components/search-bar/search-bar.js +207 -0
- package/es/common/components/search-bar/utils/fetcher.js +14 -0
- package/es/common/components/search-bar/utils/keyboard-keys.js +5 -0
- package/es/common/components/search-bar/utils/params.js +8 -0
- package/es/esf/hooks/use-booking-links.js +1 -1
- package/es/esf/hooks/use-reviews.js +1 -1
- package/es/lbm/components/msem-linker/actions.js +65 -0
- package/es/lbm/components/msem-linker/actions.module.css +75 -0
- package/es/lbm/components/msem-linker/dropdown.js +247 -0
- package/es/lbm/components/msem-linker/dropdown.module.css +225 -0
- package/es/lbm/components/msem-linker/editor/editor.js +120 -0
- package/es/lbm/components/msem-linker/editor/editor.module.css +88 -0
- package/es/lbm/components/msem-linker/editor/index.js +1 -0
- package/es/lbm/components/msem-linker/editor/lodging.js +417 -0
- package/es/lbm/components/msem-linker/editor/lodging.module.css +59 -0
- package/es/lbm/components/msem-linker/editor/messages.js +25 -0
- package/es/lbm/components/msem-linker/editor/ski-pass.js +362 -0
- package/es/lbm/components/msem-linker/editor/ski-pass.module.css +76 -0
- package/es/lbm/components/msem-linker/hooks/use-widgets.js +89 -0
- package/es/lbm/components/msem-linker/index.js +1 -0
- package/es/lbm/components/msem-linker/loader.js +13 -0
- package/es/lbm/components/msem-linker/loader.module.css +22 -0
- package/es/lbm/components/msem-linker/msem-linker.js +101 -0
- package/es/lbm/components/msem-linker/msem-linker.module.css +140 -0
- package/es/lbm/components/msem-linker/msem-logo.js +17 -0
- package/es/lbm/components/msem-linker/services/api.js +34 -0
- package/es/lbm/components/msem-linker/services/config.js +6 -0
- package/es/lbm/components/msem-linker/services/dates.js +11 -0
- package/es/lbm/components/msem-linker/services/ui.js +89 -0
- package/es/lbm/components/msem-linker/services/url-params.js +40 -0
- package/package.json +52 -49
- package/es/esf/components/contact-form/index.js +0 -2
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/es/{esf/components/contact-form → common/components/gesco-contact-form}/validation.js
RENAMED
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import debouncePromise from "awesome-debounce-promise";
|
|
3
|
+
import useConstant from "./use-constant";
|
|
4
|
+
import { useAsync } from "react-async-hook";
|
|
5
|
+
export const useDebouncedSearch = searchFunction => {
|
|
6
|
+
const [text, setText] = useState("");
|
|
7
|
+
const debouncedSearchFunction = useConstant(() => debouncePromise(searchFunction, 200));
|
|
8
|
+
const search = useAsync(async () => text.length === 0 ? undefined : debouncedSearchFunction(text), [debouncedSearchFunction, text], {
|
|
9
|
+
setLoading: state => ({ ...state,
|
|
10
|
+
loading: true
|
|
11
|
+
})
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
text,
|
|
15
|
+
setText,
|
|
16
|
+
search
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
const Icon = ({
|
|
5
|
+
width = 24,
|
|
6
|
+
height = 24,
|
|
7
|
+
...props
|
|
8
|
+
}) => _jsx("svg", {
|
|
9
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
10
|
+
width: width,
|
|
11
|
+
height: height,
|
|
12
|
+
...props,
|
|
13
|
+
children: props.children
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const SearchIcon = props => _jsx(Icon, { ...props,
|
|
17
|
+
children: _jsx("path", {
|
|
18
|
+
d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
export const LoadIcon = props => _jsx(Icon, { ...props,
|
|
22
|
+
children: _jsx("path", {
|
|
23
|
+
d: "M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1.46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6 6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l4 4 4-4H6z"
|
|
24
|
+
})
|
|
25
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const locales = {
|
|
2
|
+
fr: {
|
|
3
|
+
"what-are-you-looking-for": "Que recherchez-vous ?",
|
|
4
|
+
"no-results": "Pas de résultats..."
|
|
5
|
+
},
|
|
6
|
+
en: {
|
|
7
|
+
"what-are-you-looking-for": "What are you looking for?",
|
|
8
|
+
"no-results": "No results..."
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export const message = (lang, id, messages = locales) => {
|
|
12
|
+
if (!messages || !messages[lang]) return id;
|
|
13
|
+
const langMessages = messages[lang];
|
|
14
|
+
return langMessages[id] || `??${id}??`;
|
|
15
|
+
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useState, useEffect, useRef } from "react";
|
|
3
|
+
import classnames from "classnames";
|
|
4
|
+
import Link from "ublo/link";
|
|
5
|
+
import { useUbloContext } from "ublo/with-ublo";
|
|
6
|
+
import { SearchIcon, LoadIcon } from "./icons";
|
|
7
|
+
import * as Plausible from "../plausible";
|
|
8
|
+
import { useSearch } from "./hooks/use-search";
|
|
9
|
+
import * as KeyboardKeys from "./utils/keyboard-keys";
|
|
10
|
+
import { message } from "./messages";
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
|
|
14
|
+
const SearchBar = ({
|
|
15
|
+
resultFormatter,
|
|
16
|
+
backdrop,
|
|
17
|
+
OverrideIcons = {},
|
|
18
|
+
messages,
|
|
19
|
+
seo,
|
|
20
|
+
exclude,
|
|
21
|
+
autofocus
|
|
22
|
+
}) => {
|
|
23
|
+
const input = useRef();
|
|
24
|
+
const results = useRef();
|
|
25
|
+
const [state, setState] = useState({
|
|
26
|
+
active: 0,
|
|
27
|
+
selected: undefined
|
|
28
|
+
});
|
|
29
|
+
const {
|
|
30
|
+
lang,
|
|
31
|
+
config
|
|
32
|
+
} = useUbloContext();
|
|
33
|
+
const {
|
|
34
|
+
ubloApi,
|
|
35
|
+
site
|
|
36
|
+
} = config;
|
|
37
|
+
const {
|
|
38
|
+
text,
|
|
39
|
+
setText,
|
|
40
|
+
search
|
|
41
|
+
} = useSearch(ubloApi, site, lang, seo, exclude);
|
|
42
|
+
const DefaultIcons = {
|
|
43
|
+
SearchIcon,
|
|
44
|
+
LoadIcon
|
|
45
|
+
};
|
|
46
|
+
const Icons = Object.assign(DefaultIcons, OverrideIcons);
|
|
47
|
+
|
|
48
|
+
const close = () => setText("");
|
|
49
|
+
|
|
50
|
+
const onChange = e => {
|
|
51
|
+
const userInput = e.currentTarget.value;
|
|
52
|
+
setText(userInput);
|
|
53
|
+
setState({
|
|
54
|
+
active: 0
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const onKeyDown = e => {
|
|
59
|
+
const allowedKeys = ["ArrowUp", "ArrowDown", "Enter", "Escape"];
|
|
60
|
+
const {
|
|
61
|
+
code,
|
|
62
|
+
keyCode,
|
|
63
|
+
key,
|
|
64
|
+
which
|
|
65
|
+
} = e;
|
|
66
|
+
const isAllowed = allowedKeys.includes(code) || allowedKeys.includes(key);
|
|
67
|
+
if (!isAllowed) return;
|
|
68
|
+
const keyId = keyCode ?? which;
|
|
69
|
+
const up = keyId === KeyboardKeys.ArrowUp;
|
|
70
|
+
const enter = keyId === KeyboardKeys.Enter;
|
|
71
|
+
const escape = keyId === KeyboardKeys.Escape;
|
|
72
|
+
|
|
73
|
+
if (escape) {
|
|
74
|
+
close();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const container = results.current;
|
|
79
|
+
const firstResult = container?.querySelector(".search-bar__result");
|
|
80
|
+
const allResults = Array.from(container?.querySelectorAll(".search-bar__result"));
|
|
81
|
+
const lastResult = allResults[allResults.length - 1];
|
|
82
|
+
const selectedResult = container?.querySelector(".search-bar__result--selected");
|
|
83
|
+
|
|
84
|
+
if (enter && selectedResult) {
|
|
85
|
+
selectedResult.click();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let newSelected;
|
|
90
|
+
|
|
91
|
+
if (!selectedResult) {
|
|
92
|
+
newSelected = up ? lastResult : firstResult;
|
|
93
|
+
} else {
|
|
94
|
+
newSelected = up ? selectedResult.previousElementSibling || lastResult : selectedResult.nextElementSibling || firstResult;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
allResults.forEach(result => result.classList.remove("search-bar__result--selected"));
|
|
98
|
+
newSelected && newSelected.classList.add("search-bar__result--selected");
|
|
99
|
+
container && newSelected && (container.scrollTop = newSelected.offsetTop - newSelected.clientHeight);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const focusInput = () => {
|
|
103
|
+
input.current.focus();
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const handleKeyPresses = React.useCallback(e => {
|
|
107
|
+
const allowedKeys = ["k"];
|
|
108
|
+
const {
|
|
109
|
+
code,
|
|
110
|
+
ctrlKey,
|
|
111
|
+
key,
|
|
112
|
+
keyCode,
|
|
113
|
+
metaKey,
|
|
114
|
+
which
|
|
115
|
+
} = e;
|
|
116
|
+
const isAllowed = !text && (ctrlKey || metaKey) && (allowedKeys.includes(code) || allowedKeys.includes(key));
|
|
117
|
+
if (!isAllowed) return;
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
const keyId = keyCode ?? which;
|
|
120
|
+
|
|
121
|
+
if (keyId === KeyboardKeys.K && (ctrlKey || metaKey)) {
|
|
122
|
+
focusInput();
|
|
123
|
+
}
|
|
124
|
+
}, []);
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (autofocus) focusInput();
|
|
127
|
+
window.addEventListener("keydown", handleKeyPresses);
|
|
128
|
+
return () => {
|
|
129
|
+
window.removeEventListener("keydown", handleKeyPresses);
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
132
|
+
const Icon = search?.loading ? Icons.LoadIcon : Icons.SearchIcon;
|
|
133
|
+
const classes = classnames("search-bar", {
|
|
134
|
+
"search-bar--opened": search?.result,
|
|
135
|
+
"search-bar--loading": search?.loading
|
|
136
|
+
});
|
|
137
|
+
return _jsxs("div", {
|
|
138
|
+
className: classes,
|
|
139
|
+
children: [backdrop && _jsx("div", {
|
|
140
|
+
className: "search-bar__backdrop",
|
|
141
|
+
onClick: close
|
|
142
|
+
}), _jsxs("div", {
|
|
143
|
+
className: "search-bar__input-container",
|
|
144
|
+
children: [_jsx("input", {
|
|
145
|
+
ref: input,
|
|
146
|
+
type: "text",
|
|
147
|
+
value: text,
|
|
148
|
+
onChange: onChange,
|
|
149
|
+
onKeyDown: onKeyDown,
|
|
150
|
+
className: "search-bar__input",
|
|
151
|
+
placeholder: message(lang, "what-are-you-looking-for", messages)
|
|
152
|
+
}), _jsx(Icon, {
|
|
153
|
+
className: "search-bar__icon"
|
|
154
|
+
}), _jsxs("div", {
|
|
155
|
+
ref: results,
|
|
156
|
+
className: "search-bar__results",
|
|
157
|
+
children: [search.result?.map((result, i) => {
|
|
158
|
+
const {
|
|
159
|
+
name,
|
|
160
|
+
title,
|
|
161
|
+
page,
|
|
162
|
+
path
|
|
163
|
+
} = result;
|
|
164
|
+
const externalLink = page === undefined;
|
|
165
|
+
const Tag = externalLink ? "a" : Link;
|
|
166
|
+
const resultLabel = typeof resultFormatter === "function" ? resultFormatter({
|
|
167
|
+
lang,
|
|
168
|
+
result,
|
|
169
|
+
text
|
|
170
|
+
}) : title;
|
|
171
|
+
const anchorProps = {
|
|
172
|
+
href: path,
|
|
173
|
+
dangerouslySetInnerHTML: {
|
|
174
|
+
__html: resultLabel
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const linkProps = {
|
|
178
|
+
as: path,
|
|
179
|
+
page,
|
|
180
|
+
title: resultLabel
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const sendPlausibleGoal = () => {
|
|
184
|
+
Plausible.sendGoal("Search", {
|
|
185
|
+
"Terms - Destination": `${text} - ${path}`
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const props = externalLink ? anchorProps : linkProps;
|
|
190
|
+
const classes = classnames("search-bar__result", {
|
|
191
|
+
"search-bar__result--active": i === state.active
|
|
192
|
+
});
|
|
193
|
+
return _jsx(Tag, {
|
|
194
|
+
className: classes,
|
|
195
|
+
...props,
|
|
196
|
+
onClick: sendPlausibleGoal
|
|
197
|
+
}, `${name}-${i}`);
|
|
198
|
+
}), search.result?.length === 0 && _jsx("div", {
|
|
199
|
+
className: "search-bar__no-result",
|
|
200
|
+
children: message(lang, "no-results", messages)
|
|
201
|
+
})]
|
|
202
|
+
})]
|
|
203
|
+
})]
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export default SearchBar;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as Params from "./params";
|
|
2
|
+
export const fetchResults = async (ubloApi, site, lang, query, seo, exclude) => {
|
|
3
|
+
const seoParam = seo === false ? "false" : undefined;
|
|
4
|
+
const params = Params.build({
|
|
5
|
+
site,
|
|
6
|
+
lang,
|
|
7
|
+
query,
|
|
8
|
+
seo: seoParam,
|
|
9
|
+
exclude
|
|
10
|
+
});
|
|
11
|
+
const url = `${ubloApi}/api/search${params}`;
|
|
12
|
+
const res = await fetch(url);
|
|
13
|
+
return res.json();
|
|
14
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { useUbloContext } from "ublo/with-ublo";
|
|
3
|
-
import { loadJS } from "
|
|
3
|
+
import { loadJS } from "../../common/utils/load-js";
|
|
4
4
|
import * as Plausible from "../plausible";
|
|
5
5
|
|
|
6
6
|
const setupConfig = (lang, breadcrumb, cart = [], multipleVillages, hasLangPrefix) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
2
|
import { useUbloContext } from "ublo/with-ublo";
|
|
3
|
-
import { loadJS } from "
|
|
3
|
+
import { loadJS } from "../../common/utils/load-js";
|
|
4
4
|
|
|
5
5
|
const useReviews = (lang, resort, containerId = "msem-reviews", preventInit) => {
|
|
6
6
|
const {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as Icons from "dt-design-system/es/icons";
|
|
3
|
+
import MseMLogo from "./msem-logo";
|
|
4
|
+
import { CONNECTED, EDITING } from "./index";
|
|
5
|
+
import * as UI from "./services/ui";
|
|
6
|
+
import styles from "./actions.module.css";
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
9
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
|
|
11
|
+
const Actions = ({
|
|
12
|
+
mode,
|
|
13
|
+
setMode,
|
|
14
|
+
renderEditingUi
|
|
15
|
+
}) => {
|
|
16
|
+
const toggleMode = () => {
|
|
17
|
+
const sections = Array.from(document.querySelectorAll("section[data-class]"));
|
|
18
|
+
|
|
19
|
+
if (mode === CONNECTED) {
|
|
20
|
+
setMode(EDITING);
|
|
21
|
+
window.Cms.desactivate();
|
|
22
|
+
window.Cms.hideInfo();
|
|
23
|
+
window.Cms.pageUi.removeAttribute("active");
|
|
24
|
+
window.Cms.pageUi.setAttribute("hidden", "");
|
|
25
|
+
sections.forEach(renderEditingUi);
|
|
26
|
+
} else {
|
|
27
|
+
setMode(CONNECTED);
|
|
28
|
+
window.Cms.pageUi.removeAttribute("hidden");
|
|
29
|
+
sections.forEach(section => UI.remove(section));
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const onSaveClick = async () => {
|
|
34
|
+
if (!window.Cms) return;
|
|
35
|
+
window.Cms.pageUi.removeAttribute("hidden");
|
|
36
|
+
window.Cms.pageUi.setAttribute("active", "");
|
|
37
|
+
window.Cms.pageUi.startloading();
|
|
38
|
+
setMode(CONNECTED);
|
|
39
|
+
const sections = Array.from(document.querySelectorAll("section[data-class]"));
|
|
40
|
+
sections.forEach(section => UI.remove(section, true));
|
|
41
|
+
window.Cms.pageUi.unsavedChanges = false;
|
|
42
|
+
await window.Cms.save();
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return _jsxs(_Fragment, {
|
|
46
|
+
children: [mode === CONNECTED && _jsx("button", {
|
|
47
|
+
className: `${styles.action} ${styles.toggle}`,
|
|
48
|
+
onClick: toggleMode,
|
|
49
|
+
"data-tooltip": "G\xE9rer les widgets",
|
|
50
|
+
children: _jsx(MseMLogo, {})
|
|
51
|
+
}), mode === EDITING && _jsxs(_Fragment, {
|
|
52
|
+
children: [_jsx("button", {
|
|
53
|
+
className: `${styles.action} ${styles.cancel}`,
|
|
54
|
+
onClick: toggleMode,
|
|
55
|
+
children: _jsx(Icons.Cross, {})
|
|
56
|
+
}), _jsx("button", {
|
|
57
|
+
className: `${styles.action} ${styles.save}`,
|
|
58
|
+
onClick: onSaveClick,
|
|
59
|
+
children: _jsx(Icons.Save, {})
|
|
60
|
+
})]
|
|
61
|
+
})]
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default Actions;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
.action {
|
|
2
|
+
position: absolute;
|
|
3
|
+
display: flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
font-family: "Open Sans", sans-serif;
|
|
7
|
+
background-color: #fff;
|
|
8
|
+
border-radius: 50%;
|
|
9
|
+
box-shadow: var(--cms-shadow-100, 0 5px 10px rgba(0, 0, 0, 0.12));
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
transition: box-shadow 160ms
|
|
12
|
+
var(--cms-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
13
|
+
animation: action-button-appearance 320ms
|
|
14
|
+
var(--cms-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@keyframes action-button-appearance {
|
|
18
|
+
0% {
|
|
19
|
+
opacity: 0;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.toggle {
|
|
24
|
+
bottom: 236px;
|
|
25
|
+
right: 25px;
|
|
26
|
+
width: 36px;
|
|
27
|
+
height: 36px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.cancel,
|
|
31
|
+
.save {
|
|
32
|
+
bottom: 16px;
|
|
33
|
+
width: 56px;
|
|
34
|
+
height: 56px;
|
|
35
|
+
fill: #fff;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.cancel {
|
|
39
|
+
right: 16px;
|
|
40
|
+
background-color: var(--cms-red-400, #d50000);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.save {
|
|
44
|
+
right: 86px;
|
|
45
|
+
background-color: var(--cms-green-400, #4caf50);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.action[data-tooltip]::after {
|
|
49
|
+
content: attr(data-tooltip);
|
|
50
|
+
position: absolute;
|
|
51
|
+
top: calc(50% - 12px);
|
|
52
|
+
right: calc(100% + 4px);
|
|
53
|
+
padding: 6px 10px;
|
|
54
|
+
font-size: 11px;
|
|
55
|
+
line-height: 1;
|
|
56
|
+
font-family: "Open Sans", sans-serif;
|
|
57
|
+
color: var(--cms-grey-000, #ffffff);
|
|
58
|
+
background-color: var(--cms-grey-500, #383838);
|
|
59
|
+
white-space: nowrap;
|
|
60
|
+
border-radius: var(--cms-radius-200, 10px);
|
|
61
|
+
opacity: 0;
|
|
62
|
+
pointer-events: none;
|
|
63
|
+
touch-action: none;
|
|
64
|
+
transition: opacity 240ms
|
|
65
|
+
var(--cms-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.action:hover::after {
|
|
69
|
+
opacity: 1;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.action > svg {
|
|
73
|
+
width: 24px;
|
|
74
|
+
height: 24px;
|
|
75
|
+
}
|