allaw-ui 3.6.9 → 3.7.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.
@@ -12,6 +12,17 @@ interface CustomContentConfig {
12
12
  component: React.ComponentType<any>;
13
13
  props?: Record<string, unknown>;
14
14
  }
15
+ interface BreakpointConfig {
16
+ breakpoint: number;
17
+ maxWidth: number | string;
18
+ }
19
+ interface MaxWidthConfig {
20
+ default?: number | string;
21
+ mobile?: number | string;
22
+ tablet?: number | string;
23
+ desktop?: number | string;
24
+ breakpoints?: BreakpointConfig[];
25
+ }
15
26
  export interface ModalProps {
16
27
  show: boolean;
17
28
  title: string;
@@ -29,6 +40,7 @@ export interface ModalProps {
29
40
  isOpen: boolean;
30
41
  onClose: () => void;
31
42
  }) => React.ReactNode;
43
+ maxWidthConfig?: MaxWidthConfig;
32
44
  verticalOffset?: {
33
45
  top?: number;
34
46
  bottom?: number;
@@ -9,6 +9,15 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
13
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
14
+ if (ar || !(i in from)) {
15
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
16
+ ar[i] = from[i];
17
+ }
18
+ }
19
+ return to.concat(ar || Array.prototype.slice.call(from));
20
+ };
12
21
  import React, { useEffect, useRef, useState } from "react";
13
22
  import ReactDOM from "react-dom";
14
23
  import style from "./Modal.module.css";
@@ -17,12 +26,14 @@ import SecondaryButton from "../../atoms/buttons/SecondaryButton";
17
26
  import Heading from "../../atoms/typography/Heading";
18
27
  import Paragraph from "../../atoms/typography/Paragraph";
