@axa-fr/design-system-look-and-feel-react 0.2.0-beta.369 → 0.3.0-ci.285

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.
@@ -4,8 +4,11 @@ type TClickItem = {
4
4
  isDisabled?: boolean;
5
5
  } & Omit<ComponentProps<"button">, "disabled"> & ComponentProps<"a"> & {
6
6
  label?: ReactNode;
7
+ parentClickComponent?: ({ children, }: {
8
+ children: ReactNode;
9
+ } & Record<string, unknown>) => ReactNode;
7
10
  children?: ReactNode;
8
11
  icon?: ReactNode;
9
- };
10
- export declare const ClickItem: ({ label, children, icon, href, isDisabled, className, classModifier, ...otherProps }: TClickItem) => import("react/jsx-runtime").JSX.Element;
12
+ } & Record<string, unknown>;
13
+ export declare const ClickItem: ({ label, children, icon, parentClickComponent: ClickComponent, isDisabled, className, classModifier, ...otherProps }: TClickItem) => import("react/jsx-runtime").JSX.Element;
11
14
  export {};
@@ -3,15 +3,7 @@ import chevron from "@material-symbols/svg-400/outlined/chevron_right.svg";
3
3
  import { useMemo } from "react";
4
4
  import { Svg } from "../../../Svg";
5
5
  import { getComponentClassName } from "../../../utilities";
