@elliemae/ds-read-more 3.53.0-alpha.1 → 3.53.0-alpha.3

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 (54) hide show
  1. package/dist/cjs/DSReadMore.js +25 -12
  2. package/dist/cjs/DSReadMore.js.map +2 -2
  3. package/dist/cjs/MoreLessButton.js +26 -28
  4. package/dist/cjs/MoreLessButton.js.map +2 -2
  5. package/dist/cjs/{DSReadMoreDefinitions.js → constants/index.js} +13 -8
  6. package/dist/cjs/constants/index.js.map +7 -0
  7. package/dist/cjs/index.js +6 -4
  8. package/dist/cjs/index.js.map +2 -2
  9. package/dist/cjs/react-desc-prop-types.js +3 -2
  10. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  11. package/dist/cjs/styled.js +17 -12
  12. package/dist/cjs/styled.js.map +2 -2
  13. package/dist/cjs/useReadMoreTruncate.js +50 -37
  14. package/dist/cjs/useReadMoreTruncate.js.map +2 -2
  15. package/dist/cjs/utils.js +40 -0
  16. package/dist/cjs/utils.js.map +7 -0
  17. package/dist/esm/DSReadMore.js +23 -10
  18. package/dist/esm/DSReadMore.js.map +2 -2
  19. package/dist/esm/MoreLessButton.js +26 -28
  20. package/dist/esm/MoreLessButton.js.map +2 -2
  21. package/dist/esm/{DSReadMoreDefinitions.js → constants/index.js} +10 -5
  22. package/dist/esm/constants/index.js.map +7 -0
  23. package/dist/esm/index.js +9 -1
  24. package/dist/esm/index.js.map +2 -2
  25. package/dist/esm/react-desc-prop-types.js +3 -1
  26. package/dist/esm/react-desc-prop-types.js.map +2 -2
  27. package/dist/esm/styled.js +15 -10
  28. package/dist/esm/styled.js.map +2 -2
  29. package/dist/esm/useReadMoreTruncate.js +50 -37
  30. package/dist/esm/useReadMoreTruncate.js.map +2 -2
  31. package/dist/esm/utils.js +10 -0
  32. package/dist/esm/utils.js.map +7 -0
  33. package/dist/types/MoreLessButton.d.ts +0 -1
  34. package/dist/types/constants/index.d.ts +33 -0
  35. package/dist/types/index.d.ts +1 -1
  36. package/dist/types/react-desc-prop-types.d.ts +5 -4
  37. package/dist/types/styled.d.ts +8 -5
  38. package/dist/types/tests/DSReadMore.PUI-14965.test.d.ts +1 -0
  39. package/dist/types/tests/DSReadMore.a11y.test.d.ts +1 -0
  40. package/dist/types/tests/DSReadMore.data-testid.test.d.ts +1 -0
  41. package/dist/types/tests/DSReadMore.default-props.test.d.ts +1 -0
  42. package/dist/types/tests/DSReadMore.events.test.d.ts +1 -0
  43. package/dist/types/tests/DSReadMore.exports.test.d.ts +1 -0
  44. package/dist/types/tests/DSReadMore.get-owner-props.test.d.ts +1 -0
  45. package/dist/types/tests/DSReadMore.keyboard.test.d.ts +1 -0
  46. package/dist/types/tests/playwright/DSReadMore.ControlledTestRenderer.d.ts +1 -0
  47. package/dist/types/tests/playwright/DSReadMore.test.playwright.d.ts +1 -0
  48. package/dist/types/useOnElementResize.d.ts +1 -1
  49. package/dist/types/useReadMoreTruncate.d.ts +1 -1
  50. package/dist/types/utils.d.ts +16 -0
  51. package/package.json +10 -8
  52. package/dist/cjs/DSReadMoreDefinitions.js.map +0 -7
  53. package/dist/esm/DSReadMoreDefinitions.js.map +0 -7
  54. package/dist/types/DSReadMoreDefinitions.d.ts +0 -12
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var utils_exports = {};
30
+ __export(utils_exports, {
31
+ isSafari: () => isSafari
32
+ });
33
+ module.exports = __toCommonJS(utils_exports);
34
+ var React = __toESM(require("react"));
35
+ const isSafari = () => {
36
+ if (typeof navigator === "undefined") return false;
37
+ const ua = navigator.userAgent;
38
+ return /safari/i.test(ua) && !/chrome|chromium|android/i.test(ua);
39
+ };
40
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils.ts", "../../../../../scripts/build/transpile/react-shim.js"],
4
+ "sourcesContent": ["/**\n * Detects whether the current browser is Safari (excluding Chrome/Chromium and Android browsers).\n *\n * This utility is used to apply Safari-specific layout and styling workarounds.\n * Safari has known differences and bugs around text truncation, line-clamp,\n * and layout measurements (e.g. offsetHeight/scrollHeight), which can affect\n * components that rely on precise DOM sizing.\n *\n * The check is intentionally lightweight and user-agent based, as feature\n * detection is not reliable for these Safari-specific rendering issues.\n *\n * When used inside React components, this function should be evaluated once\n * (e.g. via useMemo) to avoid layout churn and focus instability caused by\n * re-evaluating browser detection on every render.\n */\nexport const isSafari = () => {\n if (typeof navigator === 'undefined') return false;\n\n const ua = navigator.userAgent;\n // Safari but not Chrome/Chromium/Android\n return /safari/i.test(ua) && !/chrome|chromium|android/i.test(ua);\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADehB,MAAM,WAAW,MAAM;AAC5B,MAAI,OAAO,cAAc,YAAa,QAAO;AAE7C,QAAM,KAAK,UAAU;AAErB,SAAO,UAAU,KAAK,EAAE,KAAK,CAAC,2BAA2B,KAAK,EAAE;AAClE;",
6
+ "names": []
7
+ }
@@ -1,13 +1,15 @@
1
1
  import * as React from "react";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useCallback } from "react";
3
+ import { ScreenReaderOnly } from "@elliemae/ds-accessibility";
4
4
  import { describe, useGetXstyledProps, useMemoMergePropsWithDefault } from "@elliemae/ds-props-helpers";
5
5
  import { DSTooltipV3 } from "@elliemae/ds-tooltip-v3";
6
+ import { useCallback, useMemo } from "react";
6
7
  import { MoreLessButton } from "./MoreLessButton.js";
8
+ import { DSReadMoreDataTestIds, DSReadMoreName } from "./constants/index.js";
7
9
  import { DSReadMorePropTypesSchema, defaultProps } from "./react-desc-prop-types.js";
8
- import { StyledTextWrapper, StyledTextContent, StyledTooltipWrapper } from "./styled.js";
10
+ import { StyledTextContent, StyledTextWrapper, StyledTooltipWrapper } from "./styled.js";
9
11
  import { useReadMoreTruncate } from "./useReadMoreTruncate.js";