19
28
  var Modal = function (_a) {
20
- var show = _a.show, title = _a.title, description = _a.description, confirmLabel = _a.confirmLabel, cancelLabel = _a.cancelLabel, onConfirm = _a.onConfirm, onCancel = _a.onCancel, _b = _a.isDanger, isDanger = _b === void 0 ? false : _b, _c = _a.confirmIconName, confirmIconName = _c === void 0 ? "allaw-icon-check" : _c, imageConfig = _a.imageConfig, children = _a.children, customContent = _a.customContent, renderContent = _a.renderContent, verticalOffset = _a.verticalOffset, horizontalOffset = _a.horizontalOffset;
29
+ var show = _a.show, title = _a.title, description = _a.description, confirmLabel = _a.confirmLabel, cancelLabel = _a.cancelLabel, onConfirm = _a.onConfirm, onCancel = _a.onCancel, _b = _a.isDanger, isDanger = _b === void 0 ? false : _b, _c = _a.confirmIconName, confirmIconName = _c === void 0 ? "allaw-icon-check" : _c, imageConfig = _a.imageConfig, children = _a.children, customContent = _a.customContent, renderContent = _a.renderContent, maxWidthConfig = _a.maxWidthConfig, verticalOffset = _a.verticalOffset, horizontalOffset = _a.horizontalOffset;
21
30
  var _d = useState(false), isVisible = _d[0], setIsVisible = _d[1];
22
31
  var _e = useState(false), imgError = _e[0], setImgError = _e[1];
23
32
  var portalContainerRef = useRef(null);
24
33
  var modalContentRef = useRef(null);
25
34
  var isMouseDownOutsideRef = useRef(false);
35
+ // ID unique pour ce modal (pour éviter les conflits)
36
+ var modalId = useRef("modal-".concat(Math.random().toString(36).substr(2, 9)));
26
37
  useEffect(function () {
27
38
  if (show) {
28
39
  var container = document.createElement("div");
@@ -47,6 +58,11 @@ var Modal = function (_a) {
47
58
  document.body.removeChild(portalContainerRef.current);
48
59
  document.body.style.overflow = "";
49
60
  }
61
+ // Nettoyer les styles dynamiques de ce modal
62
+ var styleElement = document.getElementById("modal-styles-".concat(modalId.current));
63
+ if (styleElement) {
64
+ styleElement.remove();
65
+ }
50
66
  };
51
67
  }, [show]);
52
68
  var handleMouseDown = function (e) {
@@ -69,25 +85,110 @@ var Modal = function (_a) {
69
85
  setImgError(true);
70
86
  };
71
87
  var renderModalContent = function () {
72
- if (renderContent) {
73
- return (React.createElement("div", { className: style.modalCustomWrapper }, renderContent({ isOpen: show, onClose: onCancel })));
74
- }
75
- if (customContent) {
76
- var Component = customContent.component, _a = customContent.props, props = _a === void 0 ? {} : _a;
77
- return (React.createElement("div", { className: style.modalCustomWrapper },
78
- React.createElement(Component, __assign({}, props))));
79
- }
80
- if (children) {
81
- return React.createElement("div", { className: style.modalCustomWrapper }, children);
82
- }
83
88
  return (React.createElement(React.Fragment, null,
84
89
  React.createElement("div", { className: style.modalHeadingWrapper },
85
90
  React.createElement(Heading, { text: title, variant: "h4", color: "noir", align: "left" })),
86
91
  React.createElement("div", { className: style.modalParagraphWrapper },
87
92
  React.createElement(Paragraph, { text: description, variant: "medium", size: "default", className: style.modalParagraph })),
88
- imageConfig && !imgError && (React.createElement("div", { className: "".concat(style.modalImageWrapper, " ").concat(imageConfig.className || ""), style: __assign({ padding: imageConfig.padding }, imageConfig.style) },
93
+ renderContent && (React.createElement("div", { className: style.modalCustomWrapper }, renderContent({ isOpen: show, onClose: onCancel }))),
94
+ !renderContent && customContent && (React.createElement("div", { className: style.modalCustomWrapper },
95
+ React.createElement(customContent.component, __assign({}, (customContent.props || {}))))),
96
+ !renderContent && !customContent && children && (React.createElement("div", { className: style.modalCustomWrapper }, children)),
97
+ !renderContent &&
98
+ !customContent &&
99
+ !children &&
100
+ imageConfig &&
101
+ !imgError && (React.createElement("div", { className: "".concat(style.modalImageWrapper, " ").concat(imageConfig.className || ""), style: __assign({ padding: imageConfig.padding }, imageConfig.style) },
89
102
  React.createElement("img", { src: imageConfig.url, alt: imageConfig.alt || "", width: imageConfig.width, height: imageConfig.height, onError: handleImageError, className: style.modalImage })))));
90
103
  };
104
+ // Générer les styles pour la largeur maximale responsive
105
+ var getMaxWidthStyles = function () {
106
+ if (!maxWidthConfig)
107
+ return {};
108
+ var styles = {};
109
+ // Approche avec breakpoints personnalisés (prioritaire)
110
+ if (maxWidthConfig.breakpoints && maxWidthConfig.breakpoints.length > 0) {
111
+ // Trier les breakpoints par ordre croissant
112
+ var sortedBreakpoints_1 = __spreadArray([], maxWidthConfig.breakpoints, true).sort(function (a, b) { return a.breakpoint - b.breakpoint; });
113
+ // Générer les media queries avec classe unique
114
+ var mediaQueries_1 = "";
115
+ var uniqueClass_1 = "modal-".concat(modalId.current);
116
+ sortedBreakpoints_1.forEach(function (bp, index) {
117
+ var maxWidth = typeof bp.maxWidth === "number" ? "".concat(bp.maxWidth, "px") : bp.maxWidth;
118
+ if (index === 0) {
119
+ // Premier breakpoint : max-width
120
+ mediaQueries_1 += "@media (max-width: ".concat(bp.breakpoint - 1, "px) { .").concat(uniqueClass_1, " { max-width: ").concat(maxWidth, " !important; } }");
121
+ }
122
+ if (index === sortedBreakpoints_1.length - 1) {
123
+ // Dernier breakpoint : min-width
124
+ mediaQueries_1 += "@media (min-width: ".concat(bp.breakpoint, "px) { .").concat(uniqueClass_1, " { max-width: ").concat(maxWidth, " !important; } }");
125
+ }
126
+ else {
127
+ // Breakpoints intermédiaires
128
+ var nextBreakpoint = sortedBreakpoints_1[index + 1].breakpoint;
129
+ mediaQueries_1 += "@media (min-width: ".concat(bp.breakpoint, "px) and (max-width: ").concat(nextBreakpoint - 1, "px) { .").concat(uniqueClass_1, " { max-width: ").concat(maxWidth, " !important; } }");
130
+ }
131
+ });
132
+ // Injecter les styles avec ID unique
133
+ if (mediaQueries_1) {
134
+ var styleElement = document.getElementById("modal-styles-".concat(modalId.current));
135
+ if (!styleElement) {
136
+ styleElement = document.createElement("style");
137
+ styleElement.id = "modal-styles-".concat(modalId.current);
138
+ document.head.appendChild(styleElement);
139
+ }
140
+ styleElement.textContent = mediaQueries_1;
141
+ }
142
+ return styles;
143
+ }
144
+ // Approche classique (backward compatibility)
145
+ if (maxWidthConfig.default) {
146
+ styles.maxWidth =
147
+ typeof maxWidthConfig.default === "number"
148
+ ? "".concat(maxWidthConfig.default, "px")
149
+ : maxWidthConfig.default;
150
+ }
151
+ // Variables CSS pour les breakpoints prédéfinis
152
+ if (maxWidthConfig.mobile) {
153
+ styles["--modal-max-width-mobile"] =
154
+ typeof maxWidthConfig.mobile === "number"
155
+ ? "".concat(maxWidthConfig.mobile, "px")
156
+ : maxWidthConfig.mobile;
157
+ }
158
+ if (maxWidthConfig.tablet) {
159
+ styles["--modal-max-width-tablet"] =
160
+ typeof maxWidthConfig.tablet === "number"
161
+ ? "".concat(maxWidthConfig.tablet, "px")
162
+ : maxWidthConfig.tablet;
163
+ }
164
+ if (maxWidthConfig.desktop) {
165
+ styles["--modal-max-width-desktop"] =
166
+ typeof maxWidthConfig.desktop === "number"
167
+ ? "".concat(maxWidthConfig.desktop, "px")
168
+ : maxWidthConfig.desktop;
169
+ }
170
+ return styles;
171
+ };
172
+ // Gérer la classe pour les breakpoints personnalisés
173
+ var getDynamicModalClass = function () {
174
+ if ((maxWidthConfig === null || maxWidthConfig === void 0 ? void 0 : maxWidthConfig.breakpoints) && maxWidthConfig.breakpoints.length > 0) {
175
+ return "modal-".concat(modalId.current);
176
+ }
177
+ return "";
178
+ };
179
+ // Générer les classes CSS dynamiques pour les breakpoints prédéfinis
180
+ var getMaxWidthClasses = function () {
181
+ if (!maxWidthConfig || maxWidthConfig.breakpoints)
182
+ return "";
183
+ var classes = "";
184
+ if (maxWidthConfig.mobile)
185
+ classes += " ".concat(style.maxWidthMobile);
186
+ if (maxWidthConfig.tablet)
187
+ classes += " ".concat(style.maxWidthTablet);
188
+ if (maxWidthConfig.desktop)
189
+ classes += " ".concat(style.maxWidthDesktop);
190
+ return classes;
191
+ };
91
192
  if (!show || !isVisible || !portalContainerRef.current)
92
193
  return null;
93
194
  var modalContent = (React.createElement("div", { className: "".concat(style.modalOverlay, " ").concat(isVisible ? style.visible : "", " ").concat(show ? style.modal : ""), onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, style: {
@@ -102,7 +203,7 @@ var Modal = function (_a) {
102
203
  ? "".concat(horizontalOffset.right, "px")
103
204
  : undefined,
104
205
  } },
105
- React.createElement("div", { className: "".concat(style.modalContent, " ").concat(show ? style.modal : ""), ref: modalContentRef },
206
+ React.createElement("div", { className: "".concat(style.modalContent, " ").concat(show ? style.modal : "", " ").concat(getMaxWidthClasses(), " ").concat(getDynamicModalClass()), ref: modalContentRef, style: __assign({}, getMaxWidthStyles()) },
106
207
  renderModalContent(),
107
208
  React.createElement("div", { className: style.modalButtons },
108
209
  cancelLabel && (React.createElement(SecondaryButton, { label: cancelLabel, onClick: onCancel, startIconName: "allaw-icon-close", startIcon: true })),
@@ -342,3 +342,35 @@
342
342
  .modal {
343
343
  /* Autres styles pour le modal */
344
344
  }
345
+
346
+ /* Classes pour largeurs maximales responsives */
347
+ .maxWidthMobile {
348
+ /* Styles appliqués sur mobile via JavaScript */
349
+ }
350
+
351
+ .maxWidthTablet {
352
+ /* Styles appliqués sur tablette via JavaScript */
353
+ }
354
+
355
+ .maxWidthDesktop {
356
+ /* Styles appliqués sur desktop via JavaScript */
357
+ }
358
+
359
+ /* Breakpoints pour largeurs maximales personnalisées */
360
+ @media (max-width: 767px) {
361
+ .modalContent.maxWidthMobile {
362
+ max-width: var(--modal-max-width-mobile, 500px) !important;
363
+ }
364
+ }
365
+
366
+ @media (min-width: 768px) and (max-width: 1023px) {
367
+ .modalContent.maxWidthTablet {
368
+ max-width: var(--modal-max-width-tablet, 500px) !important;
369
+ }
370
+ }
371
+
372
+ @media (min-width: 1024px) {
373
+ .modalContent.maxWidthDesktop {
374
+ max-width: var(--modal-max-width-desktop, 500px) !important;
375
+ }
376
+ }
@@ -21,7 +21,7 @@ declare namespace _default {
21
21
  let description_2: string;
22
22
  export { description_2 as description };
23
23
  }
24
- export namespace verticalOffset {
24
+ export namespace maxWidthConfig {
25
25
  export namespace control_3 {
26
26
  let type_1: string;
27
27
  export { type_1 as type };
@@ -30,7 +30,7 @@ declare namespace _default {
30
30
  let description_3: string;
31
31
  export { description_3 as description };
32
32
  }
33
- export namespace horizontalOffset {
33
+ export namespace verticalOffset {
34
34
  export namespace control_4 {
35
35
  let type_2: string;
36
36
  export { type_2 as type };
@@ -39,53 +39,62 @@ declare namespace _default {
39
39
  let description_4: string;
40
40
  export { description_4 as description };
41
41
  }
42
- export namespace show {
43
- let control_5: string;
42
+ export namespace horizontalOffset {
43
+ export namespace control_5 {
44
+ let type_3: string;
45
+ export { type_3 as type };
46
+ }
44
47
  export { control_5 as control };
45
48
  let description_5: string;
46
49
  export { description_5 as description };
47
50
  }
48
- export namespace title_1 {
51
+ export namespace show {
49
52
  let control_6: string;
50
53
  export { control_6 as control };
51
54
  let description_6: string;
52
55
  export { description_6 as description };
53
56
  }
54
- export { title_1 as title };
55
- export namespace description_7 {
57
+ export namespace title_1 {
56
58
  let control_7: string;
57
59
  export { control_7 as control };
58
- let description_8: string;
59
- export { description_8 as description };
60
+ let description_7: string;
61
+ export { description_7 as description };
60
62
  }
61
- export { description_7 as description };
62
- export namespace confirmLabel {
63
+ export { title_1 as title };
64
+ export namespace description_8 {
63
65
  let control_8: string;
64
66
  export { control_8 as control };
65
67
  let description_9: string;
66
68
  export { description_9 as description };
67
69
  }
68
- export namespace cancelLabel {
70
+ export { description_8 as description };
71
+ export namespace confirmLabel {
69
72
  let control_9: string;
70
73
  export { control_9 as control };
71
74
  let description_10: string;
72
75
  export { description_10 as description };
73
76
  }
74
- export namespace imageConfig {
75
- export namespace control_10 {
76
- let type_3: string;
77
- export { type_3 as type };
78
- }
77
+ export namespace cancelLabel {
78
+ let control_10: string;
79
79
  export { control_10 as control };
80
80
  let description_11: string;
81
81
  export { description_11 as description };
82
82
  }
83
- export namespace isDanger {
84
- let control_11: string;
83
+ export namespace imageConfig {
84
+ export namespace control_11 {
85
+ let type_4: string;
86
+ export { type_4 as type };
87
+ }
85
88
  export { control_11 as control };
86
89
  let description_12: string;
87
90
  export { description_12 as description };
88
91
  }
92
+ export namespace isDanger {
93
+ let control_12: string;
94
+ export { control_12 as control };
95
+ let description_13: string;
96
+ export { description_13 as description };
97
+ }
89
98
  }
90
99
  export namespace parameters {
91
100
  namespace backgrounds {
@@ -108,4 +117,10 @@ export const WithLargeOffset: any;
108
117
  export const WithImageConfig: any;
109
118
  export const WithoutCancel: any;
110
119
  export const OffsetBothWays: any;
120
+ export const WithCustomMaxWidth: any;
121
+ export const WithResponsiveMaxWidth: any;
122
+ export const WithLargeContentAndMaxWidth: any;
123
+ export const WithCustomBreakpoints: any;
124
+ export const WithManyBreakpoints: any;
125
+ export const WithMixedUnitsBreakpoints: any;
111
126
  import Modal from "./Modal";
@@ -54,6 +54,10 @@ export default {
54
54
  control: false,
55
55
  description: "Fonction de rendu (modalProps) => ReactNode",
56
56
  },
57
+ maxWidthConfig: {
58
+ control: { type: "object" },
59
+ description: "Configuration responsive pour la largeur maximale. Deux approches disponibles :\n\n**Approche classique (breakpoints pr\u00E9d\u00E9finis) :**\n{ default: 800, mobile: 350, tablet: 600, desktop: 900 }\n- mobile: \u2264 767px\n- tablet: 768px - 1023px \n- desktop: \u2265 1024px\n\n**Approche personnalis\u00E9e (breakpoints custom) :**\n{ breakpoints: [{ breakpoint: 480, maxWidth: 320 }, { breakpoint: 1200, maxWidth: 900 }] }\n- D\u00E9finissez vos propres seuils de largeur d'\u00E9cran\n- Supporte les unit\u00E9s mixtes (px, vw, rem, etc.)",
60
+ },
57
61
  verticalOffset: {
58
62
  control: { type: "object" },
59
63
  description: "Décalage vertical du modal (en px) pour éviter les barres de navigation",
@@ -228,3 +232,78 @@ export var WithoutCancel = Template.bind({});
228
232
  WithoutCancel.args = __assign(__assign({}, Default.args), { title: "Information", description: "Cette action a été effectuée avec succès.", confirmLabel: "OK", cancelLabel: undefined });
229
233
  export var OffsetBothWays = Template.bind({});
230
234
  OffsetBothWays.args = __assign(__assign({}, Default.args), { title: "Modal avec décalages", description: "Décalages verticaux et horizontaux appliqués.", verticalOffset: { top: 100, bottom: 50 }, horizontalOffset: { left: 80, right: 80 } });
235
+ // Nouvelles stories pour maxWidthConfig
236
+ export var WithCustomMaxWidth = Template.bind({});
237
+ WithCustomMaxWidth.args = __assign(__assign({}, Default.args), { title: "Modal avec largeur personnalisée", description: "Cette modal a une largeur maximale de 800px sur tous les écrans.", maxWidthConfig: {
238
+ default: 800,
239
+ } });
240
+ export var WithResponsiveMaxWidth = Template.bind({});
241
+ WithResponsiveMaxWidth.args = __assign(__assign({}, Default.args), { title: "Modal responsive", description: "Cette modal adapte sa largeur selon la taille d&apos;écran : 350px sur mobile, 600px sur tablette, 900px sur desktop.", maxWidthConfig: {
242
+ mobile: 350,
243
+ tablet: 600,
244
+ desktop: 900,
245
+ } });
246
+ export var WithLargeContentAndMaxWidth = Template.bind({});
247
+ WithLargeContentAndMaxWidth.args = {
248
+ show: false,
249
+ title: "Modal large avec contenu personnalisé",
250
+ description: "Cette modal utilise une largeur plus grande pour accommoder plus de contenu.",
251
+ confirmLabel: "Valider",
252
+ cancelLabel: "Annuler",
253
+ maxWidthConfig: {
254
+ default: 700,
255
+ mobile: 350,
256
+ tablet: 650,
257
+ desktop: 800,
258
+ },
259
+ children: (React.createElement("div", { style: { textAlign: "center", padding: "2rem" } },
260
+ React.createElement("h2", { style: { color: "#1f2937", marginBottom: "1rem" } }, "Contenu \u00E9tendu n\u00E9cessitant plus d'espace"),
261
+ React.createElement("div", { style: {
262
+ display: "grid",
263
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
264
+ gap: "1rem",
265
+ marginBottom: "1.5rem",
266
+ } },
267
+ React.createElement("div", { style: {
268
+ padding: "1rem",
269
+ backgroundColor: "#f3f4f6",
270
+ borderRadius: "0.5rem",
271
+ } },
272
+ React.createElement("h4", null, "Section 1"),
273
+ React.createElement("p", null, "Contenu de la premi\u00E8re section avec plus de texte pour tester l'espace disponible.")),
274
+ React.createElement("div", { style: {
275
+ padding: "1rem",
276
+ backgroundColor: "#f3f4f6",
277
+ borderRadius: "0.5rem",
278
+ } },
279
+ React.createElement("h4", null, "Section 2"),
280
+ React.createElement("p", null, "Contenu de la deuxi\u00E8me section avec \u00E9galement plus de texte."))),
281
+ React.createElement("p", { style: { color: "#6b7280" } }, "Cette modal d\u00E9montre l'utilisation de largeurs personnalis\u00E9es pour accommoder du contenu plus large."))),
282
+ };
283
+ // Nouvelles stories pour breakpoints personnalisés
284
+ export var WithCustomBreakpoints = Template.bind({});
285
+ WithCustomBreakpoints.args = __assign(__assign({}, Default.args), { title: "Modal avec breakpoints personnalisés", description: "Cette modal utilise des breakpoints sur mesure : 480px, 900px, et 1400px.", maxWidthConfig: {
286
+ breakpoints: [
287
+ { breakpoint: 480, maxWidth: 320 },
288
+ { breakpoint: 900, maxWidth: 700 },
289
+ { breakpoint: 1400, maxWidth: 1000 },
290
+ ],
291
+ } });
292
+ export var WithManyBreakpoints = Template.bind({});
293
+ WithManyBreakpoints.args = __assign(__assign({}, Default.args), { title: "Modal avec multiples breakpoints", description: "Exemple avec 5 breakpoints personnalisés pour un contrôle précis.", maxWidthConfig: {
294
+ breakpoints: [
295
+ { breakpoint: 360, maxWidth: 300 },
296
+ { breakpoint: 640, maxWidth: 500 },
297
+ { breakpoint: 768, maxWidth: 600 },
298
+ { breakpoint: 1024, maxWidth: 800 },
299
+ { breakpoint: 1440, maxWidth: 1200 },
300
+ ],
301
+ } });
302
+ export var WithMixedUnitsBreakpoints = Template.bind({});
303
+ WithMixedUnitsBreakpoints.args = __assign(__assign({}, Default.args), { title: "Modal avec unités mixtes", description: "Démonstration avec différentes unités : px, vw, rem.", maxWidthConfig: {
304
+ breakpoints: [
305
+ { breakpoint: 480, maxWidth: "90vw" },
306
+ { breakpoint: 768, maxWidth: "40rem" },
307
+ { breakpoint: 1200, maxWidth: 900 },
308
+ ],
309
+ } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allaw-ui",
3
- "version": "3.6.9",
3
+ "version": "3.7.1",
4
4
  "description": "Composants UI pour l'application Allaw",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",