@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.
Files changed (35) hide show
  1. package/dist/components/button/component.d.ts +1 -1
  2. package/dist/components/button/component.d.ts.map +1 -1
  3. package/dist/components/button/component.js +42 -35
  4. package/dist/components/button/component.js.map +1 -1
  5. package/dist/components/button/style.css +1 -1
  6. package/dist/components/data-table/component.d.ts.map +1 -1
  7. package/dist/components/data-table/component.js +76 -71
  8. package/dist/components/data-table/component.js.map +1 -1
  9. package/dist/components/data-table/components/TablePagination.d.ts +1 -1
  10. package/dist/components/data-table/components/TablePagination.d.ts.map +1 -1
  11. package/dist/components/data-table/components/TablePagination.js +26 -23
  12. package/dist/components/data-table/components/TablePagination.js.map +1 -1
  13. package/dist/components/data-table/hooks.d.ts.map +1 -1
  14. package/dist/components/data-table/hooks.js +82 -82
  15. package/dist/components/data-table/hooks.js.map +1 -1
  16. package/dist/components/data-table/style.css +1 -1
  17. package/dist/components/empty/component.d.ts +0 -2
  18. package/dist/components/empty/component.d.ts.map +1 -1
  19. package/dist/components/empty/component.js +14 -35
  20. package/dist/components/empty/component.js.map +1 -1
  21. package/dist/components/empty/style.css +1 -1
  22. package/dist/components/modal/Modal.d.ts.map +1 -1
  23. package/dist/components/modal/Modal.js +105 -102
  24. package/dist/components/modal/Modal.js.map +1 -1
  25. package/dist/components/truncate/component.d.ts +7 -0
  26. package/dist/components/truncate/component.d.ts.map +1 -1
  27. package/dist/components/truncate/component.js +57 -48
  28. package/dist/components/truncate/component.js.map +1 -1
  29. package/dist/components/truncate/helpers.d.ts +8 -2
  30. package/dist/components/truncate/helpers.d.ts.map +1 -1
  31. package/dist/components/truncate/helpers.js +82 -54
  32. package/dist/components/truncate/helpers.js.map +1 -1
  33. package/dist/index.js +126 -127
  34. package/dist/stats.html +1 -1
  35. package/package.json +1 -1
@@ -1,60 +1,60 @@
1
1
  "use client";
