@elliemae/ds-read-more 3.60.0-next.43 → 3.60.0-next.45

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.
@@ -49,27 +49,21 @@ const DSReadMore = (props) => {
49
49
  const propsWithDefault = (0, import_ds_props_helpers.useMemoMergePropsWithDefault)(props, import_react_desc_prop_types.defaultProps);
50
50
  const { lines, more, less, content, withTooltip, ellipsis, onMore, onLess } = propsWithDefault;
51
51
  const xstyledProps = (0, import_ds_props_helpers.useGetXstyledProps)(propsWithDefault);
52
- const { textWrapperRef, textRef, showButton, expanded, setExpanded, textProps, srOnlyText } = (0, import_useReadMoreTruncate.useReadMoreTruncate)(propsWithDefault);
52
+ const { textWrapperRef, textRef, showButton, expanded, setExpanded } = (0, import_useReadMoreTruncate.useReadMoreTruncate)(propsWithDefault);
53
53
  const toggleExpanded = (0, import_react.useCallback)(
54
54
  (newExpanded) => {
55
55
  setExpanded(newExpanded);
56
- if (newExpanded) {
57
- onMore();
58
- } else {
59
- onLess();
60
- }
56
+ if (newExpanded) onMore();
57
+ else onLess();
61
58
  },
62
59
  [onMore, onLess, setExpanded]
63
60
  );
64
61
  const getOwnerProps = (0, import_react.useCallback)(() => propsWithDefault, [propsWithDefault]);
65
62
  const getOwnerPropsArguments = (0, import_react.useCallback)(() => ({ expanded }), [expanded]);
66
- const getReadMoreDescribedByText = (0, import_react.useCallback)(() => {
67
- if (withTooltip) {
68
- return "shows the full text for sighted users but the full text is already there for screen readers";
69
- }
63
+ const readMoreDescribedByText = (0, import_react.useMemo)(() => {
64
+ if (withTooltip) return "shows the full text for sighted users but the full text is already there for screen readers";
70
65
  return `${expanded ? "collapse" : "expand"} the full text for sighted users but the full text is already there for screen readers`;
71
66
  }, [expanded, withTooltip]);
72
- const isSafariBrowser = (0, import_react.useMemo)(() => (0, import_utils.isSafari)(), []);
73
67
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
74
68
  import_styled.StyledTextWrapper,
75
69
  {
@@ -78,22 +72,22 @@ const DSReadMore = (props) => {
78
72
  expanded,
79
73
  getOwnerProps,
80
74
  getOwnerPropsArguments,
81
- isSafari: isSafariBrowser,
75
+ isSafari: import_utils.IS_SAFARI,
82
76
  ...xstyledProps,
83
77
  children: [
84
- srOnlyText,
85
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_accessibility.ScreenReaderOnly, { id: "ds-read_more-text-disclaimer", "aria-hidden": true, children: getReadMoreDescribedByText() }),
78
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_accessibility.ScreenReaderOnly, { children: content }),
79
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_accessibility.ScreenReaderOnly, { id: "ds-read_more-text-disclaimer", "aria-hidden": true, children: readMoreDescribedByText }),
86
80
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
87
81
  import_styled.StyledTextContent,
88
82
  {
89
83
  innerRef: textRef,
90
84
  "data-testid": "ds-read_more-text",
91
- ...textProps,
85
+ "aria-hidden": true,
92
86
  getOwnerProps,
93
87
  getOwnerPropsArguments,
94
88
  lines,
95
89
  expanded,
96
- isSafari: isSafariBrowser,
90
+ isSafari: import_utils.IS_SAFARI,
97
91
  children: content
98
92
  }
99
93
  ),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/DSReadMore.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["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", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;AD4CnB;AA5CJ,8BAAiC;AACjC,8BAA2E;AAC3E,2BAA4B;AAC5B,mBAAqC;AACrC,4BAA+B;AAC/B,uBAAsD;AACtD,mCAA0E;AAC1E,oBAA2E;AAC3E,iCAAoC;AACpC,mBAAyB;AAEzB,MAAM,aAAa,CAAC,UAA6B;AAC/C,QAAM,uBAAmB,sDAAwD,OAAO,yCAAY;AACpG,QAAM,EAAE,OAAO,MAAM,MAAM,SAAS,aAAa,UAAU,QAAQ,OAAO,IAAI;AAE9E,QAAM,mBAAe,4CAAmB,gBAAgB;AAExD,QAAM,EAAE,gBAAgB,SAAS,YAAY,UAAU,aAAa,WAAW,WAAW,QACxF,gDAAoB,gBAAgB;AAEtC,QAAM,qBAAiB;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,oBAAgB,0BAAY,MAAM,kBAAkB,CAAC,gBAAgB,CAAC;AAC5E,QAAM,6BAAyB,0BAAY,OAAO,EAAE,SAAS,IAAI,CAAC,QAAQ,CAAC;AAC3E,QAAM,iCAA6B,0BAAY,MAAM;AACnD,QAAI,aAAa;AACf,aAAO;AAAA,IACT;AACA,WAAO,GAAG,WAAW,aAAa,QAAQ;AAAA,EAC5C,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,QAAM,sBAAkB,sBAAQ,UAAM,uBAAS,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,4CAAC,4CAAiB,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,uCAAsB;AAAA,YAClC;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QAGD,eAAe,cACd,4CAAC,sCAAqB,eAA8B,wBAClD,sDAAC,oCAAY,MAAM,SAAS,WAAS,MACnC;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,OAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA,YAAY,uCAAsB;AAAA,YAClC;AAAA,YACA;AAAA;AAAA,QACF,GACF,GACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,WAAW,cAAc;AACzB,MAAM,2BAAuB,kCAAS,UAAU;AAChD,qBAAqB,YAAY;AAGjC,IAAO,qBAAQ;",
4
+ "sourcesContent": ["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 { IS_SAFARI } 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 } = 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(() => ({ expanded }), [expanded]);\n\n const readMoreDescribedByText = useMemo(() => {\n if (withTooltip) return 'shows the full text for sighted users but the full text is already there for screen readers';\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 return (\n <StyledTextWrapper\n innerRef={textWrapperRef}\n lines={lines}\n expanded={expanded}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n isSafari={IS_SAFARI}\n {...xstyledProps}\n >\n <ScreenReaderOnly>{content}</ScreenReaderOnly>\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 {readMoreDescribedByText}\n </ScreenReaderOnly>\n\n <StyledTextContent\n innerRef={textRef}\n data-testid=\"ds-read_more-text\"\n aria-hidden\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n lines={lines}\n expanded={expanded}\n isSafari={IS_SAFARI}\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", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADqCnB;AArCJ,8BAAiC;AACjC,8BAA2E;AAC3E,2BAA4B;AAC5B,mBAAqC;AACrC,4BAA+B;AAC/B,uBAAsD;AACtD,mCAA0E;AAC1E,oBAA2E;AAC3E,iCAAoC;AACpC,mBAA0B;AAE1B,MAAM,aAAa,CAAC,UAA6B;AAC/C,QAAM,uBAAmB,sDAAwD,OAAO,yCAAY;AACpG,QAAM,EAAE,OAAO,MAAM,MAAM,SAAS,aAAa,UAAU,QAAQ,OAAO,IAAI;AAE9E,QAAM,mBAAe,4CAAmB,gBAAgB;AAExD,QAAM,EAAE,gBAAgB,SAAS,YAAY,UAAU,YAAY,QAAI,gDAAoB,gBAAgB;AAE3G,QAAM,qBAAiB;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,oBAAgB,0BAAY,MAAM,kBAAkB,CAAC,gBAAgB,CAAC;AAC5E,QAAM,6BAAyB,0BAAY,OAAO,EAAE,SAAS,IAAI,CAAC,QAAQ,CAAC;AAE3E,QAAM,8BAA0B,sBAAQ,MAAM;AAC5C,QAAI,YAAa,QAAO;AACxB,WAAO,GAAG,WAAW,aAAa,QAAQ;AAAA,EAC5C,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACT,GAAG;AAAA,MAEJ;AAAA,oDAAC,4CAAkB,mBAAQ;AAAA,QAM3B,4CAAC,4CAAiB,IAAG,gCAA+B,eAAW,MAC5D,mCACH;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,eAAY;AAAA,YACZ,eAAW;AAAA,YACX;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,uCAAsB;AAAA,YAClC;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QAGD,eAAe,cACd,4CAAC,sCAAqB,eAA8B,wBAClD,sDAAC,oCAAY,MAAM,SAAS,WAAS,MACnC;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,OAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA,YAAY,uCAAsB;AAAA,YAClC;AAAA,YACA;AAAA;AAAA,QACF,GACF,GACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,WAAW,cAAc;AACzB,MAAM,2BAAuB,kCAAS,UAAU;AAChD,qBAAqB,YAAY;AAGjC,IAAO,qBAAQ;",
6
6
  "names": []
7
7
  }
@@ -55,7 +55,7 @@ const MoreLessButton = (props) => {
55
55
  getOwnerProps,
56
56
  getOwnerPropsArguments,
57
57
  "aria-describedby": "ds-read_more-text-disclaimer",
58
- "aria-expanded": expanded ? "true" : "false",
58
+ "aria-expanded": expanded,
59
59
  children: label
60
60
  }
61
61
  )
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/MoreLessButton.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["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 aria-expanded={expanded ? 'true' : 'false'}\n >\n {label}\n </StyledButton>\n </StyledButtonWrapper>\n );\n};\n\nexport { MoreLessButton };\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADkBnB;AAjBJ,oBAAkD;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,oDAAC,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,YACjB,iBAAe,WAAW,SAAS;AAAA,YAElC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["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 aria-expanded={expanded}\n >\n {label}\n </StyledButton>\n </StyledButtonWrapper>\n );\n};\n\nexport { MoreLessButton };\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADkBnB;AAjBJ,oBAAkD;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,oDAAC,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,YACjB,iBAAe;AAAA,YAEd;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -65,7 +65,7 @@ const DSReadMorePropTypes = {
65
65
  content: import_ds_props_helpers.PropTypes.string.description("The text content you want displayed").isRequired,
66
66
  /** The text you want to appear when truncating */
67
67
  ellipsis: import_ds_props_helpers.PropTypes.string.description("The text you want to appear when truncating").defaultValue("..."),
68
- withTooltip: import_ds_props_helpers.PropTypes.bool.description("Whether to show expandable tooltip on ellipsis focus instead of expandable buttons").defaultValue("false"),
68
+ withTooltip: import_ds_props_helpers.PropTypes.bool.description("Whether to show expandable tooltip on ellipsis focus instead of expandable buttons").defaultValue(false),
69
69
  ...(0, import_ds_props_helpers.getPropsPerDatatestIdPropTypes)(import_constants.DSReadMoreDataTestIds)
70
70
  };
71
71
  const DSReadMorePropTypesSchema = DSReadMorePropTypes;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/react-desc-prop-types.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* 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", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADEvB,8BAMO;AAIP,uBAAuE;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,OAAG,kDAAyB,iCAAgB,gCAAe;AAAA,EAC3D,GAAG;AAAA,EACH,GAAG;AAAA;AAAA,EAEH,OAAO,kCAAU,OACd,YAAY,2EAA2E,EACvF,aAAa,CAAC;AAAA;AAAA,EAEjB,MAAM,kCAAU,OAAO,YAAY,8CAA8C,EAAE,aAAa,MAAM;AAAA;AAAA,EAEtG,MAAM,kCAAU,OAAO,YAAY,8CAA8C,EAAE,aAAa,MAAM;AAAA;AAAA,EAEtG,QAAQ,kCAAU,KAAK,YAAY,mEAAmE;AAAA;AAAA,EAEtG,QAAQ,kCAAU,KAAK,YAAY,mEAAmE;AAAA;AAAA,EAEtG,SAAS,kCAAU,OAAO,YAAY,qCAAqC,EAAE;AAAA;AAAA,EAG7E,UAAU,kCAAU,OAAO,YAAY,6CAA6C,EAAE,aAAa,KAAK;AAAA,EACxG,aAAa,kCAAU,KACpB,YAAY,oFAAoF,EAChG,aAAa,OAAO;AAAA,EACvB,OAAG,wDAA+B,sCAAqB;AACzD;AAEO,MAAM,4BAA4B;",
4
+ "sourcesContent": ["/* 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", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADEvB,8BAMO;AAIP,uBAAuE;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,OAAG,kDAAyB,iCAAgB,gCAAe;AAAA,EAC3D,GAAG;AAAA,EACH,GAAG;AAAA;AAAA,EAEH,OAAO,kCAAU,OACd,YAAY,2EAA2E,EACvF,aAAa,CAAC;AAAA;AAAA,EAEjB,MAAM,kCAAU,OAAO,YAAY,8CAA8C,EAAE,aAAa,MAAM;AAAA;AAAA,EAEtG,MAAM,kCAAU,OAAO,YAAY,8CAA8C,EAAE,aAAa,MAAM;AAAA;AAAA,EAEtG,QAAQ,kCAAU,KAAK,YAAY,mEAAmE;AAAA;AAAA,EAEtG,QAAQ,kCAAU,KAAK,YAAY,mEAAmE;AAAA;AAAA,EAEtG,SAAS,kCAAU,OAAO,YAAY,qCAAqC,EAAE;AAAA;AAAA,EAG7E,UAAU,kCAAU,OAAO,YAAY,6CAA6C,EAAE,aAAa,KAAK;AAAA,EACxG,aAAa,kCAAU,KACpB,YAAY,oFAAoF,EAChG,aAAa,KAAK;AAAA,EACrB,OAAG,wDAA+B,sCAAqB;AACzD;AAEO,MAAM,4BAA4B;",
6
6
  "names": []
7
7
  }
@@ -28,7 +28,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var styled_exports = {};
30
30
  __export(styled_exports, {
31
- ScreenReaderOnly: () => ScreenReaderOnly,
32
31
  StyledButton: () => StyledButton,
33
32
  StyledButtonWrapper: () => StyledButtonWrapper,
34
33
  StyledTextContent: () => StyledTextContent,
@@ -59,12 +58,10 @@ const StyledTextWrapper = (0, import_ds_system.styled)("span", {
59
58
  display: flex;
60
59
  align-items: baseline;
61
60
  white-space: nowrap;
62
- overflow: hidden;
63
61
  `;
64
62
  }
65
63
  return `
66
64
  display: block;
67
- overflow: hidden;
68
65
  white-space: pre-wrap;
69
66
  line-height: 1.25em;
70
67
  max-height: calc(${lines} * 1.25em);
@@ -72,7 +69,6 @@ const StyledTextWrapper = (0, import_ds_system.styled)("span", {
72
69
  }
73
70
  return `
74
71
  display: block;
75
- overflow: hidden;
76
72
  white-space: pre-wrap;
77
73
  line-height: 1.25em;
78
74
  max-height: calc(${lines} * 1.25em);
@@ -118,12 +114,4 @@ const StyledButton = (0, import_ds_system.styled)(import_ds_button_v2.DSButtonV3
118
114
  text-decoration: ${({ withTooltip }) => withTooltip ? "" : "underline"};
119
115
  }
120
116
  `;
121
- const ScreenReaderOnly = import_ds_system.styled.span`
122
- clip: rect(0 0 0 0);
123
- clip-path: inset(50%);
124
- height: 100%;
125
- overflow: hidden;
126
- position: absolute;
127
- width: 100%;
128
- `;
129
117
  //# sourceMappingURL=styled.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/styled.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["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', {\n name: DSReadMoreName,\n slot: DSReadMoreSlots.ROOT,\n})<{\n lines: number;\n expanded: boolean;\n isSafari: boolean;\n}>`\n position: relative;\n\n ${({ lines, isSafari, expanded }) => {\n if (expanded) {\n return `\n display: block;\n white-space: pre-wrap;\n `;\n }\n\n if (isSafari) {\n if (lines === 1) {\n return `\n display: flex;\n align-items: baseline;\n white-space: nowrap;\n overflow: hidden;\n `;\n }\n\n return `\n display: block;\n overflow: hidden;\n white-space: pre-wrap;\n line-height: 1.25em;\n max-height: calc(${lines} * 1.25em);\n `;\n }\n\n return `\n display: block;\n overflow: hidden;\n white-space: pre-wrap;\n line-height: 1.25em;\n max-height: calc(${lines} * 1.25em);\n `;\n }}\n\n -webkit-hyphens: auto;\n -moz-hyphens: auto;\n -ms-hyphens: auto;\n hyphens: auto;\n overflow-wrap: break-word;\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: hidden;\n white-space: nowrap;\n text-overflow: hidden;\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", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,uBAA2C;AAC3C,0BAA2B;AAC3B,uBAAgD;AAEzC,MAAM,wBAAoB,yBAAO,QAAQ;AAAA,EAC9C,MAAM;AAAA,EACN,MAAM,iCAAgB;AACxB,CAAC;AAAA;AAAA;AAAA,IAOG,CAAC,EAAE,OAAO,UAAU,SAAS,MAAM;AACnC,MAAI,UAAU;AACZ,WAAO;AAAA;AAAA;AAAA;AAAA,EAIT;AAEA,MAAI,UAAU;AACZ,QAAI,UAAU,GAAG;AACf,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMT;AAEA,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKc,KAAK;AAAA;AAAA,EAE5B;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKgB,KAAK;AAAA;AAE9B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOC,mCAAkB;AAAA;AAGf,MAAM,wBAAoB,yBAAO,QAAQ,EAAE,MAAM,iCAAgB,MAAM,iCAAgB,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,2BAAuB,yBAAO,OAAO,EAAE,MAAM,iCAAgB,MAAM,iCAAgB,gBAAgB,CAAC;AAAA;AAAA;AAI1G,MAAM,0BAAsB,yBAAO,QAAQ,EAAE,MAAM,iCAAgB,MAAM,iCAAgB,eAAe,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AASzG,MAAM,mBAAe,yBAAO,gCAAY,EAAE,MAAM,iCAAgB,MAAM,iCAAgB,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,wBAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
4
+ "sourcesContent": ["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', {\n name: DSReadMoreName,\n slot: DSReadMoreSlots.ROOT,\n})<{\n lines: number;\n expanded: boolean;\n isSafari: boolean;\n}>`\n position: relative;\n\n ${({ lines, isSafari, expanded }) => {\n if (expanded) {\n return `\n display: block;\n white-space: pre-wrap;\n `;\n }\n\n if (isSafari) {\n if (lines === 1) {\n return `\n display: flex;\n align-items: baseline;\n white-space: nowrap;\n `;\n }\n\n return `\n display: block;\n white-space: pre-wrap;\n line-height: 1.25em;\n max-height: calc(${lines} * 1.25em);\n `;\n }\n\n return `\n display: block;\n white-space: pre-wrap;\n line-height: 1.25em;\n max-height: calc(${lines} * 1.25em);\n `;\n }}\n\n -webkit-hyphens: auto;\n -moz-hyphens: auto;\n -ms-hyphens: auto;\n hyphens: auto;\n overflow-wrap: break-word;\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: hidden;\n white-space: nowrap;\n text-overflow: hidden;\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", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,uBAA2C;AAC3C,0BAA2B;AAC3B,uBAAgD;AAEzC,MAAM,wBAAoB,yBAAO,QAAQ;AAAA,EAC9C,MAAM;AAAA,EACN,MAAM,iCAAgB;AACxB,CAAC;AAAA;AAAA;AAAA,IAOG,CAAC,EAAE,OAAO,UAAU,SAAS,MAAM;AACnC,MAAI,UAAU;AACZ,WAAO;AAAA;AAAA;AAAA;AAAA,EAIT;AAEA,MAAI,UAAU;AACZ,QAAI,UAAU,GAAG;AACf,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAKT;AAEA,WAAO;AAAA;AAAA;AAAA;AAAA,2BAIc,KAAK;AAAA;AAAA,EAE5B;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA,2BAIgB,KAAK;AAAA;AAE9B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOC,mCAAkB;AAAA;AAGf,MAAM,wBAAoB,yBAAO,QAAQ,EAAE,MAAM,iCAAgB,MAAM,iCAAgB,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,2BAAuB,yBAAO,OAAO,EAAE,MAAM,iCAAgB,MAAM,iCAAgB,gBAAgB,CAAC;AAAA;AAAA;AAI1G,MAAM,0BAAsB,yBAAO,QAAQ,EAAE,MAAM,iCAAgB,MAAM,iCAAgB,eAAe,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AASzG,MAAM,mBAAe,yBAAO,gCAAY,EAAE,MAAM,iCAAgB,MAAM,iCAAgB,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;",
6
6
  "names": []
7
7
  }
@@ -32,10 +32,8 @@ __export(useReadMoreTruncate_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(useReadMoreTruncate_exports);
34
34
  var React = __toESM(require("react"));
35
- var import_jsx_runtime = require("react/jsx-runtime");
36
35
  var import_react = require("react");
37
36
  var import_useOnElementResize = require("./useOnElementResize.js");
38
- var import_styled = require("./styled.js");
39
37
  var import_utils = require("./utils.js");
40
38
  const overflows = ({ offsetHeight, scrollHeight }) => offsetHeight + 4 < scrollHeight;
41
39
  const binSearchTextOverflow = (element, parent, content) => {
@@ -55,6 +53,23 @@ const binSearchTextOverflow = (element, parent, content) => {
55
53
  }
56
54
  element.innerText = content.slice(0, textEnd);
57
55
  };
56
+ const checkSafariSingleLine = (textEl, wrapperEl, content) => {
57
+ const computed = getComputedStyle(textEl);
58
+ const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;
59
+ const canvas = document.createElement("canvas");
60
+ const ctx = canvas.getContext("2d");
61
+ if (!ctx) return false;
62
+ ctx.font = font;
63
+ return ctx.measureText(content).width > wrapperEl.clientWidth;
64
+ };
65
+ const scheduleBinaryTruncate = (textEl, wrapperEl, content) => {
66
+ const run = () => requestAnimationFrame(() => binSearchTextOverflow(textEl, wrapperEl, content));
67
+ if ("fonts" in document && document.fonts.ready) {
68
+ document.fonts.ready.then(run).catch(() => setTimeout(run, 0));
69
+ } else {
70
+ setTimeout(run, 0);
71
+ }
72
+ };
58
73
  const useReadMoreTruncate = ({ lines, content }) => {
59
74
  const textWrapperRef = (0, import_react.useRef)(null);
60
75
  const textRef = (0, import_react.useRef)(null);
@@ -66,53 +81,17 @@ const useReadMoreTruncate = ({ lines, content }) => {
66
81
  const wrapperEl = textWrapperRef.current;
67
82
  if (!textEl || !wrapperEl) return;
68
83
  textEl.innerText = content;
69
- if (lines === 1 && (0, import_utils.isSafari)()) {
70
- const computed = getComputedStyle(textEl);
71
- const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;
72
- const canvas = document.createElement("canvas");
73
- const ctx = canvas.getContext("2d");
74
- let truncated = false;
75
- if (ctx) {
76
- ctx.font = font;
77
- const measuredWidth = ctx.measureText(content).width;
78
- truncated = measuredWidth > wrapperEl.clientWidth;
79
- }
84
+ if (lines === 1 && import_utils.IS_SAFARI) {
85
+ const truncated = checkSafariSingleLine(textEl, wrapperEl, content);
80
86
  setShowButton(expanded || truncated);
81
87
  return;
82
88
  }
83
- const isOverflowing = overflows({
84
- offsetHeight: wrapperEl.offsetHeight,
85
- scrollHeight: wrapperEl.scrollHeight
86
- });
89
+ const isOverflowing = overflows({ offsetHeight: wrapperEl.offsetHeight, scrollHeight: wrapperEl.scrollHeight });
87
90
  setShowButton(expanded || isOverflowing);
88
91
  if (!expanded && isOverflowing) {
89
- const doBinaryTruncate = () => {
90
- if (!textEl || !wrapperEl) return;
91
- requestAnimationFrame(() => {
92
- binSearchTextOverflow(textEl, wrapperEl, content);
93
- });
94
- };
95
- if ("fonts" in document && document.fonts.ready) {
96
- document.fonts.ready.then(() => {
97
- doBinaryTruncate();
98
- }).catch(() => {
99
- setTimeout(doBinaryTruncate, 0);
100
- });
101
- } else {
102
- setTimeout(doBinaryTruncate, 0);
103
- }
92
+ scheduleBinaryTruncate(textEl, wrapperEl, content);
104
93
  }
105
94
  }, [lines, content, expanded, width, height]);
106
- const srOnlyText = (0, import_react.useMemo)(() => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled.ScreenReaderOnly, { children: content }), [content]);
107
- const textProps = (0, import_react.useMemo)(() => ({ "aria-hidden": true }), []);
108
- return {
109
- textWrapperRef,
110
- textRef,
111
- showButton,
112
- expanded,
113
- setExpanded,
114
- textProps,
115
- srOnlyText
116
- };
95
+ return { textWrapperRef, textRef, showButton, expanded, setExpanded };
117
96
  };
118
97
  //# sourceMappingURL=useReadMoreTruncate.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/useReadMoreTruncate.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-misused-promises */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\n// useReadMoreTruncate.tsx\nimport React, { useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { useOnElementResize } from './useOnElementResize.js';\nimport type { DSReadMoreT } from './react-desc-prop-types.js';\nimport { ScreenReaderOnly } from './styled.js';\nimport { isSafari } from './utils.js';\n\n// offsetHeight + margin/buffer to avoid subpixel errors\nconst overflows = ({ offsetHeight, scrollHeight }: { offsetHeight: number; scrollHeight: number }) =>\n offsetHeight + 4 < scrollHeight;\n\n/**\n * binSearchTextOverflow slices the content until there's no overflow.\n * It assumes `element` is the <span> node containing the text, and `parent`\n * is the wrapper with the height/clamp applied.\n */\nconst binSearchTextOverflow = (element: HTMLElement, parent: HTMLElement, content: string) => {\n let left = 0;\n let right = content.length;\n let textEnd = 0;\n\n // Place the full text before starting\n element.innerText = content;\n\n while (left <= right) {\n const mid = Math.floor((left + right) / 2);\n element.innerText = content.slice(0, mid);\n\n if (overflows(parent)) {\n // Still overflowing \u2192 reduce\n right = mid - 1;\n } else {\n // No overflow \u2192 we can increase\n textEnd = mid;\n left = mid + 1;\n }\n }\n\n element.innerText = content.slice(0, textEnd);\n};\n\nexport const useReadMoreTruncate = ({ lines, content }: Pick<DSReadMoreT.InternalProps, 'lines' | 'content'>) => {\n const textWrapperRef = useRef<HTMLSpanElement>(null);\n const textRef = useRef<HTMLSpanElement>(null);\n\n const [expanded, setExpanded] = useState(false);\n const [showButton, setShowButton] = useState(false);\n\n // Detect container size changes\n const { width, height } = useOnElementResize(textWrapperRef);\n\n useLayoutEffect(() => {\n const textEl = textRef.current;\n const wrapperEl = textWrapperRef.current;\n if (!textEl || !wrapperEl) return;\n\n // 1) Always reset the text to \"content\"\n textEl.innerText = content;\n\n // 2) Case lines === 1: measure with canvas\n if (lines === 1 && isSafari()) {\n const computed = getComputedStyle(textEl);\n const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;\n\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n let truncated = false;\n\n if (ctx) {\n ctx.font = font;\n const measuredWidth = ctx.measureText(content).width;\n truncated = measuredWidth > wrapperEl.clientWidth;\n }\n\n setShowButton(expanded || truncated);\n // No need to truncate char by char in single-line: hiding with CSS is enough.\n return;\n }\n\n // 3) For multiline: first check native overflow\n const isOverflowing = overflows({\n offsetHeight: wrapperEl.offsetHeight,\n scrollHeight: wrapperEl.scrollHeight,\n });\n setShowButton(expanded || isOverflowing);\n\n // 4) If not expanded and there is overflow, adjust the slice with binary search\n if (!expanded && isOverflowing) {\n // Function that executes binSearchTextOverflow\n const doBinaryTruncate = () => {\n if (!textEl || !wrapperEl) return;\n requestAnimationFrame(() => {\n binSearchTextOverflow(textEl, wrapperEl, content);\n });\n };\n\n // If the browser supports document.fonts, wait for them to load.\n if ('fonts' in document && document.fonts.ready) {\n document.fonts.ready\n .then(() => {\n doBinaryTruncate();\n })\n .catch(() => {\n // If fonts.ready fails, fall back to timeout\n setTimeout(doBinaryTruncate, 0);\n });\n } else {\n // Fallback for browsers without the Font Loading API\n setTimeout(doBinaryTruncate, 0);\n }\n }\n }, [lines, content, expanded, width, height]);\n\n // Hidden text for screen readers (always the full string)\n const srOnlyText = useMemo(() => <ScreenReaderOnly>{content}</ScreenReaderOnly>, [content]);\n\n // Mark the visible content as aria-hidden\n const textProps = useMemo(() => ({ 'aria-hidden': true }), []);\n\n return {\n textWrapperRef,\n textRef,\n showButton,\n expanded,\n setExpanded,\n textProps,\n srOnlyText,\n };\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADqHY;AAjHnC,mBAAkE;AAClE,gCAAmC;AAEnC,oBAAiC;AACjC,mBAAyB;AAGzB,MAAM,YAAY,CAAC,EAAE,cAAc,aAAa,MAC9C,eAAe,IAAI;AAOrB,MAAM,wBAAwB,CAAC,SAAsB,QAAqB,YAAoB;AAC5F,MAAI,OAAO;AACX,MAAI,QAAQ,QAAQ;AACpB,MAAI,UAAU;AAGd,UAAQ,YAAY;AAEpB,SAAO,QAAQ,OAAO;AACpB,UAAM,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACzC,YAAQ,YAAY,QAAQ,MAAM,GAAG,GAAG;AAExC,QAAI,UAAU,MAAM,GAAG;AAErB,cAAQ,MAAM;AAAA,IAChB,OAAO;AAEL,gBAAU;AACV,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,UAAQ,YAAY,QAAQ,MAAM,GAAG,OAAO;AAC9C;AAEO,MAAM,sBAAsB,CAAC,EAAE,OAAO,QAAQ,MAA4D;AAC/G,QAAM,qBAAiB,qBAAwB,IAAI;AACnD,QAAM,cAAU,qBAAwB,IAAI;AAE5C,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAS,KAAK;AAC9C,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,KAAK;AAGlD,QAAM,EAAE,OAAO,OAAO,QAAI,8CAAmB,cAAc;AAE3D,oCAAgB,MAAM;AACpB,UAAM,SAAS,QAAQ;AACvB,UAAM,YAAY,eAAe;AACjC,QAAI,CAAC,UAAU,CAAC,UAAW;AAG3B,WAAO,YAAY;AAGnB,QAAI,UAAU,SAAK,uBAAS,GAAG;AAC7B,YAAM,WAAW,iBAAiB,MAAM;AACxC,YAAM,OAAO,GAAG,SAAS,UAAU,IAAI,SAAS,QAAQ,IAAI,SAAS,UAAU;AAE/E,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,YAAM,MAAM,OAAO,WAAW,IAAI;AAClC,UAAI,YAAY;AAEhB,UAAI,KAAK;AACP,YAAI,OAAO;AACX,cAAM,gBAAgB,IAAI,YAAY,OAAO,EAAE;AAC/C,oBAAY,gBAAgB,UAAU;AAAA,MACxC;AAEA,oBAAc,YAAY,SAAS;AAEnC;AAAA,IACF;AAGA,UAAM,gBAAgB,UAAU;AAAA,MAC9B,cAAc,UAAU;AAAA,MACxB,cAAc,UAAU;AAAA,IAC1B,CAAC;AACD,kBAAc,YAAY,aAAa;AAGvC,QAAI,CAAC,YAAY,eAAe;AAE9B,YAAM,mBAAmB,MAAM;AAC7B,YAAI,CAAC,UAAU,CAAC,UAAW;AAC3B,8BAAsB,MAAM;AAC1B,gCAAsB,QAAQ,WAAW,OAAO;AAAA,QAClD,CAAC;AAAA,MACH;AAGA,UAAI,WAAW,YAAY,SAAS,MAAM,OAAO;AAC/C,iBAAS,MAAM,MACZ,KAAK,MAAM;AACV,2BAAiB;AAAA,QACnB,CAAC,EACA,MAAM,MAAM;AAEX,qBAAW,kBAAkB,CAAC;AAAA,QAChC,CAAC;AAAA,MACL,OAAO;AAEL,mBAAW,kBAAkB,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,SAAS,UAAU,OAAO,MAAM,CAAC;AAG5C,QAAM,iBAAa,sBAAQ,MAAM,4CAAC,kCAAkB,mBAAQ,GAAqB,CAAC,OAAO,CAAC;AAG1F,QAAM,gBAAY,sBAAQ,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC,CAAC;AAE7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { useLayoutEffect, useRef, useState } from 'react';\nimport { useOnElementResize } from './useOnElementResize.js';\nimport type { DSReadMoreT } from './react-desc-prop-types.js';\nimport { IS_SAFARI } from './utils.js';\n\n// offsetHeight + margin/buffer to avoid subpixel errors\nconst overflows = ({ offsetHeight, scrollHeight }: { offsetHeight: number; scrollHeight: number }) =>\n offsetHeight + 4 < scrollHeight;\n\n/**\n * binSearchTextOverflow slices the content until there's no overflow.\n * It assumes `element` is the <span> node containing the text, and `parent`\n * is the wrapper with the height/clamp applied.\n */\nconst binSearchTextOverflow = (element: HTMLElement, parent: HTMLElement, content: string) => {\n let left = 0;\n let right = content.length;\n let textEnd = 0;\n\n element.innerText = content;\n\n while (left <= right) {\n const mid = Math.floor((left + right) / 2);\n element.innerText = content.slice(0, mid);\n\n if (overflows(parent)) {\n right = mid - 1;\n } else {\n textEnd = mid;\n left = mid + 1;\n }\n }\n\n element.innerText = content.slice(0, textEnd);\n};\n\nconst checkSafariSingleLine = (textEl: HTMLElement, wrapperEl: HTMLElement, content: string): boolean => {\n const computed = getComputedStyle(textEl);\n const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (!ctx) return false;\n ctx.font = font;\n return ctx.measureText(content).width > wrapperEl.clientWidth;\n};\n\nconst scheduleBinaryTruncate = (textEl: HTMLElement, wrapperEl: HTMLElement, content: string) => {\n const run = () => requestAnimationFrame(() => binSearchTextOverflow(textEl, wrapperEl, content));\n if ('fonts' in document && document.fonts.ready) {\n document.fonts.ready.then(run).catch(() => setTimeout(run, 0));\n } else {\n setTimeout(run, 0);\n }\n};\n\nexport const useReadMoreTruncate = ({ lines, content }: Pick<DSReadMoreT.InternalProps, 'lines' | 'content'>) => {\n const textWrapperRef = useRef<HTMLSpanElement>(null);\n const textRef = useRef<HTMLSpanElement>(null);\n\n const [expanded, setExpanded] = useState(false);\n const [showButton, setShowButton] = useState(false);\n\n const { width, height } = useOnElementResize(textWrapperRef);\n\n useLayoutEffect(() => {\n const textEl = textRef.current;\n const wrapperEl = textWrapperRef.current;\n if (!textEl || !wrapperEl) return;\n\n textEl.innerText = content;\n\n if (lines === 1 && IS_SAFARI) {\n const truncated = checkSafariSingleLine(textEl, wrapperEl, content);\n setShowButton(expanded || truncated);\n return;\n }\n\n const isOverflowing = overflows({ offsetHeight: wrapperEl.offsetHeight, scrollHeight: wrapperEl.scrollHeight });\n setShowButton(expanded || isOverflowing);\n\n if (!expanded && isOverflowing) {\n scheduleBinaryTruncate(textEl, wrapperEl, content);\n }\n }, [lines, content, expanded, width, height]);\n\n return { textWrapperRef, textRef, showButton, expanded, setExpanded };\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAkD;AAClD,gCAAmC;AAEnC,mBAA0B;AAG1B,MAAM,YAAY,CAAC,EAAE,cAAc,aAAa,MAC9C,eAAe,IAAI;AAOrB,MAAM,wBAAwB,CAAC,SAAsB,QAAqB,YAAoB;AAC5F,MAAI,OAAO;AACX,MAAI,QAAQ,QAAQ;AACpB,MAAI,UAAU;AAEd,UAAQ,YAAY;AAEpB,SAAO,QAAQ,OAAO;AACpB,UAAM,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACzC,YAAQ,YAAY,QAAQ,MAAM,GAAG,GAAG;AAExC,QAAI,UAAU,MAAM,GAAG;AACrB,cAAQ,MAAM;AAAA,IAChB,OAAO;AACL,gBAAU;AACV,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,UAAQ,YAAY,QAAQ,MAAM,GAAG,OAAO;AAC9C;AAEA,MAAM,wBAAwB,CAAC,QAAqB,WAAwB,YAA6B;AACvG,QAAM,WAAW,iBAAiB,MAAM;AACxC,QAAM,OAAO,GAAG,SAAS,UAAU,IAAI,SAAS,QAAQ,IAAI,SAAS,UAAU;AAC/E,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,QAAM,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,OAAO;AACX,SAAO,IAAI,YAAY,OAAO,EAAE,QAAQ,UAAU;AACpD;AAEA,MAAM,yBAAyB,CAAC,QAAqB,WAAwB,YAAoB;AAC/F,QAAM,MAAM,MAAM,sBAAsB,MAAM,sBAAsB,QAAQ,WAAW,OAAO,CAAC;AAC/F,MAAI,WAAW,YAAY,SAAS,MAAM,OAAO;AAC/C,aAAS,MAAM,MAAM,KAAK,GAAG,EAAE,MAAM,MAAM,WAAW,KAAK,CAAC,CAAC;AAAA,EAC/D,OAAO;AACL,eAAW,KAAK,CAAC;AAAA,EACnB;AACF;AAEO,MAAM,sBAAsB,CAAC,EAAE,OAAO,QAAQ,MAA4D;AAC/G,QAAM,qBAAiB,qBAAwB,IAAI;AACnD,QAAM,cAAU,qBAAwB,IAAI;AAE5C,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAS,KAAK;AAC9C,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,KAAK;AAElD,QAAM,EAAE,OAAO,OAAO,QAAI,8CAAmB,cAAc;AAE3D,oCAAgB,MAAM;AACpB,UAAM,SAAS,QAAQ;AACvB,UAAM,YAAY,eAAe;AACjC,QAAI,CAAC,UAAU,CAAC,UAAW;AAE3B,WAAO,YAAY;AAEnB,QAAI,UAAU,KAAK,wBAAW;AAC5B,YAAM,YAAY,sBAAsB,QAAQ,WAAW,OAAO;AAClE,oBAAc,YAAY,SAAS;AACnC;AAAA,IACF;AAEA,UAAM,gBAAgB,UAAU,EAAE,cAAc,UAAU,cAAc,cAAc,UAAU,aAAa,CAAC;AAC9G,kBAAc,YAAY,aAAa;AAEvC,QAAI,CAAC,YAAY,eAAe;AAC9B,6BAAuB,QAAQ,WAAW,OAAO;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,OAAO,SAAS,UAAU,OAAO,MAAM,CAAC;AAE5C,SAAO,EAAE,gBAAgB,SAAS,YAAY,UAAU,YAAY;AACtE;",
6
6
  "names": []
7
7
  }
package/dist/cjs/utils.js CHANGED
@@ -28,6 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var utils_exports = {};
30
30
  __export(utils_exports, {
31
+ IS_SAFARI: () => IS_SAFARI,
31
32
  isSafari: () => isSafari
32
33
  });
33
34
  module.exports = __toCommonJS(utils_exports);
@@ -37,4 +38,5 @@ const isSafari = () => {
37
38
  const ua = navigator.userAgent;
38
39
  return /safari/i.test(ua) && !/chrome|chromium|android/i.test(ua);
39
40
  };
41
+ const IS_SAFARI = isSafari();
40
42
  //# sourceMappingURL=utils.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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;",
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 */\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\n/** Evaluated once at module load \u2014 safe for SSR (returns false when navigator is unavailable). */\nexport const IS_SAFARI = isSafari();\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADWhB,MAAM,WAAW,MAAM;AAC5B,MAAI,OAAO,cAAc,YAAa,QAAO;AAE7C,QAAM,KAAK,UAAU;AAErB,SAAO,UAAU,KAAK,EAAE,KAAK,CAAC,2BAA2B,KAAK,EAAE;AAClE;AAGO,MAAM,YAAY,SAAS;",
6
6
  "names": []
7
7
  }
@@ -9,32 +9,26 @@ import { DSReadMoreDataTestIds, DSReadMoreName } from "./constants/index.js";
9
9
  import { DSReadMorePropTypesSchema, defaultProps } from "./react-desc-prop-types.js";
10
10
  import { StyledTextContent, StyledTextWrapper, StyledTooltipWrapper } from "./styled.js";
11
11
  import { useReadMoreTruncate } from "./useReadMoreTruncate.js";
12
- import { isSafari } from "./utils.js";
12
+ import { IS_SAFARI } from "./utils.js";
13
13
  const DSReadMore = (props) => {
14
14
  const propsWithDefault = useMemoMergePropsWithDefault(props, defaultProps);
15
15
  const { lines, more, less, content, withTooltip, ellipsis, onMore, onLess } = propsWithDefault;
16
16
  const xstyledProps = useGetXstyledProps(propsWithDefault);
17
- const { textWrapperRef, textRef, showButton, expanded, setExpanded, textProps, srOnlyText } = useReadMoreTruncate(propsWithDefault);
17
+ const { textWrapperRef, textRef, showButton, expanded, setExpanded } = useReadMoreTruncate(propsWithDefault);
18
18
  const toggleExpanded = useCallback(
19
19
  (newExpanded) => {
20
20
  setExpanded(newExpanded);
21
- if (newExpanded) {
22
- onMore();
23
- } else {
24
- onLess();
25
- }
21
+ if (newExpanded) onMore();
22
+ else onLess();
26
23
  },
27
24
  [onMore, onLess, setExpanded]
28
25
  );
29
26
  const getOwnerProps = useCallback(() => propsWithDefault, [propsWithDefault]);
30
27
  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
- }
28
+ const readMoreDescribedByText = useMemo(() => {
29
+ if (withTooltip) return "shows the full text for sighted users but the full text is already there for screen readers";
35
30
  return `${expanded ? "collapse" : "expand"} the full text for sighted users but the full text is already there for screen readers`;
36
31
  }, [expanded, withTooltip]);
37
- const isSafariBrowser = useMemo(() => isSafari(), []);
38
32
  return /* @__PURE__ */ jsxs(
39
33
  StyledTextWrapper,
40
34
  {
@@ -43,22 +37,22 @@ const DSReadMore = (props) => {
43
37
  expanded,
44
38
  getOwnerProps,
45
39
  getOwnerPropsArguments,
46
- isSafari: isSafariBrowser,
40
+ isSafari: IS_SAFARI,
47
41
  ...xstyledProps,
48
42
  children: [
49
- srOnlyText,
50
- /* @__PURE__ */ jsx(ScreenReaderOnly, { id: "ds-read_more-text-disclaimer", "aria-hidden": true, children: getReadMoreDescribedByText() }),
43
+ /* @__PURE__ */ jsx(ScreenReaderOnly, { children: content }),
44
+ /* @__PURE__ */ jsx(ScreenReaderOnly, { id: "ds-read_more-text-disclaimer", "aria-hidden": true, children: readMoreDescribedByText }),
51
45
  /* @__PURE__ */ jsx(
52
46
  StyledTextContent,
53
47
  {
54
48
  innerRef: textRef,
55
49
  "data-testid": "ds-read_more-text",
56
- ...textProps,
50
+ "aria-hidden": true,
57
51
  getOwnerProps,
58
52
  getOwnerPropsArguments,
59
53
  lines,
60
54
  expanded,
61
- isSafari: isSafariBrowser,
55
+ isSafari: IS_SAFARI,
62
56
  children: content
63
57
  }
64
58
  ),
@@ -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 { 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;",
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 { IS_SAFARI } 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 } = 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(() => ({ expanded }), [expanded]);\n\n const readMoreDescribedByText = useMemo(() => {\n if (withTooltip) return 'shows the full text for sighted users but the full text is already there for screen readers';\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 return (\n <StyledTextWrapper\n innerRef={textWrapperRef}\n lines={lines}\n expanded={expanded}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n isSafari={IS_SAFARI}\n {...xstyledProps}\n >\n <ScreenReaderOnly>{content}</ScreenReaderOnly>\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 {readMoreDescribedByText}\n </ScreenReaderOnly>\n\n <StyledTextContent\n innerRef={textRef}\n data-testid=\"ds-read_more-text\"\n aria-hidden\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n lines={lines}\n expanded={expanded}\n isSafari={IS_SAFARI}\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;ACqCnB,SASE,KATF;AArCJ,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,iBAAiB;AAE1B,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,YAAY,IAAI,oBAAoB,gBAAgB;AAE3G,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,EAAE,SAAS,IAAI,CAAC,QAAQ,CAAC;AAE3E,QAAM,0BAA0B,QAAQ,MAAM;AAC5C,QAAI,YAAa,QAAO;AACxB,WAAO,GAAG,WAAW,aAAa,QAAQ;AAAA,EAC5C,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACT,GAAG;AAAA,MAEJ;AAAA,4BAAC,oBAAkB,mBAAQ;AAAA,QAM3B,oBAAC,oBAAiB,IAAG,gCAA+B,eAAW,MAC5D,mCACH;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,eAAY;AAAA,YACZ,eAAW;AAAA,YACX;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
  }
@@ -22,7 +22,7 @@ const MoreLessButton = (props) => {
22
22
  getOwnerProps,
23
23
  getOwnerPropsArguments,
24
24
  "aria-describedby": "ds-read_more-text-disclaimer",
25
- "aria-expanded": expanded ? "true" : "false",
25
+ "aria-expanded": expanded,
26
26
  children: label
27
27
  }
28
28
  )
@@ -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 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 aria-expanded={expanded ? 'true' : 'false'}\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,YACjB,iBAAe,WAAW,SAAS;AAAA,YAElC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;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 aria-expanded={expanded}\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,YACjB,iBAAe;AAAA,YAEd;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -36,7 +36,7 @@ const DSReadMorePropTypes = {
36
36
  content: PropTypes.string.description("The text content you want displayed").isRequired,
37
37
  /** The text you want to appear when truncating */
38
38
  ellipsis: PropTypes.string.description("The text you want to appear when truncating").defaultValue("..."),
39
- withTooltip: PropTypes.bool.description("Whether to show expandable tooltip on ellipsis focus instead of expandable buttons").defaultValue("false"),
39
+ withTooltip: PropTypes.bool.description("Whether to show expandable tooltip on ellipsis focus instead of expandable buttons").defaultValue(false),
40
40
  ...getPropsPerDatatestIdPropTypes(DSReadMoreDataTestIds)
41
41
  };
42
42
  const DSReadMorePropTypesSchema = DSReadMorePropTypes;
@@ -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 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;",
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,KAAK;AAAA,EACrB,GAAG,+BAA+B,qBAAqB;AACzD;AAEO,MAAM,4BAA4B;",
6
6
  "names": []
7
7
  }
@@ -21,12 +21,10 @@ const StyledTextWrapper = styled("span", {
21
21
  display: flex;
22
22
  align-items: baseline;
23
23
  white-space: nowrap;
24
- overflow: hidden;
25
24
  `;
26
25
  }
27
26
  return `
28
27
  display: block;
29
- overflow: hidden;
30
28
  white-space: pre-wrap;
31
29
  line-height: 1.25em;
32
30
  max-height: calc(${lines} * 1.25em);
@@ -34,7 +32,6 @@ const StyledTextWrapper = styled("span", {
34
32
  }
35
33
  return `
36
34
  display: block;
37
- overflow: hidden;
38
35
  white-space: pre-wrap;
39
36
  line-height: 1.25em;
40
37
  max-height: calc(${lines} * 1.25em);
@@ -80,16 +77,7 @@ const StyledButton = styled(DSButtonV3, { name: DSReadMoreName, slot: DSReadMore
80
77
  text-decoration: ${({ withTooltip }) => withTooltip ? "" : "underline"};
81
78
  }
82
79
  `;
83
- const ScreenReaderOnly = styled.span`
84
- clip: rect(0 0 0 0);
85
- clip-path: inset(50%);
86
- height: 100%;
87
- overflow: hidden;
88
- position: absolute;
89
- width: 100%;
90
- `;
91
80
  export {
92
- ScreenReaderOnly,
93
81
  StyledButton,
94
82
  StyledButtonWrapper,
95
83
  StyledTextContent,
@@ -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 { DSButtonV3 } from '@elliemae/ds-button-v2';\nimport { DSReadMoreName, DSReadMoreSlots } from './constants/index.js';\n\nexport const StyledTextWrapper = styled('span', {\n name: DSReadMoreName,\n slot: DSReadMoreSlots.ROOT,\n})<{\n lines: number;\n expanded: boolean;\n isSafari: boolean;\n}>`\n position: relative;\n\n ${({ lines, isSafari, expanded }) => {\n if (expanded) {\n return `\n display: block;\n white-space: pre-wrap;\n `;\n }\n\n if (isSafari) {\n if (lines === 1) {\n return `\n display: flex;\n align-items: baseline;\n white-space: nowrap;\n overflow: hidden;\n `;\n }\n\n return `\n display: block;\n overflow: hidden;\n white-space: pre-wrap;\n line-height: 1.25em;\n max-height: calc(${lines} * 1.25em);\n `;\n }\n\n return `\n display: block;\n overflow: hidden;\n white-space: pre-wrap;\n line-height: 1.25em;\n max-height: calc(${lines} * 1.25em);\n `;\n }}\n\n -webkit-hyphens: auto;\n -moz-hyphens: auto;\n -ms-hyphens: auto;\n hyphens: auto;\n overflow-wrap: break-word;\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: hidden;\n white-space: nowrap;\n text-overflow: hidden;\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;AAAA,EAC9C,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAAA;AAAA;AAAA,IAOG,CAAC,EAAE,OAAO,UAAU,SAAS,MAAM;AACnC,MAAI,UAAU;AACZ,WAAO;AAAA;AAAA;AAAA;AAAA,EAIT;AAEA,MAAI,UAAU;AACZ,QAAI,UAAU,GAAG;AACf,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMT;AAEA,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKc,KAAK;AAAA;AAAA,EAE5B;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKgB,KAAK;AAAA;AAE9B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOC,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;",
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', {\n name: DSReadMoreName,\n slot: DSReadMoreSlots.ROOT,\n})<{\n lines: number;\n expanded: boolean;\n isSafari: boolean;\n}>`\n position: relative;\n\n ${({ lines, isSafari, expanded }) => {\n if (expanded) {\n return `\n display: block;\n white-space: pre-wrap;\n `;\n }\n\n if (isSafari) {\n if (lines === 1) {\n return `\n display: flex;\n align-items: baseline;\n white-space: nowrap;\n `;\n }\n\n return `\n display: block;\n white-space: pre-wrap;\n line-height: 1.25em;\n max-height: calc(${lines} * 1.25em);\n `;\n }\n\n return `\n display: block;\n white-space: pre-wrap;\n line-height: 1.25em;\n max-height: calc(${lines} * 1.25em);\n `;\n }}\n\n -webkit-hyphens: auto;\n -moz-hyphens: auto;\n -ms-hyphens: auto;\n hyphens: auto;\n overflow-wrap: break-word;\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: hidden;\n white-space: nowrap;\n text-overflow: hidden;\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"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,QAAQ,0BAA0B;AAC3C,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB,uBAAuB;AAEzC,MAAM,oBAAoB,OAAO,QAAQ;AAAA,EAC9C,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAAA;AAAA;AAAA,IAOG,CAAC,EAAE,OAAO,UAAU,SAAS,MAAM;AACnC,MAAI,UAAU;AACZ,WAAO;AAAA;AAAA;AAAA;AAAA,EAIT;AAEA,MAAI,UAAU;AACZ,QAAI,UAAU,GAAG;AACf,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAKT;AAEA,WAAO;AAAA;AAAA;AAAA;AAAA,2BAIc,KAAK;AAAA;AAAA,EAE5B;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA,2BAIgB,KAAK;AAAA;AAE9B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOC,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;",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,7 @@
1
1
  import * as React from "react";
2
- import { jsx } from "react/jsx-runtime";
3
- import { useLayoutEffect, useMemo, useRef, useState } from "react";
2
+ import { useLayoutEffect, useRef, useState } from "react";
4
3
  import { useOnElementResize } from "./useOnElementResize.js";
5
- import { ScreenReaderOnly } from "./styled.js";
6
- import { isSafari } from "./utils.js";
4
+ import { IS_SAFARI } from "./utils.js";
7
5
  const overflows = ({ offsetHeight, scrollHeight }) => offsetHeight + 4 < scrollHeight;
8
6
  const binSearchTextOverflow = (element, parent, content) => {
9
7
  let left = 0;
@@ -22,6 +20,23 @@ const binSearchTextOverflow = (element, parent, content) => {
22
20
  }
23
21
  element.innerText = content.slice(0, textEnd);
24
22
  };
23
+ const checkSafariSingleLine = (textEl, wrapperEl, content) => {
24
+ const computed = getComputedStyle(textEl);
25
+ const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;
26
+ const canvas = document.createElement("canvas");
27
+ const ctx = canvas.getContext("2d");
28
+ if (!ctx) return false;
29
+ ctx.font = font;
30
+ return ctx.measureText(content).width > wrapperEl.clientWidth;
31
+ };
32
+ const scheduleBinaryTruncate = (textEl, wrapperEl, content) => {
33
+ const run = () => requestAnimationFrame(() => binSearchTextOverflow(textEl, wrapperEl, content));
34
+ if ("fonts" in document && document.fonts.ready) {
35
+ document.fonts.ready.then(run).catch(() => setTimeout(run, 0));
36
+ } else {
37
+ setTimeout(run, 0);
38
+ }
39
+ };
25
40
  const useReadMoreTruncate = ({ lines, content }) => {
26
41
  const textWrapperRef = useRef(null);
27
42
  const textRef = useRef(null);
@@ -33,54 +48,18 @@ const useReadMoreTruncate = ({ lines, content }) => {
33
48
  const wrapperEl = textWrapperRef.current;
34
49
  if (!textEl || !wrapperEl) return;
35
50
  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;
46
- }
51
+ if (lines === 1 && IS_SAFARI) {
52
+ const truncated = checkSafariSingleLine(textEl, wrapperEl, content);
47
53
  setShowButton(expanded || truncated);
48
54
  return;
49
55
  }
50
- const isOverflowing = overflows({
51
- offsetHeight: wrapperEl.offsetHeight,
52
- scrollHeight: wrapperEl.scrollHeight
53
- });
56
+ const isOverflowing = overflows({ offsetHeight: wrapperEl.offsetHeight, scrollHeight: wrapperEl.scrollHeight });
54
57
  setShowButton(expanded || isOverflowing);
55
58
  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);
70
- }
59
+ scheduleBinaryTruncate(textEl, wrapperEl, content);
71
60
  }
72
61
  }, [lines, content, expanded, width, height]);
73
- const srOnlyText = useMemo(() => /* @__PURE__ */ jsx(ScreenReaderOnly, { children: content }), [content]);
74
- const textProps = useMemo(() => ({ "aria-hidden": true }), []);
75
- return {
76
- textWrapperRef,
77
- textRef,
78
- showButton,
79
- expanded,
80
- setExpanded,
81
- textProps,
82
- srOnlyText
83
- };
62
+ return { textWrapperRef, textRef, showButton, expanded, setExpanded };
84
63
  };
85
64
  export {
86
65
  useReadMoreTruncate
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/useReadMoreTruncate.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-misused-promises */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\n// useReadMoreTruncate.tsx\nimport React, { useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { useOnElementResize } from './useOnElementResize.js';\nimport type { DSReadMoreT } from './react-desc-prop-types.js';\nimport { ScreenReaderOnly } from './styled.js';\nimport { isSafari } from './utils.js';\n\n// offsetHeight + margin/buffer to avoid subpixel errors\nconst overflows = ({ offsetHeight, scrollHeight }: { offsetHeight: number; scrollHeight: number }) =>\n offsetHeight + 4 < scrollHeight;\n\n/**\n * binSearchTextOverflow slices the content until there's no overflow.\n * It assumes `element` is the <span> node containing the text, and `parent`\n * is the wrapper with the height/clamp applied.\n */\nconst binSearchTextOverflow = (element: HTMLElement, parent: HTMLElement, content: string) => {\n let left = 0;\n let right = content.length;\n let textEnd = 0;\n\n // Place the full text before starting\n element.innerText = content;\n\n while (left <= right) {\n const mid = Math.floor((left + right) / 2);\n element.innerText = content.slice(0, mid);\n\n if (overflows(parent)) {\n // Still overflowing \u2192 reduce\n right = mid - 1;\n } else {\n // No overflow \u2192 we can increase\n textEnd = mid;\n left = mid + 1;\n }\n }\n\n element.innerText = content.slice(0, textEnd);\n};\n\nexport const useReadMoreTruncate = ({ lines, content }: Pick<DSReadMoreT.InternalProps, 'lines' | 'content'>) => {\n const textWrapperRef = useRef<HTMLSpanElement>(null);\n const textRef = useRef<HTMLSpanElement>(null);\n\n const [expanded, setExpanded] = useState(false);\n const [showButton, setShowButton] = useState(false);\n\n // Detect container size changes\n const { width, height } = useOnElementResize(textWrapperRef);\n\n useLayoutEffect(() => {\n const textEl = textRef.current;\n const wrapperEl = textWrapperRef.current;\n if (!textEl || !wrapperEl) return;\n\n // 1) Always reset the text to \"content\"\n textEl.innerText = content;\n\n // 2) Case lines === 1: measure with canvas\n if (lines === 1 && isSafari()) {\n const computed = getComputedStyle(textEl);\n const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;\n\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n let truncated = false;\n\n if (ctx) {\n ctx.font = font;\n const measuredWidth = ctx.measureText(content).width;\n truncated = measuredWidth > wrapperEl.clientWidth;\n }\n\n setShowButton(expanded || truncated);\n // No need to truncate char by char in single-line: hiding with CSS is enough.\n return;\n }\n\n // 3) For multiline: first check native overflow\n const isOverflowing = overflows({\n offsetHeight: wrapperEl.offsetHeight,\n scrollHeight: wrapperEl.scrollHeight,\n });\n setShowButton(expanded || isOverflowing);\n\n // 4) If not expanded and there is overflow, adjust the slice with binary search\n if (!expanded && isOverflowing) {\n // Function that executes binSearchTextOverflow\n const doBinaryTruncate = () => {\n if (!textEl || !wrapperEl) return;\n requestAnimationFrame(() => {\n binSearchTextOverflow(textEl, wrapperEl, content);\n });\n };\n\n // If the browser supports document.fonts, wait for them to load.\n if ('fonts' in document && document.fonts.ready) {\n document.fonts.ready\n .then(() => {\n doBinaryTruncate();\n })\n .catch(() => {\n // If fonts.ready fails, fall back to timeout\n setTimeout(doBinaryTruncate, 0);\n });\n } else {\n // Fallback for browsers without the Font Loading API\n setTimeout(doBinaryTruncate, 0);\n }\n }\n }, [lines, content, expanded, width, height]);\n\n // Hidden text for screen readers (always the full string)\n const srOnlyText = useMemo(() => <ScreenReaderOnly>{content}</ScreenReaderOnly>, [content]);\n\n // Mark the visible content as aria-hidden\n const textProps = useMemo(() => ({ 'aria-hidden': true }), []);\n\n return {\n textWrapperRef,\n textRef,\n showButton,\n expanded,\n setExpanded,\n textProps,\n srOnlyText,\n };\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACqHY;AAjHnC,SAAgB,iBAAiB,SAAS,QAAQ,gBAAgB;AAClE,SAAS,0BAA0B;AAEnC,SAAS,wBAAwB;AACjC,SAAS,gBAAgB;AAGzB,MAAM,YAAY,CAAC,EAAE,cAAc,aAAa,MAC9C,eAAe,IAAI;AAOrB,MAAM,wBAAwB,CAAC,SAAsB,QAAqB,YAAoB;AAC5F,MAAI,OAAO;AACX,MAAI,QAAQ,QAAQ;AACpB,MAAI,UAAU;AAGd,UAAQ,YAAY;AAEpB,SAAO,QAAQ,OAAO;AACpB,UAAM,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACzC,YAAQ,YAAY,QAAQ,MAAM,GAAG,GAAG;AAExC,QAAI,UAAU,MAAM,GAAG;AAErB,cAAQ,MAAM;AAAA,IAChB,OAAO;AAEL,gBAAU;AACV,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,UAAQ,YAAY,QAAQ,MAAM,GAAG,OAAO;AAC9C;AAEO,MAAM,sBAAsB,CAAC,EAAE,OAAO,QAAQ,MAA4D;AAC/G,QAAM,iBAAiB,OAAwB,IAAI;AACnD,QAAM,UAAU,OAAwB,IAAI;AAE5C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAGlD,QAAM,EAAE,OAAO,OAAO,IAAI,mBAAmB,cAAc;AAE3D,kBAAgB,MAAM;AACpB,UAAM,SAAS,QAAQ;AACvB,UAAM,YAAY,eAAe;AACjC,QAAI,CAAC,UAAU,CAAC,UAAW;AAG3B,WAAO,YAAY;AAGnB,QAAI,UAAU,KAAK,SAAS,GAAG;AAC7B,YAAM,WAAW,iBAAiB,MAAM;AACxC,YAAM,OAAO,GAAG,SAAS,UAAU,IAAI,SAAS,QAAQ,IAAI,SAAS,UAAU;AAE/E,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,YAAM,MAAM,OAAO,WAAW,IAAI;AAClC,UAAI,YAAY;AAEhB,UAAI,KAAK;AACP,YAAI,OAAO;AACX,cAAM,gBAAgB,IAAI,YAAY,OAAO,EAAE;AAC/C,oBAAY,gBAAgB,UAAU;AAAA,MACxC;AAEA,oBAAc,YAAY,SAAS;AAEnC;AAAA,IACF;AAGA,UAAM,gBAAgB,UAAU;AAAA,MAC9B,cAAc,UAAU;AAAA,MACxB,cAAc,UAAU;AAAA,IAC1B,CAAC;AACD,kBAAc,YAAY,aAAa;AAGvC,QAAI,CAAC,YAAY,eAAe;AAE9B,YAAM,mBAAmB,MAAM;AAC7B,YAAI,CAAC,UAAU,CAAC,UAAW;AAC3B,8BAAsB,MAAM;AAC1B,gCAAsB,QAAQ,WAAW,OAAO;AAAA,QAClD,CAAC;AAAA,MACH;AAGA,UAAI,WAAW,YAAY,SAAS,MAAM,OAAO;AAC/C,iBAAS,MAAM,MACZ,KAAK,MAAM;AACV,2BAAiB;AAAA,QACnB,CAAC,EACA,MAAM,MAAM;AAEX,qBAAW,kBAAkB,CAAC;AAAA,QAChC,CAAC;AAAA,MACL,OAAO;AAEL,mBAAW,kBAAkB,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,SAAS,UAAU,OAAO,MAAM,CAAC;AAG5C,QAAM,aAAa,QAAQ,MAAM,oBAAC,oBAAkB,mBAAQ,GAAqB,CAAC,OAAO,CAAC;AAG1F,QAAM,YAAY,QAAQ,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC,CAAC;AAE7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { useLayoutEffect, useRef, useState } from 'react';\nimport { useOnElementResize } from './useOnElementResize.js';\nimport type { DSReadMoreT } from './react-desc-prop-types.js';\nimport { IS_SAFARI } from './utils.js';\n\n// offsetHeight + margin/buffer to avoid subpixel errors\nconst overflows = ({ offsetHeight, scrollHeight }: { offsetHeight: number; scrollHeight: number }) =>\n offsetHeight + 4 < scrollHeight;\n\n/**\n * binSearchTextOverflow slices the content until there's no overflow.\n * It assumes `element` is the <span> node containing the text, and `parent`\n * is the wrapper with the height/clamp applied.\n */\nconst binSearchTextOverflow = (element: HTMLElement, parent: HTMLElement, content: string) => {\n let left = 0;\n let right = content.length;\n let textEnd = 0;\n\n element.innerText = content;\n\n while (left <= right) {\n const mid = Math.floor((left + right) / 2);\n element.innerText = content.slice(0, mid);\n\n if (overflows(parent)) {\n right = mid - 1;\n } else {\n textEnd = mid;\n left = mid + 1;\n }\n }\n\n element.innerText = content.slice(0, textEnd);\n};\n\nconst checkSafariSingleLine = (textEl: HTMLElement, wrapperEl: HTMLElement, content: string): boolean => {\n const computed = getComputedStyle(textEl);\n const font = `${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (!ctx) return false;\n ctx.font = font;\n return ctx.measureText(content).width > wrapperEl.clientWidth;\n};\n\nconst scheduleBinaryTruncate = (textEl: HTMLElement, wrapperEl: HTMLElement, content: string) => {\n const run = () => requestAnimationFrame(() => binSearchTextOverflow(textEl, wrapperEl, content));\n if ('fonts' in document && document.fonts.ready) {\n document.fonts.ready.then(run).catch(() => setTimeout(run, 0));\n } else {\n setTimeout(run, 0);\n }\n};\n\nexport const useReadMoreTruncate = ({ lines, content }: Pick<DSReadMoreT.InternalProps, 'lines' | 'content'>) => {\n const textWrapperRef = useRef<HTMLSpanElement>(null);\n const textRef = useRef<HTMLSpanElement>(null);\n\n const [expanded, setExpanded] = useState(false);\n const [showButton, setShowButton] = useState(false);\n\n const { width, height } = useOnElementResize(textWrapperRef);\n\n useLayoutEffect(() => {\n const textEl = textRef.current;\n const wrapperEl = textWrapperRef.current;\n if (!textEl || !wrapperEl) return;\n\n textEl.innerText = content;\n\n if (lines === 1 && IS_SAFARI) {\n const truncated = checkSafariSingleLine(textEl, wrapperEl, content);\n setShowButton(expanded || truncated);\n return;\n }\n\n const isOverflowing = overflows({ offsetHeight: wrapperEl.offsetHeight, scrollHeight: wrapperEl.scrollHeight });\n setShowButton(expanded || isOverflowing);\n\n if (!expanded && isOverflowing) {\n scheduleBinaryTruncate(textEl, wrapperEl, content);\n }\n }, [lines, content, expanded, width, height]);\n\n return { textWrapperRef, textRef, showButton, expanded, setExpanded };\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,iBAAiB,QAAQ,gBAAgB;AAClD,SAAS,0BAA0B;AAEnC,SAAS,iBAAiB;AAG1B,MAAM,YAAY,CAAC,EAAE,cAAc,aAAa,MAC9C,eAAe,IAAI;AAOrB,MAAM,wBAAwB,CAAC,SAAsB,QAAqB,YAAoB;AAC5F,MAAI,OAAO;AACX,MAAI,QAAQ,QAAQ;AACpB,MAAI,UAAU;AAEd,UAAQ,YAAY;AAEpB,SAAO,QAAQ,OAAO;AACpB,UAAM,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACzC,YAAQ,YAAY,QAAQ,MAAM,GAAG,GAAG;AAExC,QAAI,UAAU,MAAM,GAAG;AACrB,cAAQ,MAAM;AAAA,IAChB,OAAO;AACL,gBAAU;AACV,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,UAAQ,YAAY,QAAQ,MAAM,GAAG,OAAO;AAC9C;AAEA,MAAM,wBAAwB,CAAC,QAAqB,WAAwB,YAA6B;AACvG,QAAM,WAAW,iBAAiB,MAAM;AACxC,QAAM,OAAO,GAAG,SAAS,UAAU,IAAI,SAAS,QAAQ,IAAI,SAAS,UAAU;AAC/E,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,QAAM,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,OAAO;AACX,SAAO,IAAI,YAAY,OAAO,EAAE,QAAQ,UAAU;AACpD;AAEA,MAAM,yBAAyB,CAAC,QAAqB,WAAwB,YAAoB;AAC/F,QAAM,MAAM,MAAM,sBAAsB,MAAM,sBAAsB,QAAQ,WAAW,OAAO,CAAC;AAC/F,MAAI,WAAW,YAAY,SAAS,MAAM,OAAO;AAC/C,aAAS,MAAM,MAAM,KAAK,GAAG,EAAE,MAAM,MAAM,WAAW,KAAK,CAAC,CAAC;AAAA,EAC/D,OAAO;AACL,eAAW,KAAK,CAAC;AAAA,EACnB;AACF;AAEO,MAAM,sBAAsB,CAAC,EAAE,OAAO,QAAQ,MAA4D;AAC/G,QAAM,iBAAiB,OAAwB,IAAI;AACnD,QAAM,UAAU,OAAwB,IAAI;AAE5C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,QAAM,EAAE,OAAO,OAAO,IAAI,mBAAmB,cAAc;AAE3D,kBAAgB,MAAM;AACpB,UAAM,SAAS,QAAQ;AACvB,UAAM,YAAY,eAAe;AACjC,QAAI,CAAC,UAAU,CAAC,UAAW;AAE3B,WAAO,YAAY;AAEnB,QAAI,UAAU,KAAK,WAAW;AAC5B,YAAM,YAAY,sBAAsB,QAAQ,WAAW,OAAO;AAClE,oBAAc,YAAY,SAAS;AACnC;AAAA,IACF;AAEA,UAAM,gBAAgB,UAAU,EAAE,cAAc,UAAU,cAAc,cAAc,UAAU,aAAa,CAAC;AAC9G,kBAAc,YAAY,aAAa;AAEvC,QAAI,CAAC,YAAY,eAAe;AAC9B,6BAAuB,QAAQ,WAAW,OAAO;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,OAAO,SAAS,UAAU,OAAO,MAAM,CAAC;AAE5C,SAAO,EAAE,gBAAgB,SAAS,YAAY,UAAU,YAAY;AACtE;",
6
6
  "names": []
7
7
  }
package/dist/esm/utils.js CHANGED
@@ -4,7 +4,9 @@ const isSafari = () => {
4
4
  const ua = navigator.userAgent;
5
5
  return /safari/i.test(ua) && !/chrome|chromium|android/i.test(ua);
6
6
  };
7
+ const IS_SAFARI = isSafari();
7
8
  export {
9
+ IS_SAFARI,
8
10
  isSafari
9
11
  };
10
12
  //# sourceMappingURL=utils.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/utils.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/**\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"],
5
- "mappings": "AAAA,YAAY,WAAW;ACehB,MAAM,WAAW,MAAM;AAC5B,MAAI,OAAO,cAAc,YAAa,QAAO;AAE7C,QAAM,KAAK,UAAU;AAErB,SAAO,UAAU,KAAK,EAAE,KAAK,CAAC,2BAA2B,KAAK,EAAE;AAClE;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/**\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 */\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\n/** Evaluated once at module load \u2014 safe for SSR (returns false when navigator is unavailable). */\nexport const IS_SAFARI = isSafari();\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACWhB,MAAM,WAAW,MAAM;AAC5B,MAAI,OAAO,cAAc,YAAa,QAAO;AAE7C,QAAM,KAAK,UAAU;AAErB,SAAO,UAAU,KAAK,EAAE,KAAK,CAAC,2BAA2B,KAAK,EAAE;AAClE;AAGO,MAAM,YAAY,SAAS;",
6
6
  "names": []
7
7
  }
@@ -15,4 +15,3 @@ export declare const StyledButtonWrapper: import("styled-components").StyledComp
15
15
  export declare const StyledButton: import("styled-components").StyledComponent<import("react").ComponentType<import("@elliemae/ds-button-v2").DSButtonV3T.Props>, import("@elliemae/ds-system").Theme, {
16
16
  withTooltip?: boolean;
17
17
  } & import("@elliemae/ds-system").OwnerInterface & import("@elliemae/ds-system").InnerRefInterface<import("react").ComponentType<import("@elliemae/ds-button-v2").DSButtonV3T.Props>>, never>;
18
- export declare const ScreenReaderOnly: import("styled-components").StyledComponent<"span", import("@elliemae/ds-system").Theme, object & import("@elliemae/ds-system").OwnerInterface & import("@elliemae/ds-system").InnerRefInterface<"span">, never>;
@@ -1,13 +1,8 @@
1
- import React from 'react';
2
1
  import type { DSReadMoreT } from './react-desc-prop-types.js';
3
2
  export declare const useReadMoreTruncate: ({ lines, content }: Pick<DSReadMoreT.InternalProps, "lines" | "content">) => {
4
- textWrapperRef: React.RefObject<HTMLSpanElement>;
5
- textRef: React.RefObject<HTMLSpanElement>;
3
+ textWrapperRef: import("react").RefObject<HTMLSpanElement>;
4
+ textRef: import("react").RefObject<HTMLSpanElement>;
6
5
  showButton: boolean;
7
6
  expanded: boolean;
8
- setExpanded: React.Dispatch<React.SetStateAction<boolean>>;
9
- textProps: {
10
- 'aria-hidden': boolean;
11
- };
12
- srOnlyText: import("react/jsx-runtime.js").JSX.Element;
7
+ setExpanded: import("react").Dispatch<import("react").SetStateAction<boolean>>;
13
8
  };
@@ -8,9 +8,7 @@
8
8
  *
9
9
  * The check is intentionally lightweight and user-agent based, as feature
10
10
  * detection is not reliable for these Safari-specific rendering issues.
11
- *
12
- * When used inside React components, this function should be evaluated once
13
- * (e.g. via useMemo) to avoid layout churn and focus instability caused by
14
- * re-evaluating browser detection on every render.
15
11
  */
16
12
  export declare const isSafari: () => boolean;
13
+ /** Evaluated once at module load — safe for SSR (returns false when navigator is unavailable). */
14
+ export declare const IS_SAFARI: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elliemae/ds-read-more",
3
- "version": "3.60.0-next.43",
3
+ "version": "3.60.0-next.45",
4
4
  "license": "MIT",
5
5
  "description": "ICE MT - Dimsum - Read More",
6
6
  "files": [
@@ -36,17 +36,17 @@
36
36
  "indent": 4
37
37
  },
38
38
  "dependencies": {
39
- "@elliemae/ds-accessibility": "3.60.0-next.43",
40
- "@elliemae/ds-button-v2": "3.60.0-next.43",
41
- "@elliemae/ds-system": "3.60.0-next.43",
42
- "@elliemae/ds-props-helpers": "3.60.0-next.43",
43
- "@elliemae/ds-tooltip-v3": "3.60.0-next.43"
39
+ "@elliemae/ds-accessibility": "3.60.0-next.45",
40
+ "@elliemae/ds-system": "3.60.0-next.45",
41
+ "@elliemae/ds-props-helpers": "3.60.0-next.45",
42
+ "@elliemae/ds-button-v2": "3.60.0-next.45",
43
+ "@elliemae/ds-tooltip-v3": "3.60.0-next.45"
44
44
  },
45
45
  "devDependencies": {
46
46
  "jest": "^30.0.0",
47
47
  "styled-components": "~5.3.9",
48
- "@elliemae/ds-monorepo-devops": "3.60.0-next.43",
49
- "@elliemae/ds-test-utils": "3.60.0-next.43"
48
+ "@elliemae/ds-monorepo-devops": "3.60.0-next.45",
49
+ "@elliemae/ds-test-utils": "3.60.0-next.45"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "lodash-es": "^4.17.21",