@edifice.io/react 2.6.5 → 2.6.6-develop-b2school.20260922101258

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.
Files changed (78) hide show
  1. package/dist/components/Form/FormText.js +11 -6
  2. package/dist/components/Input/Input.d.ts +11 -2
  3. package/dist/components/Input/Input.js +38 -21
  4. package/dist/components/Label/Label.js +4 -4
  5. package/dist/components/Layout/Layout.js +10 -5
  6. package/dist/components/LinkPill/LinkPill.d.ts +45 -0
  7. package/dist/components/LinkPill/LinkPill.js +27 -0
  8. package/dist/components/LinkPill/index.d.ts +2 -0
  9. package/dist/components/ModalBeta/ModalBeta.d.ts +47 -0
  10. package/dist/components/ModalBeta/ModalBeta.js +62 -0
  11. package/dist/components/ModalBeta/ModalBetaBody.d.ts +19 -0
  12. package/dist/components/ModalBeta/ModalBetaBody.js +15 -0
  13. package/dist/components/ModalBeta/ModalBetaContext.d.ts +7 -0
  14. package/dist/components/ModalBeta/ModalBetaContext.js +15 -0
  15. package/dist/components/ModalBeta/ModalBetaFooter.d.ts +13 -0
  16. package/dist/components/ModalBeta/ModalBetaFooter.js +7 -0
  17. package/dist/components/ModalBeta/ModalBetaHeader.d.ts +23 -0
  18. package/dist/components/ModalBeta/ModalBetaHeader.js +31 -0
  19. package/dist/components/ModalBeta/index.d.ts +2 -0
  20. package/dist/components/PageLayout/PageLayout.d.ts +4 -0
  21. package/dist/components/PageLayout/PageLayout.js +22 -12
  22. package/dist/components/PageLayout/components/PageLayoutContent.js +5 -1
  23. package/dist/components/PageLayout/components/PageLayoutHelpZone.d.ts +12 -0
  24. package/dist/components/PageLayout/components/PageLayoutHelpZone.js +6 -0
  25. package/dist/components/Table/components/Table.d.ts +2 -2
  26. package/dist/components/Table/components/TableTd.d.ts +1 -1
  27. package/dist/components/Table/components/TableTh.d.ts +1 -1
  28. package/dist/components/index.d.ts +2 -0
  29. package/dist/homepage.js +12 -1
  30. package/dist/hooks/index.d.ts +2 -0
  31. package/dist/hooks/useBackground/index.d.ts +1 -0
  32. package/dist/hooks/useBackground/useBackground.d.ts +7 -0
  33. package/dist/hooks/useBackground/useBackground.js +16 -0
  34. package/dist/hooks/useClickOutside/useClickOutside.d.ts +1 -1
  35. package/dist/hooks/useClickOutside/useClickOutside.js +3 -2
  36. package/dist/hooks/useUploadFiles/index.d.ts +1 -0
  37. package/dist/hooks/useUploadFiles/useUploadFiles.d.ts +11 -1
  38. package/dist/hooks/useUploadFiles/useUploadFiles.js +12 -7
  39. package/dist/hooks/useUserPreferences/index.d.ts +1 -0
  40. package/dist/hooks/useUserPreferences/useUserPreferences.d.ts +9 -0
  41. package/dist/hooks/useUserPreferences/useUserPreferences.js +40 -0
  42. package/dist/hooks/useZendeskGuide/useZendeskGuide.d.ts +14 -2
  43. package/dist/hooks/useZendeskGuide/useZendeskGuide.js +51 -24
  44. package/dist/index.js +168 -160
  45. package/dist/modules/HelpZone/HelpZone.d.ts +13 -0
  46. package/dist/modules/HelpZone/HelpZone.js +52 -0
  47. package/dist/modules/HelpZone/HelpZoneContainer.d.ts +4 -0
  48. package/dist/modules/HelpZone/HelpZoneContainer.js +18 -0
  49. package/dist/modules/HelpZone/index.d.ts +3 -0
  50. package/dist/modules/homepage/components/Header/Header.js +11 -4
  51. package/dist/modules/homepage/components/UsefulLinks/LinkForm.d.ts +13 -0
  52. package/dist/modules/homepage/components/UsefulLinks/LinkForm.js +67 -0
  53. package/dist/modules/homepage/components/UsefulLinks/UsefulLinks.d.ts +6 -0
  54. package/dist/modules/homepage/components/UsefulLinks/UsefulLinks.js +29 -0
  55. package/dist/modules/homepage/components/UsefulLinks/UsefulLinksContainer.d.ts +1 -0
  56. package/dist/modules/homepage/components/UsefulLinks/UsefulLinksContainer.js +40 -0
  57. package/dist/modules/homepage/components/UsefulLinks/UsefulLinksModal.d.ts +11 -0
  58. package/dist/modules/homepage/components/UsefulLinks/UsefulLinksModal.js +65 -0
  59. package/dist/modules/homepage/components/UsefulLinks/hooks/useUsefulLinksContainer.d.ts +19 -0
  60. package/dist/modules/homepage/components/UsefulLinks/hooks/useUsefulLinksContainer.js +26 -0
  61. package/dist/modules/homepage/components/UsefulLinks/index.d.ts +5 -0
  62. package/dist/modules/homepage/components/UsefulLinks/services/api/index.d.ts +6 -0
  63. package/dist/modules/homepage/components/UsefulLinks/services/api/index.js +5 -0
  64. package/dist/modules/homepage/components/UsefulLinks/services/api/usefulLinksService.d.ts +31 -0
  65. package/dist/modules/homepage/components/UsefulLinks/services/api/usefulLinksService.js +50 -0
  66. package/dist/modules/homepage/components/UsefulLinks/services/queries/usefulLinks.d.ts +20 -0
  67. package/dist/modules/homepage/components/UsefulLinks/services/queries/usefulLinks.js +65 -0
  68. package/dist/modules/homepage/components/UserSpace/hooks/useProfileLinks.js +18 -8
  69. package/dist/modules/homepage/components/index.d.ts +1 -0
  70. package/dist/modules/icons/components/logo/IconLogoEdificeFull.d.ts +7 -0
  71. package/dist/modules/icons/components/logo/IconLogoEdificeFull.js +26 -0
  72. package/dist/modules/icons/components/logo/IconLogoEdificeSmall.d.ts +7 -0
  73. package/dist/modules/icons/components/logo/IconLogoEdificeSmall.js +17 -0
  74. package/dist/modules/icons/components/logo/index.d.ts +2 -0
  75. package/dist/modules/multimedia/MediaLibrary/innertabs/Upload.js +34 -7
  76. package/dist/modules/multimedia/UploadFiles/UploadFiles.d.ts +2 -1
  77. package/dist/modules/widgets/index.d.ts +1 -1
  78. package/package.json +6 -6
