@bioturing/components 0.36.2 → 0.37.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.
- package/dist/components/button/component.d.ts +1 -1
- package/dist/components/button/component.d.ts.map +1 -1
- package/dist/components/button/component.js +42 -35
- package/dist/components/button/component.js.map +1 -1
- package/dist/components/button/style.css +1 -1
- package/dist/components/data-table/component.d.ts.map +1 -1
- package/dist/components/data-table/component.js +76 -71
- package/dist/components/data-table/component.js.map +1 -1
- package/dist/components/data-table/components/TablePagination.d.ts +1 -1
- package/dist/components/data-table/components/TablePagination.d.ts.map +1 -1
- package/dist/components/data-table/components/TablePagination.js +26 -23
- package/dist/components/data-table/components/TablePagination.js.map +1 -1
- package/dist/components/data-table/hooks.d.ts.map +1 -1
- package/dist/components/data-table/hooks.js +82 -82
- package/dist/components/data-table/hooks.js.map +1 -1
- package/dist/components/data-table/style.css +1 -1
- package/dist/components/empty/component.d.ts +0 -2
- package/dist/components/empty/component.d.ts.map +1 -1
- package/dist/components/empty/component.js +14 -35
- package/dist/components/empty/component.js.map +1 -1
- package/dist/components/empty/style.css +1 -1
- package/dist/components/modal/Modal.d.ts.map +1 -1
- package/dist/components/modal/Modal.js +105 -102
- package/dist/components/modal/Modal.js.map +1 -1
- package/dist/components/truncate/component.d.ts +7 -0
- package/dist/components/truncate/component.d.ts.map +1 -1
- package/dist/components/truncate/component.js +57 -48
- package/dist/components/truncate/component.js.map +1 -1
- package/dist/components/truncate/helpers.d.ts +8 -2
- package/dist/components/truncate/helpers.d.ts.map +1 -1
- package/dist/components/truncate/helpers.js +82 -54
- package/dist/components/truncate/helpers.js.map +1 -1
- package/dist/index.js +126 -127
- package/dist/stats.html +1 -1
- package/package.json +1 -1
|
@@ -1,60 +1,60 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
import
|
|
4
|
-
import { XIcon as
|
|
5
|
-
import { useState as
|
|
6
|
-
import { ModalContextProvider as
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import { getConfirmLocale as
|
|
10
|
-
import { useLocale as
|
|
11
|
-
import { ModalSize as
|
|
2
|
+
import { jsx as o, jsxs as c, Fragment as H } from "react/jsx-runtime";
|
|
3
|
+
import pe from "antd/es/modal";
|
|
4
|
+
import { XIcon as he } from "@bioturing/assets";
|
|
5
|
+
import { useState as R, useRef as ye, useCallback as be, useEffect as Ce } from "react";
|
|
6
|
+
import { ModalContextProvider as ve } from "antd/es/modal/context";
|
|
7
|
+
import j from "antd/es/modal/components/NormalCancelBtn";
|
|
8
|
+
import E from "antd/es/modal/components/NormalOkBtn";
|
|
9
|
+
import { getConfirmLocale as ge } from "antd/es/modal/locale";
|
|
10
|
+
import { useLocale as ke } from "antd/es/locale";
|
|
11
|
+
import { ModalSize as m } from "./constants.js";
|
|
12
12
|
import { Stack as f } from "../stack/index.js";
|
|
13
|
-
import { Truncate as
|
|
14
|
-
import { IconButton as
|
|
15
|
-
import { useCls as
|
|
16
|
-
import { useTheme as
|
|
17
|
-
import { clsx as
|
|
18
|
-
const
|
|
13
|
+
import { Truncate as we } from "../truncate/component.js";
|
|
14
|
+
import { IconButton as xe } from "../icon-button/component.js";
|
|
15
|
+
import { useCls as Oe } from "../utils/antdUtils.js";
|
|
16
|
+
import { useTheme as ze } from "../theme-provider/context/themeStore.js";
|
|
17
|
+
import { clsx as Be } from "../utils/cn.js";
|
|
18
|
+
const Je = ({
|
|
19
19
|
open: u,
|
|
20
20
|
closeIcon: p,
|
|
21
|
-
children:
|
|
22
|
-
size:
|
|
21
|
+
children: F,
|
|
22
|
+
size: L,
|
|
23
23
|
footer: h,
|
|
24
|
-
width:
|
|
25
|
-
style:
|
|
24
|
+
width: P,
|
|
25
|
+
style: W,
|
|
26
26
|
styles: y,
|
|
27
|
-
classNames:
|
|
28
|
-
okButtonProps:
|
|
29
|
-
cancelButtonProps:
|
|
30
|
-
loading:
|
|
27
|
+
classNames: $,
|
|
28
|
+
okButtonProps: q,
|
|
29
|
+
cancelButtonProps: A,
|
|
30
|
+
loading: X,
|
|
31
31
|
onOk: b,
|
|
32
|
-
onCancel:
|
|
33
|
-
okText:
|
|
34
|
-
okType:
|
|
35
|
-
confirmLoading:
|
|
36
|
-
cancelText:
|
|
32
|
+
onCancel: C,
|
|
33
|
+
okText: v,
|
|
34
|
+
okType: D = "primary",
|
|
35
|
+
confirmLoading: s,
|
|
36
|
+
cancelText: g = "Close",
|
|
37
37
|
hideOkButton: k = !1,
|
|
38
38
|
hideCancelButton: w = !1,
|
|
39
39
|
contentPadding: r,
|
|
40
40
|
title: i,
|
|
41
41
|
afterTitle: x,
|
|
42
|
-
beforeCloseButton:
|
|
43
|
-
afterCloseButton:
|
|
44
|
-
defaultFixedHeaderFooter:
|
|
45
|
-
centered:
|
|
46
|
-
type:
|
|
47
|
-
defaultOpen:
|
|
48
|
-
background:
|
|
49
|
-
bodyScrollable:
|
|
50
|
-
rootClassName:
|
|
51
|
-
...
|
|
42
|
+
beforeCloseButton: G,
|
|
43
|
+
afterCloseButton: J,
|
|
44
|
+
defaultFixedHeaderFooter: K = !1,
|
|
45
|
+
centered: Q = !0,
|
|
46
|
+
type: U = "default",
|
|
47
|
+
defaultOpen: V = !0,
|
|
48
|
+
background: Y,
|
|
49
|
+
bodyScrollable: Z = !0,
|
|
50
|
+
rootClassName: _,
|
|
51
|
+
...ee
|
|
52
52
|
}) => {
|
|
53
|
-
const
|
|
54
|
-
"--ds-modal-bg": `var(--ds-color-bg-${
|
|
55
|
-
...
|
|
53
|
+
const oe = p === void 0 ? /* @__PURE__ */ o(he, { size: 16, weight: "bold" }) : p, t = L || (U === "default" ? "medium" : "xsmall"), re = P || m[t], te = {
|
|
54
|
+
"--ds-modal-bg": `var(--ds-color-bg-${Y || (t in m && parseInt(m[t]) <= parseInt(m.medium) ? "elevated" : "container")})`,
|
|
55
|
+
...W,
|
|
56
56
|
...t === "fullscreen" ? { top: 0, maxWidth: "100%", height: "100%" } : {}
|
|
57
|
-
},
|
|
57
|
+
}, le = {
|
|
58
58
|
...y,
|
|
59
59
|
body: {
|
|
60
60
|
...typeof r < "u" ? {
|
|
@@ -62,105 +62,108 @@ const Ge = ({
|
|
|
62
62
|
} : {},
|
|
63
63
|
...y?.body
|
|
64
64
|
}
|
|
65
|
-
}, [O, z] =
|
|
66
|
-
(
|
|
67
|
-
if (!
|
|
68
|
-
const l =
|
|
65
|
+
}, [O, z] = R(!1), n = Oe(), { className: ne } = ze(), a = ye(null), se = be(
|
|
66
|
+
(e) => {
|
|
67
|
+
if (!e) return;
|
|
68
|
+
const l = e.querySelector("." + n("modal-body"));
|
|
69
69
|
if (!(l instanceof HTMLElement)) return;
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
z(
|
|
70
|
+
const T = new ResizeObserver(() => {
|
|
71
|
+
const ue = l.scrollHeight > l.clientHeight;
|
|
72
|
+
z(ue);
|
|
73
73
|
});
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
z(
|
|
74
|
+
a.current = T, T.observe(l);
|
|
75
|
+
const fe = l.scrollHeight > l.clientHeight;
|
|
76
|
+
z(fe);
|
|
77
77
|
},
|
|
78
78
|
[n]
|
|
79
79
|
);
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
Ce(() => () => {
|
|
81
|
+
a.current && (a.current.disconnect(), a.current = null);
|
|
82
82
|
}, []);
|
|
83
|
-
const [B] =
|
|
84
|
-
loading:
|
|
85
|
-
...$
|
|
86
|
-
}, M = {
|
|
83
|
+
const [B] = ke("Modal", ge()), ae = v || B?.okText, ce = g || B?.cancelText, I = {
|
|
84
|
+
// loading: typeof confirmLoading === "boolean" ? confirmLoading : loading,
|
|
87
85
|
...q
|
|
88
|
-
},
|
|
89
|
-
|
|
86
|
+
}, M = {
|
|
87
|
+
...A
|
|
88
|
+
}, [me, N] = R(V), d = typeof u > "u", ie = d ? me : u, S = (e) => {
|
|
89
|
+
s || C?.(e);
|
|
90
|
+
}, de = /* @__PURE__ */ o(
|
|
91
|
+
ve,
|
|
90
92
|
{
|
|
91
93
|
value: {
|
|
92
94
|
okButtonProps: I,
|
|
93
95
|
cancelButtonProps: M,
|
|
94
|
-
onCancel:
|
|
96
|
+
onCancel: S,
|
|
95
97
|
onOk: b,
|
|
96
|
-
okType:
|
|
97
|
-
confirmLoading:
|
|
98
|
-
okTextLocale:
|
|
99
|
-
cancelTextLocale:
|
|
98
|
+
okType: D,
|
|
99
|
+
confirmLoading: s,
|
|
100
|
+
okTextLocale: ae,
|
|
101
|
+
cancelTextLocale: ce
|
|
100
102
|
},
|
|
101
|
-
children: k ? /* @__PURE__ */
|
|
102
|
-
/* @__PURE__ */
|
|
103
|
-
/* @__PURE__ */
|
|
103
|
+
children: k ? /* @__PURE__ */ o(j, {}) : w ? /* @__PURE__ */ o(E, {}) : /* @__PURE__ */ c(H, { children: [
|
|
104
|
+
/* @__PURE__ */ o(j, {}),
|
|
105
|
+
/* @__PURE__ */ o(E, {})
|
|
104
106
|
] })
|
|
105
107
|
}
|
|
106
108
|
);
|
|
107
|
-
return /* @__PURE__ */
|
|
108
|
-
|
|
109
|
+
return /* @__PURE__ */ o(
|
|
110
|
+
pe,
|
|
109
111
|
{
|
|
110
112
|
closeIcon: !1,
|
|
111
|
-
open:
|
|
112
|
-
width:
|
|
113
|
-
style:
|
|
114
|
-
title: /* @__PURE__ */
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
-
/* @__PURE__ */
|
|
117
|
-
/* @__PURE__ */
|
|
118
|
-
|
|
119
|
-
/* @__PURE__ */
|
|
120
|
-
|
|
113
|
+
open: ie,
|
|
114
|
+
width: re,
|
|
115
|
+
style: te,
|
|
116
|
+
title: /* @__PURE__ */ c(H, { children: [
|
|
117
|
+
/* @__PURE__ */ c(f, { align: "center", gap: 8, className: n("modal-title-wrapper"), children: [
|
|
118
|
+
/* @__PURE__ */ o(f.Child, { grow: !0, children: typeof i == "string" ? /* @__PURE__ */ o(we, { children: i }) : i }),
|
|
119
|
+
/* @__PURE__ */ c(f.Child, { stack: !0, hug: !0, align: "center", gap: 8, children: [
|
|
120
|
+
G,
|
|
121
|
+
/* @__PURE__ */ o(
|
|
122
|
+
xe,
|
|
121
123
|
{
|
|
122
|
-
onClick: (
|
|
123
|
-
children:
|
|
124
|
+
onClick: (e) => S(e),
|
|
125
|
+
children: oe
|
|
124
126
|
}
|
|
125
127
|
),
|
|
126
|
-
|
|
128
|
+
J
|
|
127
129
|
] })
|
|
128
130
|
] }),
|
|
129
131
|
x || null
|
|
130
132
|
] }),
|
|
131
|
-
rootClassName:
|
|
133
|
+
rootClassName: Be(ne, _),
|
|
132
134
|
classNames: {
|
|
133
|
-
|
|
135
|
+
...$,
|
|
134
136
|
wrapper: n(
|
|
135
137
|
"modal-wrap",
|
|
136
138
|
t == "fullscreen" && "modal-fullscreen",
|
|
137
139
|
O && "modal-content-overflow",
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
Z === !1 && "modal-no-body-scroll",
|
|
141
|
+
K || O || t == "fullscreen" ? "modal-fixed" : ""
|
|
140
142
|
)
|
|
141
143
|
},
|
|
142
|
-
styles:
|
|
143
|
-
modalRender: (
|
|
144
|
+
styles: le,
|
|
145
|
+
modalRender: (e) => /* @__PURE__ */ o("div", { ref: se, className: n("modal-inner"), children: e }),
|
|
144
146
|
okButtonProps: I,
|
|
145
147
|
cancelButtonProps: M,
|
|
146
|
-
onOk: (
|
|
147
|
-
d && N(!1), b?.(
|
|
148
|
+
onOk: (e) => {
|
|
149
|
+
d && N(!1), b?.(e);
|
|
148
150
|
},
|
|
149
|
-
onCancel: (
|
|
150
|
-
d && N(!1),
|
|
151
|
+
onCancel: (e) => {
|
|
152
|
+
s || (d && N(!1), C?.(e));
|
|
151
153
|
},
|
|
152
|
-
okText:
|
|
153
|
-
cancelText:
|
|
154
|
+
okText: v,
|
|
155
|
+
cancelText: g,
|
|
154
156
|
okType: "primary",
|
|
155
|
-
confirmLoading:
|
|
156
|
-
footer: typeof h > "u" ? k && w ? null :
|
|
157
|
-
centered:
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
confirmLoading: s,
|
|
158
|
+
footer: typeof h > "u" ? k && w ? null : de : h,
|
|
159
|
+
centered: Q,
|
|
160
|
+
loading: X,
|
|
161
|
+
...ee,
|
|
162
|
+
children: F
|
|
160
163
|
}
|
|
161
164
|
);
|
|
162
165
|
};
|
|
163
166
|
export {
|
|
164
|
-
|
|
167
|
+
Je as Modal
|
|
165
168
|
};
|
|
166
169
|
//# sourceMappingURL=Modal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.js","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["\"use client\";\nimport {\n default as AntModal,\n type ModalProps as AntModalProps,\n} from \"antd/es/modal\";\nimport { XIcon } from \"@bioturing/assets\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { clsx, useCls } from \"../utils\";\nimport { ModalContextProvider } from \"antd/es/modal/context\";\nimport NormalCancelBtn from \"antd/es/modal/components/NormalCancelBtn\";\nimport NormalOkBtn from \"antd/es/modal/components/NormalOkBtn\";\nimport { getConfirmLocale } from \"antd/es/modal/locale\";\nimport { useLocale } from \"antd/es/locale\";\nimport { IconButton } from \"../icon-button\";\nimport { ModalSize } from \"./constants\";\nimport { ModalType } from \"./functions\";\nimport { Truncate } from \"../truncate\";\nimport { Stack } from \"../stack\";\nimport { useTheme } from \"../theme-provider\";\n\n// Define props interface extending Ant Design's ModalProps\nexport interface ModalProps extends Omit<AntModalProps, \"centered\"> {\n /**\n * Predefined sizes for the modal\n * - xsmall: 400px\n * - small: 520px\n * - medium: 640px (default)\n * - large: 840px\n * - xlarge: 1024px\n * - fullscreen: 100vw (takes full screen width with margins)\n * @default \"medium\" for default type, \"xsmall\" for other types\n */\n size?:\n | \"xsmall\"\n | \"small\"\n | \"medium\"\n | \"large\"\n | \"xlarge\"\n | \"xxlarge\"\n | \"fullscreen\";\n /**\n * Mark modal as loading\n * @default false\n */\n loading?: boolean;\n /**\n * Hide Ok button\n * @default false\n */\n hideOkButton?: boolean;\n /**\n * Hide Cancel button\n * @default false\n */\n hideCancelButton?: boolean;\n /**\n * Custom Content Padding\n * @default \"24px\"\n */\n contentPadding?: number | string | boolean;\n /**\n * Add more content below the title\n */\n afterTitle?: React.ReactNode;\n /**\n * Add more actions before close button\n */\n beforeCloseButton?: React.ReactNode;\n /**\n * Add more actions after close button\n */\n afterCloseButton?: React.ReactNode;\n /**\n * Set header and footer to fixed position\n * @default false\n */\n defaultFixedHeaderFooter?: boolean;\n /**\n * Centered Modal\n * @default true\n */\n centered?: boolean;\n /**\n * Modal type\n * @default \"default\"\n */\n type?: ModalType;\n /**\n * Default open state for uncontrolled modal\n * @default true\n */\n defaultOpen?: boolean;\n /**\n * Modal background\n * @default \"elevated\" if size smaller than \"medium\", otherwise \"container\"\n */\n background?: \"elevated\" | \"container\";\n /**\n * Modal old close callback\n * @deprecated use onCancel instead\n */\n onClose?: () => void;\n /**\n * Make modal body scrollable\n * @default true\n */\n bodyScrollable?: boolean;\n}\n\n// Create Modal component\nexport const Modal = ({\n open: externalOpen,\n closeIcon,\n children,\n size: sizeProp,\n footer,\n width,\n style,\n styles,\n classNames,\n okButtonProps,\n cancelButtonProps,\n loading,\n onOk,\n onCancel,\n okText,\n okType = \"primary\",\n confirmLoading,\n cancelText = \"Close\",\n hideOkButton = false,\n hideCancelButton = false,\n contentPadding,\n title,\n afterTitle,\n beforeCloseButton,\n afterCloseButton,\n defaultFixedHeaderFooter = false,\n centered = true,\n type = \"default\",\n defaultOpen = true,\n background: backgroundProp,\n bodyScrollable = true,\n rootClassName,\n ...rest\n}: ModalProps) => {\n // Default close icon with Phosphor icon\n const defaultCloseIcon =\n closeIcon === undefined ? <XIcon size={16} weight=\"bold\" /> : closeIcon;\n\n // Use custom width if provided, otherwise use the size from the map\n const defaultModalSize = type === \"default\" ? \"medium\" : \"xsmall\";\n\n const size: keyof typeof ModalSize = sizeProp || defaultModalSize;\n const modalWidth = width || ModalSize[size];\n\n const background =\n backgroundProp ||\n (size &&\n size in ModalSize &&\n parseInt(ModalSize[size]) <= parseInt(ModalSize.medium)\n ? \"elevated\"\n : \"container\");\n\n // Apply additional styles for fullscreen mode\n const modalStyle = {\n \"--ds-modal-bg\": `var(--ds-color-bg-${background})`,\n ...style,\n ...(size === \"fullscreen\"\n ? { top: 0, maxWidth: \"100%\", height: \"100%\" }\n : {}),\n };\n\n const modalStyles = {\n ...styles,\n body: {\n ...((typeof contentPadding != \"undefined\"\n ? {\n \"--ds-modal-content-padding\":\n contentPadding === false || contentPadding === 0\n ? \"0\"\n : typeof contentPadding == \"number\"\n ? `${contentPadding}px`\n : contentPadding,\n }\n : {}) as React.CSSProperties),\n ...styles?.body,\n },\n };\n\n const [isContentOverflow, setIsContentOverflow] = useState(false);\n\n const cls = useCls();\n\n const { className: themeClassName } = useTheme();\n\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n const modalInnerRef = useCallback(\n (node: HTMLElement | null) => {\n // If the node is null (component unmounting), just return\n if (!node) return;\n\n const modalBody = node.querySelector(\".\" + cls(\"modal-body\"));\n if (!(modalBody instanceof HTMLElement)) return;\n\n // Create ResizeObserver to detect overflow\n const resizeObserver = new ResizeObserver(() => {\n const hasOverflow = modalBody.scrollHeight > modalBody.clientHeight;\n setIsContentOverflow(hasOverflow);\n });\n\n // Store reference to the observer\n resizeObserverRef.current = resizeObserver;\n\n // Start observing\n resizeObserver.observe(modalBody);\n\n // Initial check\n const hasOverflow = modalBody.scrollHeight > modalBody.clientHeight;\n setIsContentOverflow(hasOverflow);\n },\n [cls]\n );\n\n // clean up resize observer\n useEffect(() => {\n return () => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n resizeObserverRef.current = null;\n }\n };\n }, []);\n\n const [locale] = useLocale(\"Modal\", getConfirmLocale());\n\n const okTextLocale: React.ReactNode = okText || locale?.okText;\n const cancelTextLocale = cancelText || locale?.cancelText;\n\n const modalOkButtonProps = {\n loading: loading,\n ...okButtonProps,\n };\n\n const modalCancelButtonProps = {\n ...cancelButtonProps,\n };\n\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n\n const uncontrolledOpen = typeof externalOpen === \"undefined\";\n\n const open = uncontrolledOpen ? internalOpen : externalOpen;\n\n const defaultFooter = (\n <ModalContextProvider\n value={{\n okButtonProps: modalOkButtonProps,\n cancelButtonProps: modalCancelButtonProps,\n onCancel,\n onOk,\n okType,\n confirmLoading,\n okTextLocale,\n cancelTextLocale,\n }}\n >\n {hideOkButton ? (\n <NormalCancelBtn />\n ) : hideCancelButton ? (\n <NormalOkBtn />\n ) : (\n <>\n <NormalCancelBtn />\n <NormalOkBtn />\n </>\n )}\n </ModalContextProvider>\n );\n const renderTitle = () => {\n return (\n <>\n <Stack align=\"center\" gap={8} className={cls(\"modal-title-wrapper\")}>\n <Stack.Child grow>\n {typeof title === \"string\" ? <Truncate>{title}</Truncate> : title}\n </Stack.Child>\n <Stack.Child stack hug align=\"center\" gap={8}>\n {beforeCloseButton}\n <IconButton\n onClick={(e: React.MouseEvent<HTMLButtonElement>) =>\n onCancel?.(e)\n }\n >\n {defaultCloseIcon}\n </IconButton>\n {afterCloseButton}\n </Stack.Child>\n {}\n </Stack>\n {afterTitle ? afterTitle : null}\n </>\n );\n };\n return (\n <AntModal\n closeIcon={false}\n open={open}\n width={modalWidth}\n style={modalStyle}\n title={renderTitle()}\n rootClassName={clsx(themeClassName, rootClassName)}\n classNames={{\n ...classNames,\n wrapper: cls(\n \"modal-wrap\",\n size == \"fullscreen\" && \"modal-fullscreen\",\n isContentOverflow && \"modal-content-overflow\",\n bodyScrollable === false && \"modal-no-body-scroll\",\n defaultFixedHeaderFooter || isContentOverflow || size == \"fullscreen\"\n ? \"modal-fixed\"\n : \"\"\n ),\n }}\n styles={modalStyles}\n modalRender={(modal) => (\n <div ref={modalInnerRef} className={cls(\"modal-inner\")}>\n {modal}\n </div>\n )}\n okButtonProps={modalOkButtonProps}\n cancelButtonProps={modalCancelButtonProps}\n onOk={(e) => {\n if (uncontrolledOpen) setInternalOpen(false);\n onOk?.(e);\n }}\n onCancel={(e) => {\n if (uncontrolledOpen) setInternalOpen(false);\n onCancel?.(e);\n }}\n okText={okText}\n cancelText={cancelText}\n okType=\"primary\"\n confirmLoading={confirmLoading}\n footer={\n typeof footer === \"undefined\"\n ? hideOkButton && hideCancelButton\n ? null\n : defaultFooter\n : footer\n }\n centered={centered}\n {...rest}\n >\n {children}\n </AntModal>\n );\n};\n"],"names":["Modal","externalOpen","closeIcon","children","sizeProp","footer","width","style","styles","classNames","okButtonProps","cancelButtonProps","loading","onOk","onCancel","okText","okType","confirmLoading","cancelText","hideOkButton","hideCancelButton","contentPadding","title","afterTitle","beforeCloseButton","afterCloseButton","defaultFixedHeaderFooter","centered","type","defaultOpen","backgroundProp","bodyScrollable","rootClassName","rest","defaultCloseIcon","jsx","XIcon","size","modalWidth","ModalSize","modalStyle","modalStyles","isContentOverflow","setIsContentOverflow","useState","cls","useCls","themeClassName","useTheme","resizeObserverRef","useRef","modalInnerRef","useCallback","node","modalBody","resizeObserver","hasOverflow","useEffect","locale","useLocale","getConfirmLocale","okTextLocale","cancelTextLocale","modalOkButtonProps","modalCancelButtonProps","internalOpen","setInternalOpen","uncontrolledOpen","open","defaultFooter","ModalContextProvider","NormalCancelBtn","NormalOkBtn","jsxs","Fragment","AntModal","Stack","Truncate","IconButton","e","clsx","modal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Modal.js","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["\"use client\";\nimport {\n default as AntModal,\n type ModalProps as AntModalProps,\n} from \"antd/es/modal\";\nimport { XIcon } from \"@bioturing/assets\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { clsx, useCls } from \"../utils\";\nimport { ModalContextProvider } from \"antd/es/modal/context\";\nimport NormalCancelBtn from \"antd/es/modal/components/NormalCancelBtn\";\nimport NormalOkBtn from \"antd/es/modal/components/NormalOkBtn\";\nimport { getConfirmLocale } from \"antd/es/modal/locale\";\nimport { useLocale } from \"antd/es/locale\";\nimport { IconButton } from \"../icon-button\";\nimport { ModalSize } from \"./constants\";\nimport { ModalType } from \"./functions\";\nimport { Truncate } from \"../truncate\";\nimport { Stack } from \"../stack\";\nimport { useTheme } from \"../theme-provider\";\n\n// Define props interface extending Ant Design's ModalProps\nexport interface ModalProps extends Omit<AntModalProps, \"centered\"> {\n /**\n * Predefined sizes for the modal\n * - xsmall: 400px\n * - small: 520px\n * - medium: 640px (default)\n * - large: 840px\n * - xlarge: 1024px\n * - fullscreen: 100vw (takes full screen width with margins)\n * @default \"medium\" for default type, \"xsmall\" for other types\n */\n size?:\n | \"xsmall\"\n | \"small\"\n | \"medium\"\n | \"large\"\n | \"xlarge\"\n | \"xxlarge\"\n | \"fullscreen\";\n /**\n * Mark modal as loading\n * @default false\n */\n loading?: boolean;\n /**\n * Hide Ok button\n * @default false\n */\n hideOkButton?: boolean;\n /**\n * Hide Cancel button\n * @default false\n */\n hideCancelButton?: boolean;\n /**\n * Custom Content Padding\n * @default \"24px\"\n */\n contentPadding?: number | string | boolean;\n /**\n * Add more content below the title\n */\n afterTitle?: React.ReactNode;\n /**\n * Add more actions before close button\n */\n beforeCloseButton?: React.ReactNode;\n /**\n * Add more actions after close button\n */\n afterCloseButton?: React.ReactNode;\n /**\n * Set header and footer to fixed position\n * @default false\n */\n defaultFixedHeaderFooter?: boolean;\n /**\n * Centered Modal\n * @default true\n */\n centered?: boolean;\n /**\n * Modal type\n * @default \"default\"\n */\n type?: ModalType;\n /**\n * Default open state for uncontrolled modal\n * @default true\n */\n defaultOpen?: boolean;\n /**\n * Modal background\n * @default \"elevated\" if size smaller than \"medium\", otherwise \"container\"\n */\n background?: \"elevated\" | \"container\";\n /**\n * Modal old close callback\n * @deprecated use onCancel instead\n */\n onClose?: () => void;\n /**\n * Make modal body scrollable\n * @default true\n */\n bodyScrollable?: boolean;\n}\n\n// Create Modal component\nexport const Modal = ({\n open: externalOpen,\n closeIcon,\n children,\n size: sizeProp,\n footer,\n width,\n style,\n styles,\n classNames,\n okButtonProps,\n cancelButtonProps,\n loading,\n onOk,\n onCancel,\n okText,\n okType = \"primary\",\n confirmLoading,\n cancelText = \"Close\",\n hideOkButton = false,\n hideCancelButton = false,\n contentPadding,\n title,\n afterTitle,\n beforeCloseButton,\n afterCloseButton,\n defaultFixedHeaderFooter = false,\n centered = true,\n type = \"default\",\n defaultOpen = true,\n background: backgroundProp,\n bodyScrollable = true,\n rootClassName,\n ...rest\n}: ModalProps) => {\n // Default close icon with Phosphor icon\n const defaultCloseIcon =\n closeIcon === undefined ? <XIcon size={16} weight=\"bold\" /> : closeIcon;\n\n // Use custom width if provided, otherwise use the size from the map\n const defaultModalSize = type === \"default\" ? \"medium\" : \"xsmall\";\n\n const size: keyof typeof ModalSize = sizeProp || defaultModalSize;\n const modalWidth = width || ModalSize[size];\n\n const background =\n backgroundProp ||\n (size &&\n size in ModalSize &&\n parseInt(ModalSize[size]) <= parseInt(ModalSize.medium)\n ? \"elevated\"\n : \"container\");\n\n // Apply additional styles for fullscreen mode\n const modalStyle = {\n \"--ds-modal-bg\": `var(--ds-color-bg-${background})`,\n ...style,\n ...(size === \"fullscreen\"\n ? { top: 0, maxWidth: \"100%\", height: \"100%\" }\n : {}),\n };\n\n const modalStyles = {\n ...styles,\n body: {\n ...((typeof contentPadding != \"undefined\"\n ? {\n \"--ds-modal-content-padding\":\n contentPadding === false || contentPadding === 0\n ? \"0\"\n : typeof contentPadding == \"number\"\n ? `${contentPadding}px`\n : contentPadding,\n }\n : {}) as React.CSSProperties),\n ...styles?.body,\n },\n };\n\n const [isContentOverflow, setIsContentOverflow] = useState(false);\n\n const cls = useCls();\n\n const { className: themeClassName } = useTheme();\n\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n const modalInnerRef = useCallback(\n (node: HTMLElement | null) => {\n // If the node is null (component unmounting), just return\n if (!node) return;\n\n const modalBody = node.querySelector(\".\" + cls(\"modal-body\"));\n if (!(modalBody instanceof HTMLElement)) return;\n\n // Create ResizeObserver to detect overflow\n const resizeObserver = new ResizeObserver(() => {\n const hasOverflow = modalBody.scrollHeight > modalBody.clientHeight;\n setIsContentOverflow(hasOverflow);\n });\n\n // Store reference to the observer\n resizeObserverRef.current = resizeObserver;\n\n // Start observing\n resizeObserver.observe(modalBody);\n\n // Initial check\n const hasOverflow = modalBody.scrollHeight > modalBody.clientHeight;\n setIsContentOverflow(hasOverflow);\n },\n [cls]\n );\n\n // clean up resize observer\n useEffect(() => {\n return () => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n resizeObserverRef.current = null;\n }\n };\n }, []);\n\n const [locale] = useLocale(\"Modal\", getConfirmLocale());\n\n const okTextLocale: React.ReactNode = okText || locale?.okText;\n const cancelTextLocale = cancelText || locale?.cancelText;\n\n const modalOkButtonProps = {\n // loading: typeof confirmLoading === \"boolean\" ? confirmLoading : loading,\n ...okButtonProps,\n };\n\n const modalCancelButtonProps = {\n ...cancelButtonProps,\n };\n\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n\n const uncontrolledOpen = typeof externalOpen === \"undefined\";\n\n const open = uncontrolledOpen ? internalOpen : externalOpen;\n\n const handleCancel = (e: React.MouseEvent<HTMLButtonElement>) => {\n if (confirmLoading) {\n return;\n }\n onCancel?.(e);\n };\n\n const defaultFooter = (\n <ModalContextProvider\n value={{\n okButtonProps: modalOkButtonProps,\n cancelButtonProps: modalCancelButtonProps,\n onCancel: handleCancel,\n onOk,\n okType,\n confirmLoading,\n okTextLocale,\n cancelTextLocale,\n }}\n >\n {hideOkButton ? (\n <NormalCancelBtn />\n ) : hideCancelButton ? (\n <NormalOkBtn />\n ) : (\n <>\n <NormalCancelBtn />\n <NormalOkBtn />\n </>\n )}\n </ModalContextProvider>\n );\n const renderTitle = () => {\n return (\n <>\n <Stack align=\"center\" gap={8} className={cls(\"modal-title-wrapper\")}>\n <Stack.Child grow>\n {typeof title === \"string\" ? <Truncate>{title}</Truncate> : title}\n </Stack.Child>\n <Stack.Child stack hug align=\"center\" gap={8}>\n {beforeCloseButton}\n <IconButton\n onClick={(e: React.MouseEvent<HTMLButtonElement>) =>\n handleCancel(e)\n }\n >\n {defaultCloseIcon}\n </IconButton>\n {afterCloseButton}\n </Stack.Child>\n {}\n </Stack>\n {afterTitle ? afterTitle : null}\n </>\n );\n };\n return (\n <AntModal\n closeIcon={false}\n open={open}\n width={modalWidth}\n style={modalStyle}\n title={renderTitle()}\n rootClassName={clsx(themeClassName, rootClassName)}\n classNames={{\n ...classNames,\n wrapper: cls(\n \"modal-wrap\",\n size == \"fullscreen\" && \"modal-fullscreen\",\n isContentOverflow && \"modal-content-overflow\",\n bodyScrollable === false && \"modal-no-body-scroll\",\n defaultFixedHeaderFooter || isContentOverflow || size == \"fullscreen\"\n ? \"modal-fixed\"\n : \"\"\n ),\n }}\n styles={modalStyles}\n modalRender={(modal) => (\n <div ref={modalInnerRef} className={cls(\"modal-inner\")}>\n {modal}\n </div>\n )}\n okButtonProps={modalOkButtonProps}\n cancelButtonProps={modalCancelButtonProps}\n onOk={(e) => {\n if (uncontrolledOpen) setInternalOpen(false);\n onOk?.(e);\n }}\n onCancel={(e) => {\n if (confirmLoading) return;\n if (uncontrolledOpen) setInternalOpen(false);\n onCancel?.(e);\n }}\n okText={okText}\n cancelText={cancelText}\n okType=\"primary\"\n confirmLoading={confirmLoading}\n footer={\n typeof footer === \"undefined\"\n ? hideOkButton && hideCancelButton\n ? null\n : defaultFooter\n : footer\n }\n centered={centered}\n loading={loading}\n {...rest}\n >\n {children}\n </AntModal>\n );\n};\n"],"names":["Modal","externalOpen","closeIcon","children","sizeProp","footer","width","style","styles","classNames","okButtonProps","cancelButtonProps","loading","onOk","onCancel","okText","okType","confirmLoading","cancelText","hideOkButton","hideCancelButton","contentPadding","title","afterTitle","beforeCloseButton","afterCloseButton","defaultFixedHeaderFooter","centered","type","defaultOpen","backgroundProp","bodyScrollable","rootClassName","rest","defaultCloseIcon","jsx","XIcon","size","modalWidth","ModalSize","modalStyle","modalStyles","isContentOverflow","setIsContentOverflow","useState","cls","useCls","themeClassName","useTheme","resizeObserverRef","useRef","modalInnerRef","useCallback","node","modalBody","resizeObserver","hasOverflow","useEffect","locale","useLocale","getConfirmLocale","okTextLocale","cancelTextLocale","modalOkButtonProps","modalCancelButtonProps","internalOpen","setInternalOpen","uncontrolledOpen","open","handleCancel","defaultFooter","ModalContextProvider","NormalCancelBtn","NormalOkBtn","jsxs","Fragment","AntModal","Stack","Truncate","IconButton","clsx","modal"],"mappings":"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"}
|
|
@@ -12,6 +12,13 @@ export interface TruncateProps extends Omit<React.ComponentPropsWithoutRef<"span
|
|
|
12
12
|
*/
|
|
13
13
|
lines?: number | "auto";
|
|
14
14
|
container?: HTMLElement | React.RefObject<HTMLElement>;
|
|
15
|
+
/**
|
|
16
|
+
* Custom render function to transform text before display
|
|
17
|
+
* Useful for keyword highlighting, text transformations, etc.
|
|
18
|
+
* @param text - The text to render (may be truncated)
|
|
19
|
+
* @returns React node to render
|
|
20
|
+
*/
|
|
21
|
+
renderText?: (text: string) => React.ReactNode;
|
|
15
22
|
}
|
|
16
23
|
export declare const Truncate: React.FC<TruncateProps>;
|
|
17
24
|
//# sourceMappingURL=component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../src/components/truncate/component.tsx"],"names":[],"mappings":"AACA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAK9E,OAAO,aAAa,CAAC;AAErB,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEhD,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC7D,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAIxB,SAAS,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../src/components/truncate/component.tsx"],"names":[],"mappings":"AACA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAK9E,OAAO,aAAa,CAAC;AAErB,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEhD,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC7D,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAIxB,SAAS,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACvD;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CAChD;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAiM5C,CAAC"}
|
|
@@ -1,112 +1,121 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
import { useRef as
|
|
4
|
-
import { calculateAvailableHeight as
|
|
2
|
+
import { jsx as C } from "react/jsx-runtime";
|
|
3
|
+
import { useRef as A, useState as F, useCallback as p, useLayoutEffect as R } from "react";
|
|
4
|
+
import { calculateAvailableHeight as k, getMiddleTruncatedString as q } from "./helpers.js";
|
|
5
5
|
import { useOverflowDetection as g } from "./useOverflowDetection.js";
|
|
6
6
|
import './style.css';/* empty css */
|
|
7
|
-
import { useCls as
|
|
8
|
-
import { clsx as
|
|
9
|
-
const
|
|
7
|
+
import { useCls as B } from "../utils/antdUtils.js";
|
|
8
|
+
import { clsx as j } from "../utils/cn.js";
|
|
9
|
+
const Q = ({
|
|
10
10
|
children: w,
|
|
11
11
|
position: i = "end",
|
|
12
12
|
lines: e = 1,
|
|
13
|
-
className:
|
|
14
|
-
style:
|
|
13
|
+
className: O,
|
|
14
|
+
style: v,
|
|
15
15
|
container: o,
|
|
16
|
-
|
|
16
|
+
renderText: d,
|
|
17
|
+
...S
|
|
17
18
|
}) => {
|
|
18
|
-
const
|
|
19
|
+
const f = B(), l = A(null), [m, y] = F(w), a = w, x = g({
|
|
19
20
|
container: l,
|
|
20
21
|
additionalElements: [l.current?.parentElement].filter(Boolean),
|
|
21
22
|
type: "vertical",
|
|
22
|
-
text:
|
|
23
|
+
text: a,
|
|
23
24
|
enabled: e === "auto"
|
|
24
|
-
}),
|
|
25
|
+
}), E = g({
|
|
25
26
|
container: l,
|
|
26
27
|
type: "vertical",
|
|
27
|
-
text:
|
|
28
|
+
text: a,
|
|
28
29
|
enabled: typeof e == "number" && e > 1
|
|
29
|
-
}),
|
|
30
|
+
}), H = g({
|
|
30
31
|
container: l,
|
|
31
32
|
type: "horizontal",
|
|
32
33
|
enabled: i === "end" && e === 1
|
|
33
|
-
}),
|
|
34
|
-
...
|
|
34
|
+
}), M = e === "auto" && x.isOverflowing || typeof e == "number" && e > 1 && E.isOverflowing || i === "end" && e === 1 && H.isOverflowing || i === "middle" && a !== m, L = p(() => e !== "auto" ? {
|
|
35
|
+
...v,
|
|
35
36
|
...e > 1 ? { "--ds-line-clamp": e } : {}
|
|
36
37
|
} : {
|
|
37
|
-
...
|
|
38
|
+
...v,
|
|
38
39
|
// Set a temporary high value to ensure it fits the parent
|
|
39
40
|
"--ds-line-clamp": 999
|
|
40
|
-
}, [e,
|
|
41
|
+
}, [e, v]), b = p(() => {
|
|
41
42
|
const t = l.current;
|
|
42
43
|
if (!t) return;
|
|
43
|
-
const n = window.getComputedStyle(t),
|
|
44
|
-
t.style.setProperty("--ds-line-clamp", String(
|
|
45
|
-
}, [
|
|
46
|
-
(t, n,
|
|
44
|
+
const n = window.getComputedStyle(t), r = parseFloat(n.fontSize), u = n.lineHeight === "normal" ? r * 1.2 : parseFloat(n.lineHeight), c = k(t), s = Math.max(1, Math.floor(c / u));
|
|
45
|
+
t.style.setProperty("--ds-line-clamp", String(s));
|
|
46
|
+
}, []), h = p(
|
|
47
|
+
(t, n, r) => {
|
|
47
48
|
const u = t.filter(Boolean);
|
|
48
49
|
if (u.length === 0) return;
|
|
49
50
|
window.document.fonts?.ready?.then(n);
|
|
50
51
|
const c = new ResizeObserver(() => {
|
|
51
52
|
window.requestAnimationFrame(n);
|
|
52
53
|
});
|
|
53
|
-
return u.forEach((
|
|
54
|
-
c.disconnect(),
|
|
54
|
+
return u.forEach((s) => c.observe(s)), () => {
|
|
55
|
+
c.disconnect(), r && r();
|
|
55
56
|
};
|
|
56
57
|
},
|
|
57
58
|
[]
|
|
58
59
|
);
|
|
59
|
-
|
|
60
|
+
R(() => {
|
|
60
61
|
const t = l.current;
|
|
61
62
|
let n = o instanceof HTMLElement ? o : o && "current" in o ? o.current : null;
|
|
62
63
|
if (t && (n || (n = t.closest("[data-truncate-container]")), !(typeof o < "u" && !n))) {
|
|
63
|
-
if (
|
|
64
|
-
return
|
|
64
|
+
if (y(a), e === "auto")
|
|
65
|
+
return h(
|
|
65
66
|
[t, t.parentElement],
|
|
66
|
-
|
|
67
|
+
b
|
|
67
68
|
);
|
|
68
69
|
if (i === "middle") {
|
|
69
|
-
let
|
|
70
|
-
return
|
|
70
|
+
let r = { cancelled: !1 };
|
|
71
|
+
return h(
|
|
71
72
|
[n || t],
|
|
72
73
|
() => {
|
|
73
|
-
|
|
74
|
+
r && (r.cancelled = !0);
|
|
74
75
|
const c = { cancelled: !1 };
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
76
|
+
r = c;
|
|
77
|
+
const s = q(
|
|
78
|
+
a,
|
|
79
|
+
"…",
|
|
80
|
+
t,
|
|
81
|
+
d
|
|
82
|
+
);
|
|
83
|
+
c.cancelled || y(s);
|
|
78
84
|
},
|
|
79
85
|
() => {
|
|
80
|
-
|
|
86
|
+
r.cancelled = !0;
|
|
81
87
|
}
|
|
82
88
|
);
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
}, [
|
|
86
|
-
|
|
92
|
+
a,
|
|
87
93
|
i,
|
|
88
94
|
e,
|
|
89
95
|
o,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
b,
|
|
97
|
+
h,
|
|
98
|
+
d
|
|
99
|
+
]);
|
|
100
|
+
const T = d ? d(m) : m, z = a !== m;
|
|
101
|
+
return /* @__PURE__ */ C(
|
|
93
102
|
"span",
|
|
94
103
|
{
|
|
95
104
|
ref: l,
|
|
96
|
-
style:
|
|
97
|
-
className:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
style: L(),
|
|
106
|
+
className: j(
|
|
107
|
+
f(e === 1 ? "truncate" : "truncate-multiline"),
|
|
108
|
+
f(i === "middle" ? "truncate-middle" : "truncate-end"),
|
|
109
|
+
O
|
|
101
110
|
),
|
|
102
|
-
title:
|
|
111
|
+
title: M ? a : void 0,
|
|
103
112
|
"data-truncate-text-node": !0,
|
|
104
|
-
...
|
|
105
|
-
children:
|
|
113
|
+
...S,
|
|
114
|
+
children: z ? /* @__PURE__ */ C("span", { children: T }) : T
|
|
106
115
|
}
|
|
107
116
|
);
|
|
108
117
|
};
|
|
109
118
|
export {
|
|
110
|
-
|
|
119
|
+
Q as Truncate
|
|
111
120
|
};
|
|
112
121
|
//# sourceMappingURL=component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","sources":["../../../src/components/truncate/component.tsx"],"sourcesContent":["\"use client\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport { clsx, useCls } from \"../utils\";\nimport { calculateAvailableHeight, getMiddleTruncatedString } from \"./helpers\";\nimport { useOverflowDetection } from \"./useOverflowDetection\";\n\nimport \"./style.css\";\n\nexport type TruncatePosition = \"middle\" | \"end\";\n\nexport interface TruncateProps\n extends Omit<React.ComponentPropsWithoutRef<\"span\">, \"title\"> {\n /** Text content to be truncated */\n children: string;\n /** Position where the truncation should occur */\n position?: TruncatePosition;\n /**\n * Number of lines to display before truncating\n * @default 1\n * @remarks Use 'auto' to fit parent height\n */\n lines?: number | \"auto\";\n /*\n * Ref to the container element of the truncated text. It will have resize observer attached to it.\n */\n container?: HTMLElement | React.RefObject<HTMLElement>;\n}\n\nexport const Truncate: React.FC<TruncateProps> = ({\n children,\n position = \"end\",\n lines = 1,\n className,\n style,\n container: containerProp,\n ...rest\n}) => {\n const cls = useCls();\n const containerRef = useRef<HTMLElement>(null);\n const [truncatedText, setTruncatedText] = useState(children);\n\n const text = children;\n\n // Overflow detection for different scenarios\n const autoLineOverflow = useOverflowDetection({\n container: containerRef,\n additionalElements: [containerRef.current?.parentElement].filter(Boolean),\n type: \"vertical\",\n text,\n enabled: lines === \"auto\",\n });\n\n const multilineOverflow = useOverflowDetection({\n container: containerRef,\n type: \"vertical\",\n text,\n enabled: typeof lines === \"number\" && lines > 1,\n });\n\n const endTruncateOverflow = useOverflowDetection({\n container: containerRef,\n type: \"horizontal\",\n enabled: position === \"end\" && lines === 1,\n });\n\n // Determine if content is truncated based on the active mode\n const isTruncated =\n (lines === \"auto\" && autoLineOverflow.isOverflowing) ||\n (typeof lines === \"number\" &&\n lines > 1 &&\n multilineOverflow.isOverflowing) ||\n (position === \"end\" && lines === 1 && endTruncateOverflow.isOverflowing) ||\n (position === \"middle\" && text !== truncatedText);\n\n // Get appropriate container styles based on position and lines\n const getContainerStyles = useCallback(() => {\n // For explicit line numbers or single line\n if (lines !== \"auto\") {\n return {\n ...style,\n ...(lines > 1 ? { \"--ds-line-clamp\": lines } : {}),\n } as React.CSSProperties;\n }\n\n // For auto line calculation, we'll let the useLayoutEffect handle it\n return {\n ...style,\n // Set a temporary high value to ensure it fits the parent\n \"--ds-line-clamp\": 999,\n } as React.CSSProperties;\n }, [lines, style]);\n\n // Handle auto line calculation\n const handleAutoLineCalculation = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const styles = window.getComputedStyle(container);\n const fontSize = parseFloat(styles.fontSize);\n const lineHeight =\n styles.lineHeight === \"normal\"\n ? fontSize * 1.2\n : parseFloat(styles.lineHeight);\n\n const availableHeight = calculateAvailableHeight(container);\n const maxLines = Math.max(1, Math.floor(availableHeight / lineHeight));\n\n container.style.setProperty(\"--ds-line-clamp\", String(maxLines));\n }, [text]);\n\n const observe = useCallback(\n (\n elements: (HTMLElement | null)[],\n callback: () => void,\n cleanup?: () => void\n ) => {\n const validElements = elements.filter(Boolean) as HTMLElement[];\n if (validElements.length === 0) return;\n\n window.document.fonts?.ready?.then(callback);\n\n const observer = new ResizeObserver(() => {\n window.requestAnimationFrame(callback);\n });\n\n validElements.forEach((el) => observer.observe(el));\n return () => {\n observer.disconnect();\n if (cleanup) cleanup();\n };\n },\n []\n );\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n let flexContainer =\n containerProp instanceof HTMLElement\n ? containerProp\n : containerProp && \"current\" in containerProp\n ? containerProp.current\n : null;\n if (!container) return;\n if (!flexContainer) {\n flexContainer = container.closest(\"[data-truncate-container]\");\n }\n if (typeof containerProp !== \"undefined\" && !flexContainer) return;\n\n // reset\n setTruncatedText(text);\n\n // Handle auto-height calculation\n if (lines === \"auto\") {\n return observe(\n [container, container.parentElement],\n handleAutoLineCalculation\n );\n }\n\n // Handle middle truncation with resize observer\n if (position === \"middle\") {\n let cancellationToken = { cancelled: false };\n\n const handleMiddleTruncate = () => {\n if (cancellationToken) cancellationToken.cancelled = true;\n\n const requestCancellationToken = { cancelled: false };\n cancellationToken = requestCancellationToken;\n\n const truncated = getMiddleTruncatedString(text, \"\\u2026\", container);\n\n if (requestCancellationToken.cancelled) return;\n\n setTruncatedText(truncated);\n };\n\n return observe(\n [flexContainer ? flexContainer : container],\n handleMiddleTruncate,\n () => {\n cancellationToken.cancelled = true;\n }\n );\n }\n }, [\n text,\n position,\n lines,\n containerProp,\n handleAutoLineCalculation,\n observe,\n ]);\n\n return (\n <span\n ref={containerRef}\n style={getContainerStyles()}\n className={clsx(\n lines === 1 ? cls(\"truncate\") : cls(\"truncate-multiline\"),\n position === \"middle\" ? cls(\"truncate-middle\") : cls(\"truncate-end\"),\n className\n )}\n title={isTruncated ? text : undefined}\n data-truncate-text-node\n {...rest}\n >\n {text === truncatedText ? text : <span>{truncatedText}</span>}\n </span>\n );\n};\n"],"names":["Truncate","children","position","lines","className","style","containerProp","rest","cls","useCls","containerRef","useRef","truncatedText","setTruncatedText","useState","text","autoLineOverflow","useOverflowDetection","multilineOverflow","endTruncateOverflow","isTruncated","getContainerStyles","useCallback","handleAutoLineCalculation","container","styles","fontSize","lineHeight","availableHeight","calculateAvailableHeight","maxLines","observe","elements","callback","cleanup","validElements","observer","el","useLayoutEffect","flexContainer","cancellationToken","requestCancellationToken","truncated","getMiddleTruncatedString","jsx","clsx"],"mappings":";;;;;;;;AA4BO,MAAMA,IAAoC,CAAC;AAAA,EAChD,UAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,OAAAC,IAAQ;AAAA,EACR,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,WAAWC;AAAA,EACX,GAAGC;AACL,MAAM;AACJ,QAAMC,IAAMC,EAAA,GACNC,IAAeC,EAAoB,IAAI,GACvC,CAACC,GAAeC,CAAgB,IAAIC,EAASb,CAAQ,GAErDc,IAAOd,GAGPe,IAAmBC,EAAqB;AAAA,IAC5C,WAAWP;AAAA,IACX,oBAAoB,CAACA,EAAa,SAAS,aAAa,EAAE,OAAO,OAAO;AAAA,IACxE,MAAM;AAAA,IACN,MAAAK;AAAA,IACA,SAASZ,MAAU;AAAA,EAAA,CACpB,GAEKe,IAAoBD,EAAqB;AAAA,IAC7C,WAAWP;AAAA,IACX,MAAM;AAAA,IACN,MAAAK;AAAA,IACA,SAAS,OAAOZ,KAAU,YAAYA,IAAQ;AAAA,EAAA,CAC/C,GAEKgB,IAAsBF,EAAqB;AAAA,IAC/C,WAAWP;AAAA,IACX,MAAM;AAAA,IACN,SAASR,MAAa,SAASC,MAAU;AAAA,EAAA,CAC1C,GAGKiB,IACHjB,MAAU,UAAUa,EAAiB,iBACrC,OAAOb,KAAU,YAChBA,IAAQ,KACRe,EAAkB,iBACnBhB,MAAa,SAASC,MAAU,KAAKgB,EAAoB,iBACzDjB,MAAa,YAAYa,MAASH,GAG/BS,IAAqBC,EAAY,MAEjCnB,MAAU,SACL;AAAA,IACL,GAAGE;AAAA,IACH,GAAIF,IAAQ,IAAI,EAAE,mBAAmBA,EAAA,IAAU,CAAA;AAAA,EAAC,IAK7C;AAAA,IACL,GAAGE;AAAA;AAAA,IAEH,mBAAmB;AAAA,EAAA,GAEpB,CAACF,GAAOE,CAAK,CAAC,GAGXkB,IAA4BD,EAAY,MAAM;AAClD,UAAME,IAAYd,EAAa;AAC/B,QAAI,CAACc,EAAW;AAEhB,UAAMC,IAAS,OAAO,iBAAiBD,CAAS,GAC1CE,IAAW,WAAWD,EAAO,QAAQ,GACrCE,IACJF,EAAO,eAAe,WAClBC,IAAW,MACX,WAAWD,EAAO,UAAU,GAE5BG,IAAkBC,EAAyBL,CAAS,GACpDM,IAAW,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAkBD,CAAU,CAAC;AAErE,IAAAH,EAAU,MAAM,YAAY,mBAAmB,OAAOM,CAAQ,CAAC;AAAA,EACjE,GAAG,CAACf,CAAI,CAAC,GAEHgB,IAAUT;AAAA,IACd,CACEU,GACAC,GACAC,MACG;AACH,YAAMC,IAAgBH,EAAS,OAAO,OAAO;AAC7C,UAAIG,EAAc,WAAW,EAAG;AAEhC,aAAO,SAAS,OAAO,OAAO,KAAKF,CAAQ;AAE3C,YAAMG,IAAW,IAAI,eAAe,MAAM;AACxC,eAAO,sBAAsBH,CAAQ;AAAA,MACvC,CAAC;AAED,aAAAE,EAAc,QAAQ,CAACE,MAAOD,EAAS,QAAQC,CAAE,CAAC,GAC3C,MAAM;AACX,QAAAD,EAAS,WAAA,GACLF,KAASA,EAAA;AAAA,MACf;AAAA,IACF;AAAA,IACA,CAAA;AAAA,EAAC;AAGH,SAAAI,EAAgB,MAAM;AACpB,UAAMd,IAAYd,EAAa;AAC/B,QAAI6B,IACFjC,aAAyB,cACrBA,IACAA,KAAiB,aAAaA,IAC9BA,EAAc,UACd;AACN,QAAKkB,MACAe,MACHA,IAAgBf,EAAU,QAAQ,2BAA2B,IAE3D,SAAOlB,IAAkB,OAAe,CAACiC,KAM7C;AAAA,UAHA1B,EAAiBE,CAAI,GAGjBZ,MAAU;AACZ,eAAO4B;AAAA,UACL,CAACP,GAAWA,EAAU,aAAa;AAAA,UACnCD;AAAA,QAAA;AAKJ,UAAIrB,MAAa,UAAU;AACzB,YAAIsC,IAAoB,EAAE,WAAW,GAAA;AAerC,eAAOT;AAAA,UACL,CAACQ,KAAgCf,CAAS;AAAA,UAdf,MAAM;AACjC,YAAIgB,QAAqC,YAAY;AAErD,kBAAMC,IAA2B,EAAE,WAAW,GAAA;AAC9C,YAAAD,IAAoBC;AAEpB,kBAAMC,IAAYC,EAAyB5B,GAAM,KAAUS,CAAS;AAEpE,YAAIiB,EAAyB,aAE7B5B,EAAiB6B,CAAS;AAAA,UAC5B;AAAA,UAKE,MAAM;AACJ,YAAAF,EAAkB,YAAY;AAAA,UAChC;AAAA,QAAA;AAAA,MAEJ;AAAA;AAAA,EACF,GAAG;AAAA,IACDzB;AAAA,IACAb;AAAA,IACAC;AAAA,IACAG;AAAA,IACAiB;AAAA,IACAQ;AAAA,EAAA,CACD,GAGC,gBAAAa;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKlC;AAAA,MACL,OAAOW,EAAA;AAAA,MACP,WAAWwB;AAAA,QACKrC,EAAdL,MAAU,IAAQ,aAAkB,oBAAR;AAAA,QACJK,EAAxBN,MAAa,WAAe,oBAAyB,cAAR;AAAA,QAC7CE;AAAA,MAAA;AAAA,MAEF,OAAOgB,IAAcL,IAAO;AAAA,MAC5B,2BAAuB;AAAA,MACtB,GAAGR;AAAA,MAEH,UAAAQ,MAASH,IAAgBG,IAAO,gBAAA6B,EAAC,UAAM,UAAAhC,EAAA,CAAc;AAAA,IAAA;AAAA,EAAA;AAG5D;"}
|
|
1
|
+
{"version":3,"file":"component.js","sources":["../../../src/components/truncate/component.tsx"],"sourcesContent":["\"use client\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport { clsx, useCls } from \"../utils\";\nimport { calculateAvailableHeight, getMiddleTruncatedString } from \"./helpers\";\nimport { useOverflowDetection } from \"./useOverflowDetection\";\n\nimport \"./style.css\";\n\nexport type TruncatePosition = \"middle\" | \"end\";\n\nexport interface TruncateProps\n extends Omit<React.ComponentPropsWithoutRef<\"span\">, \"title\"> {\n /** Text content to be truncated */\n children: string;\n /** Position where the truncation should occur */\n position?: TruncatePosition;\n /**\n * Number of lines to display before truncating\n * @default 1\n * @remarks Use 'auto' to fit parent height\n */\n lines?: number | \"auto\";\n /*\n * Ref to the container element of the truncated text. It will have resize observer attached to it.\n */\n container?: HTMLElement | React.RefObject<HTMLElement>;\n /**\n * Custom render function to transform text before display\n * Useful for keyword highlighting, text transformations, etc.\n * @param text - The text to render (may be truncated)\n * @returns React node to render\n */\n renderText?: (text: string) => React.ReactNode;\n}\n\nexport const Truncate: React.FC<TruncateProps> = ({\n children,\n position = \"end\",\n lines = 1,\n className,\n style,\n container: containerProp,\n renderText,\n ...rest\n}) => {\n const cls = useCls();\n const containerRef = useRef<HTMLElement>(null);\n const [truncatedText, setTruncatedText] = useState(children);\n\n const text = children;\n\n // Overflow detection for different scenarios\n const autoLineOverflow = useOverflowDetection({\n container: containerRef,\n additionalElements: [containerRef.current?.parentElement].filter(Boolean),\n type: \"vertical\",\n text,\n enabled: lines === \"auto\",\n });\n\n const multilineOverflow = useOverflowDetection({\n container: containerRef,\n type: \"vertical\",\n text,\n enabled: typeof lines === \"number\" && lines > 1,\n });\n\n const endTruncateOverflow = useOverflowDetection({\n container: containerRef,\n type: \"horizontal\",\n enabled: position === \"end\" && lines === 1,\n });\n\n // Determine if content is truncated based on the active mode\n const isTruncated =\n (lines === \"auto\" && autoLineOverflow.isOverflowing) ||\n (typeof lines === \"number\" &&\n lines > 1 &&\n multilineOverflow.isOverflowing) ||\n (position === \"end\" && lines === 1 && endTruncateOverflow.isOverflowing) ||\n (position === \"middle\" && text !== truncatedText);\n\n // Get appropriate container styles based on position and lines\n const getContainerStyles = useCallback(() => {\n // For explicit line numbers or single line\n if (lines !== \"auto\") {\n return {\n ...style,\n ...(lines > 1 ? { \"--ds-line-clamp\": lines } : {}),\n } as React.CSSProperties;\n }\n\n // For auto line calculation, we'll let the useLayoutEffect handle it\n return {\n ...style,\n // Set a temporary high value to ensure it fits the parent\n \"--ds-line-clamp\": 999,\n } as React.CSSProperties;\n }, [lines, style]);\n\n // Handle auto line calculation\n const handleAutoLineCalculation = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const styles = window.getComputedStyle(container);\n const fontSize = parseFloat(styles.fontSize);\n const lineHeight =\n styles.lineHeight === \"normal\"\n ? fontSize * 1.2\n : parseFloat(styles.lineHeight);\n\n const availableHeight = calculateAvailableHeight(container);\n const maxLines = Math.max(1, Math.floor(availableHeight / lineHeight));\n\n container.style.setProperty(\"--ds-line-clamp\", String(maxLines));\n }, []);\n\n const observe = useCallback(\n (\n elements: (HTMLElement | null)[],\n callback: () => void,\n cleanup?: () => void\n ) => {\n const validElements = elements.filter(Boolean) as HTMLElement[];\n if (validElements.length === 0) return;\n\n window.document.fonts?.ready?.then(callback);\n\n const observer = new ResizeObserver(() => {\n window.requestAnimationFrame(callback);\n });\n\n validElements.forEach((el) => observer.observe(el));\n return () => {\n observer.disconnect();\n if (cleanup) cleanup();\n };\n },\n []\n );\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n let flexContainer =\n containerProp instanceof HTMLElement\n ? containerProp\n : containerProp && \"current\" in containerProp\n ? containerProp.current\n : null;\n if (!container) return;\n if (!flexContainer) {\n flexContainer = container.closest(\"[data-truncate-container]\");\n }\n if (typeof containerProp !== \"undefined\" && !flexContainer) return;\n\n // reset\n setTruncatedText(text);\n\n // Handle auto-height calculation\n if (lines === \"auto\") {\n return observe(\n [container, container.parentElement],\n handleAutoLineCalculation\n );\n }\n\n // Handle middle truncation with resize observer\n if (position === \"middle\") {\n let cancellationToken = { cancelled: false };\n\n const handleMiddleTruncate = () => {\n if (cancellationToken) cancellationToken.cancelled = true;\n\n const requestCancellationToken = { cancelled: false };\n cancellationToken = requestCancellationToken;\n\n // Pass renderText function for styled content measurement\n const truncated = getMiddleTruncatedString(\n text,\n \"\\u2026\",\n container,\n renderText\n );\n\n if (requestCancellationToken.cancelled) return;\n\n setTruncatedText(truncated);\n };\n\n return observe(\n [flexContainer ? flexContainer : container],\n handleMiddleTruncate,\n () => {\n cancellationToken.cancelled = true;\n }\n );\n }\n }, [\n text,\n position,\n lines,\n containerProp,\n handleAutoLineCalculation,\n observe,\n renderText,\n ]);\n\n // Determine content to display\n const displayContent = renderText ? renderText(truncatedText) : truncatedText;\n const shouldWrapInSpan = text !== truncatedText;\n\n return (\n <span\n ref={containerRef}\n style={getContainerStyles()}\n className={clsx(\n lines === 1 ? cls(\"truncate\") : cls(\"truncate-multiline\"),\n position === \"middle\" ? cls(\"truncate-middle\") : cls(\"truncate-end\"),\n className\n )}\n title={isTruncated ? text : undefined}\n data-truncate-text-node\n {...rest}\n >\n {shouldWrapInSpan ? <span>{displayContent}</span> : displayContent}\n </span>\n );\n};\n"],"names":["Truncate","children","position","lines","className","style","containerProp","renderText","rest","cls","useCls","containerRef","useRef","truncatedText","setTruncatedText","useState","text","autoLineOverflow","useOverflowDetection","multilineOverflow","endTruncateOverflow","isTruncated","getContainerStyles","useCallback","handleAutoLineCalculation","container","styles","fontSize","lineHeight","availableHeight","calculateAvailableHeight","maxLines","observe","elements","callback","cleanup","validElements","observer","el","useLayoutEffect","flexContainer","cancellationToken","requestCancellationToken","truncated","getMiddleTruncatedString","displayContent","shouldWrapInSpan","jsx","clsx"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
1
2
|
/**
|
|
2
3
|
* Finds the closest parent element that has inline flex display
|
|
3
4
|
* @param element - The starting HTMLElement
|
|
@@ -5,11 +6,16 @@
|
|
|
5
6
|
*/
|
|
6
7
|
export declare function findClosestInlineFlexParent(element: HTMLElement): HTMLElement | null;
|
|
7
8
|
export declare function getFlexRemainingSpace(flexContainer: HTMLElement, ignoreElement?: HTMLElement | ((e: HTMLElement) => boolean)): number;
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Measures text width with optional render function for styled content
|
|
11
|
+
* @param container - The container element to clone styles from
|
|
12
|
+
* @param renderText - Optional render function to apply styling to text before measurement
|
|
13
|
+
*/
|
|
14
|
+
export declare const measureText: (container: HTMLElement, renderText?: ((text: string) => React.ReactNode) | null) => {
|
|
9
15
|
measure: (text: string) => number;
|
|
10
16
|
destroy: () => void;
|
|
11
17
|
};
|
|
12
|
-
export declare const getMiddleTruncatedString: (text: string, ellipsis: string, container: HTMLElement) => string;
|
|
18
|
+
export declare const getMiddleTruncatedString: (text: string, ellipsis: string, container: HTMLElement, renderText?: ((text: string) => React.ReactNode) | null) => string;
|
|
13
19
|
export declare const createMeasurementClone: (text: string, container: HTMLElement) => HTMLSpanElement;
|
|
14
20
|
export declare const checkIfTextTruncated: (text: string, container: HTMLElement, availableHeight?: number) => boolean;
|
|
15
21
|
export declare const calculateAvailableHeight: (container: HTMLElement) => number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/components/truncate/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,WAAW,GACnB,WAAW,GAAG,IAAI,CAqBpB;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,WAAW,EAC1B,aAAa,GAAE,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,OAAO,CAAQ,UA2ClE;
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/components/truncate/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,WAAW,GACnB,WAAW,GAAG,IAAI,CAqBpB;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,WAAW,EAC1B,aAAa,GAAE,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,OAAO,CAAQ,UA2ClE;AAKD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACtB,WAAW,WAAW,EACtB,aAAa,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI;oBAwBrC,MAAM;;CA0DzB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,WAAW,WAAW,EACtB,aAAa,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,KACtD,MAgEF,CAAC;AAGF,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,WAAW,WAAW,oBAavB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,EACZ,WAAW,WAAW,EACtB,kBAAkB,MAAM,YAQzB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,WAAW,WAAW,WAiB9D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,WAAW,WAAW,WAiB7D,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,uBAAuB,GAAI,WAAW,WAAW,KAAG,OAEhE,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,WAAW,WAAW,EACtB,kBAAkB,MAAM,KACvB,OAGF,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,WAAW,WAAW,EACtB,UAAS,oBAAyB,KACjC,OAyCF,CAAC"}
|