2
- import { jsx as e, jsxs as a, Fragment as T } from "react/jsx-runtime";
3
- import ue from "antd/es/modal";
4
- import { XIcon as pe } from "@bioturing/assets";
5
- import { useState as H, useRef as he, useCallback as ye, useEffect as be } from "react";
6
- import { ModalContextProvider as ge } from "antd/es/modal/context";
7
- import R from "antd/es/modal/components/NormalCancelBtn";
8
- import L from "antd/es/modal/components/NormalOkBtn";
9
- import { getConfirmLocale as ve } from "antd/es/modal/locale";
10
- import { useLocale as Ce } from "antd/es/locale";
11
- import { ModalSize as c } from "./constants.js";
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 ke } from "../truncate/component.js";
14
- import { IconButton as we } from "../icon-button/component.js";
15
- import { useCls as xe } from "../utils/antdUtils.js";
16
- import { useTheme as Oe } from "../theme-provider/context/themeStore.js";
17
- import { clsx as ze } from "../utils/cn.js";
18
- const Ge = ({
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: j,
22
- size: E,
21
+ children: F,
22
+ size: L,
23
23
  footer: h,
24
- width: F,
25
- style: P,
24
+ width: P,
25
+ style: W,
26
26
  styles: y,
27
- classNames: W,
28
- okButtonProps: $,
29
- cancelButtonProps: q,
30
- loading: A,
27
+ classNames: $,
28
+ okButtonProps: q,
29
+ cancelButtonProps: A,
30
+ loading: X,
31
31
  onOk: b,
32
- onCancel: m,
33
- okText: g,
34
- okType: X = "primary",
35
- confirmLoading: v,
36
- cancelText: C = "Close",
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: D,
43
- afterCloseButton: G,
44
- defaultFixedHeaderFooter: J = !1,
45
- centered: K = !0,
46
- type: Q = "default",
47
- defaultOpen: U = !0,
48
- background: V,
49
- bodyScrollable: Y = !0,
50
- rootClassName: Z,
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 ee = p === void 0 ? /* @__PURE__ */ e(pe, { size: 16, weight: "bold" }) : p, t = E || (Q === "default" ? "medium" : "xsmall"), oe = F || c[t], re = {
54
- "--ds-modal-bg": `var(--ds-color-bg-${V || (t in c && parseInt(c[t]) <= parseInt(c.medium) ? "elevated" : "container")})`,
55
- ...P,
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
- }, te = {
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] = H(!1), n = xe(), { className: le } = Oe(), s = he(null), ne = ye(
66
- (o) => {
67
- if (!o) return;
68
- const l = o.querySelector("." + n("modal-body"));
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 S = new ResizeObserver(() => {
71
- const fe = l.scrollHeight > l.clientHeight;
72
- z(fe);
70
+ const T = new ResizeObserver(() => {
71
+ const ue = l.scrollHeight > l.clientHeight;
72
+ z(ue);
73
73
  });
74
- s.current = S, S.observe(l);
75
- const de = l.scrollHeight > l.clientHeight;
76
- z(de);
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
- be(() => () => {
81
- s.current && (s.current.disconnect(), s.current = null);
80
+ Ce(() => () => {
81
+ a.current && (a.current.disconnect(), a.current = null);
82
82
  }, []);
83
- const [B] = Ce("Modal", ve()), se = g || B?.okText, ae = C || B?.cancelText, I = {
84
- loading: A,
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
- }, [ce, N] = H(U), d = typeof u > "u", me = d ? ce : u, ie = /* @__PURE__ */ e(
89
- ge,
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: m,
96
+ onCancel: S,
95
97
  onOk: b,
96
- okType: X,
97
- confirmLoading: v,
98
- okTextLocale: se,
99
- cancelTextLocale: ae
98
+ okType: D,
99
+ confirmLoading: s,
100
+ okTextLocale: ae,
101
+ cancelTextLocale: ce
100
102
  },
101
- children: k ? /* @__PURE__ */ e(R, {}) : w ? /* @__PURE__ */ e(L, {}) : /* @__PURE__ */ a(T, { children: [
102
- /* @__PURE__ */ e(R, {}),
103
- /* @__PURE__ */ e(L, {})
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__ */ e(
108
- ue,
109
+ return /* @__PURE__ */ o(
110
+ pe,
109
111
  {
110
112
  closeIcon: !1,
111
- open: me,
112
- width: oe,
113
- style: re,
114
- title: /* @__PURE__ */ a(T, { children: [
115
- /* @__PURE__ */ a(f, { align: "center", gap: 8, className: n("modal-title-wrapper"), children: [
116
- /* @__PURE__ */ e(f.Child, { grow: !0, children: typeof i == "string" ? /* @__PURE__ */ e(ke, { children: i }) : i }),
117
- /* @__PURE__ */ a(f.Child, { stack: !0, hug: !0, align: "center", gap: 8, children: [
118
- D,
119
- /* @__PURE__ */ e(
120
- we,
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: (o) => m?.(o),
123
- children: ee
124
+ onClick: (e) => S(e),
125
+ children: oe
124
126
  }
125
127
  ),
126
- G
128
+ J
127
129
  ] })
128
130
  ] }),
129
131
  x || null
130
132
  ] }),
131
- rootClassName: ze(le, Z),
133
+ rootClassName: Be(ne, _),
132
134
  classNames: {
133
- ...W,
135
+ ...$,
134
136
  wrapper: n(
135
137
  "modal-wrap",
136
138
  t == "fullscreen" && "modal-fullscreen",
137
139
  O && "modal-content-overflow",
138
- Y === !1 && "modal-no-body-scroll",
139
- J || O || t == "fullscreen" ? "modal-fixed" : ""
140
+ Z === !1 && "modal-no-body-scroll",
141
+ K || O || t == "fullscreen" ? "modal-fixed" : ""
140
142
  )
141
143
  },
142
- styles: te,
143
- modalRender: (o) => /* @__PURE__ */ e("div", { ref: ne, className: n("modal-inner"), children: o }),
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: (o) => {
147
- d && N(!1), b?.(o);
148
+ onOk: (e) => {
149
+ d && N(!1), b?.(e);
148
150
  },
149
- onCancel: (o) => {
150
- d && N(!1), m?.(o);
151
+ onCancel: (e) => {
152
+ s || (d && N(!1), C?.(e));
151
153
  },
152
- okText: g,
153
- cancelText: C,
154
+ okText: v,
155
+ cancelText: g,
154
156
  okType: "primary",
155
- confirmLoading: v,
156
- footer: typeof h > "u" ? k && w ? null : ie : h,
157
- centered: K,
158
- ..._,
159
- children: j
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
- Ge as Modal
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;CACxD;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAqL5C,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 T } from "react/jsx-runtime";
3
- import { useRef as M, useState as L, useCallback as h, useLayoutEffect as z } from "react";
4
- import { calculateAvailableHeight as A, getMiddleTruncatedString as F } from "./helpers.js";
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 R } from "../utils/antdUtils.js";
8
- import { clsx as k } from "../utils/cn.js";
9
- const J = ({
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: b,
14
- style: f,
13
+ className: O,
14
+ style: v,
15
15
  container: o,
16
- ...x
16
+ renderText: d,
17
+ ...S
17
18
  }) => {
18
- const s = R(), l = M(null), [m, p] = L(w), r = w, O = g({
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: r,
23
+ text: a,
23
24
  enabled: e === "auto"
24
- }), C = g({
25
+ }), E = g({
25
26
  container: l,
26
27
  type: "vertical",
27
- text: r,
28
+ text: a,
28
29
  enabled: typeof e == "number" && e > 1
29
- }), E = g({
30
+ }), H = g({
30
31
  container: l,
31
32
  type: "horizontal",
32
33
  enabled: i === "end" && e === 1
33
- }), S = e === "auto" && O.isOverflowing || typeof e == "number" && e > 1 && C.isOverflowing || i === "end" && e === 1 && E.isOverflowing || i === "middle" && r !== m, H = h(() => e !== "auto" ? {
34
- ...f,
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
- ...f,
38
+ ...v,
38
39
  // Set a temporary high value to ensure it fits the parent
39
40
  "--ds-line-clamp": 999
40
- }, [e, f]), y = h(() => {
41
+ }, [e, v]), b = p(() => {
41
42
  const t = l.current;
42
43
  if (!t) return;
43
- const n = window.getComputedStyle(t), a = parseFloat(n.fontSize), u = n.lineHeight === "normal" ? a * 1.2 : parseFloat(n.lineHeight), c = A(t), d = Math.max(1, Math.floor(c / u));
44
- t.style.setProperty("--ds-line-clamp", String(d));
45
- }, [r]), v = h(
46
- (t, n, a) => {
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((d) => c.observe(d)), () => {
54
- c.disconnect(), a && a();
54
+ return u.forEach((s) => c.observe(s)), () => {
55
+ c.disconnect(), r && r();
55
56
  };
56
57
  },
57
58
  []
58
59
  );
59
- return z(() => {
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 (p(r), e === "auto")
64
- return v(
64
+ if (y(a), e === "auto")
65
+ return h(
65
66
  [t, t.parentElement],
66
- y
67
+ b
67
68
  );
68
69
  if (i === "middle") {
69
- let a = { cancelled: !1 };
70
- return v(
70
+ let r = { cancelled: !1 };
71
+ return h(
71
72
  [n || t],
72
73
  () => {
73
- a && (a.cancelled = !0);
74
+ r && (r.cancelled = !0);
74
75
  const c = { cancelled: !1 };
75
- a = c;
76
- const d = F(r, "…", t);
77
- c.cancelled || p(d);
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
- a.cancelled = !0;
86
+ r.cancelled = !0;
81
87
  }
82
88
  );
83
89
  }
84
90
  }
85
91
  }, [
86
- r,
92
+ a,
87
93
  i,
88
94
  e,
89
95
  o,
90
- y,
91
- v
92
- ]), /* @__PURE__ */ T(
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: H(),
97
- className: k(
98
- s(e === 1 ? "truncate" : "truncate-multiline"),
99
- s(i === "middle" ? "truncate-middle" : "truncate-end"),
100
- b
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: S ? r : void 0,
111
+ title: M ? a : void 0,
103
112
  "data-truncate-text-node": !0,
104
- ...x,
105
- children: r === m ? r : /* @__PURE__ */ T("span", { children: m })
113
+ ...S,
114
+ children: z ? /* @__PURE__ */ C("span", { children: T }) : T
106
115
  }
107
116
  );
108
117
  };
109
118
  export {
110
- J as Truncate
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":"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"}
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
- export declare const measureText: (container: HTMLElement) => {
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;AAED,eAAO,MAAM,WAAW,GAAI,WAAW,WAAW;oBAuB9B,MAAM;;CASzB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,WAAW,WAAW,KACrB,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"}
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"}