@@ -1,16 +1,21 @@
1
- import { jsx } from "react/jsx-runtime";
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import clsx from "clsx";
3
+ import SvgIconError from "../../modules/icons/components/IconError.js";
4
+ import SvgIconSuccessOutline from "../../modules/icons/components/IconSuccessOutline.js";
3
5
  import { useFormControl } from "./FormContext.js";
4
6
  const FormText = ({
5
7
  children
6
8
  }) => {
7
9
  const {
8
10
  status
9
- } = useFormControl(), classes = clsx("form-text", {
10
- "is-invalid": status === "invalid",
11
- valid: status === "valid"
12
- });
13
- return /* @__PURE__ */ jsx("p", { className: classes, children: /* @__PURE__ */ jsx("em", { children }) });
11
+ } = useFormControl(), classes = clsx("input-message", {
12
+ "input-message--invalid": status === "invalid",
13
+ "input-message--valid": status === "valid"
14
+ }), Icon = status === "invalid" ? SvgIconError : status === "valid" ? SvgIconSuccessOutline : null;
15
+ return /* @__PURE__ */ jsxs("p", { className: classes, children: [
16
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "input-message__icon", "aria-hidden": "true" }),
17
+ children
18
+ ] });
14
19
  };
15
20
  export {
16
21
  FormText as default
@@ -2,7 +2,8 @@ import { Size } from '../../types';
2
2
  export type OmitInputProps = 'disabled' | 'required' | 'size' | 'id' | 'readOnly';
3
3
  export interface InputProps extends Omit<React.ComponentPropsWithRef<'input'>, OmitInputProps> {
4
4
  /**
5
- * Control size of input
5
+ * Control size of input. `sm` and `md` share the same visual size
6
+ * ("Medium" in the design system); only `lg` ("Big") differs.
6
7
  */
7
8
  size: Size;
8
9
  /**
@@ -18,7 +19,8 @@ export interface InputProps extends Omit<React.ComponentPropsWithRef<'input'>, O
18
19
  */
19
20
  disabled?: boolean;
20
21
  /**
21
- * Remove validation icon
22
+ * @deprecated Validation icons no longer render inside the field —
23
+ * this prop has no effect and will be removed in a future major version.
22
24
  */
23
25
  noValidationIcon?: boolean;
24
26
  /**
@@ -33,6 +35,13 @@ export interface InputProps extends Omit<React.ComponentPropsWithRef<'input'>, O
33
35
  * Browser autocomplete feature
34
36
  */
35
37
  autoComplete?: string;
38
+ /**
39
+ * Show a built-in clear (×) button while the field is focused. Opt-in:
40
+ * several consumers render their own clear affordance already (e.g.
41
+ * `SearchBar`), and a broad audit of every `Input` usage hasn't been done
42
+ * yet — see INPUT-MIGRATION-PLAN.md §07.
43
+ */
44
+ clearable?: boolean;
36
45
  }
37
46
  /**
38
47
  * Input Form Component
@@ -1,40 +1,57 @@
1
- import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
- import { forwardRef, useState } from "react";
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useRef, useState } from "react";
3
3
  import clsx from "clsx";
4
+ import { useTranslation } from "react-i18next";
5
+ import SvgIconClose from "../../modules/icons/components/IconClose.js";
4
6
  import { useFormControl } from "../Form/FormContext.js";
5
- import Textcounter from "../TextCounter/TextCounter.js";
6
7
  const Input = /* @__PURE__ */ forwardRef(({
7
- noValidationIcon,
8
8
  placeholder,
9
9
  size = "md",
10
10
  type = "text",
11
11
  className,
12
12
  showCounter = !1,
13
13
  autoComplete = "off",
14
+ clearable = !1,
15
+ noValidationIcon: _noValidationIcon,
14
16
  ...restProps
15
- }, ref) => {
17
+ }, forwardedRef) => {
16
18
  var _a;
17
19
  const {
18
20
  id,
19
21
  isRequired,
20
22
  isReadOnly,
21
23
  status
22
- } = useFormControl(), [currentLength, setCurrentLength] = useState(((_a = restProps.defaultValue) == null ? void 0 : _a.toString().length) || 0), classes = clsx({
23
- "form-control": !isReadOnly,
24
- "form-control-lg": size === "lg",
25
- "form-control-sm": size === "sm",
26
- "is-invalid": status === "invalid",
27
- "is-valid": status === "valid",
28
- "form-control-plaintext": isReadOnly,
29
- "no-validation-icon": noValidationIcon,
30
- "pe-64": showCounter && !status
31
- }, className);
32
- return /* @__PURE__ */ jsxs(Fragment, { children: [
33
- /* @__PURE__ */ jsx("input", { ref, id, className: classes, type, placeholder, required: isRequired, readOnly: isReadOnly, ...restProps, onChange: (e) => {
34
- var _a2;
35
- setCurrentLength(e.target.value.length), (_a2 = restProps.onChange) == null || _a2.call(restProps, e);
36
- }, autoComplete }),
37
- showCounter && !status && /* @__PURE__ */ jsx(Textcounter, { currentLength, maxLength: restProps.maxLength ?? 0 })
24
+ } = useFormControl(), {
25
+ t
26
+ } = useTranslation(), inputRef = useRef(null), [currentLength, setCurrentLength] = useState(((_a = restProps.defaultValue) == null ? void 0 : _a.toString().length) || 0), setRefs = (node) => {
27
+ inputRef.current = node, typeof forwardedRef == "function" ? forwardedRef(node) : forwardedRef && (forwardedRef.current = node);
28
+ }, wrapperClasses = clsx("input", {
29
+ "input--lg": size === "lg",
30
+ "input--invalid": status === "invalid",
31
+ "input--valid": status === "valid",
32
+ "input--plaintext": isReadOnly
33
+ }, className), handleChange = (e) => {
34
+ var _a2;
35
+ setCurrentLength(e.target.value.length), (_a2 = restProps.onChange) == null || _a2.call(restProps, e);
36
+ }, handleClear = () => {
37
+ var _a2;
38
+ const node = inputRef.current;
39
+ if (!node) return;
40
+ const nativeSetter = (_a2 = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")) == null ? void 0 : _a2.set;
41
+ nativeSetter == null || nativeSetter.call(node, ""), node.dispatchEvent(new Event("input", {
42
+ bubbles: !0
43
+ })), node.focus();
44
+ }, maxLength = restProps.maxLength ?? 0;
45
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClasses, children: [
46
+ /* @__PURE__ */ jsx("input", { ref: setRefs, id, className: "input__field", type, placeholder, required: isRequired, readOnly: isReadOnly, ...restProps, onChange: handleChange, autoComplete }),
47
+ clearable && !isReadOnly && /* @__PURE__ */ jsx("button", { type: "button", className: "input__clear", onClick: handleClear, "aria-label": t("clear"), children: /* @__PURE__ */ jsx(SvgIconClose, {}) }),
48
+ showCounter && /* @__PURE__ */ jsxs("span", { className: clsx("input__counter", {
49
+ "input__counter--max": currentLength === maxLength
50
+ }), children: [
51
+ currentLength,
52
+ " / ",
53
+ maxLength
54
+ ] })
38
55
  ] });
39
56
  });
40
57
  export {
@@ -16,8 +16,8 @@ const Label = /* @__PURE__ */ forwardRef(({
16
16
  isRequired
17
17
  } = useFormControl(), {
18
18
  t
19
- } = useTranslation(), classes = clsx("form-label", {
20
- "has-icon": leftIcon
19
+ } = useTranslation(), classes = clsx("input-label", {
20
+ "input-label--has-icon": leftIcon
21
21
  }, className), optionalState = isOptional && !isRequired, requiredState = isRequired && !isOptional;
22
22
  return useEffect(() => {
23
23
  if (isOptional && isRequired)
@@ -25,11 +25,11 @@ const Label = /* @__PURE__ */ forwardRef(({
25
25
  }, [isOptional, isRequired]), /* @__PURE__ */ jsxs("label", { ref, htmlFor: id, className: classes, children: [
26
26
  leftIcon,
27
27
  children,
28
- optionalState && /* @__PURE__ */ jsxs("em", { className: "optional", children: [
28
+ optionalState && /* @__PURE__ */ jsxs("em", { className: "input-label__optional", children: [
29
29
  "- ",
30
30
  optionalText ?? t("explorer.optional")
31
31
  ] }),
32
- requiredState && /* @__PURE__ */ jsx("em", { className: "required", children: requiredText })
32
+ requiredState && /* @__PURE__ */ jsx("em", { className: "input-label__required", children: requiredText })
33
33
  ] });
34
34
  });
35
35
  export {
@@ -4,10 +4,11 @@ import clsx from "clsx";
4
4
  import { Toaster } from "react-hot-toast";
5
5
  import { useTranslation } from "react-i18next";
6
6
  import { useEdificeTheme } from "../../providers/EdificeThemeProvider/EdificeThemeProvider.hook.js";
7
+ import { useOverlay } from "../PageLayout/hook/useOverlay.js";
7
8
  import Header from "./components/Header.js";
8
9
  import HeaderNotificationsOverlay from "./components/HeaderNotificationsOverlay.js";
9
- import { useOverlay } from "../PageLayout/hook/useOverlay.js";
10
10
  import useUiOverride from "../../hooks/useUiOverride/useUiOverride.js";
11
+ import useBackground from "../../hooks/useBackground/useBackground.js";
11
12
  import useCookiesConsent from "../../hooks/useCookiesConsent/useCookiesConsent.js";
12
13
  import useZendeskGuide from "../../hooks/useZendeskGuide/useZendeskGuide.js";
13
14
  import useCantoo from "../../hooks/useCantoo/useCantoo.js";
@@ -22,7 +23,11 @@ const HeaderV2 = /* @__PURE__ */ lazy(() => import("../../modules/homepage/compo
22
23
  }) => {
23
24
  const {
24
25
  theme
25
- } = useEdificeTheme(), override = useUiOverride("layout.header"), isHeaderV2 = (override == null ? void 0 : override.variant) === "v2", backgroundOverride = useUiOverride("layout.background"), hasBackgroundImage = (backgroundOverride == null ? void 0 : backgroundOverride.variant) === "image", {
26
+ } = useEdificeTheme(), override = useUiOverride("layout.header"), isHeaderV2 = (override == null ? void 0 : override.variant) === "v2", {
27
+ productOverride,
28
+ background,
29
+ isBackgroundImageOverridden
30
+ } = useBackground(), {
26
31
  toggleOverlay
27
32
  } = useOverlay(), {
28
33
  t
@@ -40,9 +45,9 @@ const HeaderV2 = /* @__PURE__ */ lazy(() => import("../../modules/homepage/compo
40
45
  }, className), renderHeader = headless ? null : isHeaderV2 ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(HeaderV2, { src: theme == null ? void 0 : theme.basePath, dataProduct: override == null ? void 0 : override.theme, onNotificationsClick: toggleOverlay }) }) : /* @__PURE__ */ jsx(Header, { is1d: theme == null ? void 0 : theme.is1d, src: theme == null ? void 0 : theme.basePath }), renderNotificationsOverlay = !headless && isHeaderV2 && /* @__PURE__ */ jsx(HeaderNotificationsOverlay, {}), renderCookies = showCookiesConsent && /* @__PURE__ */ jsx(Alert, { type: "info", className: "m-12 rgpd", isConfirm: !0, position: "bottom-right", button: /* @__PURE__ */ jsx(Button, { color: "tertiary", variant: "ghost", onClick: handleConsultCookies, children: t("rgpd.cookies.banner.button.consult") }), onClose: handleCloseCookiesConsent, children: t("rgpd.cookies.banner.text1") }), renderToaster = /* @__PURE__ */ jsx(Toaster, { containerClassName: "toaster-container", toastOptions: {
41
46
  position: "top-right"
42
47
  } });
43
- return /* @__PURE__ */ jsxs("div", { className: clsx("layout", {
44
- "layout-has-background-image": hasBackgroundImage
45
- }), "data-product": hasBackgroundImage ? backgroundOverride == null ? void 0 : backgroundOverride.theme : void 0, children: [
48
+ return /* @__PURE__ */ jsxs("div", { "data-product": productOverride, "data-background": background, className: clsx("layout", {
49
+ "layout-has-background-image": isBackgroundImageOverridden
50
+ }), children: [
46
51
  renderHeader,
47
52
  renderNotificationsOverlay,
48
53
  /* @__PURE__ */ jsx("main", { className: classes, ...restProps, children }),
@@ -0,0 +1,45 @@
1
+ import { ReactNode } from 'react';
2
+ export type LinkPillIllustrationType = 'icon' | 'img';
3
+ export type LinkPillIllustrationPosition = 'left' | 'right';
4
+ export interface LinkPillProps {
5
+ /**
6
+ * URL opened in a new tab when the pill is clicked.
7
+ */
8
+ href: string;
9
+ /**
10
+ * Text displayed inside the pill (single line, ellipsis on overflow).
11
+ */
12
+ label: string;
13
+ /**
14
+ * Optional second line displayed below the label (single line, ellipsis
15
+ * on overflow). Does not affect the label's font size.
16
+ */
17
+ subtitle?: string;
18
+ /**
19
+ * Illustration node. Defaults to `<IconLink />` for the `icon` type.
20
+ * For the `img` type, the caller must provide an `<img>` element.
21
+ */
22
+ illustration?: ReactNode;
23
+ /**
24
+ * `icon` (default): illustration wrapped in a small rounded box.
25
+ * `img`: illustration rendered as a 36x36 rounded square (e.g. a favicon).
26
+ */
27
+ illustrationType?: LinkPillIllustrationType;
28
+ /**
29
+ * Side the illustration is displayed on.
30
+ */
31
+ illustrationPosition?: LinkPillIllustrationPosition;
32
+ /**
33
+ * Optional class for styling purpose
34
+ */
35
+ className?: string;
36
+ }
37
+ /**
38
+ * LinkPill – design system component used to display a link to an
39
+ * external resource as a small rounded pill.
40
+ */
41
+ declare const LinkPill: {
42
+ ({ href, label, subtitle, illustration, illustrationType, illustrationPosition, className, }: LinkPillProps): import("react/jsx-runtime").JSX.Element;
43
+ displayName: string;
44
+ };
45
+ export default LinkPill;
@@ -0,0 +1,27 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import clsx from "clsx";
3
+ import SvgIconLink from "../../modules/icons/components/IconLink.js";
4
+ const LinkPill = ({
5
+ href,
6
+ label,
7
+ subtitle,
8
+ illustration,
9
+ illustrationType = "icon",
10
+ illustrationPosition = "left",
11
+ className
12
+ }) => {
13
+ const illustrationNode = illustrationType === "icon" ? /* @__PURE__ */ jsx("span", { className: "link-pill-icon", children: illustration ?? /* @__PURE__ */ jsx(SvgIconLink, {}) }) : /* @__PURE__ */ jsx("span", { className: "link-pill-image", children: illustration }), contentNode = /* @__PURE__ */ jsxs("span", { className: "link-pill-content", children: [
14
+ /* @__PURE__ */ jsx("span", { className: "link-pill-label", title: label, children: label }),
15
+ subtitle && /* @__PURE__ */ jsx("span", { className: "link-pill-subtitle", title: subtitle, children: subtitle })
16
+ ] });
17
+ return /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", "data-testid": "link-pill", className: clsx("link-pill", `link-pill--illustration-${illustrationPosition}`, className), children: illustrationPosition === "left" ? /* @__PURE__ */ jsxs(Fragment, { children: [
18
+ illustrationNode,
19
+ contentNode
20
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
21
+ contentNode,
22
+ illustrationNode
23
+ ] }) });
24
+ };
25
+ export {
26
+ LinkPill as default
27
+ };
@@ -0,0 +1,2 @@
1
+ export { default as LinkPill } from './LinkPill';
2
+ export * from './LinkPill';
@@ -0,0 +1,47 @@
1
+ export type ModalBetaElement = HTMLDivElement;
2
+ export type ModalBetaSize = 's' | 'm' | 'l' | 'xl';
3
+ export interface ModalBetaProps {
4
+ /**
5
+ * Modal id (useful when multiple modal on the same page)
6
+ */
7
+ id: string;
8
+ /**
9
+ * Modal testid
10
+ */
11
+ ['data-testid']?: string;
12
+ /**
13
+ * Is Modal Open
14
+ */
15
+ isOpen: boolean;
16
+ /**
17
+ * Function to call when closing modal
18
+ */
19
+ onModalClose: () => void;
20
+ /**
21
+ * Size of the modal (width, padding and corner radius)
22
+ */
23
+ size?: ModalBetaSize;
24
+ /**
25
+ * ID of the HTML element to receive focus when modal is active.
26
+ */
27
+ focusId?: string;
28
+ /**
29
+ * Children
30
+ */
31
+ children: React.ReactNode;
32
+ }
33
+ declare const ModalBeta: import('react').ForwardRefExoticComponent<ModalBetaProps & import('react').RefAttributes<HTMLDivElement>> & {
34
+ Header: {
35
+ ({ onModalClose, children, subtitle, }: import('./ModalBetaHeader').ModalBetaHeaderProps): import("react/jsx-runtime").JSX.Element;
36
+ displayName: string;
37
+ };
38
+ Body: {
39
+ ({ children, className }: import('./ModalBetaBody').ModalBetaBodyProps): import("react/jsx-runtime").JSX.Element;
40
+ displayName: string;
41
+ };
42
+ Footer: {
43
+ ({ children }: import('./ModalBetaFooter').ModalBetaFooterProps): import("react/jsx-runtime").JSX.Element;
44
+ displayName: string;
45
+ };
46
+ };
47
+ export default ModalBeta;
@@ -0,0 +1,62 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { forwardRef, useCallback, useEffect } from "react";
3
+ import { useTransition, animated } from "@react-spring/web";
4
+ import clsx from "clsx";
5
+ import ModalBetaBody from "./ModalBetaBody.js";
6
+ import { ModalBetaContext } from "./ModalBetaContext.js";
7
+ import ModalBetaFooter from "./ModalBetaFooter.js";
8
+ import ModalBetaHeader from "./ModalBetaHeader.js";
9
+ import useClickOutside from "../../hooks/useClickOutside/useClickOutside.js";
10
+ import useTrapFocus from "../../hooks/useTrapFocus/useTrapFocus.js";
11
+ import useKeyPress from "../../hooks/useKeyPress/useKeyPress.js";
12
+ const Root = /* @__PURE__ */ forwardRef(({
13
+ id,
14
+ isOpen,
15
+ onModalClose,
16
+ size = "m",
17
+ focusId,
18
+ children,
19
+ ...otherDivProps
20
+ }, ref) => {
21
+ const ariaLabelId = `aria_label_${id}`, ariaDescriptionId = `aria_desc_${id}`, modalRef = useClickOutside(onModalClose, void 0, void 0, isOpen), trapRef = useTrapFocus(isOpen), setDialogRef = useCallback((node) => {
22
+ modalRef.current = node, trapRef.current = node;
23
+ }, [modalRef, trapRef]);
24
+ useKeyPress(onModalClose, ["Escape"]), useEffect(() => {
25
+ if (isOpen && (document.body.style.overflow = "hidden", focusId)) {
26
+ const elem = document.getElementById(focusId);
27
+ elem == null || elem.focus();
28
+ }
29
+ return () => {
30
+ document.body.style.overflow = "";
31
+ };
32
+ }, [focusId, isOpen]);
33
+ const modalClasses = clsx("modal-beta", `modal-beta--${size}`), modalContextValue = {
34
+ ariaLabelId,
35
+ ariaDescriptionId,
36
+ focusId
37
+ }, transition = useTransition(isOpen, {
38
+ from: {
39
+ y: -20,
40
+ opacity: 0
41
+ },
42
+ enter: {
43
+ y: 0,
44
+ opacity: 1
45
+ },
46
+ leave: {
47
+ y: 20,
48
+ opacity: 0
49
+ }
50
+ });
51
+ return /* @__PURE__ */ jsx(ModalBetaContext.Provider, { value: modalContextValue, children: transition((style, isOpen2) => /* @__PURE__ */ jsxs(Fragment, { children: [
52
+ isOpen2 && /* @__PURE__ */ jsx(animated.div, { id, ref, role: "dialog", "aria-modal": "true", "aria-labelledby": ariaLabelId, "aria-describedby": ariaDescriptionId, className: modalClasses, style, tabIndex: -1, ...otherDivProps, children: /* @__PURE__ */ jsx("div", { id: `${id}_ref`, ref: setDialogRef, className: "modal-beta-dialog", children: /* @__PURE__ */ jsx("div", { className: "modal-beta-content", children }) }) }),
53
+ isOpen2 && /* @__PURE__ */ jsx("div", { className: "modal-beta-backdrop" })
54
+ ] })) });
55
+ }), ModalBeta = Object.assign(Root, {
56
+ Header: ModalBetaHeader,
57
+ Body: ModalBetaBody,
58
+ Footer: ModalBetaFooter
59
+ });
60
+ export {
61
+ ModalBeta as default
62
+ };
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ModalBetaBodyProps {
3
+ /**
4
+ * Children
5
+ */
6
+ children: ReactNode;
7
+ /**
8
+ * Optional class for styling purpose
9
+ */
10
+ className?: string;
11
+ }
12
+ /**
13
+ * ModalBeta Body
14
+ */
15
+ declare const ModalBetaBody: {
16
+ ({ children, className }: ModalBetaBodyProps): import("react/jsx-runtime").JSX.Element;
17
+ displayName: string;
18
+ };
19
+ export default ModalBetaBody;
@@ -0,0 +1,15 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import clsx from "clsx";
3
+ import { useModalBetaContext } from "./ModalBetaContext.js";
4
+ const ModalBetaBody = ({
5
+ children,
6
+ className
7
+ }) => {
8
+ const {
9
+ ariaDescriptionId
10
+ } = useModalBetaContext();
11
+ return /* @__PURE__ */ jsx("div", { id: ariaDescriptionId, className: clsx("modal-beta-body", className), children });
12
+ };
13
+ export {
14
+ ModalBetaBody as default
15
+ };
@@ -0,0 +1,7 @@
1
+ export interface ModalBetaContextProps {
2
+ ariaLabelId: string;
3
+ ariaDescriptionId: string;
4
+ focusId: string | undefined;
5
+ }
6
+ export declare const ModalBetaContext: import('react').Context<ModalBetaContextProps>;
7
+ export declare const useModalBetaContext: () => ModalBetaContextProps;
@@ -0,0 +1,15 @@
1
+ import { createContext, useContext } from "react";
2
+ const ModalBetaContext = /* @__PURE__ */ createContext({
3
+ ariaLabelId: "",
4
+ ariaDescriptionId: "",
5
+ focusId: ""
6
+ }), useModalBetaContext = () => {
7
+ const context = useContext(ModalBetaContext);
8
+ if (!context)
9
+ throw new Error("Cannot be rendered outside the ModalBeta component");
10
+ return context;
11
+ };
12
+ export {
13
+ ModalBetaContext,
14
+ useModalBetaContext
15
+ };
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ModalBetaFooterProps {
3
+ children: ReactNode;
4
+ }
5
+ /**
6
+ * ModalBeta Footer — right-aligns its children, typically two ButtonBeta
7
+ * (a ghost/tertiary action followed by the primary filled action).
8
+ */
9
+ declare const ModalBetaFooter: {
10
+ ({ children }: ModalBetaFooterProps): import("react/jsx-runtime").JSX.Element;
11
+ displayName: string;
12
+ };
13
+ export default ModalBetaFooter;
@@ -0,0 +1,7 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ const ModalBetaFooter = ({
3
+ children
4
+ }) => /* @__PURE__ */ jsx("div", { className: "modal-beta-footer", children });
5
+ export {
6
+ ModalBetaFooter as default
7
+ };
@@ -0,0 +1,23 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ModalBetaHeaderProps {
3
+ /**
4
+ * Method called on modal close
5
+ */
6
+ onModalClose: () => void;
7
+ /**
8
+ * Modal title
9
+ */
10
+ children: ReactNode;
11
+ /**
12
+ * Optional text displayed below the title
13
+ */
14
+ subtitle?: ReactNode;
15
+ }
16
+ /**
17
+ * ModalBeta Header
18
+ */
19
+ declare const ModalBetaHeader: {
20
+ ({ onModalClose, children, subtitle, }: ModalBetaHeaderProps): import("react/jsx-runtime").JSX.Element;
21
+ displayName: string;
22
+ };
23
+ export default ModalBetaHeader;
@@ -0,0 +1,31 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useRef, useEffect } from "react";
3
+ import { useTranslation } from "react-i18next";
4
+ import SvgIconClose from "../../modules/icons/components/IconClose.js";
5
+ import ButtonBeta from "../ButtonBeta/ButtonBeta.js";
6
+ import { useModalBetaContext } from "./ModalBetaContext.js";
7
+ const ModalBetaHeader = ({
8
+ onModalClose,
9
+ children,
10
+ subtitle
11
+ }) => {
12
+ const {
13
+ ariaLabelId,
14
+ focusId
15
+ } = useModalBetaContext(), closeButtonRef = useRef(null), {
16
+ t
17
+ } = useTranslation();
18
+ return useEffect(() => {
19
+ var _a;
20
+ focusId || (_a = closeButtonRef.current) == null || _a.focus();
21
+ }, [focusId]), /* @__PURE__ */ jsxs("div", { className: "modal-beta-header", children: [
22
+ /* @__PURE__ */ jsxs("div", { className: "modal-beta-title-row", children: [
23
+ /* @__PURE__ */ jsx("h2", { id: ariaLabelId, className: "modal-beta-title", tabIndex: -1, children }),
24
+ /* @__PURE__ */ jsx(ButtonBeta, { ref: closeButtonRef, "aria-label": t("close"), title: t("close"), type: "button", variant: "ghost", color: "tertiary", leftIcon: /* @__PURE__ */ jsx(SvgIconClose, {}), onClick: onModalClose })
25
+ ] }),
26
+ subtitle && /* @__PURE__ */ jsx("p", { className: "modal-beta-subtitle", children: subtitle })
27
+ ] });
28
+ };
29
+ export {
30
+ ModalBetaHeader as default
31
+ };
@@ -0,0 +1,2 @@
1
+ export { default as ModalBeta } from './ModalBeta';
2
+ export * from './ModalBeta';
@@ -41,5 +41,9 @@ declare const PageLayout: {
41
41
  ({ children, onClose, closeButton, backdrop, className, ...props }: import('./components/PageLayoutOverlay').PageLayoutOverlayProps): import("react/jsx-runtime").JSX.Element;
42
42
  displayName: string;
43
43
  };
44
+ HelpZone: {
45
+ (): import("react/jsx-runtime").JSX.Element;
46
+ displayName: string;
47
+ };
44
48
  };
45
49
  export default PageLayout;
@@ -1,15 +1,16 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useMemo, Children, isValidElement } from "react";
3
3
  import clsx from "clsx";
4
4
  import PageLayoutBreadcrumb from "./components/PageLayoutBreadcrumb.js";
5
5
  import PageLayoutContent from "./components/PageLayoutContent.js";
6
6
  import PageLayoutHeader from "./components/PageLayoutHeader.js";
7
+ import PageLayoutHelpZone from "./components/PageLayoutHelpZone.js";
7
8
  import PageLayoutOverlay from "./components/PageLayoutOverlay.js";
8
9
  import PageLayoutSidebarLeft from "./components/PageLayoutSidebarLeft.js";
9
10
  import PageLayoutSidebarRight from "./components/PageLayoutSidebarRight.js";
10
11
  import { PageLayoutContext } from "./PageLayoutContext.js";
11
12
  function analyzeChildren(children) {
12
- let hasLeftSidebar = !1, hasRightSidebar = !1, breadcrumb = null, overlay = null;
13
+ let hasLeftSidebar = !1, hasRightSidebar = !1, breadcrumb = null, overlay = null, helpZone = null;
13
14
  const headerChildren = [], mainChildren = [];
14
15
  return Children.toArray(children).forEach((child) => {
15
16
  if (/* @__PURE__ */ isValidElement(child))
@@ -23,6 +24,9 @@ function analyzeChildren(children) {
23
24
  case PageLayoutOverlay:
24
25
  overlay = child;
25
26
  break;
27
+ case PageLayoutHelpZone:
28
+ helpZone = child;
29
+ break;
26
30
  case PageLayoutSidebarLeft:
27
31
  hasLeftSidebar = !0, mainChildren.push(child);
28
32
  break;
@@ -41,6 +45,7 @@ function analyzeChildren(children) {
41
45
  hasRightSidebar,
42
46
  breadcrumb,
43
47
  overlay,
48
+ helpZone,
44
49
  headerChildren,
45
50
  mainChildren
46
51
  };
@@ -63,6 +68,7 @@ const Root = ({
63
68
  hasRightSidebar,
64
69
  breadcrumb,
65
70
  overlay,
71
+ helpZone,
66
72
  headerChildren,
67
73
  mainChildren
68
74
  } = analyzeChildren(children), mainAreaClasses = clsx("pagelayout-mainarea", {
@@ -71,23 +77,27 @@ const Root = ({
71
77
  "has-right-sidebar-only": !hasLeftSidebar && hasRightSidebar,
72
78
  "has-gap": withGap
73
79
  }), isFullpage = variant === "fullpage";
74
- return /* @__PURE__ */ jsx(PageLayoutContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs("div", { className: clsx("pagelayout", `pagelayout-${variant}`, scrollMode && `pagelayout-scroll-${scrollMode}`, className), ...props, children: [
75
- headerChildren,
76
- headerChildren.length > 0 && /* @__PURE__ */ jsx("div", { className: "pagelayout-headerspacer" }),
77
- !isFullpage && breadcrumb,
78
- /* @__PURE__ */ jsxs("div", { className: mainAreaClasses, children: [
79
- isFullpage && breadcrumb,
80
- mainChildren
80
+ return /* @__PURE__ */ jsxs(PageLayoutContext.Provider, { value: contextValue, children: [
81
+ /* @__PURE__ */ jsxs("div", { className: clsx("pagelayout", `pagelayout-${variant}`, scrollMode && `pagelayout-scroll-${scrollMode}`, className), ...props, children: [
82
+ headerChildren,
83
+ headerChildren.length > 0 && /* @__PURE__ */ jsx("div", { className: "pagelayout-headerspacer" }),
84
+ !isFullpage && breadcrumb,
85
+ /* @__PURE__ */ jsxs("div", { className: mainAreaClasses, children: [
86
+ isFullpage && breadcrumb,
87
+ mainChildren
88
+ ] }),
89
+ overlay
81
90
  ] }),
82
- overlay
83
- ] }) });
91
+ helpZone
92
+ ] });
84
93
  }, PageLayout = Object.assign(Root, {
85
94
  Header: PageLayoutHeader,
86
95
  Breadcrumb: PageLayoutBreadcrumb,
87
96
  SidebarLeft: PageLayoutSidebarLeft,
88
97
  Content: PageLayoutContent,
89
98
  SidebarRight: PageLayoutSidebarRight,
90
- Overlay: PageLayoutOverlay
99
+ Overlay: PageLayoutOverlay,
100
+ HelpZone: PageLayoutHelpZone
91
101
  });
92
102
  export {
93
103
  PageLayout as default