10
- import { DSReadMoreDataTestIds, DSReadMoreName } from "./DSReadMoreDefinitions.js";
12
+ import { isSafari } from "./utils.js";
11
13
  const DSReadMore = (props) => {
12
14
  const propsWithDefault = useMemoMergePropsWithDefault(props, defaultProps);
13
15
  const { lines, more, less, content, withTooltip, ellipsis, onMore, onLess } = propsWithDefault;
@@ -16,13 +18,23 @@ const DSReadMore = (props) => {
16
18
  const toggleExpanded = useCallback(
17
19
  (newExpanded) => {
18
20
  setExpanded(newExpanded);
19
- if (newExpanded) onMore();
20
- else onLess();
21
+ if (newExpanded) {
22
+ onMore();
23
+ } else {
24
+ onLess();
25
+ }
21
26
  },
22
27
  [onMore, onLess, setExpanded]
23
28
  );
24
29
  const getOwnerProps = useCallback(() => propsWithDefault, [propsWithDefault]);
25
- const getOwnerPropsArguments = useCallback(() => ({}), []);
30
+ const getOwnerPropsArguments = useCallback(() => ({ expanded }), [expanded]);
31
+ const getReadMoreDescribedByText = useCallback(() => {
32
+ if (withTooltip) {
33
+ return "shows the full text for sighted users but the full text is already there for screen readers";
34
+ }
35
+ return `${expanded ? "collapse" : "expand"} the full text for sighted users but the full text is already there for screen readers`;
36
+ }, [expanded, withTooltip]);
37
+ const isSafariBrowser = useMemo(() => isSafari(), []);
26
38
  return /* @__PURE__ */ jsxs(
27
39
  StyledTextWrapper,
28
40
  {
@@ -31,19 +43,22 @@ const DSReadMore = (props) => {
31
43
  expanded,
32
44
  getOwnerProps,
33
45
  getOwnerPropsArguments,
46
+ isSafari: isSafariBrowser,
34
47
  ...xstyledProps,
35
48
  children: [
36
49
  srOnlyText,
50
+ /* @__PURE__ */ jsx(ScreenReaderOnly, { id: "ds-read_more-text-disclaimer", "aria-hidden": true, children: getReadMoreDescribedByText() }),
37
51
  /* @__PURE__ */ jsx(
38
52
  StyledTextContent,
39
53
  {
40
- lines,
41
- expanded,
42
54
  innerRef: textRef,
43
55
  "data-testid": "ds-read_more-text",
44
56
  ...textProps,
45
57
  getOwnerProps,
46
58
  getOwnerPropsArguments,
59
+ lines,
60
+ expanded,
61
+ isSafari: isSafariBrowser,
47
62
  children: content
48
63
  }
49
64
  ),
@@ -53,7 +68,6 @@ const DSReadMore = (props) => {
53
68
  expanded,
54
69
  label: expanded ? less : more,
55
70
  onClick: () => toggleExpanded(!expanded),
56
- ariaLabel: expanded ? "Read less" : "Read more",
57
71
  ellipsis,
58
72
  dataTestId: DSReadMoreDataTestIds.READ_MORE_BUTTON,
59
73
  getOwnerProps,
@@ -65,7 +79,6 @@ const DSReadMore = (props) => {
65
79
  {
66
80
  expanded,
67
81
  label: "...",
68
- ariaLabel: expanded ? "Read less" : "Read more",
69
82
  ellipsis,
70
83
  withTooltip,
71
84
  dataTestId: DSReadMoreDataTestIds.READ_MORE_TOOLTIP_BUTTON,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/DSReadMore.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useCallback } from 'react';\nimport { describe, useGetXstyledProps, useMemoMergePropsWithDefault } from '@elliemae/ds-props-helpers';\nimport { DSTooltipV3 } from '@elliemae/ds-tooltip-v3';\nimport { MoreLessButton } from './MoreLessButton.js';\nimport { type DSReadMoreT, DSReadMorePropTypesSchema, defaultProps } from './react-desc-prop-types.js';\nimport { StyledTextWrapper, StyledTextContent, StyledTooltipWrapper } from './styled.js';\nimport { useReadMoreTruncate } from './useReadMoreTruncate.js';\nimport { DSReadMoreDataTestIds, DSReadMoreName } from './DSReadMoreDefinitions.js';\n\nconst DSReadMore = (props: DSReadMoreT.Props) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSReadMoreT.InternalProps>(props, defaultProps);\n const { lines, more, less, content, withTooltip, ellipsis, onMore, onLess } = propsWithDefault;\n\n const xstyledProps = useGetXstyledProps(propsWithDefault);\n\n const { textWrapperRef, textRef, showButton, expanded, setExpanded, textProps, srOnlyText } =\n useReadMoreTruncate(propsWithDefault);\n\n const toggleExpanded = useCallback(\n (newExpanded: boolean) => {\n setExpanded(newExpanded);\n if (newExpanded) onMore();\n else onLess();\n },\n [onMore, onLess, setExpanded],\n );\n\n const getOwnerProps = useCallback(() => propsWithDefault, [propsWithDefault]);\n const getOwnerPropsArguments = useCallback(() => ({}), []);\n\n return (\n <StyledTextWrapper\n innerRef={textWrapperRef}\n lines={lines}\n expanded={expanded}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n {...xstyledProps}\n >\n {srOnlyText}\n <StyledTextContent\n lines={lines}\n expanded={expanded}\n innerRef={textRef}\n data-testid=\"ds-read_more-text\"\n {...textProps}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n >\n {content}\n </StyledTextContent>\n {showButton && !withTooltip && (\n <MoreLessButton\n expanded={expanded}\n label={expanded ? less : more}\n onClick={() => toggleExpanded(!expanded)}\n ariaLabel={expanded ? 'Read less' : 'Read more'}\n ellipsis={ellipsis}\n dataTestId={DSReadMoreDataTestIds.READ_MORE_BUTTON}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n />\n )}\n {withTooltip && showButton && (\n <StyledTooltipWrapper getOwnerProps={getOwnerProps} getOwnerPropsArguments={getOwnerPropsArguments}>\n <DSTooltipV3 text={content} wrapWords>\n <MoreLessButton\n expanded={expanded}\n label=\"...\"\n ariaLabel={expanded ? 'Read less' : 'Read more'}\n ellipsis={ellipsis}\n withTooltip={withTooltip}\n dataTestId={DSReadMoreDataTestIds.READ_MORE_TOOLTIP_BUTTON}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n />\n </DSTooltipV3>\n </StyledTooltipWrapper>\n )}\n </StyledTextWrapper>\n );\n};\n\nDSReadMore.displayName = DSReadMoreName;\n\nconst DSReadMoreWithSchema = describe(DSReadMore);\n\nDSReadMoreWithSchema.propTypes = DSReadMorePropTypesSchema;\n\nexport { DSReadMore, DSReadMoreWithSchema };\nexport default DSReadMore;\n"],
5
- "mappings": "AAAA,YAAY,WAAW;AC+BnB,SASE,KATF;AA/BJ,SAAgB,mBAAmB;AACnC,SAAS,UAAU,oBAAoB,oCAAoC;AAC3E,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAC/B,SAA2B,2BAA2B,oBAAoB;AAC1E,SAAS,mBAAmB,mBAAmB,4BAA4B;AAC3E,SAAS,2BAA2B;AACpC,SAAS,uBAAuB,sBAAsB;AAEtD,MAAM,aAAa,CAAC,UAA6B;AAC/C,QAAM,mBAAmB,6BAAwD,OAAO,YAAY;AACpG,QAAM,EAAE,OAAO,MAAM,MAAM,SAAS,aAAa,UAAU,QAAQ,OAAO,IAAI;AAE9E,QAAM,eAAe,mBAAmB,gBAAgB;AAExD,QAAM,EAAE,gBAAgB,SAAS,YAAY,UAAU,aAAa,WAAW,WAAW,IACxF,oBAAoB,gBAAgB;AAEtC,QAAM,iBAAiB;AAAA,IACrB,CAAC,gBAAyB;AACxB,kBAAY,WAAW;AACvB,UAAI,YAAa,QAAO;AAAA,UACnB,QAAO;AAAA,IACd;AAAA,IACA,CAAC,QAAQ,QAAQ,WAAW;AAAA,EAC9B;AAEA,QAAM,gBAAgB,YAAY,MAAM,kBAAkB,CAAC,gBAAgB,CAAC;AAC5E,QAAM,yBAAyB,YAAY,OAAO,CAAC,IAAI,CAAC,CAAC;AAEzD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,QACD;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA,UAAU;AAAA,YACV,eAAY;AAAA,YACX,GAAG;AAAA,YACJ;AAAA,YACA;AAAA,YAEC;AAAA;AAAA,QACH;AAAA,QACC,cAAc,CAAC,eACd;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,OAAO,WAAW,OAAO;AAAA,YACzB,SAAS,MAAM,eAAe,CAAC,QAAQ;AAAA,YACvC,WAAW,WAAW,cAAc;AAAA,YACpC;AAAA,YACA,YAAY,sBAAsB;AAAA,YAClC;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QAED,eAAe,cACd,oBAAC,wBAAqB,eAA8B,wBAClD,8BAAC,eAAY,MAAM,SAAS,WAAS,MACnC;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,OAAM;AAAA,YACN,WAAW,WAAW,cAAc;AAAA,YACpC;AAAA,YACA;AAAA,YACA,YAAY,sBAAsB;AAAA,YAClC;AAAA,YACA;AAAA;AAAA,QACF,GACF,GACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,WAAW,cAAc;AAEzB,MAAM,uBAAuB,SAAS,UAAU;AAEhD,qBAAqB,YAAY;AAGjC,IAAO,qBAAQ;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { ScreenReaderOnly } from '@elliemae/ds-accessibility';\nimport { describe, useGetXstyledProps, useMemoMergePropsWithDefault } from '@elliemae/ds-props-helpers';\nimport { DSTooltipV3 } from '@elliemae/ds-tooltip-v3';\nimport { useCallback, useMemo } from 'react';\nimport { MoreLessButton } from './MoreLessButton.js';\nimport { DSReadMoreDataTestIds, DSReadMoreName } from './constants/index.js';\nimport { DSReadMorePropTypesSchema, defaultProps, type DSReadMoreT } from './react-desc-prop-types.js';\nimport { StyledTextContent, StyledTextWrapper, StyledTooltipWrapper } from './styled.js';\nimport { useReadMoreTruncate } from './useReadMoreTruncate.js';\nimport { isSafari } from './utils.js';\n\nconst DSReadMore = (props: DSReadMoreT.Props) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSReadMoreT.InternalProps>(props, defaultProps);\n const { lines, more, less, content, withTooltip, ellipsis, onMore, onLess } = propsWithDefault;\n\n const xstyledProps = useGetXstyledProps(propsWithDefault);\n\n const { textWrapperRef, textRef, showButton, expanded, setExpanded, textProps, srOnlyText } =\n useReadMoreTruncate(propsWithDefault);\n\n const toggleExpanded = useCallback(\n (newExpanded: boolean) => {\n setExpanded(newExpanded);\n if (newExpanded) {\n onMore();\n } else {\n onLess();\n }\n },\n [onMore, onLess, setExpanded],\n );\n\n const getOwnerProps = useCallback(() => propsWithDefault, [propsWithDefault]);\n const getOwnerPropsArguments = useCallback(() => ({ expanded }), [expanded]);\n const getReadMoreDescribedByText = useCallback(() => {\n if (withTooltip) {\n return 'shows the full text for sighted users but the full text is already there for screen readers';\n }\n return `${expanded ? 'collapse' : 'expand'} the full text for sighted users but the full text is already there for screen readers`;\n }, [expanded, withTooltip]);\n\n const isSafariBrowser = useMemo(() => isSafari(), []);\n\n return (\n <StyledTextWrapper\n innerRef={textWrapperRef}\n lines={lines}\n expanded={expanded}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n isSafari={isSafariBrowser}\n {...xstyledProps}\n >\n {srOnlyText}\n {/**\n * Hidden from screen readers unless referenced by `aria-describedby`\n * Ensures the text is only read when associated with a control\n * Prevents it from being focusable or announced independently\n */}\n <ScreenReaderOnly id=\"ds-read_more-text-disclaimer\" aria-hidden>\n {getReadMoreDescribedByText()}\n </ScreenReaderOnly>\n\n <StyledTextContent\n innerRef={textRef}\n data-testid=\"ds-read_more-text\"\n {...textProps}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n lines={lines}\n expanded={expanded}\n isSafari={isSafariBrowser}\n >\n {content}\n </StyledTextContent>\n\n {showButton && !withTooltip && (\n <MoreLessButton\n expanded={expanded}\n label={expanded ? less : more}\n onClick={() => toggleExpanded(!expanded)}\n ellipsis={ellipsis}\n dataTestId={DSReadMoreDataTestIds.READ_MORE_BUTTON}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n />\n )}\n\n {withTooltip && showButton && (\n <StyledTooltipWrapper getOwnerProps={getOwnerProps} getOwnerPropsArguments={getOwnerPropsArguments}>\n <DSTooltipV3 text={content} wrapWords>\n <MoreLessButton\n expanded={expanded}\n label=\"...\"\n ellipsis={ellipsis}\n withTooltip={withTooltip}\n dataTestId={DSReadMoreDataTestIds.READ_MORE_TOOLTIP_BUTTON}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n />\n </DSTooltipV3>\n </StyledTooltipWrapper>\n )}\n </StyledTextWrapper>\n );\n};\n\nDSReadMore.displayName = DSReadMoreName;\nconst DSReadMoreWithSchema = describe(DSReadMore);\nDSReadMoreWithSchema.propTypes = DSReadMorePropTypesSchema;\n\nexport { DSReadMore, DSReadMoreWithSchema };\nexport default DSReadMore;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AC4CnB,SAeE,KAfF;AA5CJ,SAAS,wBAAwB;AACjC,SAAS,UAAU,oBAAoB,oCAAoC;AAC3E,SAAS,mBAAmB;AAC5B,SAAS,aAAa,eAAe;AACrC,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB,sBAAsB;AACtD,SAAS,2BAA2B,oBAAsC;AAC1E,SAAS,mBAAmB,mBAAmB,4BAA4B;AAC3E,SAAS,2BAA2B;AACpC,SAAS,gBAAgB;AAEzB,MAAM,aAAa,CAAC,UAA6B;AAC/C,QAAM,mBAAmB,6BAAwD,OAAO,YAAY;AACpG,QAAM,EAAE,OAAO,MAAM,MAAM,SAAS,aAAa,UAAU,QAAQ,OAAO,IAAI;AAE9E,QAAM,eAAe,mBAAmB,gBAAgB;AAExD,QAAM,EAAE,gBAAgB,SAAS,YAAY,UAAU,aAAa,WAAW,WAAW,IACxF,oBAAoB,gBAAgB;AAEtC,QAAM,iBAAiB;AAAA,IACrB,CAAC,gBAAyB;AACxB,kBAAY,WAAW;AACvB,UAAI,aAAa;AACf,eAAO;AAAA,MACT,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,QAAQ,WAAW;AAAA,EAC9B;AAEA,QAAM,gBAAgB,YAAY,MAAM,kBAAkB,CAAC,gBAAgB,CAAC;AAC5E,QAAM,yBAAyB,YAAY,OAAO,EAAE,SAAS,IAAI,CAAC,QAAQ,CAAC;AAC3E,QAAM,6BAA6B,YAAY,MAAM;AACnD,QAAI,aAAa;AACf,aAAO;AAAA,IACT;AACA,WAAO,GAAG,WAAW,aAAa,QAAQ;AAAA,EAC5C,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,QAAM,kBAAkB,QAAQ,MAAM,SAAS,GAAG,CAAC,CAAC;AAEpD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACT,GAAG;AAAA,MAEH;AAAA;AAAA,QAMD,oBAAC,oBAAiB,IAAG,gCAA+B,eAAW,MAC5D,qCAA2B,GAC9B;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,eAAY;AAAA,YACX,GAAG;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,UAAU;AAAA,YAET;AAAA;AAAA,QACH;AAAA,QAEC,cAAc,CAAC,eACd;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,OAAO,WAAW,OAAO;AAAA,YACzB,SAAS,MAAM,eAAe,CAAC,QAAQ;AAAA,YACvC;AAAA,YACA,YAAY,sBAAsB;AAAA,YAClC;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QAGD,eAAe,cACd,oBAAC,wBAAqB,eAA8B,wBAClD,8BAAC,eAAY,MAAM,SAAS,WAAS,MACnC;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,OAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA,YAAY,sBAAsB;AAAA,YAClC;AAAA,YACA;AAAA;AAAA,QACF,GACF,GACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,WAAW,cAAc;AACzB,MAAM,uBAAuB,SAAS,UAAU;AAChD,qBAAqB,YAAY;AAGjC,IAAO,qBAAQ;",
6
6
  "names": []
7
7
  }
@@ -2,34 +2,32 @@ import * as React from "react";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { StyledButton, StyledButtonWrapper } from "./styled.js";
4
4
  const MoreLessButton = (props) => {
5
- const {
6
- expanded,
7
- ariaLabel,
8
- label,
9
- onClick,
10
- ellipsis,
11
- withTooltip,
12
- dataTestId,
13
- getOwnerProps,
14
- getOwnerPropsArguments
15
- } = props;
16
- return /* @__PURE__ */ jsxs(StyledButtonWrapper, { getOwnerProps, getOwnerPropsArguments, children: [
17
- expanded || withTooltip ? " " : ellipsis,
18
- /* @__PURE__ */ jsx(
19
- StyledButton,
20
- {
21
- withTooltip,
22
- "aria-label": ariaLabel,
23
- buttonType: "text",
24
- onClick,
25
- size: "s",
26
- "data-testid": dataTestId,
27
- getOwnerProps,
28
- getOwnerPropsArguments,
29
- children: label
30
- }
31
- )
32
- ] });
5
+ const { expanded, label, onClick, ellipsis, withTooltip, dataTestId, getOwnerProps, getOwnerPropsArguments } = props;
6
+ return /* @__PURE__ */ jsxs(
7
+ StyledButtonWrapper,
8
+ {
9
+ expanded,
10
+ getOwnerProps,
11
+ getOwnerPropsArguments,
12
+ children: [
13
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: expanded || withTooltip ? " " : ellipsis }),
14
+ /* @__PURE__ */ jsx(
15
+ StyledButton,
16
+ {
17
+ withTooltip,
18
+ buttonType: "text",
19
+ onClick,
20
+ size: "s",
21
+ "data-testid": dataTestId,
22
+ getOwnerProps,
23
+ getOwnerPropsArguments,
24
+ "aria-describedby": "ds-read_more-text-disclaimer",
25
+ children: label
26
+ }
27
+ )
28
+ ]
29
+ }
30
+ );
33
31
  };
34
32
  export {
35
33
  MoreLessButton
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/MoreLessButton.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { StyledButton, StyledButtonWrapper } from './styled.js';\n\ninterface MoreLessButtonProps {\n expanded: boolean;\n label: string;\n onClick?: () => void;\n ellipsis: string;\n withTooltip?: boolean;\n ariaLabel: string;\n dataTestId: string;\n getOwnerProps: () => object;\n getOwnerPropsArguments: () => object;\n}\n\nconst MoreLessButton = (props: MoreLessButtonProps) => {\n const {\n expanded,\n ariaLabel,\n label,\n onClick,\n ellipsis,\n withTooltip,\n dataTestId,\n getOwnerProps,\n getOwnerPropsArguments,\n } = props;\n\n return (\n <StyledButtonWrapper getOwnerProps={getOwnerProps} getOwnerPropsArguments={getOwnerPropsArguments}>\n {expanded || withTooltip ? ' ' : ellipsis}\n\n <StyledButton\n withTooltip={withTooltip}\n aria-label={ariaLabel}\n buttonType=\"text\"\n onClick={onClick}\n size=\"s\"\n data-testid={dataTestId}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n >\n {label}\n </StyledButton>\n </StyledButtonWrapper>\n );\n};\n\nexport { MoreLessButton };\n"],
5
- "mappings": "AAAA,YAAY,WAAW;AC6BnB,SAGE,KAHF;AA5BJ,SAAS,cAAc,2BAA2B;AAclD,MAAM,iBAAiB,CAAC,UAA+B;AACrD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,SACE,qBAAC,uBAAoB,eAA8B,wBAChD;AAAA,gBAAY,cAAc,MAAM;AAAA,IAEjC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,cAAY;AAAA,QACZ,YAAW;AAAA,QACX;AAAA,QACA,MAAK;AAAA,QACL,eAAa;AAAA,QACb;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { StyledButton, StyledButtonWrapper } from './styled.js';\n\ninterface MoreLessButtonProps {\n expanded: boolean;\n label: string;\n onClick?: () => void;\n ellipsis: string;\n withTooltip?: boolean;\n dataTestId: string;\n getOwnerProps: () => object;\n getOwnerPropsArguments: () => object;\n}\n\nconst MoreLessButton = (props: MoreLessButtonProps) => {\n const { expanded, label, onClick, ellipsis, withTooltip, dataTestId, getOwnerProps, getOwnerPropsArguments } = props;\n\n return (\n <StyledButtonWrapper\n expanded={expanded}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n >\n <span aria-hidden>{expanded || withTooltip ? ' ' : ellipsis}</span>\n\n <StyledButton\n withTooltip={withTooltip}\n buttonType=\"text\"\n onClick={onClick}\n size=\"s\"\n data-testid={dataTestId}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n aria-describedby=\"ds-read_more-text-disclaimer\"\n >\n {label}\n </StyledButton>\n </StyledButtonWrapper>\n );\n};\n\nexport { MoreLessButton };\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACkBnB,SAKE,KALF;AAjBJ,SAAS,cAAc,2BAA2B;AAalD,MAAM,iBAAiB,CAAC,UAA+B;AACrD,QAAM,EAAE,UAAU,OAAO,SAAS,UAAU,aAAa,YAAY,eAAe,uBAAuB,IAAI;AAE/G,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,4BAAC,UAAK,eAAW,MAAE,sBAAY,cAAc,MAAM,UAAS;AAAA,QAE5D;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,YAAW;AAAA,YACX;AAAA,YACA,MAAK;AAAA,YACL,eAAa;AAAA,YACb;AAAA,YACA;AAAA,YACA,oBAAiB;AAAA,YAEhB;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -2,21 +2,26 @@ import * as React from "react";
2
2
  import { omit } from "lodash-es";
3
3
  import { slotObjectToDataTestIds } from "@elliemae/ds-system";
4
4
  const DSReadMoreName = "DSReadmore";
5
- const DSReadMoreSlots = {
5
+ const READ_MORE_SLOTS = {
6
6
  ROOT: "root",
7
7
  TEXT_CONTENT: "text-content",
8
8
  TOOLTIP_WRAPPER: "tooltip-wrapper",
9
9
  BUTTON_WRAPPER: "button-wrapper",
10
10
  BUTTON: "button"
11
11
  };
12
- const DSReadMoreDataTestIds = {
12
+ const DSReadMoreSlots = READ_MORE_SLOTS;
13
+ const READ_MORE_DATA_TESTID = {
13
14
  ...omit(slotObjectToDataTestIds(DSReadMoreName, DSReadMoreSlots), "BUTTON"),
14
15
  READ_MORE_BUTTON: "ds-read_more-button",
15
- READ_MORE_TOOLTIP_BUTTON: "ds-read_more-tooltip-button"
16
+ READ_MORE_TOOLTIP_BUTTON: "ds-read_more-tooltip-button",
17
+ READ_MORE_TEXT: "ds-read_more-text"
16
18
  };
19
+ const DSReadMoreDataTestIds = READ_MORE_DATA_TESTID;
17
20
  export {
18
21
  DSReadMoreDataTestIds,
19
22
  DSReadMoreName,
20
- DSReadMoreSlots
23
+ DSReadMoreSlots,
24
+ READ_MORE_DATA_TESTID,
25
+ READ_MORE_SLOTS
21
26
  };
22
- //# sourceMappingURL=DSReadMoreDefinitions.js.map
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/constants/index.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { omit } from 'lodash-es';\nimport { slotObjectToDataTestIds } from '@elliemae/ds-system';\n\nexport const DSReadMoreName = 'DSReadmore';\n// we are naming this with the ${component_name}_slots convention to namespace & avoid errors on duplicate exports variables in aggregators\nexport const READ_MORE_SLOTS = {\n ROOT: 'root',\n TEXT_CONTENT: 'text-content',\n TOOLTIP_WRAPPER: 'tooltip-wrapper',\n BUTTON_WRAPPER: 'button-wrapper',\n BUTTON: 'button',\n} as const;\n\n// keeping legacy code to avoid breaking changes, the code above this is the new convention\nexport const DSReadMoreSlots = READ_MORE_SLOTS;\n\n// we are naming this with the ${component_name}_data_testid convention to namespace & avoid errors on duplicate exports variables in aggregators\nexport const READ_MORE_DATA_TESTID = {\n ...omit(slotObjectToDataTestIds(DSReadMoreName, DSReadMoreSlots), 'BUTTON'),\n READ_MORE_BUTTON: 'ds-read_more-button',\n READ_MORE_TOOLTIP_BUTTON: 'ds-read_more-tooltip-button',\n READ_MORE_TEXT: 'ds-read_more-text',\n};\n\n// keeping legacy code to avoid breaking changes\nexport const DSReadMoreDataTestIds = READ_MORE_DATA_TESTID;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,YAAY;AACrB,SAAS,+BAA+B;AAEjC,MAAM,iBAAiB;AAEvB,MAAM,kBAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,QAAQ;AACV;AAGO,MAAM,kBAAkB;AAGxB,MAAM,wBAAwB;AAAA,EACnC,GAAG,KAAK,wBAAwB,gBAAgB,eAAe,GAAG,QAAQ;AAAA,EAC1E,kBAAkB;AAAA,EAClB,0BAA0B;AAAA,EAC1B,gBAAgB;AAClB;AAGO,MAAM,wBAAwB;",
6
+ "names": []
7
+ }
package/dist/esm/index.js CHANGED
@@ -1,6 +1,12 @@
1
1
  import * as React from "react";
2
2
  import { DSReadMore, DSReadMoreWithSchema } from "./DSReadMore.js";
3
- import { DSReadMoreName, DSReadMoreSlots, DSReadMoreDataTestIds } from "./DSReadMoreDefinitions.js";
3
+ import {
4
+ DSReadMoreName,
5
+ DSReadMoreSlots,
6
+ READ_MORE_SLOTS,
7
+ DSReadMoreDataTestIds,
8
+ READ_MORE_DATA_TESTID
9
+ } from "./constants/index.js";
4
10
  import { useReadMoreTruncate } from "./useReadMoreTruncate.js";
5
11
  export {
6
12
  DSReadMore,
@@ -8,6 +14,8 @@ export {
8
14
  DSReadMoreName,
9
15
  DSReadMoreSlots,
10
16
  DSReadMoreWithSchema,
17
+ READ_MORE_DATA_TESTID,
18
+ READ_MORE_SLOTS,
11
19
  useReadMoreTruncate
12
20
  };
13
21
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/index.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "export { DSReadMore, DSReadMoreWithSchema } from './DSReadMore.js';\nexport { DSReadMoreName, DSReadMoreSlots, DSReadMoreDataTestIds } from './DSReadMoreDefinitions.js';\nexport type { DSReadMoreT } from './react-desc-prop-types.js';\nexport { useReadMoreTruncate } from './useReadMoreTruncate.js';\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,YAAY,4BAA4B;AACjD,SAAS,gBAAgB,iBAAiB,6BAA6B;AAEvE,SAAS,2BAA2B;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "export { DSReadMore, DSReadMoreWithSchema } from './DSReadMore.js';\nexport {\n DSReadMoreName,\n DSReadMoreSlots,\n READ_MORE_SLOTS,\n DSReadMoreDataTestIds,\n READ_MORE_DATA_TESTID,\n} from './constants/index.js';\nexport type { DSReadMoreT } from './react-desc-prop-types.js';\nexport { useReadMoreTruncate } from './useReadMoreTruncate.js';\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,YAAY,4BAA4B;AACjD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,2BAA2B;",
6
6
  "names": []
7
7
  }
@@ -1,11 +1,12 @@
1
1
  import * as React from "react";
2
2
  import {
3
3
  getPropsPerDatatestIdPropTypes,
4
+ getPropsPerSlotPropTypes,
4
5
  globalAttributesPropTypes,
5
6
  PropTypes,
6
7
  xstyledPropTypes
7
8
  } from "@elliemae/ds-props-helpers";
8
- import { DSReadMoreDataTestIds } from "./DSReadMoreDefinitions.js";
9
+ import { DSReadMoreDataTestIds, DSReadMoreName, READ_MORE_SLOTS } from "./constants/index.js";
9
10
  const defaultProps = {
10
11
  lines: 2,
11
12
  more: "more",
@@ -18,6 +19,7 @@ const defaultProps = {
18
19
  withTooltip: false
19
20
  };
20
21
  const DSReadMorePropTypes = {
22
+ ...getPropsPerSlotPropTypes(DSReadMoreName, READ_MORE_SLOTS),
21
23
  ...globalAttributesPropTypes,
22
24
  ...xstyledPropTypes,
23
25
  /** Ammount of lines after you want to display an ellipsis + more/less button */
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/react-desc-prop-types.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\n/* eslint-disable @typescript-eslint/no-empty-interface */\nimport {\n getPropsPerDatatestIdPropTypes,\n globalAttributesPropTypes,\n PropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport type { WeakValidationMap } from 'react';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema } from '@elliemae/ds-props-helpers';\nimport { DSReadMoreDataTestIds } from './DSReadMoreDefinitions.js';\n\nexport namespace DSReadMoreT {\n type PropsT<D, R, O, E> = Partial<D> & R & O & Omit<GlobalAttributesT<E>, keyof D | keyof R | keyof O> & XstyledProps;\n type InternalPropsT<D, R, O, E> = D & R & O & Omit<GlobalAttributesT<E>, keyof D | keyof R | keyof O> & XstyledProps;\n\n export interface DefaultProps {\n lines: number;\n more: string;\n less: string;\n onMore: () => void;\n onLess: () => void;\n ellipsis: string;\n withTooltip: boolean;\n }\n\n export interface OptionalProps {}\n\n export interface RequiredProps {\n content: string;\n }\n\n export type Props = PropsT<DefaultProps, RequiredProps, OptionalProps, HTMLSpanElement>;\n\n export type InternalProps = InternalPropsT<DefaultProps, RequiredProps, OptionalProps, HTMLSpanElement>;\n}\n\nexport const defaultProps: DSReadMoreT.DefaultProps = {\n lines: 2,\n more: 'more',\n less: 'less',\n onMore: () => {},\n onLess: () => {},\n ellipsis: '...',\n withTooltip: false,\n};\n\nexport const DSReadMorePropTypes: DSPropTypesSchema<DSReadMoreT.Props> = {\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n /** Ammount of lines after you want to display an ellipsis + more/less button */\n lines: PropTypes.number\n .description('Ammount of lines after you want to display an ellipsis + more/less button')\n .defaultValue(2),\n /** Label which will appear on the 'More' button */\n more: PropTypes.string.description(\"Label which will appear on the 'More' button\").defaultValue('more'),\n /** Label which will appear on the 'Less' button */\n less: PropTypes.string.description(\"Label which will appear on the 'Less' button\").defaultValue('less'),\n /** Function which will execute when the user click the 'More' button */\n onMore: PropTypes.func.description(\"Function which will execute when the user click the 'More' button\"),\n /** Function which will execute when the user click the 'Less' button */\n onLess: PropTypes.func.description(\"Function which will execute when the user click the 'Less' button\"),\n /** The text content you want displayed */\n content: PropTypes.string.description('The text content you want displayed').isRequired,\n\n /** The text you want to appear when truncating */\n ellipsis: PropTypes.string.description('The text you want to appear when truncating').defaultValue('...'),\n withTooltip: PropTypes.bool\n .description('Whether to show expandable tooltip on ellipsis focus instead of expandable buttons')\n .defaultValue('false'),\n ...getPropsPerDatatestIdPropTypes(DSReadMoreDataTestIds),\n};\n\nexport const DSReadMorePropTypesSchema = DSReadMorePropTypes as unknown as WeakValidationMap<DSReadMoreT.Props>;\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACEvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,6BAA6B;AA2B/B,MAAM,eAAyC;AAAA,EACpD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ,MAAM;AAAA,EAAC;AAAA,EACf,QAAQ,MAAM;AAAA,EAAC;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AACf;AAEO,MAAM,sBAA4D;AAAA,EACvE,GAAG;AAAA,EACH,GAAG;AAAA;AAAA,EAEH,OAAO,UAAU,OACd,YAAY,2EAA2E,EACvF,aAAa,CAAC;AAAA;AAAA,EAEjB,MAAM,UAAU,OAAO,YAAY,8CAA8C,EAAE,aAAa,MAAM;AAAA;AAAA,EAEtG,MAAM,UAAU,OAAO,YAAY,8CAA8C,EAAE,aAAa,MAAM;AAAA;AAAA,EAEtG,QAAQ,UAAU,KAAK,YAAY,mEAAmE;AAAA;AAAA,EAEtG,QAAQ,UAAU,KAAK,YAAY,mEAAmE;AAAA;AAAA,EAEtG,SAAS,UAAU,OAAO,YAAY,qCAAqC,EAAE;AAAA;AAAA,EAG7E,UAAU,UAAU,OAAO,YAAY,6CAA6C,EAAE,aAAa,KAAK;AAAA,EACxG,aAAa,UAAU,KACpB,YAAY,oFAAoF,EAChG,aAAa,OAAO;AAAA,EACvB,GAAG,+BAA+B,qBAAqB;AACzD;AAEO,MAAM,4BAA4B;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\n/* eslint-disable @typescript-eslint/no-empty-interface */\nimport {\n getPropsPerDatatestIdPropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n PropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\n\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSReadMoreDataTestIds, DSReadMoreName, READ_MORE_SLOTS } from './constants/index.js';\n\nexport namespace DSReadMoreT {\n type PropsT<D, R, O, E> = Partial<D> & R & O & Omit<GlobalAttributesT<E>, keyof D | keyof R | keyof O> & XstyledProps;\n type InternalPropsT<D, R, O, E> = D & R & O & Omit<GlobalAttributesT<E>, keyof D | keyof R | keyof O> & XstyledProps;\n\n export interface DefaultProps {\n lines: number;\n more: string;\n less: string;\n onMore: () => void;\n onLess: () => void;\n ellipsis: string;\n withTooltip: boolean;\n }\n\n export interface OptionalProps\n extends TypescriptHelpersT.PropsForGlobalOnSlots<typeof DSReadMoreName, typeof READ_MORE_SLOTS> {}\n\n export interface RequiredProps {\n content: string;\n }\n\n export type Props = PropsT<DefaultProps, RequiredProps, OptionalProps, HTMLSpanElement>;\n\n export type InternalProps = InternalPropsT<DefaultProps, RequiredProps, OptionalProps, HTMLSpanElement>;\n}\n\nexport const defaultProps: DSReadMoreT.DefaultProps = {\n lines: 2,\n more: 'more',\n less: 'less',\n onMore: () => {},\n onLess: () => {},\n ellipsis: '...',\n withTooltip: false,\n};\n\nexport const DSReadMorePropTypes: DSPropTypesSchema<DSReadMoreT.Props> = {\n ...getPropsPerSlotPropTypes(DSReadMoreName, READ_MORE_SLOTS),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n /** Ammount of lines after you want to display an ellipsis + more/less button */\n lines: PropTypes.number\n .description('Ammount of lines after you want to display an ellipsis + more/less button')\n .defaultValue(2),\n /** Label which will appear on the 'More' button */\n more: PropTypes.string.description(\"Label which will appear on the 'More' button\").defaultValue('more'),\n /** Label which will appear on the 'Less' button */\n less: PropTypes.string.description(\"Label which will appear on the 'Less' button\").defaultValue('less'),\n /** Function which will execute when the user click the 'More' button */\n onMore: PropTypes.func.description(\"Function which will execute when the user click the 'More' button\"),\n /** Function which will execute when the user click the 'Less' button */\n onLess: PropTypes.func.description(\"Function which will execute when the user click the 'Less' button\"),\n /** The text content you want displayed */\n content: PropTypes.string.description('The text content you want displayed').isRequired,\n\n /** The text you want to appear when truncating */\n ellipsis: PropTypes.string.description('The text you want to appear when truncating').defaultValue('...'),\n withTooltip: PropTypes.bool\n .description('Whether to show expandable tooltip on ellipsis focus instead of expandable buttons')\n .defaultValue('false'),\n ...getPropsPerDatatestIdPropTypes(DSReadMoreDataTestIds),\n};\n\nexport const DSReadMorePropTypesSchema = DSReadMorePropTypes as unknown as ValidationMap<DSReadMoreT.Props>;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACEvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP,SAAS,uBAAuB,gBAAgB,uBAAuB;AA4BhE,MAAM,eAAyC;AAAA,EACpD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ,MAAM;AAAA,EAAC;AAAA,EACf,QAAQ,MAAM;AAAA,EAAC;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AACf;AAEO,MAAM,sBAA4D;AAAA,EACvE,GAAG,yBAAyB,gBAAgB,eAAe;AAAA,EAC3D,GAAG;AAAA,EACH,GAAG;AAAA;AAAA,EAEH,OAAO,UAAU,OACd,YAAY,2EAA2E,EACvF,aAAa,CAAC;AAAA;AAAA,EAEjB,MAAM,UAAU,OAAO,YAAY,8CAA8C,EAAE,aAAa,MAAM;AAAA;AAAA,EAEtG,MAAM,UAAU,OAAO,YAAY,8CAA8C,EAAE,aAAa,MAAM;AAAA;AAAA,EAEtG,QAAQ,UAAU,KAAK,YAAY,mEAAmE;AAAA;AAAA,EAEtG,QAAQ,UAAU,KAAK,YAAY,mEAAmE;AAAA;AAAA,EAEtG,SAAS,UAAU,OAAO,YAAY,qCAAqC,EAAE;AAAA;AAAA,EAG7E,UAAU,UAAU,OAAO,YAAY,6CAA6C,EAAE,aAAa,KAAK;AAAA,EACxG,aAAa,UAAU,KACpB,YAAY,oFAAoF,EAChG,aAAa,OAAO;AAAA,EACvB,GAAG,+BAA+B,qBAAqB;AACzD;AAEO,MAAM,4BAA4B;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { styled, xStyledCommonProps } from "@elliemae/ds-system";
3
- import { DSButtonV2 } from "@elliemae/ds-button-v2";
4
- import { DSReadMoreName, DSReadMoreSlots } from "./DSReadMoreDefinitions.js";
3
+ import { DSButtonV3 } from "@elliemae/ds-button-v2";
4
+ import { DSReadMoreName, DSReadMoreSlots } from "./constants/index.js";
5
5
  const StyledTextWrapper = styled("span", { name: DSReadMoreName, slot: DSReadMoreSlots.ROOT })`
6
6
  position: relative;
7
7
  /**
@@ -13,10 +13,9 @@ const StyledTextWrapper = styled("span", { name: DSReadMoreName, slot: DSReadMor
13
13
  * - Avoids -webkit-line-clamp: 1 which breaks layout and can cause infinite ResizeObserver loops.
14
14
  * - Instead, uses flex + white-space + overflow hidden for single-line truncation.
15
15
  */
16
- ${({ lines, expanded }) => lines === 1 && !expanded ? `
16
+ ${({ lines, isSafari, expanded }) => lines === 1 && isSafari && !expanded ? `
17
17
  display: flex;
18
18
  align-items: baseline;
19
- overflow: hidden;
20
19
  white-space: nowrap;
21
20
  ` : `
22
21
  display: -webkit-box;
@@ -28,13 +27,14 @@ const StyledTextWrapper = styled("span", { name: DSReadMoreName, slot: DSReadMor
28
27
  -moz-hyphens: auto;
29
28
  -ms-hyphens: auto;
30
29
  hyphens: auto;
31
- word-break: break-all;
30
+ overflow-wrap: break-word;
31
+ white-space: pre-wrap;
32
32
  ${xStyledCommonProps}
33
33
  `;
34
34
  const StyledTextContent = styled("span", { name: DSReadMoreName, slot: DSReadMoreSlots.TEXT_CONTENT })`
35
- ${({ lines, expanded }) => lines === 1 && !expanded ? `
35
+ ${({ lines, expanded, isSafari }) => lines === 1 && isSafari && !expanded ? `
36
36
  flex: 1 1 auto;
37
- overflow: hidden;
37
+ overflow-x: clip;
38
38
  white-space: nowrap;
39
39
  text-overflow: clip;
40
40
  ` : ""}
@@ -42,9 +42,14 @@ const StyledTextContent = styled("span", { name: DSReadMoreName, slot: DSReadMor
42
42
  const StyledTooltipWrapper = styled("div", { name: DSReadMoreName, slot: DSReadMoreSlots.TOOLTIP_WRAPPER })`
43
43
  display: inline-block;
44
44
  `;
45
- const StyledButtonWrapper = styled("span", { name: DSReadMoreName, slot: DSReadMoreSlots.BUTTON_WRAPPER })``;
46
- const StyledButton = styled(DSButtonV2, { name: DSReadMoreName, slot: DSReadMoreSlots.BUTTON })`
47
- padding: 0;
45
+ const StyledButtonWrapper = styled("span", { name: DSReadMoreName, slot: DSReadMoreSlots.BUTTON_WRAPPER })`
46
+ flex: none;
47
+ display: -webkit-inline-box;
48
+ -webkit-line-clamp: 2;
49
+ -webkit-box-orient: vertical;
50
+ `;
51
+ const StyledButton = styled(DSButtonV3, { name: DSReadMoreName, slot: DSReadMoreSlots.BUTTON })`
52
+ padding: ${({ theme }) => `0 ${theme.space.xxxs}`};
48
53
  color: ${({ withTooltip, theme }) => withTooltip ? "inherit" : `${theme.colors.brand["600"]}`};
49
54
  border: 0;
50
55
  margin: 0;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/styled.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { styled, xStyledCommonProps } from '@elliemae/ds-system';\nimport { DSButtonV2 } from '@elliemae/ds-button-v2';\nimport { DSReadMoreName, DSReadMoreSlots } from './DSReadMoreDefinitions.js';\n\nexport const StyledTextWrapper = styled('span', { name: DSReadMoreName, slot: DSReadMoreSlots.ROOT })<{\n lines: number;\n expanded: boolean;\n}>`\n position: relative;\n /**\n * PUI-16110 - [ReadMore] Autotriggered-Visually broken in safari + Sequoia\n * -----------------------------------\n * In Safari 17.4+ (macOS Sequoia), using scrollHeight or offsetHeight with line-clamp\n * can break the layout and, potentially, trigger infinite loops through ResizeObserver.\n *\n * - Avoids -webkit-line-clamp: 1 which breaks layout and can cause infinite ResizeObserver loops.\n * - Instead, uses flex + white-space + overflow hidden for single-line truncation.\n */\n ${({ lines, expanded }) =>\n lines === 1 && !expanded\n ? `\n display: flex;\n align-items: baseline;\n overflow: hidden;\n white-space: nowrap;\n `\n : `\n display: -webkit-box;\n -webkit-line-clamp: ${expanded ? 'unset' : lines};\n -webkit-box-orient: vertical;\n `}\n\n -webkit-hyphens: auto;\n -moz-hyphens: auto;\n -ms-hyphens: auto;\n hyphens: auto;\n word-break: break-all;\n ${xStyledCommonProps}\n`;\n\nexport const StyledTextContent = styled('span', { name: DSReadMoreName, slot: DSReadMoreSlots.TEXT_CONTENT })<{\n lines: number;\n expanded: boolean;\n}>`\n ${({ lines, expanded }) =>\n lines === 1 && !expanded\n ? `\n flex: 1 1 auto;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: clip;\n `\n : ''}\n`;\n\nexport const StyledTooltipWrapper = styled('div', { name: DSReadMoreName, slot: DSReadMoreSlots.TOOLTIP_WRAPPER })`\n display: inline-block;\n`;\n\nexport const StyledButtonWrapper = styled('span', { name: DSReadMoreName, slot: DSReadMoreSlots.BUTTON_WRAPPER })``;\n\nexport const StyledButton = styled(DSButtonV2, { name: DSReadMoreName, slot: DSReadMoreSlots.BUTTON })<{\n withTooltip?: boolean;\n}>`\n padding: 0;\n color: ${({ withTooltip, theme }) => (withTooltip ? 'inherit' : `${theme.colors.brand['600']}`)};\n border: 0;\n margin: 0;\n font-size: 12px;\n min-width: 0px;\n height: auto;\n text-transform: unset;\n &:hover:not([disabled]) {\n color: ${({ withTooltip, theme }) => (withTooltip ? 'inherit' : `${theme.colors.brand['600']}`)};\n background-color: transparent;\n text-decoration: ${({ withTooltip }) => (withTooltip ? '' : 'underline')};\n }\n`;\n\nexport const ScreenReaderOnly = styled.span`\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n height: 100%;\n overflow: hidden;\n position: absolute;\n width: 100%;\n`;\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,QAAQ,0BAA0B;AAC3C,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB,uBAAuB;AAEzC,MAAM,oBAAoB,OAAO,QAAQ,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAchG,CAAC,EAAE,OAAO,SAAS,MACnB,UAAU,KAAK,CAAC,WACZ;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA;AAAA;AAAA,0BAEkB,WAAW,UAAU,KAAK;AAAA;AAAA,GAEjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOC,kBAAkB;AAAA;AAGf,MAAM,oBAAoB,OAAO,QAAQ,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,aAAa,CAAC;AAAA,IAIxG,CAAC,EAAE,OAAO,SAAS,MACnB,UAAU,KAAK,CAAC,WACZ;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,EAAE;AAAA;AAGH,MAAM,uBAAuB,OAAO,OAAO,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,gBAAgB,CAAC;AAAA;AAAA;AAI1G,MAAM,sBAAsB,OAAO,QAAQ,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,eAAe,CAAC;AAEzG,MAAM,eAAe,OAAO,YAAY,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,OAAO,CAAC;AAAA;AAAA,WAI1F,CAAC,EAAE,aAAa,MAAM,MAAO,cAAc,YAAY,GAAG,MAAM,OAAO,MAAM,KAAK,CAAC,EAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAQpF,CAAC,EAAE,aAAa,MAAM,MAAO,cAAc,YAAY,GAAG,MAAM,OAAO,MAAM,KAAK,CAAC,EAAG;AAAA;AAAA,uBAE5E,CAAC,EAAE,YAAY,MAAO,cAAc,KAAK,WAAY;AAAA;AAAA;AAIrE,MAAM,mBAAmB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { styled, xStyledCommonProps } from '@elliemae/ds-system';\nimport { DSButtonV3 } from '@elliemae/ds-button-v2';\nimport { DSReadMoreName, DSReadMoreSlots } from './constants/index.js';\n\nexport const StyledTextWrapper = styled('span', { name: DSReadMoreName, slot: DSReadMoreSlots.ROOT })<{\n lines: number;\n expanded: boolean;\n isSafari: boolean;\n}>`\n position: relative;\n /**\n * PUI-16110 - [ReadMore] Autotriggered-Visually broken in safari + Sequoia\n * -----------------------------------\n * In Safari 17.4+ (macOS Sequoia), using scrollHeight or offsetHeight with line-clamp\n * can break the layout and, potentially, trigger infinite loops through ResizeObserver.\n *\n * - Avoids -webkit-line-clamp: 1 which breaks layout and can cause infinite ResizeObserver loops.\n * - Instead, uses flex + white-space + overflow hidden for single-line truncation.\n */\n ${({ lines, isSafari, expanded }) =>\n lines === 1 && isSafari && !expanded\n ? `\n display: flex;\n align-items: baseline;\n white-space: nowrap;\n `\n : `\n display: -webkit-box;\n -webkit-line-clamp: ${expanded ? 'unset' : lines};\n -webkit-box-orient: vertical;\n `}\n\n -webkit-hyphens: auto;\n -moz-hyphens: auto;\n -ms-hyphens: auto;\n hyphens: auto;\n overflow-wrap: break-word;\n white-space: pre-wrap;\n ${xStyledCommonProps}\n`;\n\nexport const StyledTextContent = styled('span', { name: DSReadMoreName, slot: DSReadMoreSlots.TEXT_CONTENT })<{\n lines: number;\n expanded: boolean;\n isSafari: boolean;\n}>`\n ${({ lines, expanded, isSafari }) =>\n lines === 1 && isSafari && !expanded\n ? `\n flex: 1 1 auto;\n overflow-x: clip;\n white-space: nowrap;\n text-overflow: clip;\n `\n : ''}\n`;\n\nexport const StyledTooltipWrapper = styled('div', { name: DSReadMoreName, slot: DSReadMoreSlots.TOOLTIP_WRAPPER })`\n display: inline-block;\n`;\n\nexport const StyledButtonWrapper = styled('span', { name: DSReadMoreName, slot: DSReadMoreSlots.BUTTON_WRAPPER })<{\n expanded: boolean;\n}>`\n flex: none;\n display: -webkit-inline-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n`;\n\nexport const StyledButton = styled(DSButtonV3, { name: DSReadMoreName, slot: DSReadMoreSlots.BUTTON })<{\n withTooltip?: boolean;\n}>`\n padding: ${({ theme }) => `0 ${theme.space.xxxs}`};\n color: ${({ withTooltip, theme }) => (withTooltip ? 'inherit' : `${theme.colors.brand['600']}`)};\n border: 0;\n margin: 0;\n font-size: 12px;\n min-width: 0px;\n height: auto;\n text-transform: unset;\n &:hover:not([disabled]) {\n color: ${({ withTooltip, theme }) => (withTooltip ? 'inherit' : `${theme.colors.brand['600']}`)};\n background-color: transparent;\n text-decoration: ${({ withTooltip }) => (withTooltip ? '' : 'underline')};\n }\n`;\n\nexport const ScreenReaderOnly = styled.span`\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n height: 100%;\n overflow: hidden;\n position: absolute;\n width: 100%;\n`;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,QAAQ,0BAA0B;AAC3C,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB,uBAAuB;AAEzC,MAAM,oBAAoB,OAAO,QAAQ,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAehG,CAAC,EAAE,OAAO,UAAU,SAAS,MAC7B,UAAU,KAAK,YAAY,CAAC,WACxB;AAAA;AAAA;AAAA;AAAA,MAKA;AAAA;AAAA,0BAEkB,WAAW,UAAU,KAAK;AAAA;AAAA,GAEjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQC,kBAAkB;AAAA;AAGf,MAAM,oBAAoB,OAAO,QAAQ,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,aAAa,CAAC;AAAA,IAKxG,CAAC,EAAE,OAAO,UAAU,SAAS,MAC7B,UAAU,KAAK,YAAY,CAAC,WACxB;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,EAAE;AAAA;AAGH,MAAM,uBAAuB,OAAO,OAAO,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,gBAAgB,CAAC;AAAA;AAAA;AAI1G,MAAM,sBAAsB,OAAO,QAAQ,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,eAAe,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AASzG,MAAM,eAAe,OAAO,YAAY,EAAE,MAAM,gBAAgB,MAAM,gBAAgB,OAAO,CAAC;AAAA,aAGxF,CAAC,EAAE,MAAM,MAAM,KAAK,MAAM,MAAM,IAAI,EAAE;AAAA,WACxC,CAAC,EAAE,aAAa,MAAM,MAAO,cAAc,YAAY,GAAG,MAAM,OAAO,MAAM,KAAK,CAAC,EAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAQpF,CAAC,EAAE,aAAa,MAAM,MAAO,cAAc,YAAY,GAAG,MAAM,OAAO,MAAM,KAAK,CAAC,EAAG;AAAA;AAAA,uBAE5E,CAAC,EAAE,YAAY,MAAO,cAAc,KAAK,WAAY;AAAA;AAAA;AAIrE,MAAM,mBAAmB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -3,19 +3,21 @@ import { jsx } from "react/jsx-runtime";
3
3
  import { useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { useOnElementResize } from "./useOnElementResize.js";
5
5
  import { ScreenReaderOnly } from "./styled.js";
6
- const overflows = ({ offsetHeight, scrollHeight }) => offsetHeight + 2 < scrollHeight;
6
+ import { isSafari } from "./utils.js";
7
+ const overflows = ({ offsetHeight, scrollHeight }) => offsetHeight + 4 < scrollHeight;
7
8
  const binSearchTextOverflow = (element, parent, content) => {
8
- const text = element.innerText;
9
- let left = 1;
10
- let right = text.length;
9
+ let left = 0;
10
+ let right = content.length;
11
11
  let textEnd = 0;
12
+ element.innerText = content;
12
13
  while (left <= right) {
13
- const middle = (left + right) / 2;
14
- element.innerText = content.slice(0, middle);
15
- if (overflows(parent)) right = middle - 1;
16
- else {
17
- left = middle + 1;
18
- textEnd = middle;
14
+ const mid = Math.floor((left + right) / 2);
15
+ element.innerText = content.slice(0, mid);
16
+ if (overflows(parent)) {
17
+ right = mid - 1;
18
+ } else {
19
+ textEnd = mid;
20
+ left = mid + 1;
19
21
  }
20
22
  }
21
23
  element.innerText = content.slice(0, textEnd);
@@ -27,38 +29,49 @@ const useReadMoreTruncate = ({ lines, content }) => {
27
29
  const [showButton, setShowButton] = useState(false);
28
30
  const { width, height } = useOnElementResize(textWrapperRef);
29
31
  useLayoutEffect(() => {
30
- const textElement = textRef.current;
31
- const parentElement = textWrapperRef.current;
32
- if (parentElement && textElement) {
33
- textElement.innerText = content;
34
- if (lines === 1) {
35
- const computed = getComputedStyle(textElement);
36
- const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;
37
- const canvas = document.createElement("canvas");
38
- const ctx = canvas.getContext("2d");
39
- let isTruncated = false;
40
- if (ctx) {
41
- ctx.font = font;
42
- const measuredWidth = ctx.measureText(content).width;
43
- isTruncated = measuredWidth > parentElement.clientWidth;
44
- }
45
- setShowButton(expanded || isTruncated);
46
- return;
32
+ const textEl = textRef.current;
33
+ const wrapperEl = textWrapperRef.current;
34
+ if (!textEl || !wrapperEl) return;
35
+ textEl.innerText = content;
36
+ if (lines === 1 && isSafari()) {
37
+ const computed = getComputedStyle(textEl);
38
+ const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;
39
+ const canvas = document.createElement("canvas");
40
+ const ctx = canvas.getContext("2d");
41
+ let truncated = false;
42
+ if (ctx) {
43
+ ctx.font = font;
44
+ const measuredWidth = ctx.measureText(content).width;
45
+ truncated = measuredWidth > wrapperEl.clientWidth;
47
46
  }
48
- const isOverflowing = overflows(parentElement);
49
- setShowButton(expanded || isOverflowing);
50
- if (!expanded && isOverflowing) {
51
- binSearchTextOverflow(textElement, parentElement, content);
47
+ setShowButton(expanded || truncated);
48
+ return;
49
+ }
50
+ const isOverflowing = overflows({
51
+ offsetHeight: wrapperEl.offsetHeight,
52
+ scrollHeight: wrapperEl.scrollHeight
53
+ });
54
+ setShowButton(expanded || isOverflowing);
55
+ if (!expanded && isOverflowing) {
56
+ const doBinaryTruncate = () => {
57
+ if (!textEl || !wrapperEl) return;
58
+ requestAnimationFrame(() => {
59
+ binSearchTextOverflow(textEl, wrapperEl, content);
60
+ });
61
+ };
62
+ if ("fonts" in document && document.fonts.ready) {
63
+ document.fonts.ready.then(() => {
64
+ doBinaryTruncate();
65
+ }).catch(() => {
66
+ setTimeout(doBinaryTruncate, 0);
67
+ });
68
+ } else {
69
+ setTimeout(doBinaryTruncate, 0);
52
70
  }
53
71
  }
54
72
  }, [lines, content, expanded, width, height]);
55
73
  const srOnlyText = useMemo(() => /* @__PURE__ */ jsx(ScreenReaderOnly, { children: content }), [content]);
56
- const textProps = useMemo(
57
- () => ({
58
- "aria-hidden": true
59
- }),
60
- []
61
- );
74
+ const textProps = useMemo(() => ({ "aria-hidden": true }), []);
62
75
  return {
63
76
  textWrapperRef,
64
77
  textRef,