se-design 1.0.83-dev.4 → 1.0.83
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { default as React, FC } from 'react';
|
|
1
|
+
import { default as React, FC, MutableRefObject, RefObject } from 'react';
|
|
2
2
|
export interface CustomModalProps {
|
|
3
3
|
onSubmit?: () => void;
|
|
4
4
|
onClose?: () => void;
|
|
@@ -19,6 +19,12 @@ export interface CustomModalProps {
|
|
|
19
19
|
* Ignored when `ariaLabelledBy` is provided.
|
|
20
20
|
*/
|
|
21
21
|
ariaLabel?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Additional container refs for elements outside the modal DOM that should
|
|
24
|
+
* remain focusable while the focus trap is active (e.g. a header bar above
|
|
25
|
+
* a full-page overlay). Forwarded to useFocusTrap's portalContainerRefs.
|
|
26
|
+
*/
|
|
27
|
+
portalContainerRefs?: MutableRefObject<RefObject<HTMLElement | null>[]>;
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
24
30
|
* Modal container with built-in focus trap, Escape dismissal, and dialog semantics.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { default as React
|
|
1
|
+
import { default as React } from 'react';
|
|
2
2
|
export interface HeaderProps {
|
|
3
3
|
leftContainer?: React.ReactNode;
|
|
4
4
|
centerContainer?: React.ReactNode;
|
|
@@ -7,4 +7,4 @@ export interface HeaderProps {
|
|
|
7
7
|
className?: string;
|
|
8
8
|
id?: string;
|
|
9
9
|
}
|
|
10
|
-
export declare const Header:
|
|
10
|
+
export declare const Header: React.ForwardRefExoticComponent<HeaderProps & React.RefAttributes<HTMLElement>>;
|
package/dist/index13.js
CHANGED
|
@@ -1,54 +1,68 @@
|
|
|
1
|
-
import i from "react";
|
|
1
|
+
import i, { useEffect as h } from "react";
|
|
2
2
|
import "./index72.js";
|
|
3
|
-
import { useModalA11y as
|
|
3
|
+
import { useModalA11y as y } from "./index207.js";
|
|
4
|
+
import { useFocusTrapPortalRegistry as R, FocusTrapPortalContext as w } from "./index208.js";
|
|
4
5
|
/* empty css */
|
|
5
|
-
function
|
|
6
|
-
return
|
|
6
|
+
function l() {
|
|
7
|
+
return l = Object.assign ? Object.assign.bind() : function(a) {
|
|
7
8
|
for (var t = 1; t < arguments.length; t++) {
|
|
8
9
|
var e = arguments[t];
|
|
9
|
-
for (var
|
|
10
|
+
for (var r in e) ({}).hasOwnProperty.call(e, r) && (a[r] = e[r]);
|
|
10
11
|
}
|
|
11
|
-
return
|
|
12
|
-
},
|
|
12
|
+
return a;
|
|
13
|
+
}, l.apply(null, arguments);
|
|
13
14
|
}
|
|
14
|
-
const
|
|
15
|
+
const O = (a) => {
|
|
15
16
|
const {
|
|
16
17
|
renderModalContent: t,
|
|
17
18
|
isOpen: e,
|
|
18
|
-
width:
|
|
19
|
-
className:
|
|
20
|
-
contentClassName:
|
|
21
|
-
automationId:
|
|
22
|
-
onModalClick:
|
|
19
|
+
width: r = "500px",
|
|
20
|
+
className: c = "",
|
|
21
|
+
contentClassName: d = "",
|
|
22
|
+
automationId: m = "",
|
|
23
|
+
onModalClick: u = () => {
|
|
23
24
|
},
|
|
24
|
-
onClose:
|
|
25
|
-
ariaLabel:
|
|
26
|
-
ariaLabelledBy:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
onClose: p,
|
|
26
|
+
ariaLabel: f,
|
|
27
|
+
ariaLabelledBy: g,
|
|
28
|
+
portalContainerRefs: n
|
|
29
|
+
} = a, {
|
|
30
|
+
register: o,
|
|
31
|
+
portalContainerRefs: v
|
|
32
|
+
} = R();
|
|
33
|
+
h(() => {
|
|
34
|
+
if (!n?.current) return;
|
|
35
|
+
const C = n.current.map((s) => o(s));
|
|
36
|
+
return () => C.forEach((s) => s());
|
|
37
|
+
}, [o, n]);
|
|
38
|
+
const {
|
|
39
|
+
containerRef: b,
|
|
40
|
+
dialogProps: x
|
|
41
|
+
} = y({
|
|
31
42
|
isOpen: e,
|
|
32
|
-
onDismiss:
|
|
33
|
-
ariaLabel:
|
|
34
|
-
ariaLabelledBy:
|
|
43
|
+
onDismiss: p,
|
|
44
|
+
ariaLabel: f,
|
|
45
|
+
ariaLabelledBy: g,
|
|
46
|
+
portalContainerRefs: v
|
|
35
47
|
});
|
|
36
|
-
return /* @__PURE__ */ i.createElement(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
return /* @__PURE__ */ i.createElement(w.Provider, {
|
|
49
|
+
value: o
|
|
50
|
+
}, /* @__PURE__ */ i.createElement("div", {
|
|
51
|
+
className: `se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${e ? "visible" : "invisible pointer-events-none"} ${c}`,
|
|
52
|
+
"data-automation-id": m,
|
|
53
|
+
onClick: u,
|
|
40
54
|
"aria-hidden": e ? void 0 : !0
|
|
41
|
-
}, /* @__PURE__ */ i.createElement("div",
|
|
42
|
-
ref:
|
|
43
|
-
},
|
|
44
|
-
className: `modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${
|
|
55
|
+
}, /* @__PURE__ */ i.createElement("div", l({
|
|
56
|
+
ref: b
|
|
57
|
+
}, x, {
|
|
58
|
+
className: `modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${d}`,
|
|
45
59
|
style: {
|
|
46
|
-
width:
|
|
60
|
+
width: r,
|
|
47
61
|
maxWidth: "100vw"
|
|
48
62
|
}
|
|
49
|
-
}), t()));
|
|
63
|
+
}), t())));
|
|
50
64
|
};
|
|
51
65
|
export {
|
|
52
|
-
|
|
66
|
+
O as CustomModal
|
|
53
67
|
};
|
|
54
68
|
//# sourceMappingURL=index13.js.map
|
package/dist/index13.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index13.js","sources":["../src/components/CustomModal/index.tsx"],"sourcesContent":["import React, { FC } from 'react';\nimport { useModalA11y } from 'src/utils/a11y';\nimport './style.scss';\n\nexport interface CustomModalProps {\n onSubmit?: () => void;\n onClose?: () => void;\n onModalClick?: () => void;\n renderModalContent: () => React.ReactNode;\n isOpen: boolean;\n width?: string;\n className?: string;\n contentClassName?: string;\n automationId?: string;\n /**\n * ID of a visible heading element rendered inside `renderModalContent`.\n * Add `id={ariaLabelledBy}` to that element to complete the association.\n */\n ariaLabelledBy?: string;\n /**\n * aria-label for modals without a visible title heading.\n * Ignored when `ariaLabelledBy` is provided.\n */\n ariaLabel?: string;\n}\n\n/**\n * Modal container with built-in focus trap, Escape dismissal, and dialog semantics.\n *\n * Labelling (pick one):\n * - `ariaLabelledBy` — ID of a heading rendered inside `renderModalContent`\n * - `ariaLabel` — for modals with no visible title\n *\n * Escape dismissal requires `onClose` to be passed.\n *\n * ---\n * ## Header + close button pattern (zoom-safe)\n *\n * If your modal has a title and a close button, use a flex row — NOT absolute positioning.\n * Absolute positioning causes the close icon to overlap the title at 200%/400% zoom.\n *\n * ✅ Correct:\n * ```tsx\n * renderModalContent={() => (\n * <>\n * <div className=\"modal-header\"> // display:flex; align-items:flex-start; justify-content:space-between; gap:12px\n * <h2 className=\"modal-title\">Title</h2> // flex:1 so it wraps without touching the icon\n * <Icon name=\"close\" onClick={onClose} ariaLabel=\"Close\" className=\"shrink-0\" />\n * </div>\n * <div className=\"modal-body\">...content...</div>\n * </>\n * )}\n * ```\n *\n * ❌ Avoid:\n * ```tsx\n * renderModalContent={() => (\n * <div style={{ position: 'relative' }}>\n * <h2>Title</h2>\n * <Icon name=\"close\" style={{ position: 'absolute', top: 8, right: 8 }} />\n * </div>\n * )}\n * ```\n */\nexport const CustomModal: FC<CustomModalProps> = (props) => {\n const {\n renderModalContent,\n isOpen,\n width = '500px',\n className = '',\n contentClassName = '',\n automationId = '',\n onModalClick = () => {},\n onClose,\n ariaLabel,\n ariaLabelledBy,\n } = props;\n\n const { containerRef, dialogProps } = useModalA11y({\n isOpen,\n onDismiss: onClose,\n ariaLabel,\n ariaLabelledBy,\n });\n\n return (\n <div\n
|
|
1
|
+
{"version":3,"file":"index13.js","sources":["../src/components/CustomModal/index.tsx"],"sourcesContent":["import React, { FC, useEffect } from 'react';\nimport type { MutableRefObject, RefObject } from 'react';\nimport { useModalA11y } from 'src/utils/a11y';\nimport { FocusTrapPortalContext, useFocusTrapPortalRegistry } from 'src/utils/a11y/FocusTrapPortalContext';\nimport './style.scss';\n\nexport interface CustomModalProps {\n onSubmit?: () => void;\n onClose?: () => void;\n onModalClick?: () => void;\n renderModalContent: () => React.ReactNode;\n isOpen: boolean;\n width?: string;\n className?: string;\n contentClassName?: string;\n automationId?: string;\n /**\n * ID of a visible heading element rendered inside `renderModalContent`.\n * Add `id={ariaLabelledBy}` to that element to complete the association.\n */\n ariaLabelledBy?: string;\n /**\n * aria-label for modals without a visible title heading.\n * Ignored when `ariaLabelledBy` is provided.\n */\n ariaLabel?: string;\n /**\n * Additional container refs for elements outside the modal DOM that should\n * remain focusable while the focus trap is active (e.g. a header bar above\n * a full-page overlay). Forwarded to useFocusTrap's portalContainerRefs.\n */\n portalContainerRefs?: MutableRefObject<RefObject<HTMLElement | null>[]>;\n}\n\n/**\n * Modal container with built-in focus trap, Escape dismissal, and dialog semantics.\n *\n * Labelling (pick one):\n * - `ariaLabelledBy` — ID of a heading rendered inside `renderModalContent`\n * - `ariaLabel` — for modals with no visible title\n *\n * Escape dismissal requires `onClose` to be passed.\n *\n * ---\n * ## Header + close button pattern (zoom-safe)\n *\n * If your modal has a title and a close button, use a flex row — NOT absolute positioning.\n * Absolute positioning causes the close icon to overlap the title at 200%/400% zoom.\n *\n * ✅ Correct:\n * ```tsx\n * renderModalContent={() => (\n * <>\n * <div className=\"modal-header\"> // display:flex; align-items:flex-start; justify-content:space-between; gap:12px\n * <h2 className=\"modal-title\">Title</h2> // flex:1 so it wraps without touching the icon\n * <Icon name=\"close\" onClick={onClose} ariaLabel=\"Close\" className=\"shrink-0\" />\n * </div>\n * <div className=\"modal-body\">...content...</div>\n * </>\n * )}\n * ```\n *\n * ❌ Avoid:\n * ```tsx\n * renderModalContent={() => (\n * <div style={{ position: 'relative' }}>\n * <h2>Title</h2>\n * <Icon name=\"close\" style={{ position: 'absolute', top: 8, right: 8 }} />\n * </div>\n * )}\n * ```\n */\nexport const CustomModal: FC<CustomModalProps> = (props) => {\n const {\n renderModalContent,\n isOpen,\n width = '500px',\n className = '',\n contentClassName = '',\n automationId = '',\n onModalClick = () => {},\n onClose,\n ariaLabel,\n ariaLabelledBy,\n portalContainerRefs,\n } = props;\n\n const { register, portalContainerRefs: registryRefs } = useFocusTrapPortalRegistry();\n\n // Append explicit portalContainerRefs (e.g. header ref) into the registry\n // so they're included alongside auto-registered portal refs from Popovers/Dropdowns.\n useEffect(() => {\n if (!portalContainerRefs?.current) return;\n const unregisters = portalContainerRefs.current.map((ref) => register(ref));\n return () => unregisters.forEach((unregister) => unregister());\n }, [register, portalContainerRefs]);\n\n const { containerRef, dialogProps } = useModalA11y({\n isOpen,\n onDismiss: onClose,\n ariaLabel,\n ariaLabelledBy,\n portalContainerRefs: registryRefs,\n });\n\n return (\n <FocusTrapPortalContext.Provider value={register}>\n <div\n className={`se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${\n isOpen ? 'visible' : 'invisible pointer-events-none'\n } ${className}`}\n data-automation-id={automationId}\n onClick={onModalClick}\n aria-hidden={isOpen ? undefined : true}\n >\n <div\n ref={containerRef}\n {...dialogProps}\n className={`modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${contentClassName}`}\n style={{ width, maxWidth: '100vw' }}\n >\n {renderModalContent()}\n </div>\n </div>\n </FocusTrapPortalContext.Provider>\n );\n};\n"],"names":["CustomModal","props","renderModalContent","isOpen","width","className","contentClassName","automationId","onModalClick","onClose","ariaLabel","ariaLabelledBy","portalContainerRefs","register","registryRefs","useFocusTrapPortalRegistry","useEffect","current","unregisters","map","ref","forEach","unregister","containerRef","dialogProps","useModalA11y","onDismiss","React","createElement","FocusTrapPortalContext","Provider","value","onClick","undefined","_extends","style","maxWidth"],"mappings":";;;;;;;;;;;;;;AAwEO,MAAMA,IAAqCC,CAAAA,MAAU;AAC1D,QAAM;AAAA,IACJC,oBAAAA;AAAAA,IACAC,QAAAA;AAAAA,IACAC,OAAAA,IAAQ;AAAA,IACRC,WAAAA,IAAY;AAAA,IACZC,kBAAAA,IAAmB;AAAA,IACnBC,cAAAA,IAAe;AAAA,IACfC,cAAAA,IAAeA,MAAM;AAAA,IAAC;AAAA,IACtBC,SAAAA;AAAAA,IACAC,WAAAA;AAAAA,IACAC,gBAAAA;AAAAA,IACAC,qBAAAA;AAAAA,EAAAA,IACEX,GAEE;AAAA,IAAEY,UAAAA;AAAAA,IAAUD,qBAAqBE;AAAAA,EAAAA,IAAiBC,EAAAA;AAIxDC,EAAAA,EAAU,MAAM;AACd,QAAI,CAACJ,GAAqBK,QAAS;AACnC,UAAMC,IAAcN,EAAoBK,QAAQE,IAAKC,CAAAA,MAAQP,EAASO,CAAG,CAAC;AAC1E,WAAO,MAAMF,EAAYG,QAASC,CAAAA,MAAeA,GAAY;AAAA,EAC/D,GAAG,CAACT,GAAUD,CAAmB,CAAC;AAElC,QAAM;AAAA,IAAEW,cAAAA;AAAAA,IAAcC,aAAAA;AAAAA,EAAAA,IAAgBC,EAAa;AAAA,IACjDtB,QAAAA;AAAAA,IACAuB,WAAWjB;AAAAA,IACXC,WAAAA;AAAAA,IACAC,gBAAAA;AAAAA,IACAC,qBAAqBE;AAAAA,EAAAA,CACtB;AAED,SACEa,gBAAAA,EAAAC,cAACC,EAAuBC,UAAQ;AAAA,IAACC,OAAOlB;AAAAA,EAAAA,GACtCc,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEvB,WAAW,kHACTF,IAAS,YAAY,+BAA+B,IAClDE,CAAS;AAAA,IACb,sBAAoBE;AAAAA,IACpByB,SAASxB;AAAAA,IACT,eAAaL,IAAS8B,SAAY;AAAA,EAAA,GAElCN,gBAAAA,EAAAC,cAAA,OAAAM,EAAA;AAAA,IACEd,KAAKG;AAAAA,EAAAA,GACDC,GAAW;AAAA,IACfnB,WAAW,6FAA6FC,CAAgB;AAAA,IACxH6B,OAAO;AAAA,MAAE/B,OAAAA;AAAAA,MAAOgC,UAAU;AAAA,IAAA;AAAA,EAAQ,CAAE,GAEnClC,EAAAA,CACE,CACF,CAC0B;AAErC;"}
|
package/dist/index20.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import e from "react";
|
|
2
|
-
const
|
|
1
|
+
import e, { forwardRef as u } from "react";
|
|
2
|
+
const m = /* @__PURE__ */ u(({
|
|
3
3
|
leftContainer: t,
|
|
4
4
|
centerContainer: l,
|
|
5
5
|
rightContainer: r,
|
|
6
6
|
className: a,
|
|
7
|
-
id:
|
|
8
|
-
...
|
|
9
|
-
}) => /* @__PURE__ */ e.createElement("header", {
|
|
10
|
-
|
|
7
|
+
id: o,
|
|
8
|
+
...c
|
|
9
|
+
}, n) => /* @__PURE__ */ e.createElement("header", {
|
|
10
|
+
ref: n,
|
|
11
|
+
id: o,
|
|
11
12
|
tabIndex: -1,
|
|
12
13
|
style: {
|
|
13
14
|
"--focus-color": "var(--color-blue-300)"
|
|
14
15
|
},
|
|
15
|
-
className: `se-design-header ${a} sticky top-0 h-[48px] w-full z-[1010] bg-[var(--color-blue-600)] flex justify-between items-center focus:outline-none ${
|
|
16
|
-
}, t && /* @__PURE__ */ e.createElement(e.Fragment, null, t), l && /* @__PURE__ */ e.createElement(e.Fragment, null, l), r && /* @__PURE__ */ e.createElement(e.Fragment, null, r));
|
|
16
|
+
className: `se-design-header ${a} sticky top-0 h-[48px] w-full z-[1010] bg-[var(--color-blue-600)] flex justify-between items-center focus:outline-none ${c?.type === "fixed" ? "fixed left-0 right-0 top-0" : ""}`
|
|
17
|
+
}, t && /* @__PURE__ */ e.createElement(e.Fragment, null, t), l && /* @__PURE__ */ e.createElement(e.Fragment, null, l), r && /* @__PURE__ */ e.createElement(e.Fragment, null, r)));
|
|
17
18
|
export {
|
|
18
|
-
|
|
19
|
+
m as Header
|
|
19
20
|
};
|
|
20
21
|
//# sourceMappingURL=index20.js.map
|
package/dist/index20.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index20.js","sources":["../src/components/Header/index.tsx"],"sourcesContent":["import React, {
|
|
1
|
+
{"version":3,"file":"index20.js","sources":["../src/components/Header/index.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\n\nexport interface HeaderProps {\n leftContainer?: React.ReactNode;\n centerContainer?: React.ReactNode;\n rightContainer?: React.ReactNode;\n type?: string;\n className?: string;\n id?: string;\n}\n\nexport const Header = forwardRef<HTMLElement, HeaderProps>(({\n leftContainer,\n centerContainer,\n rightContainer,\n className,\n id,\n ...props\n}, ref) => {\n return (\n <header\n ref={ref}\n id={id}\n tabIndex={-1}\n style={{ '--focus-color': 'var(--color-blue-300)' } as React.CSSProperties}\n className={`se-design-header ${className} sticky top-0 h-[48px] w-full z-[1010] bg-[var(--color-blue-600)] flex justify-between items-center focus:outline-none ${\n props?.type === 'fixed' ? 'fixed left-0 right-0 top-0' : ''\n }`}\n >\n {leftContainer && <>{leftContainer}</>}\n {centerContainer && <>{centerContainer}</>}\n {rightContainer && <>{rightContainer}</>}\n </header>\n );\n});\n"],"names":["React__default","forwardRef","Header","leftContainer","centerContainer","rightContainer","className","id","props","ref","React","createElement","tabIndex","style","type","Fragment"],"mappings":"AAWO,OAAAA,KAAA,cAAAC,SAAA;AAAA,MAAMC,sBAA8C,CAAC;AAAA,EAC1DC,eAAAA;AAAAA,EACAC,iBAAAA;AAAAA,EACAC,gBAAAA;AAAAA,EACAC,WAAAA;AAAAA,EACAC,IAAAA;AAAAA,EACA,GAAGC;AACL,GAAGC,MAECC,gBAAAA,EAAAC,cAAA,UAAA;AAAA,EACEF,KAAAA;AAAAA,EACAF,IAAAA;AAAAA,EACAK,UAAU;AAAA,EACVC,OAAO;AAAA,IAAE,iBAAiB;AAAA,EAAA;AAAA,EAC1BP,WAAW,oBAAoBA,CAAS,0HACtCE,GAAOM,SAAS,UAAU,+BAA+B,EAAE;AAAA,GAG5DX,KAAiBO,gBAAAA,EAAAC,cAAAD,EAAAK,UAAA,MAAGZ,CAAgB,GACpCC,KAAmBM,gBAAAA,EAAAC,cAAAD,EAAAK,UAAA,MAAGX,CAAkB,GACxCC,KAAkBK,gBAAAA,EAAAC,cAAAD,EAAAK,UAAA,MAAGV,CAAiB,CACjC,CAEX;"}
|