ublo-lib 1.15.1 → 1.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/common/components/carousel.js +124 -113
- package/es/common/components/instant-search/hooks/use-constant.d.ts +2 -0
- package/es/common/components/instant-search/hooks/use-constant.d.ts.map +1 -0
- package/es/common/components/instant-search/hooks/use-constant.js +8 -0
- package/es/common/components/instant-search/hooks/use-debounced-search.d.ts +7 -0
- package/es/common/components/instant-search/hooks/use-debounced-search.d.ts.map +1 -0
- package/es/common/components/instant-search/hooks/use-debounced-search.js +11 -0
- package/es/common/components/instant-search/hooks/use-search.d.ts +16 -0
- package/es/common/components/instant-search/hooks/use-search.d.ts.map +1 -0
- package/es/common/components/instant-search/hooks/use-search.js +10 -0
- package/es/common/components/instant-search/i18n.json +76 -0
- package/es/common/components/instant-search/index.d.ts +3 -0
- package/es/common/components/instant-search/index.d.ts.map +1 -0
- package/es/common/components/instant-search/index.js +2 -0
- package/es/common/components/instant-search/input.d.ts +16 -0
- package/es/common/components/instant-search/input.d.ts.map +1 -0
- package/es/common/components/instant-search/input.js +56 -0
- package/es/common/components/instant-search/input.module.css +87 -0
- package/es/common/components/instant-search/instant-search.d.ts +15 -0
- package/es/common/components/instant-search/instant-search.d.ts.map +1 -0
- package/es/common/components/instant-search/instant-search.js +95 -0
- package/es/common/components/instant-search/instant-search.module.css +38 -0
- package/es/common/components/instant-search/links.d.ts +13 -0
- package/es/common/components/instant-search/links.d.ts.map +1 -0
- package/es/common/components/instant-search/links.js +30 -0
- package/es/common/components/instant-search/links.module.css +96 -0
- package/es/common/components/instant-search/no-product.d.ts +7 -0
- package/es/common/components/instant-search/no-product.d.ts.map +1 -0
- package/es/common/components/instant-search/no-product.js +4 -0
- package/es/common/components/instant-search/products.d.ts +14 -0
- package/es/common/components/instant-search/products.d.ts.map +1 -0
- package/es/common/components/instant-search/products.js +42 -0
- package/es/common/components/instant-search/products.module.css +133 -0
- package/es/common/components/instant-search/results.d.ts +77 -0
- package/es/common/components/instant-search/results.d.ts.map +1 -0
- package/es/common/components/instant-search/results.js +41 -0
- package/es/common/components/instant-search/results.module.css +95 -0
- package/es/common/components/instant-search/services/api.d.ts +2 -0
- package/es/common/components/instant-search/services/api.d.ts.map +1 -0
- package/es/common/components/instant-search/services/api.js +13 -0
- package/es/common/components/instant-search/services/dates.js +50 -0
- package/es/common/components/instant-search/services/messages.d.ts +2 -0
- package/es/common/components/instant-search/services/messages.d.ts.map +1 -0
- package/es/common/components/instant-search/services/messages.js +5 -0
- package/es/common/components/instant-search/services/utils.d.ts +4 -0
- package/es/common/components/instant-search/services/utils.d.ts.map +1 -0
- package/es/common/components/instant-search/services/utils.js +39 -0
- package/package.json +3 -3
|
@@ -4,99 +4,10 @@ import { useUbloContext } from "ublo/with-ublo";
|
|
|
4
4
|
import * as Icons from "dt-design-system/es/icons";
|
|
5
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
6
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
const TARGETS = "section[data-class]";
|
|
7
8
|
const UNDRAGGABLE_TAGS = "img, a, button";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return m < 0 ? b < 0 ? m - b : m + b : m;
|
|
11
|
-
};
|
|
12
|
-
const preventDrag = element => element.setAttribute("draggable", false);
|
|
13
|
-
const enableDrag = element => element.removeAttribute("draggable");
|
|
14
|
-
const show = section => {
|
|
15
|
-
const propertiesToRemove = ["opacity", "pointer-events", "touch-action"];
|
|
16
|
-
propertiesToRemove.forEach(property => section.style.removeProperty(property));
|
|
17
|
-
};
|
|
18
|
-
function useInterval(callback, delay, current, dragging) {
|
|
19
|
-
const savedCallback = React.useRef();
|
|
20
|
-
React.useEffect(() => {
|
|
21
|
-
savedCallback.current = callback;
|
|
22
|
-
}, [callback]);
|
|
23
|
-
React.useEffect(() => {
|
|
24
|
-
function tick() {
|
|
25
|
-
savedCallback.current();
|
|
26
|
-
}
|
|
27
|
-
if (!dragging && delay !== null && delay !== 0) {
|
|
28
|
-
const interval = setInterval(tick, delay);
|
|
29
|
-
return () => clearInterval(interval);
|
|
30
|
-
}
|
|
31
|
-
}, [current, delay, dragging]);
|
|
32
|
-
}
|
|
33
|
-
const Dots = ({
|
|
34
|
-
count,
|
|
35
|
-
current,
|
|
36
|
-
setCurrent
|
|
37
|
-
}) => {
|
|
38
|
-
const length = [...new Array(count)];
|
|
39
|
-
return _jsx("div", {
|
|
40
|
-
className: "carousel__dots",
|
|
41
|
-
children: length.map((_, i) => {
|
|
42
|
-
const updateCurrent = e => {
|
|
43
|
-
e.stopPropagation();
|
|
44
|
-
setCurrent(i);
|
|
45
|
-
};
|
|
46
|
-
const classes = classNames("carousel__dot", {
|
|
47
|
-
"carousel__dot--current": i === current
|
|
48
|
-
});
|
|
49
|
-
return _jsx("button", {
|
|
50
|
-
className: classes,
|
|
51
|
-
onClick: updateCurrent,
|
|
52
|
-
"aria-label": i
|
|
53
|
-
}, i);
|
|
54
|
-
})
|
|
55
|
-
});
|
|
56
|
-
};
|
|
57
|
-
const Thumbnails = ({
|
|
58
|
-
carouselRef,
|
|
59
|
-
count,
|
|
60
|
-
current,
|
|
61
|
-
setCurrent,
|
|
62
|
-
targets
|
|
63
|
-
}) => {
|
|
64
|
-
const [thumbnails, setThumbnails] = React.useState([]);
|
|
65
|
-
React.useEffect(() => {
|
|
66
|
-
const carousel = carouselRef.current;
|
|
67
|
-
if (carousel) {
|
|
68
|
-
const sections = carousel.querySelectorAll(targets);
|
|
69
|
-
if (sections.length) {
|
|
70
|
-
const images = Array.from(sections).reduce((acc, section) => {
|
|
71
|
-
const image = section.querySelector("img");
|
|
72
|
-
if (!image?.src) return acc;
|
|
73
|
-
return [...acc, image.src];
|
|
74
|
-
}, []);
|
|
75
|
-
setThumbnails(images);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}, [carouselRef, count, targets]);
|
|
79
|
-
if (!count || !thumbnails.length) return null;
|
|
80
|
-
return _jsx("div", {
|
|
81
|
-
className: "carousel__thumbnails",
|
|
82
|
-
children: thumbnails.map((thumbnail, i) => {
|
|
83
|
-
const updateCurrent = e => {
|
|
84
|
-
e.stopPropagation();
|
|
85
|
-
setCurrent(i);
|
|
86
|
-
};
|
|
87
|
-
const classes = classNames("carousel__thumbnail", {
|
|
88
|
-
"carousel__thumbnail--current": i === current
|
|
89
|
-
});
|
|
90
|
-
return _jsx("input", {
|
|
91
|
-
type: "image",
|
|
92
|
-
className: classes,
|
|
93
|
-
src: thumbnail,
|
|
94
|
-
onClick: updateCurrent
|
|
95
|
-
}, i);
|
|
96
|
-
})
|
|
97
|
-
});
|
|
98
|
-
};
|
|
99
|
-
const Carousel = ({
|
|
9
|
+
export default React.memo(Carousel);
|
|
10
|
+
function Carousel({
|
|
100
11
|
delay = 4000,
|
|
101
12
|
fade = false,
|
|
102
13
|
controls,
|
|
@@ -106,18 +17,18 @@ const Carousel = ({
|
|
|
106
17
|
allowDragOnDesktop,
|
|
107
18
|
children,
|
|
108
19
|
onChange
|
|
109
|
-
})
|
|
20
|
+
}) {
|
|
110
21
|
const carouselRef = React.useRef();
|
|
111
22
|
const {
|
|
112
23
|
cmsMode
|
|
113
24
|
} = useUbloContext();
|
|
114
|
-
const [
|
|
25
|
+
const [sections, setSections] = React.useState([]);
|
|
115
26
|
const [current, setCurrent] = React.useState(0);
|
|
116
27
|
const [touchStartPosition, setTouchStartPosition] = React.useState();
|
|
117
28
|
const [dragging, setDragging] = React.useState(0);
|
|
118
29
|
const editing = cmsMode === "editing";
|
|
119
30
|
const draggingAllowed = !editing && allowDragOnDesktop;
|
|
120
|
-
const
|
|
31
|
+
const count = sections.length;
|
|
121
32
|
const showNextArrow = current < count - 1;
|
|
122
33
|
const showPrevArrow = current !== 0;
|
|
123
34
|
const next = React.useCallback(e => {
|
|
@@ -219,30 +130,37 @@ const Carousel = ({
|
|
|
219
130
|
if (startX > endX && current < count - 1) next();
|
|
220
131
|
setTouchStartPosition(undefined);
|
|
221
132
|
};
|
|
222
|
-
const
|
|
133
|
+
const getSections = React.useCallback(() => {
|
|
223
134
|
const carousel = carouselRef.current;
|
|
224
|
-
const sections = carousel.querySelectorAll(
|
|
225
|
-
|
|
226
|
-
|
|
135
|
+
const sections = carousel.querySelectorAll(TARGETS);
|
|
136
|
+
const visibleSections = Array.from(sections).filter(section => {
|
|
137
|
+
return window.getComputedStyle(section).display !== "none";
|
|
138
|
+
});
|
|
139
|
+
return visibleSections;
|
|
140
|
+
}, []);
|
|
141
|
+
const updateSections = React.useCallback(() => {
|
|
142
|
+
const sections = getSections();
|
|
143
|
+
setSections(sections);
|
|
144
|
+
}, [getSections]);
|
|
227
145
|
React.useEffect(() => {
|
|
228
146
|
const zone = carouselRef.current?.querySelector(".cms");
|
|
229
147
|
if (zone) {
|
|
230
|
-
zone.addEventListener("ublo-section-created",
|
|
231
|
-
zone.addEventListener("ublo-section-pasted",
|
|
232
|
-
zone.addEventListener("ublo-section-removed",
|
|
148
|
+
zone.addEventListener("ublo-section-created", updateSections);
|
|
149
|
+
zone.addEventListener("ublo-section-pasted", updateSections);
|
|
150
|
+
zone.addEventListener("ublo-section-removed", updateSections);
|
|
233
151
|
return () => {
|
|
234
|
-
zone.removeEventListener("ublo-section-removed",
|
|
235
|
-
zone.removeEventListener("ublo-section-pasted",
|
|
236
|
-
zone.removeEventListener("ublo-section-created",
|
|
152
|
+
zone.removeEventListener("ublo-section-removed", updateSections);
|
|
153
|
+
zone.removeEventListener("ublo-section-pasted", updateSections);
|
|
154
|
+
zone.removeEventListener("ublo-section-created", updateSections);
|
|
237
155
|
};
|
|
238
156
|
}
|
|
239
|
-
}, [
|
|
157
|
+
}, [updateSections]);
|
|
240
158
|
React.useEffect(() => {
|
|
241
159
|
const carousel = carouselRef.current;
|
|
242
160
|
const inner = carousel.firstElementChild;
|
|
243
|
-
const sections =
|
|
161
|
+
const sections = getSections();
|
|
244
162
|
const undraggableElements = Array.from(carousel.querySelectorAll(UNDRAGGABLE_TAGS));
|
|
245
|
-
|
|
163
|
+
setSections(sections);
|
|
246
164
|
if (!editing) {
|
|
247
165
|
sections.forEach((section, index) => {
|
|
248
166
|
const anchors = Array.from(section.querySelectorAll("a"));
|
|
@@ -280,7 +198,7 @@ const Carousel = ({
|
|
|
280
198
|
});
|
|
281
199
|
if (fade) inner.style.removeProperty("transform");
|
|
282
200
|
}
|
|
283
|
-
}, [
|
|
201
|
+
}, [current, editing, fade, getSections]);
|
|
284
202
|
const onUndraggableElementClick = React.useCallback(e => {
|
|
285
203
|
e.preventDefault();
|
|
286
204
|
e.stopPropagation();
|
|
@@ -339,14 +257,107 @@ const Carousel = ({
|
|
|
339
257
|
}), dots && _jsx(Dots, {
|
|
340
258
|
count: count,
|
|
341
259
|
current: current,
|
|
342
|
-
setCurrent: setCurrent
|
|
260
|
+
setCurrent: setCurrent,
|
|
261
|
+
sections: sections
|
|
343
262
|
}), thumbnails && count > 1 && _jsx(Thumbnails, {
|
|
344
263
|
carouselRef: carouselRef,
|
|
345
264
|
count: count,
|
|
346
265
|
current: current,
|
|
347
266
|
setCurrent: setCurrent,
|
|
348
|
-
|
|
267
|
+
sections: sections
|
|
349
268
|
})]
|
|
350
269
|
});
|
|
351
|
-
}
|
|
352
|
-
|
|
270
|
+
}
|
|
271
|
+
function Dots({
|
|
272
|
+
count,
|
|
273
|
+
current,
|
|
274
|
+
setCurrent
|
|
275
|
+
}) {
|
|
276
|
+
const length = [...new Array(count)];
|
|
277
|
+
return _jsx("div", {
|
|
278
|
+
className: "carousel__dots",
|
|
279
|
+
children: length.map((_, i) => {
|
|
280
|
+
const updateCurrent = e => {
|
|
281
|
+
e.stopPropagation();
|
|
282
|
+
setCurrent(i);
|
|
283
|
+
};
|
|
284
|
+
const classes = classNames("carousel__dot", {
|
|
285
|
+
"carousel__dot--current": i === current
|
|
286
|
+
});
|
|
287
|
+
return _jsx("button", {
|
|
288
|
+
className: classes,
|
|
289
|
+
onClick: updateCurrent,
|
|
290
|
+
"aria-label": i
|
|
291
|
+
}, i);
|
|
292
|
+
})
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
function Thumbnails({
|
|
296
|
+
carouselRef,
|
|
297
|
+
current,
|
|
298
|
+
setCurrent,
|
|
299
|
+
sections
|
|
300
|
+
}) {
|
|
301
|
+
const [thumbnails, setThumbnails] = React.useState([]);
|
|
302
|
+
React.useEffect(() => {
|
|
303
|
+
const carousel = carouselRef.current;
|
|
304
|
+
if (carousel) {
|
|
305
|
+
if (sections.length) {
|
|
306
|
+
const images = Array.from(sections).reduce((acc, section) => {
|
|
307
|
+
const image = section.querySelector("img");
|
|
308
|
+
if (!image?.src) return acc;
|
|
309
|
+
return [...acc, image.src];
|
|
310
|
+
}, []);
|
|
311
|
+
setThumbnails(images);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}, [carouselRef, sections]);
|
|
315
|
+
if (!thumbnails.length) return null;
|
|
316
|
+
return _jsx("div", {
|
|
317
|
+
className: "carousel__thumbnails",
|
|
318
|
+
children: thumbnails.map((thumbnail, i) => {
|
|
319
|
+
const updateCurrent = e => {
|
|
320
|
+
e.stopPropagation();
|
|
321
|
+
setCurrent(i);
|
|
322
|
+
};
|
|
323
|
+
const classes = classNames("carousel__thumbnail", {
|
|
324
|
+
"carousel__thumbnail--current": i === current
|
|
325
|
+
});
|
|
326
|
+
return _jsx("input", {
|
|
327
|
+
type: "image",
|
|
328
|
+
className: classes,
|
|
329
|
+
src: thumbnail,
|
|
330
|
+
onClick: updateCurrent
|
|
331
|
+
}, i);
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
function euclideanModulo(a, b) {
|
|
336
|
+
const m = a % b;
|
|
337
|
+
return m < 0 ? b < 0 ? m - b : m + b : m;
|
|
338
|
+
}
|
|
339
|
+
function preventDrag(element) {
|
|
340
|
+
element.setAttribute("draggable", false);
|
|
341
|
+
}
|
|
342
|
+
function enableDrag(element) {
|
|
343
|
+
element.removeAttribute("draggable");
|
|
344
|
+
}
|
|
345
|
+
function show(section) {
|
|
346
|
+
const propertiesToRemove = ["opacity", "pointer-events", "touch-action"];
|
|
347
|
+
propertiesToRemove.forEach(property => section.style.removeProperty(property));
|
|
348
|
+
}
|
|
349
|
+
function useInterval(callback, delay, current, dragging) {
|
|
350
|
+
const savedCallback = React.useRef();
|
|
351
|
+
React.useEffect(() => {
|
|
352
|
+
savedCallback.current = callback;
|
|
353
|
+
}, [callback]);
|
|
354
|
+
React.useEffect(() => {
|
|
355
|
+
function tick() {
|
|
356
|
+
savedCallback.current();
|
|
357
|
+
}
|
|
358
|
+
if (!dragging && delay !== null && delay !== 0) {
|
|
359
|
+
const interval = setInterval(tick, delay);
|
|
360
|
+
return () => clearInterval(interval);
|
|
361
|
+
}
|
|
362
|
+
}, [current, delay, dragging]);
|
|
363
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-constant.d.ts","sourceRoot":"","sources":["../../../../../src/common/components/instant-search/hooks/use-constant.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,EAAE,GAAG,OAQ1C"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export default function useDebouncedSearch(searchFunction: any): {
|
|
3
|
+
text: string;
|
|
4
|
+
setText: React.Dispatch<React.SetStateAction<string>>;
|
|
5
|
+
search: import("react-async-hook").UseAsyncReturn<any, any[]>;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=use-debounced-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-debounced-search.d.ts","sourceRoot":"","sources":["../../../../../src/common/components/instant-search/hooks/use-debounced-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,cAAc,KAAA;;;;EAWxD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import debouncePromise from "awesome-debounce-promise";
|
|
3
|
+
import { useAsync } from "react-async-hook";
|
|
4
|
+
import useConstant from "./use-constant";
|
|
5
|
+
const DEBOUNCE_AMOUNT = 400;
|
|
6
|
+
export default function useDebouncedSearch(searchFunction) {
|
|
7
|
+
const [text, setText] = React.useState("");
|
|
8
|
+
const debouncedSearchFunction = useConstant(() => debouncePromise(searchFunction, DEBOUNCE_AMOUNT));
|
|
9
|
+
const search = useAsync(async () => (text.length === 0 ? undefined : debouncedSearchFunction(text)), [debouncedSearchFunction, text], { setLoading: (state) => ({ ...state, loading: true }) });
|
|
10
|
+
return { text, setText, search };
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export declare type SearchOptions = {
|
|
3
|
+
groupLimit?: number;
|
|
4
|
+
page?: number;
|
|
5
|
+
perPage?: number;
|
|
6
|
+
queryBy?: string;
|
|
7
|
+
queryByWeights?: string;
|
|
8
|
+
filterBy?: string;
|
|
9
|
+
sortBy?: string;
|
|
10
|
+
};
|
|
11
|
+
export default function useSearch(lang: string, options?: SearchOptions): {
|
|
12
|
+
text: string;
|
|
13
|
+
setText: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
14
|
+
search: import("react-async-hook").UseAsyncReturn<any, any[]>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=use-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-search.d.ts","sourceRoot":"","sources":["../../../../../src/common/components/instant-search/hooks/use-search.ts"],"names":[],"mappings":";AAOA,oBAAY,aAAa,GAAG;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB;;;;EAW1E"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import getConfig from "next/config";
|
|
2
|
+
import useDebouncedSearch from "./use-debounced-search";
|
|
3
|
+
import * as API from "../services/api";
|
|
4
|
+
const { publicRuntimeConfig } = getConfig();
|
|
5
|
+
const { site } = publicRuntimeConfig;
|
|
6
|
+
export default function useSearch(lang, options = {}) {
|
|
7
|
+
return useDebouncedSearch(async (query) => {
|
|
8
|
+
return API.fetchResults(site, lang, query, options.groupLimit, options.queryBy, options.queryByWeights);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fr": {
|
|
3
|
+
"try": "Essayez",
|
|
4
|
+
"pages": "Pages",
|
|
5
|
+
"faqs": "Questions fréquentes",
|
|
6
|
+
"information": "Informations",
|
|
7
|
+
"instructors": "Moniteurs",
|
|
8
|
+
"noProducts": "Pas de produit correspondant",
|
|
9
|
+
"productTitleWithWeek": "Les offres pour la période du ",
|
|
10
|
+
"productTitleWithoutWeek": "Choisissez votre période pour afficher les tarifs et affiner les résultats",
|
|
11
|
+
"chooseWeek": "Choisir ma période",
|
|
12
|
+
"updateWeek": "Modifier ma période",
|
|
13
|
+
"showOtherResults": "Afficher les autres résultats"
|
|
14
|
+
},
|
|
15
|
+
"en": {
|
|
16
|
+
"try": "Try",
|
|
17
|
+
"pages": "Pages",
|
|
18
|
+
"faqs": "FAQs",
|
|
19
|
+
"information": "Information",
|
|
20
|
+
"instructors": "Instructors",
|
|
21
|
+
"noProducts": "No matching product",
|
|
22
|
+
"productTitleWithWeek": "Offers for the period from ",
|
|
23
|
+
"productTitleWithoutWeek": "Choose your period to view rates and refine results below",
|
|
24
|
+
"chooseWeek": "Choose my period",
|
|
25
|
+
"updateWeek": "Change my period",
|
|
26
|
+
"showOtherResults": "Show other results"
|
|
27
|
+
},
|
|
28
|
+
"es": {
|
|
29
|
+
"pages": "Paginas",
|
|
30
|
+
"faqs": "Preguntas frecuentes",
|
|
31
|
+
"information": "Informaciones",
|
|
32
|
+
"instructors": "Instructores",
|
|
33
|
+
"noProducts": "Ningún producto coincidente",
|
|
34
|
+
"productTitleWithWeek": "Ofertas para el período de ",
|
|
35
|
+
"productTitleWithoutWeek": "Elija su período para ver las tarifas y refinar los resultados a continuación",
|
|
36
|
+
"chooseWeek": "Elige mi periodo",
|
|
37
|
+
"updateWeek": "Cambiar mi periodo",
|
|
38
|
+
"showOtherResults": "Mostrar otros resultados"
|
|
39
|
+
},
|
|
40
|
+
"it": {
|
|
41
|
+
"pages": "Pagine",
|
|
42
|
+
"faqs": "Domande frequenti",
|
|
43
|
+
"information": "Informazioni",
|
|
44
|
+
"instructors": "Insegnanti",
|
|
45
|
+
"noProducts": "Nessun prodotto corrispondente",
|
|
46
|
+
"productTitleWithWeek": "Offerte per il periodo dal ",
|
|
47
|
+
"productTitleWithoutWeek": "Scegli il tuo periodo per visualizzare le tariffe e perfezionare i risultati di seguito",
|
|
48
|
+
"chooseWeek": "Scegli il mio periodo",
|
|
49
|
+
"updateWeek": "Cambia il mio ciclo",
|
|
50
|
+
"showOtherResults": "Mostra altri risultati"
|
|
51
|
+
},
|
|
52
|
+
"nl": {
|
|
53
|
+
"pages": "Pagina's",
|
|
54
|
+
"faqs": "Veel Gestelde Vragen",
|
|
55
|
+
"information": "Informatie",
|
|
56
|
+
"instructors": "Instructeurs",
|
|
57
|
+
"noProducts": "Geen bijpassend product",
|
|
58
|
+
"productTitleWithWeek": "Aanbiedingen voor de periode van ",
|
|
59
|
+
"productTitleWithoutWeek": "Kies hieronder uw periode om tarieven te bekijken en resultaten te verfijnen",
|
|
60
|
+
"chooseWeek": "Kies mijn periode",
|
|
61
|
+
"updateWeek": "Wijzig mijn menstruatie",
|
|
62
|
+
"showOtherResults": "Toon andere resultaten"
|
|
63
|
+
},
|
|
64
|
+
"ru": {
|
|
65
|
+
"pages": "Страницы",
|
|
66
|
+
"faqs": "Часто задаваемые вопросы",
|
|
67
|
+
"information": "Информация",
|
|
68
|
+
"instructors": "Преподаватели",
|
|
69
|
+
"noProducts": "Нет подходящего продукта",
|
|
70
|
+
"productTitleWithWeek": "Предложения на период с ",
|
|
71
|
+
"productTitleWithoutWeek": "Выберите период, чтобы просмотреть цены и уточнить результаты ниже",
|
|
72
|
+
"chooseWeek": "Выберите мой период",
|
|
73
|
+
"updateWeek": "Изменить мой период",
|
|
74
|
+
"showOtherResults": "Показать другие результаты"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/common/components/instant-search/index.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAE7C,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
declare type Suggestions = {
|
|
3
|
+
fr?: string[];
|
|
4
|
+
en?: string[];
|
|
5
|
+
};
|
|
6
|
+
declare type Props = {
|
|
7
|
+
lang: string;
|
|
8
|
+
text: string;
|
|
9
|
+
setText: (value: string) => void;
|
|
10
|
+
loading: boolean;
|
|
11
|
+
closeSearch: () => void;
|
|
12
|
+
suggestions?: Suggestions;
|
|
13
|
+
};
|
|
14
|
+
export default function SearchInput({ lang, text, setText, closeSearch, loading, suggestions, }: Props): JSX.Element;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../../src/common/components/instant-search/input.tsx"],"names":[],"mappings":";AASA,aAAK,WAAW,GAAG;IACjB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;CACf,CAAC;AAEF,aAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAIF,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,WAAW,EACX,OAAO,EACP,WAAW,GACZ,EAAE,KAAK,eA8EP"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import Input from "dt-design-system/es/input";
|
|
5
|
+
import Button from "dt-design-system/es/button";
|
|
6
|
+
import * as Icons from "dt-design-system/es/icons";
|
|
7
|
+
import * as Ripple from "dt-design-system/es/ripple";
|
|
8
|
+
import message from "./services/messages";
|
|
9
|
+
import css from "./input.module.css";
|
|
10
|
+
const TRANSITION_DURATION = 1800;
|
|
11
|
+
export default function SearchInput({ lang, text, setText, closeSearch, loading, suggestions, }) {
|
|
12
|
+
const [currentSuggestion, setCurrentSuggestion] = React.useState(0);
|
|
13
|
+
const updateText = (value) => () => {
|
|
14
|
+
setText(value);
|
|
15
|
+
};
|
|
16
|
+
const classes = classNames(css.input, {
|
|
17
|
+
[css.inputLoading]: loading,
|
|
18
|
+
});
|
|
19
|
+
const inputIcon = loading ? "Loader2" : "Search";
|
|
20
|
+
const suggestionsSet = getSuggestions(suggestions)[lang];
|
|
21
|
+
const enableSuggestion = Boolean(suggestionsSet);
|
|
22
|
+
const createRipple = (e) => {
|
|
23
|
+
Ripple.create(e);
|
|
24
|
+
};
|
|
25
|
+
React.useEffect(() => {
|
|
26
|
+
if (enableSuggestion && !text) {
|
|
27
|
+
const interval = setInterval(() => {
|
|
28
|
+
setCurrentSuggestion((current) => {
|
|
29
|
+
const nextSuggestion = current >= suggestionsSet.length - 1 ? 0 : current + 1;
|
|
30
|
+
return nextSuggestion;
|
|
31
|
+
});
|
|
32
|
+
}, TRANSITION_DURATION);
|
|
33
|
+
return () => {
|
|
34
|
+
clearInterval(interval);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}, [enableSuggestion, suggestionsSet, text]);
|
|
38
|
+
return (_jsxs("div", { className: css.container, children: [_jsx(Input, { value: text, onValueChange: setText, icon: inputIcon, className: classes }), enableSuggestion && !text && (_jsxs("div", { className: css.suggestion, children: [message(lang, "try"), _jsx("div", { className: css.buttons, children: suggestionsSet.map((suggestion, i) => {
|
|
39
|
+
const isCurrent = i === currentSuggestion;
|
|
40
|
+
const isPrev = currentSuggestion === 0
|
|
41
|
+
? i === suggestionsSet.length - 1
|
|
42
|
+
: i === currentSuggestion - 1;
|
|
43
|
+
const classes = classNames(css.button, {
|
|
44
|
+
[css.buttonCurrent]: isCurrent,
|
|
45
|
+
[css.buttonPrev]: isPrev,
|
|
46
|
+
});
|
|
47
|
+
return (_jsxs("button", { className: classes, onClick: updateText(suggestion), onMouseDown: createRipple, children: ["\u00AB ", suggestion, " \u00BB"] }, suggestion));
|
|
48
|
+
}) })] })), _jsx(Button, { variant: "transparent", className: css.close, onClick: closeSearch, children: _jsx(Icons.Cross, {}) })] }));
|
|
49
|
+
}
|
|
50
|
+
function getSuggestions(suggestions = {}) {
|
|
51
|
+
return {
|
|
52
|
+
fr: ["cours de ski", "cours privés", "compétition", "cours débutants"],
|
|
53
|
+
en: ["ski lessons", "private lessons", "competition"],
|
|
54
|
+
...suggestions,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
position: relative;
|
|
3
|
+
padding: 10px;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.input {
|
|
7
|
+
--ds-input-padding: 14px;
|
|
8
|
+
--ds-input-background: var(--ds-grey-000, #fff);
|
|
9
|
+
|
|
10
|
+
width: 100%;
|
|
11
|
+
border-radius: var(--ds-radius-200, 10px);
|
|
12
|
+
box-shadow: var(--ds-shadow-200, 0 5px 10px rgba(0, 0, 0, 0.12));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.inputLoading svg {
|
|
16
|
+
animation: search-loader-spinning 1280ms
|
|
17
|
+
var(--ds-transition-easing, cubic-bezier(0.4, 0.1, 0.2, 0.9)) infinite;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@keyframes search-loader-spinning {
|
|
21
|
+
100% {
|
|
22
|
+
transform: rotate(1turn);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.suggestion {
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: 50%;
|
|
29
|
+
left: 54px;
|
|
30
|
+
height: 21px;
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
line-height: 1;
|
|
34
|
+
color: var(--ds-grey-500, #484848);
|
|
35
|
+
transform: translateY(-50%);
|
|
36
|
+
pointer-events: none;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.buttons {
|
|
40
|
+
position: relative;
|
|
41
|
+
height: inherit;
|
|
42
|
+
color: inherit;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.button {
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: 0;
|
|
48
|
+
left: 0;
|
|
49
|
+
width: max-content;
|
|
50
|
+
height: 100%;
|
|
51
|
+
padding: 2px 5px 4px 5px;
|
|
52
|
+
color: inherit;
|
|
53
|
+
line-height: 1;
|
|
54
|
+
font-weight: 700;
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
pointer-events: auto;
|
|
57
|
+
border-radius: var(--ds-radius-100, 6px);
|
|
58
|
+
transform: translateY(100%);
|
|
59
|
+
opacity: 0;
|
|
60
|
+
pointer-events: none;
|
|
61
|
+
transition: background-color 160ms
|
|
62
|
+
var(--ds-transition-easing, cubic-bezier(0.4, 0.1, 0.2, 0.9)),
|
|
63
|
+
opacity 320ms var(--ds-transition-easing, cubic-bezier(0.4, 0.1, 0.2, 0.9)),
|
|
64
|
+
transform 320ms
|
|
65
|
+
var(--ds-transition-easing, cubic-bezier(0.4, 0.1, 0.2, 0.9));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.buttonPrev {
|
|
69
|
+
transform: translateY(-100%);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.buttonCurrent {
|
|
73
|
+
opacity: 1;
|
|
74
|
+
transform: none;
|
|
75
|
+
pointer-events: auto;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.button:is(:hover, :focus) {
|
|
79
|
+
background-color: var(--ds-grey-100, #f5f5f5);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.close {
|
|
83
|
+
position: absolute;
|
|
84
|
+
top: 17px;
|
|
85
|
+
right: 14px;
|
|
86
|
+
color: inherit;
|
|
87
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { SearchOptions } from "./hooks/use-search";
|
|
3
|
+
declare type Props = {
|
|
4
|
+
lang: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
ubloContext: any;
|
|
7
|
+
suggestions?: {
|
|
8
|
+
fr?: string[];
|
|
9
|
+
en?: string[];
|
|
10
|
+
};
|
|
11
|
+
options?: SearchOptions;
|
|
12
|
+
};
|
|
13
|
+
export default function InstantSearch({ lang, suggestions, className, ubloContext, options, }: Props): JSX.Element;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=instant-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instant-search.d.ts","sourceRoot":"","sources":["../../../../src/common/components/instant-search/instant-search.tsx"],"names":[],"mappings":";AAUA,OAAkB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAK9D,aAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,GAAG,CAAC;IACjB,WAAW,CAAC,EAAE;QACZ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;KACf,CAAC;IACF,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EACpC,IAAI,EACJ,WAAW,EACX,SAAS,EACT,WAAW,EACX,OAAY,GACb,EAAE,KAAK,eAsIP"}
|