ublo-lib 1.47.81 → 1.47.84

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,3 @@
1
+ import InfiniteCarousel from "./infinite-carousel";
2
+ export default InfiniteCarousel;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/common/components/infinite-carousel/index.tsx"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,qBAAqB,CAAC;AAEnD,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import InfiniteCarousel from "./infinite-carousel";
2
+ export default InfiniteCarousel;
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ type CarouselVariant = "wheel" | "scale";
3
+ type Props = {
4
+ className?: string;
5
+ children: React.ReactNode;
6
+ variant?: CarouselVariant;
7
+ cloneNumber?: number;
8
+ options: {
9
+ hide_wheel_items?: boolean;
10
+ wheel_items_gap?: number;
11
+ scale_items_gap?: number;
12
+ scale_number?: number;
13
+ rotate_number?: number;
14
+ translateY_number?: number;
15
+ transition_duration?: number;
16
+ };
17
+ };
18
+ export default function InfiniteCarousel({ className, children, variant, options, cloneNumber, }: Props): import("react/jsx-runtime").JSX.Element;
19
+ export {};
20
+ //# sourceMappingURL=infinite-carousel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infinite-carousel.d.ts","sourceRoot":"","sources":["../../../../src/common/components/infinite-carousel/infinite-carousel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,KAAK,eAAe,GAAG,OAAO,GAAG,OAAO,CAAC;AAEzC,KAAK,KAAK,GAAG;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE;QACP,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,SAAS,EACT,QAAQ,EACR,OAAiB,EACjB,OAAY,EACZ,WAAW,GACZ,EAAE,KAAK,2CAqSP"}
@@ -0,0 +1,188 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import classNames from "classnames";
4
+ import { useUbloContext } from "ublo/with-ublo";
5
+ import Button from "dt-design-system/es/button";
6
+ import ChevronLeftIcon from "dt-design-system/es/icons/chevron-left";
7
+ import ChevronRightIcon from "dt-design-system/es/icons/chevron-right";
8
+ import ScrollbarSize from "../scrollbar-size";
9
+ import css from "./infinite-carousel.module.css";
10
+ export default function InfiniteCarousel({ className, children, variant = "wheel", options = {}, cloneNumber, }) {
11
+ const { cmsMode } = useUbloContext();
12
+ const zoneRef = React.useRef(null);
13
+ const itemWidth = React.useRef(null);
14
+ const itemHeight = React.useRef(null);
15
+ const [items, setItems] = React.useState([]);
16
+ const [currentIndex, setCurrentIndex] = React.useState(0);
17
+ const [isTransitioning, setIsTransitioning] = React.useState(false);
18
+ const { wheel_items_gap = 100, scale_items_gap = 10, hide_wheel_items = false, scale_number = 0.75, rotate_number = 25, translateY_number = 80, transition_duration = 500, } = options;
19
+ const cloneCount = React.useMemo(() => {
20
+ if (cloneNumber !== undefined)
21
+ return cloneNumber;
22
+ return variant === "scale" ? 6 : 3;
23
+ }, [variant, cloneNumber]);
24
+ const extractItems = React.useCallback(() => {
25
+ if (!zoneRef.current)
26
+ return [];
27
+ const zone = zoneRef.current;
28
+ const sections = Array.from(zone.querySelectorAll("section:not([data-hidden], [hidden], [style*='display: none'])"));
29
+ return sections;
30
+ }, []);
31
+ React.useEffect(() => {
32
+ if (cmsMode)
33
+ return;
34
+ const foundItems = extractItems();
35
+ if (foundItems.length > 0) {
36
+ setItems(foundItems);
37
+ setCurrentIndex(cloneCount);
38
+ if (!itemWidth.current && !itemHeight.current) {
39
+ itemWidth.current = foundItems[0].offsetWidth;
40
+ itemHeight.current = foundItems[0].offsetHeight;
41
+ }
42
+ }
43
+ }, [extractItems, cmsMode, cloneCount]);
44
+ React.useEffect(() => {
45
+ if (!zoneRef.current || cmsMode)
46
+ return;
47
+ const observer = new MutationObserver(() => {
48
+ const foundItems = extractItems();
49
+ if (foundItems.length > 0 && items.length === 0) {
50
+ setItems(foundItems);
51
+ }
52
+ });
53
+ observer.observe(zoneRef.current, {
54
+ attributes: true,
55
+ childList: true,
56
+ subtree: true,
57
+ });
58
+ return () => observer.disconnect();
59
+ }, [extractItems, items, cmsMode]);
60
+ const infiniteItems = React.useMemo(() => {
61
+ if (items.length === 0)
62
+ return [];
63
+ const createClone = (element) => {
64
+ const clone = element.cloneNode(true);
65
+ clone.setAttribute("aria-hidden", "true");
66
+ clone.removeAttribute("id");
67
+ clone.querySelectorAll("[id]").forEach((el) => {
68
+ el.removeAttribute("id");
69
+ });
70
+ return clone;
71
+ };
72
+ const beforeClones = [];
73
+ const afterClones = [];
74
+ for (let i = 0; i < cloneCount; i++) {
75
+ const itemIndex = (items.length - cloneCount + i + items.length) % items.length;
76
+ beforeClones.push(createClone(items[itemIndex]));
77
+ }
78
+ for (let i = 0; i < cloneCount; i++) {
79
+ const itemIndex = i % items.length;
80
+ afterClones.push(createClone(items[itemIndex]));
81
+ }
82
+ return [...beforeClones, ...items, ...afterClones];
83
+ }, [items, cloneCount]);
84
+ const slideTo = (direction) => {
85
+ if (isTransitioning || items.length === 0)
86
+ return;
87
+ setIsTransitioning(true);
88
+ setCurrentIndex((prev) => {
89
+ if (direction === "next") {
90
+ return prev + 1;
91
+ }
92
+ else {
93
+ return prev - 1;
94
+ }
95
+ });
96
+ };
97
+ React.useEffect(() => {
98
+ if (!isTransitioning)
99
+ return;
100
+ const timer = setTimeout(() => {
101
+ setIsTransitioning(false);
102
+ if (currentIndex === items.length + cloneCount) {
103
+ setCurrentIndex(cloneCount);
104
+ }
105
+ else if (currentIndex < cloneCount) {
106
+ setCurrentIndex(items.length + cloneCount - 1);
107
+ }
108
+ }, transition_duration);
109
+ return () => clearTimeout(timer);
110
+ }, [
111
+ isTransitioning,
112
+ currentIndex,
113
+ items.length,
114
+ cloneCount,
115
+ transition_duration,
116
+ ]);
117
+ const getItemStyle = (index) => {
118
+ const offset = index - currentIndex;
119
+ const absOffset = Math.abs(offset);
120
+ const width = itemWidth.current;
121
+ if (variant === "wheel") {
122
+ let rotate = 0;
123
+ let translateX = 0;
124
+ let translateY = 0;
125
+ let opacity = 1;
126
+ const gap = wheel_items_gap;
127
+ if (offset === 0) {
128
+ translateX = 0;
129
+ translateY = 0;
130
+ }
131
+ else {
132
+ rotate = rotate_number * offset;
133
+ translateX = (width + gap) * offset;
134
+ translateY = translateY_number * (absOffset * absOffset);
135
+ const condition = hide_wheel_items ? absOffset >= 2 : absOffset >= 3;
136
+ if (condition) {
137
+ opacity = 0;
138
+ }
139
+ }
140
+ return {
141
+ transform: `translateX(${translateX}px) translateY(${translateY}px) rotate(${rotate}deg)`,
142
+ opacity,
143
+ transition: isTransitioning
144
+ ? `all ${transition_duration}ms cubic-bezier(0.4, 0.0, 0.2, 1)`
145
+ : "none",
146
+ };
147
+ }
148
+ else {
149
+ let scale = scale_number;
150
+ let opacity = 1;
151
+ let translateX = 0;
152
+ const gap = scale_items_gap;
153
+ if (offset === 0) {
154
+ translateX = 0;
155
+ scale = 1;
156
+ }
157
+ else if (absOffset === 1) {
158
+ translateX = offset * (width + gap - (width - width * scale) / 2);
159
+ }
160
+ else {
161
+ const sign = offset > 0 ? 1 : -1;
162
+ translateX = sign * (width + gap - (width - width * scale) / 2);
163
+ for (let i = 2; i <= absOffset; i++) {
164
+ translateX += sign * (width * scale + gap);
165
+ }
166
+ }
167
+ return {
168
+ transform: `translateX(${translateX}px) scale(${scale})`,
169
+ opacity,
170
+ transition: isTransitioning
171
+ ? `all ${transition_duration}ms cubic-bezier(0.4, 0.0, 0.2, 1)`
172
+ : "none",
173
+ };
174
+ }
175
+ };
176
+ const classes = classNames(css.carousel, css[`carousel--${variant}`], className);
177
+ if (items.length === 0 || cmsMode) {
178
+ return (_jsx("div", { className: classes, children: _jsx("div", { className: css.inner, children: React.cloneElement(children, {
179
+ ref: zoneRef,
180
+ }) }) }));
181
+ }
182
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: classes, style: {
183
+ "--carousel-item-width": `${itemWidth.current}px`,
184
+ "--carousel-item-height": `${itemHeight.current}px`,
185
+ }, children: [_jsxs("div", { className: css.controls, children: [_jsx(Button, { className: css.control, variant: "link", onClick: () => slideTo("prev"), "data-control": "prev", children: _jsx(ChevronLeftIcon, { className: css.controlIcon }) }), _jsx(Button, { className: css.control, variant: "link", onClick: () => slideTo("next"), "data-control": "next", children: _jsx(ChevronRightIcon, { className: css.controlIcon }) })] }), _jsx("div", { className: css.viewport, children: _jsx("div", { className: css.track, children: infiniteItems.map((item, index) => (_jsx("div", { className: css.item, style: getItemStyle(index), dangerouslySetInnerHTML: { __html: item.outerHTML } }, `item-${index}`))) }) }), _jsx("div", { style: { display: "none" }, children: React.cloneElement(children, {
186
+ ref: zoneRef,
187
+ }) })] }), _jsx(ScrollbarSize, {})] }));
188
+ }
@@ -0,0 +1,173 @@
1
+ .carousel {
2
+ --carousel-width: var(--content-width);
3
+ --carousel-padding-top: 60px;
4
+ --carousel-button-width: 48px;
5
+ --carousel-button-background: hsl(0, 0%, 100%);
6
+ --carousel-button-hover-background: hsl(0, 0%, 100%);
7
+ --carousel-left-button-glow: transparent;
8
+ --carousel-right-button-glow: transparent;
9
+ --carousel-button-radius: 50%;
10
+ --carousel-button-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
11
+ --carousel-button-icon-size: 16px;
12
+ --carousel-button-icon-color: #081527;
13
+ --carousel-before-background: transparent;
14
+ --carousel-after-background: transparent;
15
+
16
+ position: relative;
17
+ display: flex;
18
+ justify-content: center;
19
+ /* 2px viennent des pseudo-elements after des boutons de control */
20
+ width: calc(100vw - var(--scrollbar-size) - 2px);
21
+ max-width: var(--carousel-width);
22
+ margin: 0 auto;
23
+ padding-top: var(--carousel-padding-top);
24
+ }
25
+
26
+ .carousel--wheel {
27
+ --carousel-height: calc(var(--carousel-item-height) + 150px);
28
+ }
29
+
30
+ .carousel--scale {
31
+ --carousel-height: calc(var(--carousel-item-height) + 100px);
32
+ }
33
+
34
+ /* ----- FALLBACK : Cas où il n'y a pas de logique de carousel ----- */
35
+
36
+ .inner {
37
+ display: flex;
38
+ align-items: center;
39
+ gap: 10px;
40
+ max-width: var(--content-width);
41
+ overflow-x: auto;
42
+ }
43
+ /* ---------- */
44
+
45
+ .controls {
46
+ position: absolute;
47
+ top: var(--carousel-item-height);
48
+ left: 0;
49
+ width: 100%;
50
+ margin: 0 auto;
51
+ display: flex;
52
+ justify-content: space-between;
53
+ align-items: center;
54
+ pointer-events: none;
55
+ z-index: 2;
56
+ }
57
+
58
+ .carousel--wheel .controls {
59
+ /* boutons au milieu de l'item central (item height / 2 - paddingtop carousel) */
60
+ top: calc((var(--carousel-item-height) + var(--carousel-padding-top)) / 2);
61
+ left: auto;
62
+ /* largeur de la taille de l'item + des boutons + petit écart */
63
+ width: calc(
64
+ var(--carousel-item-width) + (var(--carousel-button-width) * 2) + 20px
65
+ );
66
+ transform: none;
67
+ }
68
+
69
+ .control {
70
+ --ds-button-background: var(--carousel-button-background);
71
+ --ds-button-hover-background: var(--carousel-button-hover-background);
72
+ --ds-button-radius: var(--carousel-button-radius);
73
+ --ds-button-border: var(--carousel-button-border);
74
+ --ds-button-shadow: var(--carousel-button-shadow);
75
+
76
+ pointer-events: auto;
77
+ width: var(--carousel-button-width);
78
+ height: var(--carousel-button-width);
79
+ display: flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ transition: background-color 240ms var(--transition-easing);
83
+ }
84
+
85
+ .control::after {
86
+ content: "";
87
+ position: absolute;
88
+ top: 1px;
89
+ left: -1px;
90
+ height: 100%;
91
+ width: 100%;
92
+ background-image: var(--carousel-left-button-glow);
93
+ border-radius: var(--carousel-button-radius);
94
+ z-index: -1;
95
+ }
96
+
97
+ .control + .control::after {
98
+ left: auto;
99
+ right: -1px;
100
+ background-image: var(--carousel-right-button-glow);
101
+ z-index: -1;
102
+ }
103
+
104
+ .controlIcon {
105
+ --size: var(--carousel-button-icon-size);
106
+
107
+ fill: var(--carousel-button-icon-color);
108
+ }
109
+
110
+ .viewport {
111
+ position: relative;
112
+ min-width: calc(100vw - var(--scrollbar-size));
113
+ height: 100%;
114
+ min-height: var(--carousel-height);
115
+ overflow: hidden;
116
+ }
117
+
118
+ .carousel--scale .viewport::before {
119
+ content: "";
120
+ position: absolute;
121
+ top: 0;
122
+ left: 0;
123
+ height: 100%;
124
+ width: var(--carousel-item-width);
125
+ background: var(--carousel-before-background);
126
+ z-index: 1;
127
+ }
128
+
129
+ .carousel--scale .viewport::after {
130
+ content: "";
131
+ position: absolute;
132
+ top: 0;
133
+ right: 0;
134
+ height: 100%;
135
+ width: var(--carousel-item-width);
136
+ background: var(--carousel-after-background);
137
+ z-index: 1;
138
+ }
139
+
140
+ .track {
141
+ position: relative;
142
+ width: 100%;
143
+ height: 100%;
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ }
148
+
149
+ .item {
150
+ position: absolute;
151
+ top: 50%;
152
+ transform: translate(-50%, -50%);
153
+ will-change: transform, opacity;
154
+ pointer-events: auto;
155
+ }
156
+
157
+ .carousel--wheel .item {
158
+ max-width: 90vw;
159
+ }
160
+
161
+ .carousel--scale .item {
162
+ max-width: 85vw;
163
+ transform-origin: top center;
164
+ }
165
+
166
+ /* CMS */
167
+ [data-cms-mode="true"] .carousel {
168
+ pointer-events: none;
169
+ }
170
+
171
+ [data-cms-mode="true"] .controls {
172
+ display: none;
173
+ }
@@ -14,7 +14,7 @@ export default function Book({ instructors, trombi }) {
14
14
  const [language, setLanguage] = React.useState("");
15
15
  const [search, setSearch] = React.useState("");
16
16
  const [loading, setLoading] = React.useState(false);
17
- const isTrombi = trombi || !Object.keys(prefixes).includes(lang);
17
+ const isTrombi = !Object.keys(prefixes).includes(lang) || trombi;
18
18
  const refreshContext = React.useCallback(async () => {
19
19
  try {
20
20
  setLoading(true);
@@ -1 +1 @@
1
- {"version":3,"file":"instructor.d.ts","sourceRoot":"","sources":["../../../../src/esf/components/instructors-book/instructor.js"],"names":[],"mappings":"AAYA;;;;;;4CAyFC"}
1
+ {"version":3,"file":"instructor.d.ts","sourceRoot":"","sources":["../../../../src/esf/components/instructors-book/instructor.js"],"names":[],"mappings":"AAYA;;;;;;4CA2FC"}
@@ -16,6 +16,7 @@ export default function Instructor({ instructor, formFields, formSendFunction, t
16
16
  const [loading, setLoading] = React.useState(true);
17
17
  const [picture, setPicture] = React.useState(photo);
18
18
  const [popupOpened, setPopupOpened] = React.useState(false);
19
+ const prefixLang = lang === "fr" ? "fr" : "en";
19
20
  const openPopup = async (e) => {
20
21
  if (!popup)
21
22
  return;
@@ -28,7 +29,7 @@ export default function Instructor({ instructor, formFields, formSendFunction, t
28
29
  const Tag = trombi ? "div" : Link;
29
30
  const divProps = {};
30
31
  const linkProps = {
31
- href: `${prefixes[lang]}/${uri}`,
32
+ href: `${prefixes[prefixLang]}/${uri}`,
32
33
  onClick: openPopup,
33
34
  };
34
35
  const props = trombi ? divProps : linkProps;
@@ -2,6 +2,5 @@ export default prefixes;
2
2
  declare namespace prefixes {
3
3
  let fr: string;
4
4
  let en: string;
5
- let nl: string;
6
5
  }
7
6
  //# sourceMappingURL=prefixes.d.ts.map
@@ -1,6 +1,5 @@
1
1
  const prefixes = {
2
2
  fr: "/moniteur",
3
3
  en: "/instructor",
4
- nl: "/instructeur",
5
4
  };
6
5
  export default prefixes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ublo-lib",
3
- "version": "1.47.81",
3
+ "version": "1.47.84",
4
4
  "peerDependencies": {
5
5
  "classnames": "^2.5.1",
6
6
  "dt-design-system": "^3.12.0",