6
- export const ClickItem = ({ label, children, icon, href, isDisabled = false, className, classModifier = "", ...otherProps }) => {
6
+ export const ClickItem = ({ label, children, icon, parentClickComponent: ClickComponent = ({ children: parentClickComponentChildren, ...parentClickComponentProps }) => (_jsx("button", { type: "button", ...parentClickComponentProps, children: parentClickComponentChildren })), isDisabled = false, className, classModifier = "", ...otherProps }) => {
7
7
  const componentClassName = useMemo(() => getComponentClassName(className, `${classModifier}${isDisabled ? " disabled" : ""}`, "af-click-item"), [className, classModifier, isDisabled]);
8
- const ClickComponent = useMemo(() => (href ? "a" : "button"), [href]);
9
- const clickComponentProps = useMemo(() => href
10
- ? { href, "aria-disabled": isDisabled, ...otherProps }
11
- : {
12
- type: "button",
13
- disabled: isDisabled,
14
- ...otherProps,
15
- }, [isDisabled, href, otherProps]);
16
- return (_jsxs(ClickComponent, { className: componentClassName, ...clickComponentProps, children: [_jsxs("div", { className: "af-click-item__content", children: [icon && _jsx("div", { className: "af-click-item__icon", children: icon }), _jsx("div", { className: "af-click-item__label", children: children || label })] }), _jsx("div", { className: "af-click-item__action", children: _jsx(Svg, { src: chevron }) })] }));
8
+ return (_jsxs(ClickComponent, { className: componentClassName, disabled: isDisabled, "aria-disabled": isDisabled, ...otherProps, children: [_jsxs("div", { className: "af-click-item__content", children: [icon && _jsx("div", { className: "af-click-item__icon", children: icon }), _jsx("div", { className: "af-click-item__label", children: children || label })] }), _jsx("div", { className: "af-click-item__action", children: _jsx(Svg, { src: chevron, "aria-hidden": true }) })] }));
17
9
  };
@@ -0,0 +1,4 @@
1
+ import "@axa-fr/design-system-look-and-feel-css/dist/Modal/Modal.scss";
2
+ import { PropsWithChildren } from "react";
3
+ import { ModalProps } from "./type";
4
+ export declare const ModalContainer: ({ open, setIsOpen, hasCloseButton, onClose, onClickOutside, children, title, subtitle, iconTitle, actions, fullWidthButtons, }: PropsWithChildren<ModalProps>) => import("react").ReactPortal;
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import "@axa-fr/design-system-look-and-feel-css/dist/Modal/Modal.scss";
3
+ import { useEffect, useId, useRef } from "react";
4
+ import { createPortal } from "react-dom";
5
+ import { Modal } from "./Modal";
6
+ import { useModal } from "./Modal.hook";
7
+ export const ModalContainer = ({ open, setIsOpen, hasCloseButton = true, onClose, onClickOutside, children, title, subtitle, iconTitle, actions, fullWidthButtons, }) => {
8
+ const { handleClickOutside, handleKeyDown, handleCloseModal } = useModal({
9
+ setIsOpen,
10
+ onClose,
11
+ onClickOutside,
12
+ });
13
+ const modalRef = useRef(null);
14
+ const idTitle = useId();
15
+ const idContent = useId();
16
+ const actionCallback = (callback) => {
17
+ callback?.();
18
+ setIsOpen(false);
19
+ };
20
+ useEffect(() => {
21
+ const modalElement = modalRef.current;
22
+ if (modalElement) {
23
+ if (open) {
24
+ document.body.style.overflow = "hidden";
25
+ modalElement.showModal?.();
26
+ }
27
+ else {
28
+ document.body.style.overflow = "inherit";
29
+ modalElement.close?.();
30
+ }
31
+ }
32
+ return () => {
33
+ document.body.style.overflow = "inherit";
34
+ };
35
+ }, [open]);
36
+ useEffect(() => {
37
+ document.body.addEventListener("keydown", handleKeyDown);
38
+ document.body.addEventListener("click", handleClickOutside);
39
+ return () => {
40
+ document.body.removeEventListener("keydown", handleKeyDown);
41
+ document.body.removeEventListener("click", handleClickOutside);
42
+ };
43
+ }, [handleClickOutside, handleKeyDown]);
44
+ return createPortal(_jsx(Modal, { modalRef: modalRef, idTitle: idTitle, idContent: idContent, iconTitle: iconTitle, title: title, subtitle: subtitle, hasCloseButton: hasCloseButton, handleCloseModal: handleCloseModal, actionCallback: actionCallback, actions: actions, fullWidthButtons: fullWidthButtons, children: children }), document.body);
45
+ };
@@ -1,24 +1,4 @@
1
- import { PropsWithChildren, ReactNode } from "react";
1
+ import { PropsWithChildren } from "react";
2
2
  import "@axa-fr/design-system-look-and-feel-css/dist/Modal/Modal.scss";
3
- export type ButtonAction = {
4
- text: string;
5
- disabled?: boolean;
6
- callback: () => void;
7
- };
8
- type ModalProps = {
9
- isOpen: boolean;
10
- hasCloseBtn?: boolean;
11
- onClose?: () => void;
12
- onClickOutside?: () => void;
13
- title: string;
14
- subtitle?: string;
15
- iconTitle?: ReactNode;
16
- fullWidthButtons?: boolean;
17
- actions?: {
18
- primary?: ButtonAction;
19
- secondary?: ButtonAction;
20
- tertiary?: ButtonAction;
21
- };
22
- };
23
- export declare const Modal: ({ isOpen, hasCloseBtn, onClose, onClickOutside, children, title, subtitle, iconTitle, actions, fullWidthButtons, }: PropsWithChildren<ModalProps>) => import("react/jsx-runtime").JSX.Element;
24
- export {};
3
+ import { TModalType } from "./type";
4
+ export declare const Modal: ({ modalRef, idTitle, idContent, iconTitle, title, subtitle, hasCloseButton, handleCloseModal, actionCallback, children, actions, fullWidthButtons, }: PropsWithChildren<TModalType>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { TModalHook } from "./type";
2
+ export declare const useModal: ({ setIsOpen, onClose, onClickOutside, }: TModalHook) => {
3
+ handleClickOutside: (event: MouseEvent) => void;
4
+ handleKeyDown: (event: KeyboardEvent) => void;
5
+ handleCloseModal: () => void;
6
+ };
@@ -0,0 +1,25 @@
1
+ import { useCallback } from "react";
2
+ export const useModal = ({ setIsOpen, onClose, onClickOutside, }) => {
3
+ const handleCloseModal = useCallback(() => {
4
+ onClose?.();
5
+ setIsOpen(false);
6
+ }, [onClose, setIsOpen]);
7
+ const handleClickOutside = useCallback((event) => {
8
+ if (event.target.tagName !== "DIALOG") {
9
+ return;
10
+ }
11
+ if (onClickOutside) {
12
+ onClickOutside();
13
+ setIsOpen(false);
14
+ }
15
+ else {
16
+ handleCloseModal();
17
+ }
18
+ }, [handleCloseModal, onClickOutside, setIsOpen]);
19
+ const handleKeyDown = useCallback((event) => {
20
+ if (event.key === "Escape") {
21
+ handleCloseModal();
22
+ }
23
+ }, [handleCloseModal]);
24
+ return { handleClickOutside, handleKeyDown, handleCloseModal };
25
+ };
@@ -1,53 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useId, useRef, useState, } from "react";
3
2
  import close from "@material-symbols/svg-400/outlined/close.svg";
4
- import { ButtonClient as Button, Variants as ButtonVariants, } from "../Button/Button";
3
+ import { ButtonClient as Button, Variants, Variants as ButtonVariants, } from "../Button/Button";
5
4
  import "@axa-fr/design-system-look-and-feel-css/dist/Modal/Modal.scss";
6
5
  import { Svg } from "../Svg";
7
- export const Modal = ({ isOpen, hasCloseBtn = true, onClose, onClickOutside, children, title, subtitle, iconTitle, actions, fullWidthButtons, }) => {
8
- const [isModalOpen, setIsModalOpen] = useState(isOpen);
9
- const modalRef = useRef(null);
10
- const idTitle = useId();
11
- const idContent = useId();
12
- useEffect(() => {
13
- setIsModalOpen(isOpen);
14
- }, [isOpen]);
15
- useEffect(() => {
16
- const modalElement = modalRef.current;
17
- if (!modalRef.current) {
18
- return;
19
- }
20
- if (isModalOpen) {
21
- document.body.style.overflow = "hidden";
22
- modalElement.showModal();
23
- }
24
- else {
25
- document.body.style.overflow = "inherit";
26
- modalElement.close();
27
- }
28
- }, [isModalOpen]);
29
- useEffect(() => {
30
- return () => {
31
- document.body.style.overflow = "inherit";
32
- };
33
- }, []);
34
- const handleCloseModal = () => {
35
- onClose?.();
36
- setIsModalOpen(false);
37
- };
38
- const handleClickOutside = () => {
39
- if (onClickOutside) {
40
- onClickOutside();
41
- setIsModalOpen(false);
42
- }
43
- else {
44
- handleCloseModal();
45
- }
46
- };
47
- const handleKeyDown = (event) => {
48
- if (event.key === "Escape") {
49
- handleCloseModal();
50
- }
51
- };
52
- return (_jsxs("dialog", { ref: modalRef, onKeyDown: handleKeyDown, onClick: (e) => e.target === modalRef.current && handleClickOutside(), className: "af-modal", "aria-labelledby": idTitle, "aria-describedby": idContent, children: [_jsxs("div", { id: idTitle, className: "af-modal__top", children: [iconTitle, _jsxs("h2", { className: "af-modal__top-title", children: [_jsxs("div", { children: [_jsx("div", { className: "af-modal__top-title-text", children: title }), subtitle && (_jsx("span", { className: "af-modal__top-title-subtitle", children: subtitle }))] }), hasCloseBtn && (_jsx(Button, { className: "af-modal__top-title-close-btn", onClick: handleCloseModal, type: "button", "aria-label": "close", children: _jsx(Svg, { src: close, width: 32, height: 32 }) }))] })] }), _jsxs("div", { id: idContent, className: "af-modal__content", children: [children, actions && (_jsxs("div", { className: `af-modal__actions${fullWidthButtons ? " af-modal__actions--fullWidth" : ""} `, children: [actions?.primary && (_jsx(Button, { variant: ButtonVariants.primary, onClick: actions?.primary.callback, disabled: actions?.primary.disabled, children: actions?.primary.text })), actions?.secondary && (_jsx(Button, { variant: ButtonVariants.secondary, onClick: actions?.secondary.callback, disabled: actions?.secondary.disabled, children: actions?.secondary.text })), actions?.tertiary && (_jsx(Button, { variant: ButtonVariants.tertiary, onClick: actions?.tertiary.callback, disabled: actions?.tertiary.disabled, children: actions?.tertiary.text }))] }))] })] }));
53
- };
6
+ export const Modal = ({ modalRef, idTitle, idContent, iconTitle, title, subtitle, hasCloseButton, handleCloseModal, actionCallback, children, actions, fullWidthButtons, }) => (_jsxs("dialog", { ref: modalRef, className: "af-modal", "aria-labelledby": idTitle, "aria-describedby": idContent, children: [_jsxs("div", { id: idTitle, className: "af-modal__top", children: [iconTitle, _jsxs("h2", { className: "af-modal__top-title", children: [_jsxs("div", { children: [_jsx("div", { className: "af-modal__top-title-text", children: title }), subtitle && (_jsx("span", { className: "af-modal__top-title-subtitle", children: subtitle }))] }), hasCloseButton && (_jsx(Button, { className: "af-modal__top-title-close-btn", onClick: handleCloseModal, variant: Variants.ghost, type: "button", "aria-label": "close", children: _jsx(Svg, { src: close, width: 32, height: 32 }) }))] })] }), _jsxs("div", { id: idContent, className: "af-modal__content", children: [children, actions && (_jsxs("div", { className: `af-modal__actions${fullWidthButtons ? " af-modal__actions--fullWidth" : ""} `, children: [actions?.primary && (_jsx(Button, { variant: ButtonVariants.primary, onClick: () => actionCallback(actions?.primary?.callback), disabled: actions?.primary.disabled, children: actions?.primary.text })), actions?.secondary && (_jsx(Button, { variant: ButtonVariants.secondary, onClick: () => actionCallback(actions?.secondary?.callback), disabled: actions?.secondary.disabled, children: actions?.secondary.text })), actions?.tertiary && (_jsx(Button, { variant: ButtonVariants.tertiary, onClick: () => actionCallback(actions?.tertiary?.callback), disabled: actions?.tertiary.disabled, children: actions?.tertiary.text }))] }))] })] }));
@@ -0,0 +1 @@
1
+ export { ModalContainer as Modal } from "./Modal.container";
@@ -0,0 +1 @@
1
+ export { ModalContainer as Modal } from "./Modal.container";
@@ -0,0 +1,38 @@
1
+ import { ReactNode, RefObject } from "react";
2
+ export type ButtonAction = {
3
+ text: string;
4
+ disabled?: boolean;
5
+ callback: () => void;
6
+ };
7
+ export type TActionButton = {
8
+ primary?: ButtonAction;
9
+ secondary?: ButtonAction;
10
+ tertiary?: ButtonAction;
11
+ };
12
+ export type TModalHook = {
13
+ setIsOpen: (value: boolean) => void;
14
+ onClose?: () => void;
15
+ onClickOutside?: () => void;
16
+ };
17
+ export type ModalProps = TModalHook & {
18
+ open: boolean;
19
+ hasCloseButton?: boolean;
20
+ title: string;
21
+ subtitle?: string;
22
+ iconTitle?: ReactNode;
23
+ fullWidthButtons?: boolean;
24
+ actions?: TActionButton;
25
+ };
26
+ export type TModalType = {
27
+ modalRef: RefObject<HTMLDialogElement>;
28
+ idTitle: string;
29
+ idContent: string;
30
+ iconTitle: ReactNode;
31
+ title: string;
32
+ subtitle?: string;
33
+ hasCloseButton: boolean;
34
+ handleCloseModal: () => void;
35
+ actionCallback: (callback?: () => void) => void;
36
+ actions?: TActionButton;
37
+ fullWidthButtons?: boolean;
38
+ };
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -20,11 +20,11 @@ export { ContentItemDuo } from "./List/ContentItemDuo";
20
20
  export { ContentItemMono, ContentItemMonoSize } from "./List/ContentItemMono";
21
21
  export { ContentTabList } from "./List/ContentTabList";
22
22
  export { Loader } from "./Loader";
23
- export { Modal } from "./ModalClient/Modal";
24
- export type { ButtonAction as ModalButtonAction } from "./ModalClient/Modal";
23
+ export { Modal } from "./ModalClient";
24
+ export type { ButtonAction as ModalButtonAction } from "./ModalClient/type";
25
25
  export { Pagination } from "./Pagination/Pagination";
26
26
  export { Stepper } from "./Stepper/Stepper";
27
27
  export { Svg } from "./Svg";
28
- export { TabsClient as Tabs } from "./Tabs/Tabs";
28
+ export { TabsClient as Tabs, Direction as TabsDirection } from "./Tabs/Tabs";
29
29
  export { Tag } from "./Tag";
30
30
  export { Title, TitleSize, type TitleLevel } from "./Title";
package/dist/index.js CHANGED
@@ -19,10 +19,10 @@ export { ContentItemDuo } from "./List/ContentItemDuo";
19
19
  export { ContentItemMono, ContentItemMonoSize } from "./List/ContentItemMono";
20
20
  export { ContentTabList } from "./List/ContentTabList";
21
21
  export { Loader } from "./Loader";
22
- export { Modal } from "./ModalClient/Modal";
22
+ export { Modal } from "./ModalClient";
23
23
  export { Pagination } from "./Pagination/Pagination";
24
24
  export { Stepper } from "./Stepper/Stepper";
25
25
  export { Svg } from "./Svg";
26
- export { TabsClient as Tabs } from "./Tabs/Tabs";
26
+ export { TabsClient as Tabs, Direction as TabsDirection } from "./Tabs/Tabs";
27
27
  export { Tag } from "./Tag";
28
28
  export { Title, TitleSize } from "./Title";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axa-fr/design-system-look-and-feel-react",
3
- "version": "0.2.0-beta.369",
3
+ "version": "0.3.0-ci.285",
4
4
  "description": "",
5
5
  "exports": {
6
6
  ".": {
@@ -21,6 +21,7 @@
21
21
  "postbuild": "copyfiles --up 1 \"src/assets/svg/*.svg\" ./dist/",
22
22
  "start:storybook": "storybook dev -p 6009",
23
23
  "build:storybook": "storybook build",
24
+ "build-storybook": "storybook build",
24
25
  "eslint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"",
25
26
  "eslint:fix": "eslint src --ext js,jsx,ts,tsx --fix",
26
27
  "prettier": "prettier \"src/**/*.!(js|jsx|ts|tsx|svg)\" --check",
@@ -28,20 +29,23 @@
28
29
  "tsc": "tsc --noEmit",
29
30
  "test": "vitest",
30
31
  "test:ui": "vitest --ui",
31
- "test:ci": "vitest run --coverage"
32
+ "test:ci": "vitest run --coverage",
33
+ "chromatic": "npx chromatic"
32
34
  },
33
35
  "repository": {
34
36
  "type": "git",
35
37
  "url": "git+https://github.com/AxaFrance/design-system.git"
36
38
  },
37
- "author": "AxaFrance",
39
+ "author": {
40
+ "name": "AxaFrance"
41
+ },
38
42
  "license": "MIT",
39
43
  "bugs": {
40
44
  "url": "https://github.com/AxaFrance/design-system/issues"
41
45
  },
42
46
  "homepage": "https://github.com/AxaFrance/design-system#readme",
43
47
  "peerDependencies": {
44
- "@axa-fr/design-system-look-and-feel-css": "0.2.0-beta.369",
48
+ "@axa-fr/design-system-look-and-feel-css": "0.3.0-ci.285",
45
49
  "@material-symbols/svg-400": ">= 0.19.0",
46
50
  "react": ">= 18"
47
51
  },
@@ -53,6 +57,7 @@
53
57
  "dependencies": {
54
58
  "@fontsource/source-sans-pro": "^5.0.8",
55
59
  "@tanem/svg-injector": "^10.1.68",
60
+ "@types/react-dom": "^18.2.24",
56
61
  "classnames": "^2.5.1",
57
62
  "dompurify": "^3.1.5",
58
63
  "rc-slider": "^10.5.0",
@@ -67,7 +72,6 @@
67
72
  "@storybook/addon-links": "^8.3.5",
68
73
  "@storybook/addon-mdx-gfm": "^8.3.5",
69
74
  "@storybook/addon-onboarding": "^8.3.5",
70
- "@storybook/addons": "^7.6.17",
71
75
  "@storybook/blocks": "^8.3.5",
72
76
  "@storybook/manager-api": "^8.3.5",
73
77
  "@storybook/react": "^8.3.5",
@@ -88,6 +92,7 @@
88
92
  "@vitejs/plugin-react": "^4.3.1",
89
93
  "@vitest/coverage-v8": "^2.0.5",
90
94
  "@vitest/ui": "^2.1.2",
95
+ "chromatic": "^11.12.0",
91
96
  "copyfiles": "^2.4.1",
92
97
  "eslint": "^8.57.0",
93
98
  "eslint-config-airbnb": "^19.0.4",