@chayns-components/core 5.5.14 → 5.5.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/lib/cjs/components/copyable-content/CopyableContent.js +18 -12
  2. package/lib/cjs/components/copyable-content/CopyableContent.js.map +1 -1
  3. package/lib/cjs/components/copyable-content/CopyableContent.styles.js +2 -1
  4. package/lib/cjs/components/copyable-content/CopyableContent.styles.js.map +1 -1
  5. package/lib/cjs/components/copyable-content/CopyableContent.test.js +26 -17
  6. package/lib/cjs/components/copyable-content/CopyableContent.test.js.map +1 -1
  7. package/lib/cjs/components/copyable-content/copyableContentClipboard.js +45 -28
  8. package/lib/cjs/components/copyable-content/copyableContentClipboard.js.map +1 -1
  9. package/lib/cjs/components/copyable-content/copyableContentClipboard.test.js +13 -11
  10. package/lib/cjs/components/copyable-content/copyableContentClipboard.test.js.map +1 -1
  11. package/lib/cjs/components/sharing-context-menu/SharingContextMenu.js +11 -12
  12. package/lib/cjs/components/sharing-context-menu/SharingContextMenu.js.map +1 -1
  13. package/lib/cjs/components/sharing-context-menu/SharingContextMenu.test.js +48 -0
  14. package/lib/cjs/components/sharing-context-menu/SharingContextMenu.test.js.map +1 -0
  15. package/lib/cjs/constants/textStrings.js +0 -4
  16. package/lib/cjs/constants/textStrings.js.map +1 -1
  17. package/lib/cjs/utils/sharingBar.js +14 -17
  18. package/lib/cjs/utils/sharingBar.js.map +1 -1
  19. package/lib/esm/components/copyable-content/CopyableContent.js +19 -13
  20. package/lib/esm/components/copyable-content/CopyableContent.js.map +1 -1
  21. package/lib/esm/components/copyable-content/CopyableContent.styles.js +2 -1
  22. package/lib/esm/components/copyable-content/CopyableContent.styles.js.map +1 -1
  23. package/lib/esm/components/copyable-content/CopyableContent.test.js +24 -16
  24. package/lib/esm/components/copyable-content/CopyableContent.test.js.map +1 -1
  25. package/lib/esm/components/copyable-content/copyableContentClipboard.js +41 -28
  26. package/lib/esm/components/copyable-content/copyableContentClipboard.js.map +1 -1
  27. package/lib/esm/components/copyable-content/copyableContentClipboard.test.js +13 -11
  28. package/lib/esm/components/copyable-content/copyableContentClipboard.test.js.map +1 -1
  29. package/lib/esm/components/sharing-context-menu/SharingContextMenu.js +11 -12
  30. package/lib/esm/components/sharing-context-menu/SharingContextMenu.js.map +1 -1
  31. package/lib/esm/components/sharing-context-menu/SharingContextMenu.test.js +45 -0
  32. package/lib/esm/components/sharing-context-menu/SharingContextMenu.test.js.map +1 -0
  33. package/lib/esm/constants/textStrings.js +0 -4
  34. package/lib/esm/constants/textStrings.js.map +1 -1
  35. package/lib/esm/utils/sharingBar.js +15 -18
  36. package/lib/esm/utils/sharingBar.js.map +1 -1
  37. package/lib/types/components/copyable-content/CopyableContent.d.ts +0 -1
  38. package/lib/types/components/sharing-context-menu/SharingContextMenu.d.ts +16 -0
  39. package/lib/types/constants/textStrings.d.ts +0 -4
  40. package/package.json +5 -7
  41. package/LICENSE +0 -21
@@ -23,22 +23,21 @@ var _CopyableContent2 = require("./CopyableContent.types");
23
23
  var _copyableContentClipboard = require("./copyableContentClipboard");
24
24
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
25
25
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
26
+ const COPY_FEEDBACK_DURATION = 1500;
26
27
  const CopyableContent = ({
27
28
  appearance = _CopyableContent2.CopyableContentAppearance.Default,
28
29
  content,
29
30
  children,
30
- copiedMessage,
31
31
  copyFailedMessage
32
32
  }) => {
33
33
  const rootRef = (0, _react.useRef)(null);
34
34
  const actionGroupRef = (0, _react.useRef)(null);
35
+ const copyFeedbackTimeoutRef = (0, _react.useRef)();
35
36
  const isActionGroupSticky = (0, _useStickyActionState.useStickyActionState)(rootRef, actionGroupRef);
37
+ const [hasCopied, setHasCopied] = (0, _react.useState)(false);
36
38
  const defaultCopyButtonText = (0, _textstring.useTextstringValue)({
37
39
  textstring: (0, _textstring.ttsToITextString)(_textStrings.default.components.copyableContent.copy)
38
40
  });
39
- const defaultCopiedMessage = (0, _textstring.useTextstringValue)({
40
- textstring: (0, _textstring.ttsToITextString)(_textStrings.default.components.copyableContent.copied)
41
- });
42
41
  const defaultCopyFailedMessage = (0, _textstring.useTextstringValue)({
43
42
  textstring: (0, _textstring.ttsToITextString)(_textStrings.default.components.copyableContent.copyFailed)
44
43
  });
@@ -46,15 +45,20 @@ const CopyableContent = ({
46
45
  textstring: (0, _textstring.ttsToITextString)(_textStrings.default.components.copyableContent.share)
47
46
  });
48
47
  const html = (0, _react.useMemo)(() => (0, _format.formatStringToHtml)(content).html, [content]);
48
+ (0, _react.useEffect)(() => () => {
49
+ window.clearTimeout(copyFeedbackTimeoutRef.current);
50
+ }, []);
51
+ const showCopyFeedback = (0, _react.useCallback)(() => {
52
+ window.clearTimeout(copyFeedbackTimeoutRef.current);
53
+ setHasCopied(true);
54
+ copyFeedbackTimeoutRef.current = window.setTimeout(() => {
55
+ setHasCopied(false);
56
+ }, COPY_FEEDBACK_DURATION);
57
+ }, []);
49
58
  const handleCopy = (0, _react.useCallback)(async () => {
50
59
  try {
51
60
  await (0, _copyableContentClipboard.copyableContentToClipboard)(content);
52
- void (0, _chaynsApi.createDialog)({
53
- showCloseIcon: true,
54
- text: copiedMessage ?? defaultCopiedMessage,
55
- toastType: _chaynsApi.ToastType.SUCCESS,
56
- type: _chaynsApi.DialogType.TOAST
57
- }).open();
61
+ showCopyFeedback();
58
62
  } catch {
59
63
  void (0, _chaynsApi.createDialog)({
60
64
  showCloseIcon: true,
@@ -63,7 +67,7 @@ const CopyableContent = ({
63
67
  type: _chaynsApi.DialogType.TOAST
64
68
  }).open();
65
69
  }
66
- }, [content, copiedMessage, defaultCopiedMessage, defaultCopyFailedMessage, copyFailedMessage]);
70
+ }, [content, defaultCopyFailedMessage, copyFailedMessage, showCopyFeedback]);
67
71
  return /*#__PURE__*/_react.default.createElement(_CopyableContent.StyledCopyableContent, {
68
72
  $appearance: appearance,
69
73
  className: "copyable-content",
@@ -78,9 +82,11 @@ const CopyableContent = ({
78
82
  },
79
83
  type: "button"
80
84
  }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
81
- icons: ['fa-light fa-copy']
85
+ icons: hasCopied ? ['fa fa-check'] : ['fa-light fa-copy']
82
86
  })), /*#__PURE__*/_react.default.createElement(_SharingContextMenu.default, {
83
87
  link: content,
88
+ shouldShowCallingCodeAction: false,
89
+ shouldShowCopyAction: false,
84
90
  shouldUseDefaultTriggerStyles: false
85
91
  }, /*#__PURE__*/_react.default.createElement(_CopyableContent.StyledCopyableContentButton, {
86
92
  $isSticky: isActionGroupSticky,
@@ -1 +1 @@
1
- {"version":3,"file":"CopyableContent.js","names":["_format","require","_textstring","_chaynsApi","_react","_interopRequireWildcard","_textStrings","_interopRequireDefault","_useStickyActionState","_SharingContextMenu","_Icon","_CopyableContent","_CopyableContent2","_copyableContentClipboard","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","CopyableContent","appearance","CopyableContentAppearance","Default","content","children","copiedMessage","copyFailedMessage","rootRef","useRef","actionGroupRef","isActionGroupSticky","useStickyActionState","defaultCopyButtonText","useTextstringValue","textstring","ttsToITextString","textStrings","components","copyableContent","copy","defaultCopiedMessage","copied","defaultCopyFailedMessage","copyFailed","shareText","share","html","useMemo","formatStringToHtml","handleCopy","useCallback","copyableContentToClipboard","createDialog","showCloseIcon","text","toastType","ToastType","SUCCESS","type","DialogType","TOAST","open","ERROR","createElement","StyledCopyableContent","$appearance","className","ref","StyledCopyableContentActions","StyledCopyableContentActionGroup","StyledCopyableContentButton","$isSticky","onClick","icons","link","shouldUseDefaultTriggerStyles","StyledCopyableContentBody","dangerouslySetInnerHTML","__html","displayName","_default","exports"],"sources":["../../../../src/components/copyable-content/CopyableContent.tsx"],"sourcesContent":["import { formatStringToHtml } from '@chayns-components/format';\nimport { ttsToITextString, useTextstringValue } from '@chayns-components/textstring';\nimport { createDialog, DialogType, ToastType } from 'chayns-api';\nimport React, { FC, ReactNode, useCallback, useMemo, useRef } from 'react';\nimport textStrings from '../../constants/textStrings';\nimport { useStickyActionState } from '../../hooks/useStickyActionState';\nimport SharingContextMenu from '../sharing-context-menu/SharingContextMenu';\nimport Icon from '../icon/Icon';\nimport {\n StyledCopyableContent,\n StyledCopyableContentActionGroup,\n StyledCopyableContentActions,\n StyledCopyableContentBody,\n StyledCopyableContentButton,\n} from './CopyableContent.styles';\nimport { CopyableContentAppearance } from './CopyableContent.types';\nimport { copyableContentToClipboard } from './copyableContentClipboard';\n\nexport type CopyableContentProps = {\n /**\n * Controls the visual surface of the content block.\n */\n appearance?: CopyableContentAppearance;\n content: string;\n children?: ReactNode;\n copiedMessage?: string;\n copyFailedMessage?: string;\n};\n\nconst CopyableContent: FC<CopyableContentProps> = ({\n appearance = CopyableContentAppearance.Default,\n content,\n children,\n copiedMessage,\n copyFailedMessage,\n}) => {\n const rootRef = useRef<HTMLElement>(null);\n const actionGroupRef = useRef<HTMLDivElement>(null);\n const isActionGroupSticky = useStickyActionState(rootRef, actionGroupRef);\n\n const defaultCopyButtonText = useTextstringValue({\n textstring: ttsToITextString(textStrings.components.copyableContent.copy),\n });\n const defaultCopiedMessage = useTextstringValue({\n textstring: ttsToITextString(textStrings.components.copyableContent.copied),\n });\n const defaultCopyFailedMessage = useTextstringValue({\n textstring: ttsToITextString(textStrings.components.copyableContent.copyFailed),\n });\n const shareText = useTextstringValue({\n textstring: ttsToITextString(textStrings.components.copyableContent.share),\n });\n\n const html = useMemo(() => formatStringToHtml(content).html, [content]);\n\n const handleCopy = useCallback(async () => {\n try {\n await copyableContentToClipboard(content);\n void createDialog({\n showCloseIcon: true,\n text: copiedMessage ?? defaultCopiedMessage,\n toastType: ToastType.SUCCESS,\n type: DialogType.TOAST,\n }).open();\n } catch {\n void createDialog({\n showCloseIcon: true,\n text: copyFailedMessage ?? defaultCopyFailedMessage,\n toastType: ToastType.ERROR,\n type: DialogType.TOAST,\n }).open();\n }\n }, [content, copiedMessage, defaultCopiedMessage, defaultCopyFailedMessage, copyFailedMessage]);\n\n return (\n <StyledCopyableContent $appearance={appearance} className=\"copyable-content\" ref={rootRef}>\n <StyledCopyableContentActions ref={actionGroupRef}>\n <StyledCopyableContentActionGroup>\n <StyledCopyableContentButton\n $isSticky={isActionGroupSticky}\n aria-label={defaultCopyButtonText}\n onClick={() => {\n void handleCopy();\n }}\n type=\"button\"\n >\n <Icon icons={['fa-light fa-copy']} />\n </StyledCopyableContentButton>\n <SharingContextMenu link={content} shouldUseDefaultTriggerStyles={false}>\n <StyledCopyableContentButton\n $isSticky={isActionGroupSticky}\n aria-label={shareText}\n type=\"button\"\n >\n <Icon icons={['fa fa-share-nodes']} />\n </StyledCopyableContentButton>\n </SharingContextMenu>\n </StyledCopyableContentActionGroup>\n </StyledCopyableContentActions>\n <StyledCopyableContentBody>\n {children ?? <div dangerouslySetInnerHTML={{ __html: html }} />}\n </StyledCopyableContentBody>\n </StyledCopyableContent>\n );\n};\n\nCopyableContent.displayName = 'CopyableContent';\n\nexport default CopyableContent;\n\nexport { CopyableContentAppearance } from './CopyableContent.types';\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"CopyableContent.js","names":["_format","require","_textstring","_chaynsApi","_react","_interopRequireWildcard","_textStrings","_interopRequireDefault","_useStickyActionState","_SharingContextMenu","_Icon","_CopyableContent","_CopyableContent2","_copyableContentClipboard","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","COPY_FEEDBACK_DURATION","CopyableContent","appearance","CopyableContentAppearance","Default","content","children","copyFailedMessage","rootRef","useRef","actionGroupRef","copyFeedbackTimeoutRef","isActionGroupSticky","useStickyActionState","hasCopied","setHasCopied","useState","defaultCopyButtonText","useTextstringValue","textstring","ttsToITextString","textStrings","components","copyableContent","copy","defaultCopyFailedMessage","copyFailed","shareText","share","html","useMemo","formatStringToHtml","useEffect","window","clearTimeout","current","showCopyFeedback","useCallback","setTimeout","handleCopy","copyableContentToClipboard","createDialog","showCloseIcon","text","toastType","ToastType","ERROR","type","DialogType","TOAST","open","createElement","StyledCopyableContent","$appearance","className","ref","StyledCopyableContentActions","StyledCopyableContentActionGroup","StyledCopyableContentButton","$isSticky","onClick","icons","link","shouldShowCallingCodeAction","shouldShowCopyAction","shouldUseDefaultTriggerStyles","StyledCopyableContentBody","dangerouslySetInnerHTML","__html","displayName","_default","exports"],"sources":["../../../../src/components/copyable-content/CopyableContent.tsx"],"sourcesContent":["import { formatStringToHtml } from '@chayns-components/format';\nimport { ttsToITextString, useTextstringValue } from '@chayns-components/textstring';\nimport { createDialog, DialogType, ToastType } from 'chayns-api';\nimport React, { FC, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport textStrings from '../../constants/textStrings';\nimport { useStickyActionState } from '../../hooks/useStickyActionState';\nimport SharingContextMenu from '../sharing-context-menu/SharingContextMenu';\nimport Icon from '../icon/Icon';\nimport {\n StyledCopyableContent,\n StyledCopyableContentActionGroup,\n StyledCopyableContentActions,\n StyledCopyableContentBody,\n StyledCopyableContentButton,\n} from './CopyableContent.styles';\nimport { CopyableContentAppearance } from './CopyableContent.types';\nimport { copyableContentToClipboard } from './copyableContentClipboard';\n\nconst COPY_FEEDBACK_DURATION = 1500;\n\nexport type CopyableContentProps = {\n /**\n * Controls the visual surface of the content block.\n */\n appearance?: CopyableContentAppearance;\n content: string;\n children?: ReactNode;\n copyFailedMessage?: string;\n};\n\nconst CopyableContent: FC<CopyableContentProps> = ({\n appearance = CopyableContentAppearance.Default,\n content,\n children,\n copyFailedMessage,\n}) => {\n const rootRef = useRef<HTMLElement>(null);\n const actionGroupRef = useRef<HTMLDivElement>(null);\n const copyFeedbackTimeoutRef = useRef<number>();\n const isActionGroupSticky = useStickyActionState(rootRef, actionGroupRef);\n const [hasCopied, setHasCopied] = useState(false);\n\n const defaultCopyButtonText = useTextstringValue({\n textstring: ttsToITextString(textStrings.components.copyableContent.copy),\n });\n const defaultCopyFailedMessage = useTextstringValue({\n textstring: ttsToITextString(textStrings.components.copyableContent.copyFailed),\n });\n const shareText = useTextstringValue({\n textstring: ttsToITextString(textStrings.components.copyableContent.share),\n });\n\n const html = useMemo(() => formatStringToHtml(content).html, [content]);\n\n useEffect(\n () => () => {\n window.clearTimeout(copyFeedbackTimeoutRef.current);\n },\n [],\n );\n\n const showCopyFeedback = useCallback(() => {\n window.clearTimeout(copyFeedbackTimeoutRef.current);\n setHasCopied(true);\n\n copyFeedbackTimeoutRef.current = window.setTimeout(() => {\n setHasCopied(false);\n }, COPY_FEEDBACK_DURATION);\n }, []);\n\n const handleCopy = useCallback(async () => {\n try {\n await copyableContentToClipboard(content);\n showCopyFeedback();\n } catch {\n void createDialog({\n showCloseIcon: true,\n text: copyFailedMessage ?? defaultCopyFailedMessage,\n toastType: ToastType.ERROR,\n type: DialogType.TOAST,\n }).open();\n }\n }, [content, defaultCopyFailedMessage, copyFailedMessage, showCopyFeedback]);\n\n return (\n <StyledCopyableContent $appearance={appearance} className=\"copyable-content\" ref={rootRef}>\n <StyledCopyableContentActions ref={actionGroupRef}>\n <StyledCopyableContentActionGroup>\n <StyledCopyableContentButton\n $isSticky={isActionGroupSticky}\n aria-label={defaultCopyButtonText}\n onClick={() => {\n void handleCopy();\n }}\n type=\"button\"\n >\n <Icon icons={hasCopied ? ['fa fa-check'] : ['fa-light fa-copy']} />\n </StyledCopyableContentButton>\n <SharingContextMenu\n link={content}\n shouldShowCallingCodeAction={false}\n shouldShowCopyAction={false}\n shouldUseDefaultTriggerStyles={false}\n >\n <StyledCopyableContentButton\n $isSticky={isActionGroupSticky}\n aria-label={shareText}\n type=\"button\"\n >\n <Icon icons={['fa fa-share-nodes']} />\n </StyledCopyableContentButton>\n </SharingContextMenu>\n </StyledCopyableContentActionGroup>\n </StyledCopyableContentActions>\n <StyledCopyableContentBody>\n {children ?? <div dangerouslySetInnerHTML={{ __html: html }} />}\n </StyledCopyableContentBody>\n </StyledCopyableContent>\n );\n};\n\nCopyableContent.displayName = 'CopyableContent';\n\nexport default CopyableContent;\n\nexport { CopyableContentAppearance } from './CopyableContent.types';\n"],"mappings":"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","ignoreList":[]}
@@ -12,7 +12,7 @@ const getBackgroundColor = ({
12
12
  theme
13
13
  }) => {
14
14
  if ($appearance === _CopyableContent.CopyableContentAppearance.Chat) {
15
- return theme.colorMode === 'dark' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.2)';
15
+ return 'rgba(0, 0, 0, 0.2)';
16
16
  }
17
17
  const secondaryColor = theme['secondary-100-rgb'] ?? '255, 255, 255';
18
18
  const opacity = theme.cardBackgroundOpacity ?? 1;
@@ -22,6 +22,7 @@ const StyledCopyableContent = exports.StyledCopyableContent = _styledComponents.
22
22
  --copyable-content-action-size: 32px;
23
23
  --copyable-content-action-inset: 8px;
24
24
 
25
+ margin: 4px 0;
25
26
  min-width: 0;
26
27
  max-width: 100%;
27
28
  overflow-x: clip;
@@ -1 +1 @@
1
- {"version":3,"file":"CopyableContent.styles.js","names":["_styledComponents","_interopRequireDefault","require","_CopyableContent","e","__esModule","default","getBackgroundColor","$appearance","theme","CopyableContentAppearance","Chat","colorMode","secondaryColor","opacity","cardBackgroundOpacity","StyledCopyableContent","exports","styled","section","cardBorderRadius","text","StyledCopyableContentActions","div","StyledCopyableContentActionGroup","StyledCopyableContentButton","button","$isSticky","buttonBackgroundColor","StyledCopyableContentBody","headline","primary"],"sources":["../../../../src/components/copyable-content/CopyableContent.styles.ts"],"sourcesContent":["import type { WithTheme } from '../color-scheme-provider/ColorSchemeProvider';\nimport styled from 'styled-components';\nimport { CopyableContentAppearance } from './CopyableContent.types';\n\ntype StyledCopyableContentProps = WithTheme<{\n $appearance: CopyableContentAppearance;\n}>;\n\nconst getBackgroundColor = ({ $appearance, theme }: StyledCopyableContentProps) => {\n if ($appearance === CopyableContentAppearance.Chat) {\n return theme.colorMode === 'dark' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.2)';\n }\n\n const secondaryColor = theme['secondary-100-rgb'] ?? '255, 255, 255';\n const opacity = theme.cardBackgroundOpacity ?? 1;\n\n return `rgba(${secondaryColor}, ${opacity})`;\n};\n\nexport const StyledCopyableContent = styled.section<StyledCopyableContentProps>`\n --copyable-content-action-size: 32px;\n --copyable-content-action-inset: 8px;\n\n min-width: 0;\n max-width: 100%;\n overflow-x: clip;\n overflow-wrap: anywhere;\n padding-top: calc(\n var(--copyable-content-action-size) + var(--copyable-content-action-inset) * 2\n );\n border-radius: ${({ theme }) => theme.cardBorderRadius}px;\n background-color: ${getBackgroundColor};\n color: ${({ theme }) => theme.text};\n`;\n\ntype StyledCopyableContentButtonProps = WithTheme<{\n $isSticky: boolean;\n}>;\n\nexport const StyledCopyableContentActions = styled.div`\n position: sticky;\n top: var(--copyable-content-action-inset);\n z-index: 1;\n display: flex;\n justify-content: flex-end;\n height: calc(var(--copyable-content-action-size) + var(--copyable-content-action-inset));\n margin-top: calc(\n (var(--copyable-content-action-size) + var(--copyable-content-action-inset)) * -1\n );\n padding-right: var(--copyable-content-action-inset);\n`;\n\nexport const StyledCopyableContentActionGroup = styled.div`\n display: flex;\n gap: 4px;\n height: var(--copyable-content-action-size);\n`;\n\nexport const StyledCopyableContentButton = styled.button<StyledCopyableContentButtonProps>`\n box-sizing: border-box;\n border: 1px solid ${({ $isSticky, theme }) => ($isSticky ? theme['202'] : 'transparent')};\n border-radius: 4px;\n width: var(--copyable-content-action-size);\n height: var(--copyable-content-action-size);\n padding: 0;\n cursor: pointer;\n background-color: ${({ $isSticky, theme }) => ($isSticky ? theme['100'] : 'transparent')};\n color: ${({ theme }) => theme.text};\n box-shadow: ${({ $isSticky }) => ($isSticky ? '0 2px 8px rgba(0, 0, 0, 0.16)' : 'none')};\n transition:\n background-color 0.15s ease,\n border-color 0.15s ease,\n box-shadow 0.15s ease,\n transform 0.15s ease;\n\n &:hover {\n background-color: rgba(${({ theme }) => theme['text-rgb']}, 0.1);\n box-shadow: inset 0 0 0 1px rgba(${({ theme }) => theme['text-rgb']}, 0.06);\n }\n\n &:active {\n transform: scale(0.9);\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.buttonBackgroundColor};\n outline-offset: 2px;\n }\n`;\n\nexport const StyledCopyableContentBody = styled.div<WithTheme<unknown>>`\n min-width: 0;\n max-width: 100%;\n overflow-wrap: anywhere;\n padding: 0 12px 12px;\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6,\n p,\n ul,\n ol,\n blockquote {\n margin: 0 0 12px;\n }\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n color: ${({ theme }) => theme.headline};\n }\n\n ul,\n ol {\n padding-left: 24px;\n }\n\n blockquote {\n padding-left: 12px;\n border-left: 3px solid ${({ theme }) => theme['202']};\n }\n\n a {\n color: ${({ theme }) => theme.primary};\n overflow-wrap: anywhere;\n }\n\n > :last-child {\n margin-bottom: 0;\n }\n`;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"CopyableContent.styles.js","names":["_styledComponents","_interopRequireDefault","require","_CopyableContent","e","__esModule","default","getBackgroundColor","$appearance","theme","CopyableContentAppearance","Chat","secondaryColor","opacity","cardBackgroundOpacity","StyledCopyableContent","exports","styled","section","cardBorderRadius","text","StyledCopyableContentActions","div","StyledCopyableContentActionGroup","StyledCopyableContentButton","button","$isSticky","buttonBackgroundColor","StyledCopyableContentBody","headline","primary"],"sources":["../../../../src/components/copyable-content/CopyableContent.styles.ts"],"sourcesContent":["import type { WithTheme } from '../color-scheme-provider/ColorSchemeProvider';\nimport styled from 'styled-components';\nimport { CopyableContentAppearance } from './CopyableContent.types';\n\ntype StyledCopyableContentProps = WithTheme<{\n $appearance: CopyableContentAppearance;\n}>;\n\nconst getBackgroundColor = ({ $appearance, theme }: StyledCopyableContentProps) => {\n if ($appearance === CopyableContentAppearance.Chat) {\n return 'rgba(0, 0, 0, 0.2)';\n }\n\n const secondaryColor = theme['secondary-100-rgb'] ?? '255, 255, 255';\n const opacity = theme.cardBackgroundOpacity ?? 1;\n\n return `rgba(${secondaryColor}, ${opacity})`;\n};\n\nexport const StyledCopyableContent = styled.section<StyledCopyableContentProps>`\n --copyable-content-action-size: 32px;\n --copyable-content-action-inset: 8px;\n\n margin: 4px 0;\n min-width: 0;\n max-width: 100%;\n overflow-x: clip;\n overflow-wrap: anywhere;\n padding-top: calc(\n var(--copyable-content-action-size) + var(--copyable-content-action-inset) * 2\n );\n border-radius: ${({ theme }) => theme.cardBorderRadius}px;\n background-color: ${getBackgroundColor};\n color: ${({ theme }) => theme.text};\n`;\n\ntype StyledCopyableContentButtonProps = WithTheme<{\n $isSticky: boolean;\n}>;\n\nexport const StyledCopyableContentActions = styled.div`\n position: sticky;\n top: var(--copyable-content-action-inset);\n z-index: 1;\n display: flex;\n justify-content: flex-end;\n height: calc(var(--copyable-content-action-size) + var(--copyable-content-action-inset));\n margin-top: calc(\n (var(--copyable-content-action-size) + var(--copyable-content-action-inset)) * -1\n );\n padding-right: var(--copyable-content-action-inset);\n`;\n\nexport const StyledCopyableContentActionGroup = styled.div`\n display: flex;\n gap: 4px;\n height: var(--copyable-content-action-size);\n`;\n\nexport const StyledCopyableContentButton = styled.button<StyledCopyableContentButtonProps>`\n box-sizing: border-box;\n border: 1px solid ${({ $isSticky, theme }) => ($isSticky ? theme['202'] : 'transparent')};\n border-radius: 4px;\n width: var(--copyable-content-action-size);\n height: var(--copyable-content-action-size);\n padding: 0;\n cursor: pointer;\n background-color: ${({ $isSticky, theme }) => ($isSticky ? theme['100'] : 'transparent')};\n color: ${({ theme }) => theme.text};\n box-shadow: ${({ $isSticky }) => ($isSticky ? '0 2px 8px rgba(0, 0, 0, 0.16)' : 'none')};\n transition:\n background-color 0.15s ease,\n border-color 0.15s ease,\n box-shadow 0.15s ease,\n transform 0.15s ease;\n\n &:hover {\n background-color: rgba(${({ theme }) => theme['text-rgb']}, 0.1);\n box-shadow: inset 0 0 0 1px rgba(${({ theme }) => theme['text-rgb']}, 0.06);\n }\n\n &:active {\n transform: scale(0.9);\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.buttonBackgroundColor};\n outline-offset: 2px;\n }\n`;\n\nexport const StyledCopyableContentBody = styled.div<WithTheme<unknown>>`\n min-width: 0;\n max-width: 100%;\n overflow-wrap: anywhere;\n padding: 0 12px 12px;\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6,\n p,\n ul,\n ol,\n blockquote {\n margin: 0 0 12px;\n }\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n color: ${({ theme }) => theme.headline};\n }\n\n ul,\n ol {\n padding-left: 24px;\n }\n\n blockquote {\n padding-left: 12px;\n border-left: 3px solid ${({ theme }) => theme['202']};\n }\n\n a {\n color: ${({ theme }) => theme.primary};\n overflow-wrap: anywhere;\n }\n\n > :last-child {\n margin-bottom: 0;\n }\n`;\n"],"mappings":";;;;;;AACA,IAAAA,iBAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,gBAAA,GAAAD,OAAA;AAAoE,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAMpE,MAAMG,kBAAkB,GAAGA,CAAC;EAAEC,WAAW;EAAEC;AAAkC,CAAC,KAAK;EAC/E,IAAID,WAAW,KAAKE,0CAAyB,CAACC,IAAI,EAAE;IAChD,OAAO,oBAAoB;EAC/B;EAEA,MAAMC,cAAc,GAAGH,KAAK,CAAC,mBAAmB,CAAC,IAAI,eAAe;EACpE,MAAMI,OAAO,GAAGJ,KAAK,CAACK,qBAAqB,IAAI,CAAC;EAEhD,OAAO,QAAQF,cAAc,KAAKC,OAAO,GAAG;AAChD,CAAC;AAEM,MAAME,qBAAqB,GAAAC,OAAA,CAAAD,qBAAA,GAAGE,yBAAM,CAACC,OAAmC;AAC/E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,CAAC;EAAET;AAAM,CAAC,KAAKA,KAAK,CAACU,gBAAgB;AAC1D,wBAAwBZ,kBAAkB;AAC1C,aAAa,CAAC;EAAEE;AAAM,CAAC,KAAKA,KAAK,CAACW,IAAI;AACtC,CAAC;AAMM,MAAMC,4BAA4B,GAAAL,OAAA,CAAAK,4BAAA,GAAGJ,yBAAM,CAACK,GAAG;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAEM,MAAMC,gCAAgC,GAAAP,OAAA,CAAAO,gCAAA,GAAGN,yBAAM,CAACK,GAAG;AAC1D;AACA;AACA;AACA,CAAC;AAEM,MAAME,2BAA2B,GAAAR,OAAA,CAAAQ,2BAAA,GAAGP,yBAAM,CAACQ,MAAwC;AAC1F;AACA,wBAAwB,CAAC;EAAEC,SAAS;EAAEjB;AAAM,CAAC,KAAMiB,SAAS,GAAGjB,KAAK,CAAC,KAAK,CAAC,GAAG,aAAc;AAC5F;AACA;AACA;AACA;AACA;AACA,wBAAwB,CAAC;EAAEiB,SAAS;EAAEjB;AAAM,CAAC,KAAMiB,SAAS,GAAGjB,KAAK,CAAC,KAAK,CAAC,GAAG,aAAc;AAC5F,aAAa,CAAC;EAAEA;AAAM,CAAC,KAAKA,KAAK,CAACW,IAAI;AACtC,kBAAkB,CAAC;EAAEM;AAAU,CAAC,KAAMA,SAAS,GAAG,+BAA+B,GAAG,MAAO;AAC3F;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC,CAAC;EAAEjB;AAAM,CAAC,KAAKA,KAAK,CAAC,UAAU,CAAC;AACjE,2CAA2C,CAAC;EAAEA;AAAM,CAAC,KAAKA,KAAK,CAAC,UAAU,CAAC;AAC3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B,CAAC;EAAEA;AAAM,CAAC,KAAKA,KAAK,CAACkB,qBAAqB;AACvE;AACA;AACA,CAAC;AAEM,MAAMC,yBAAyB,GAAAZ,OAAA,CAAAY,yBAAA,GAAGX,yBAAM,CAACK,GAAuB;AACvE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,CAAC;EAAEb;AAAM,CAAC,KAAKA,KAAK,CAACoB,QAAQ;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC,CAAC;EAAEpB;AAAM,CAAC,KAAKA,KAAK,CAAC,KAAK,CAAC;AAC5D;AACA;AACA;AACA,iBAAiB,CAAC;EAAEA;AAAM,CAAC,KAAKA,KAAK,CAACqB,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}
@@ -5,14 +5,24 @@ var _react2 = _interopRequireDefault(require("react"));
5
5
  var _vitest = require("vitest");
6
6
  var _CopyableContent = _interopRequireDefault(require("./CopyableContent"));
7
7
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /* eslint-disable @typescript-eslint/no-unsafe-call */
8
+ /* eslint-disable @typescript-eslint/no-unsafe-call */
9
+
9
10
  _vitest.vi.mock('../icon/Icon', () => ({
10
- default: () => /*#__PURE__*/_react2.default.createElement("span", null)
11
+ default: ({
12
+ icons
13
+ }) => /*#__PURE__*/_react2.default.createElement("span", {
14
+ "data-icons": icons.join(' ')
15
+ })
11
16
  }));
12
17
  _vitest.vi.mock('../sharing-context-menu/SharingContextMenu', () => ({
13
18
  default: ({
14
- children
15
- }) => children
19
+ children,
20
+ shouldShowCallingCodeAction,
21
+ shouldShowCopyAction
22
+ }) => /*#__PURE__*/_react2.default.createElement("div", {
23
+ "data-calling-code-action": shouldShowCallingCodeAction,
24
+ "data-copy-action": shouldShowCopyAction
25
+ }, children)
16
26
  }));
17
27
  _vitest.vi.mock('chayns-api', async importOriginal => ({
18
28
  ...(await importOriginal()),
@@ -52,32 +62,31 @@ const readBlob = blob => new Promise((resolve, reject) => {
52
62
  const item = write.mock.calls[0][0][0];
53
63
  await (0, _vitest.expect)(readBlob(await item.getType('text/plain'))).resolves.toBe('source markdown');
54
64
  });
55
- (0, _vitest.it)('shows a toast after a successful copy', async () => {
65
+ (0, _vitest.it)('shows a checkmark after a successful copy', async () => {
56
66
  _vitest.vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();
57
- (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_CopyableContent.default, {
58
- content: "source",
59
- copiedMessage: "Done"
67
+ const {
68
+ container
69
+ } = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_CopyableContent.default, {
70
+ content: "source"
60
71
  }));
61
72
  _react.fireEvent.click(_react.screen.getByRole('button', {
62
73
  name: 'Kopieren'
63
74
  }));
64
- await (0, _react.waitFor)(async () => {
65
- const {
66
- createDialog
67
- } = await Promise.resolve().then(() => _interopRequireWildcard(require('chayns-api')));
68
- (0, _vitest.expect)(createDialog).toHaveBeenCalledWith(_vitest.expect.objectContaining({
69
- text: 'Done'
70
- }));
75
+ await (0, _react.waitFor)(() => {
76
+ (0, _vitest.expect)(container.querySelector('[data-icons="fa fa-check"]')).toBeInTheDocument();
71
77
  });
72
- (0, _vitest.expect)(_react.screen.queryByRole('status')).not.toBeInTheDocument();
73
78
  });
74
79
  (0, _vitest.it)('offers sharing actions', () => {
75
- (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_CopyableContent.default, {
80
+ const {
81
+ container
82
+ } = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_CopyableContent.default, {
76
83
  content: "source"
77
84
  }));
78
85
  (0, _vitest.expect)(_react.screen.getByRole('button', {
79
86
  name: 'Teilen'
80
87
  })).toBeInTheDocument();
88
+ (0, _vitest.expect)(container.querySelector('[data-copy-action="false"]')).toBeInTheDocument();
89
+ (0, _vitest.expect)(container.querySelector('[data-calling-code-action="false"]')).toBeInTheDocument();
81
90
  });
82
91
  });
83
92
  //# sourceMappingURL=CopyableContent.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CopyableContent.test.js","names":["_react","require","_react2","_interopRequireDefault","_vitest","_CopyableContent","e","__esModule","default","_interopRequireWildcard","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","vi","mock","createElement","children","importOriginal","createDialog","fn","open","readBlob","blob","Promise","resolve","reject","reader","FileReader","onerror","error","onload","result","readAsText","describe","it","render","content","expect","screen","getByRole","name","toBeInTheDocument","toHaveAttribute","document","querySelector","not","write","spyOn","navigator","clipboard","mockResolvedValue","fireEvent","click","waitFor","toHaveBeenCalled","item","calls","getType","resolves","toBe","copiedMessage","then","toHaveBeenCalledWith","objectContaining","text","queryByRole"],"sources":["../../../../src/components/copyable-content/CopyableContent.test.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-call */\nimport { fireEvent, render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { describe, expect, it, vi } from 'vitest';\nimport CopyableContent from './CopyableContent';\n\nvi.mock('../icon/Icon', () => ({\n default: () => <span />,\n}));\n\nvi.mock('../sharing-context-menu/SharingContextMenu', () => ({\n default: ({ children }: { children: React.ReactNode }) => children,\n}));\n\nvi.mock('chayns-api', async (importOriginal) => ({\n ...(await importOriginal<typeof import('chayns-api')>()),\n createDialog: vi.fn(() => ({ open: vi.fn() })),\n}));\n\nconst readBlob = (blob: Blob) =>\n new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error);\n reader.onload = () => resolve(reader.result as string);\n reader.readAsText(blob);\n });\n\ndescribe('CopyableContent', () => {\n it('renders formatted markdown without active input HTML', () => {\n render(\n <CopyableContent\n content={\n '# Heading\\n\\n- Entry\\n\\n[Link](https://example.com)\\n<script onload=\"x\">bad</script>'\n }\n />,\n );\n\n expect(screen.getByRole('heading', { name: 'Heading' })).toBeInTheDocument();\n expect(screen.getByRole('link', { name: 'Link' })).toHaveAttribute(\n 'href',\n 'https://example.com',\n );\n expect(document.querySelector('script')).not.toBeInTheDocument();\n expect(document.querySelector('[onload]')).not.toBeInTheDocument();\n });\n\n it('copies content instead of custom children', async () => {\n const write = vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n render(<CopyableContent content=\"source markdown\">Visible replacement</CopyableContent>);\n\n fireEvent.click(screen.getByRole('button', { name: 'Kopieren' }));\n\n await waitFor(() => expect(write).toHaveBeenCalled());\n const item = write.mock.calls[0][0][0] as unknown as ClipboardItem;\n await expect(readBlob(await item.getType('text/plain'))).resolves.toBe('source markdown');\n });\n\n it('shows a toast after a successful copy', async () => {\n vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n render(<CopyableContent content=\"source\" copiedMessage=\"Done\" />);\n\n fireEvent.click(screen.getByRole('button', { name: 'Kopieren' }));\n\n await waitFor(async () => {\n const { createDialog } = await import('chayns-api');\n expect(createDialog).toHaveBeenCalledWith(expect.objectContaining({ text: 'Done' }));\n });\n expect(screen.queryByRole('status')).not.toBeInTheDocument();\n });\n\n it('offers sharing actions', () => {\n render(<CopyableContent content=\"source\" />);\n\n expect(screen.getByRole('button', { name: 'Teilen' })).toBeInTheDocument();\n });\n});\n"],"mappings":";;AACA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,gBAAA,GAAAF,sBAAA,CAAAF,OAAA;AAAgD,SAAAE,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,SAAAG,wBAAAH,CAAA,EAAAI,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAF,uBAAA,YAAAA,CAAAH,CAAA,EAAAI,CAAA,SAAAA,CAAA,IAAAJ,CAAA,IAAAA,CAAA,CAAAC,UAAA,SAAAD,CAAA,MAAAQ,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAT,OAAA,EAAAF,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAU,CAAA,MAAAF,CAAA,GAAAJ,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAE,CAAA,CAAAI,GAAA,CAAAZ,CAAA,UAAAQ,CAAA,CAAAK,GAAA,CAAAb,CAAA,GAAAQ,CAAA,CAAAM,GAAA,CAAAd,CAAA,EAAAU,CAAA,gBAAAN,CAAA,IAAAJ,CAAA,gBAAAI,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAI,CAAA,OAAAK,CAAA,IAAAD,CAAA,GAAAS,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAnB,CAAA,EAAAI,CAAA,OAAAK,CAAA,CAAAI,GAAA,IAAAJ,CAAA,CAAAK,GAAA,IAAAN,CAAA,CAAAE,CAAA,EAAAN,CAAA,EAAAK,CAAA,IAAAC,CAAA,CAAAN,CAAA,IAAAJ,CAAA,CAAAI,CAAA,WAAAM,CAAA,KAAAV,CAAA,EAAAI,CAAA,KAJhD;AAMAgB,UAAE,CAACC,IAAI,CAAC,cAAc,EAAE,OAAO;EAC3BnB,OAAO,EAAEA,CAAA,kBAAMN,OAAA,CAAAM,OAAA,CAAAoB,aAAA,aAAO;AAC1B,CAAC,CAAC,CAAC;AAEHF,UAAE,CAACC,IAAI,CAAC,4CAA4C,EAAE,OAAO;EACzDnB,OAAO,EAAEA,CAAC;IAAEqB;EAAwC,CAAC,KAAKA;AAC9D,CAAC,CAAC,CAAC;AAEHH,UAAE,CAACC,IAAI,CAAC,YAAY,EAAE,MAAOG,cAAc,KAAM;EAC7C,IAAI,MAAMA,cAAc,CAA8B,CAAC,CAAC;EACxDC,YAAY,EAAEL,UAAE,CAACM,EAAE,CAAC,OAAO;IAAEC,IAAI,EAAEP,UAAE,CAACM,EAAE,CAAC;EAAE,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,MAAME,QAAQ,GAAIC,IAAU,IACxB,IAAIC,OAAO,CAAS,CAACC,OAAO,EAAEC,MAAM,KAAK;EACrC,MAAMC,MAAM,GAAG,IAAIC,UAAU,CAAC,CAAC;EAC/BD,MAAM,CAACE,OAAO,GAAG,MAAMH,MAAM,CAACC,MAAM,CAACG,KAAK,CAAC;EAC3CH,MAAM,CAACI,MAAM,GAAG,MAAMN,OAAO,CAACE,MAAM,CAACK,MAAgB,CAAC;EACtDL,MAAM,CAACM,UAAU,CAACV,IAAI,CAAC;AAC3B,CAAC,CAAC;AAEN,IAAAW,gBAAQ,EAAC,iBAAiB,EAAE,MAAM;EAC9B,IAAAC,UAAE,EAAC,sDAAsD,EAAE,MAAM;IAC7D,IAAAC,aAAM,eACF9C,OAAA,CAAAM,OAAA,CAAAoB,aAAA,CAACvB,gBAAA,CAAAG,OAAe;MACZyC,OAAO,EACH;IACH,CACJ,CACL,CAAC;IAED,IAAAC,cAAM,EAACC,aAAM,CAACC,SAAS,CAAC,SAAS,EAAE;MAAEC,IAAI,EAAE;IAAU,CAAC,CAAC,CAAC,CAACC,iBAAiB,CAAC,CAAC;IAC5E,IAAAJ,cAAM,EAACC,aAAM,CAACC,SAAS,CAAC,MAAM,EAAE;MAAEC,IAAI,EAAE;IAAO,CAAC,CAAC,CAAC,CAACE,eAAe,CAC9D,MAAM,EACN,qBACJ,CAAC;IACD,IAAAL,cAAM,EAACM,QAAQ,CAACC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAACC,GAAG,CAACJ,iBAAiB,CAAC,CAAC;IAChE,IAAAJ,cAAM,EAACM,QAAQ,CAACC,aAAa,CAAC,UAAU,CAAC,CAAC,CAACC,GAAG,CAACJ,iBAAiB,CAAC,CAAC;EACtE,CAAC,CAAC;EAEF,IAAAP,UAAE,EAAC,2CAA2C,EAAE,YAAY;IACxD,MAAMY,KAAK,GAAGjC,UAAE,CAACkC,KAAK,CAACC,SAAS,CAACC,SAAS,EAAE,OAAO,CAAC,CAACC,iBAAiB,CAAC,CAAC;IACxE,IAAAf,aAAM,eAAC9C,OAAA,CAAAM,OAAA,CAAAoB,aAAA,CAACvB,gBAAA,CAAAG,OAAe;MAACyC,OAAO,EAAC;IAAiB,GAAC,qBAAoC,CAAC,CAAC;IAExFe,gBAAS,CAACC,KAAK,CAACd,aAAM,CAACC,SAAS,CAAC,QAAQ,EAAE;MAAEC,IAAI,EAAE;IAAW,CAAC,CAAC,CAAC;IAEjE,MAAM,IAAAa,cAAO,EAAC,MAAM,IAAAhB,cAAM,EAACS,KAAK,CAAC,CAACQ,gBAAgB,CAAC,CAAC,CAAC;IACrD,MAAMC,IAAI,GAAGT,KAAK,CAAChC,IAAI,CAAC0C,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAA6B;IAClE,MAAM,IAAAnB,cAAM,EAAChB,QAAQ,CAAC,MAAMkC,IAAI,CAACE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAACC,QAAQ,CAACC,IAAI,CAAC,iBAAiB,CAAC;EAC7F,CAAC,CAAC;EAEF,IAAAzB,UAAE,EAAC,uCAAuC,EAAE,YAAY;IACpDrB,UAAE,CAACkC,KAAK,CAACC,SAAS,CAACC,SAAS,EAAE,OAAO,CAAC,CAACC,iBAAiB,CAAC,CAAC;IAC1D,IAAAf,aAAM,eAAC9C,OAAA,CAAAM,OAAA,CAAAoB,aAAA,CAACvB,gBAAA,CAAAG,OAAe;MAACyC,OAAO,EAAC,QAAQ;MAACwB,aAAa,EAAC;IAAM,CAAE,CAAC,CAAC;IAEjET,gBAAS,CAACC,KAAK,CAACd,aAAM,CAACC,SAAS,CAAC,QAAQ,EAAE;MAAEC,IAAI,EAAE;IAAW,CAAC,CAAC,CAAC;IAEjE,MAAM,IAAAa,cAAO,EAAC,YAAY;MACtB,MAAM;QAAEnC;MAAa,CAAC,GAAG,MAAAK,OAAA,CAAAC,OAAA,GAAAqC,IAAA,OAAAjE,uBAAA,CAAAR,OAAA,CAAa,YAAY,GAAC;MACnD,IAAAiD,cAAM,EAACnB,YAAY,CAAC,CAAC4C,oBAAoB,CAACzB,cAAM,CAAC0B,gBAAgB,CAAC;QAAEC,IAAI,EAAE;MAAO,CAAC,CAAC,CAAC;IACxF,CAAC,CAAC;IACF,IAAA3B,cAAM,EAACC,aAAM,CAAC2B,WAAW,CAAC,QAAQ,CAAC,CAAC,CAACpB,GAAG,CAACJ,iBAAiB,CAAC,CAAC;EAChE,CAAC,CAAC;EAEF,IAAAP,UAAE,EAAC,wBAAwB,EAAE,MAAM;IAC/B,IAAAC,aAAM,eAAC9C,OAAA,CAAAM,OAAA,CAAAoB,aAAA,CAACvB,gBAAA,CAAAG,OAAe;MAACyC,OAAO,EAAC;IAAQ,CAAE,CAAC,CAAC;IAE5C,IAAAC,cAAM,EAACC,aAAM,CAACC,SAAS,CAAC,QAAQ,EAAE;MAAEC,IAAI,EAAE;IAAS,CAAC,CAAC,CAAC,CAACC,iBAAiB,CAAC,CAAC;EAC9E,CAAC,CAAC;AACN,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"CopyableContent.test.js","names":["_react","require","_react2","_interopRequireDefault","_vitest","_CopyableContent","e","__esModule","default","vi","mock","icons","createElement","join","children","shouldShowCallingCodeAction","shouldShowCopyAction","importOriginal","createDialog","fn","open","readBlob","blob","Promise","resolve","reject","reader","FileReader","onerror","error","onload","result","readAsText","describe","it","render","content","expect","screen","getByRole","name","toBeInTheDocument","toHaveAttribute","document","querySelector","not","write","spyOn","navigator","clipboard","mockResolvedValue","fireEvent","click","waitFor","toHaveBeenCalled","item","calls","getType","resolves","toBe","container"],"sources":["../../../../src/components/copyable-content/CopyableContent.test.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-call */\nimport { fireEvent, render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { describe, expect, it, vi } from 'vitest';\nimport CopyableContent from './CopyableContent';\n\nvi.mock('../icon/Icon', () => ({\n default: ({ icons }: { icons: string[] }) => <span data-icons={icons.join(' ')} />,\n}));\n\nvi.mock('../sharing-context-menu/SharingContextMenu', () => ({\n default: ({\n children,\n shouldShowCallingCodeAction,\n shouldShowCopyAction,\n }: {\n children: React.ReactNode;\n shouldShowCallingCodeAction?: boolean;\n shouldShowCopyAction?: boolean;\n }) => (\n <div\n data-calling-code-action={shouldShowCallingCodeAction}\n data-copy-action={shouldShowCopyAction}\n >\n {children}\n </div>\n ),\n}));\n\nvi.mock('chayns-api', async (importOriginal) => ({\n ...(await importOriginal<typeof import('chayns-api')>()),\n createDialog: vi.fn(() => ({ open: vi.fn() })),\n}));\n\nconst readBlob = (blob: Blob) =>\n new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error);\n reader.onload = () => resolve(reader.result as string);\n reader.readAsText(blob);\n });\n\ndescribe('CopyableContent', () => {\n it('renders formatted markdown without active input HTML', () => {\n render(\n <CopyableContent\n content={\n '# Heading\\n\\n- Entry\\n\\n[Link](https://example.com)\\n<script onload=\"x\">bad</script>'\n }\n />,\n );\n\n expect(screen.getByRole('heading', { name: 'Heading' })).toBeInTheDocument();\n expect(screen.getByRole('link', { name: 'Link' })).toHaveAttribute(\n 'href',\n 'https://example.com',\n );\n expect(document.querySelector('script')).not.toBeInTheDocument();\n expect(document.querySelector('[onload]')).not.toBeInTheDocument();\n });\n\n it('copies content instead of custom children', async () => {\n const write = vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n render(<CopyableContent content=\"source markdown\">Visible replacement</CopyableContent>);\n\n fireEvent.click(screen.getByRole('button', { name: 'Kopieren' }));\n\n await waitFor(() => expect(write).toHaveBeenCalled());\n const item = write.mock.calls[0][0][0] as unknown as ClipboardItem;\n await expect(readBlob(await item.getType('text/plain'))).resolves.toBe('source markdown');\n });\n\n it('shows a checkmark after a successful copy', async () => {\n vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n const { container } = render(<CopyableContent content=\"source\" />);\n\n fireEvent.click(screen.getByRole('button', { name: 'Kopieren' }));\n\n await waitFor(() => {\n expect(container.querySelector('[data-icons=\"fa fa-check\"]')).toBeInTheDocument();\n });\n });\n\n it('offers sharing actions', () => {\n const { container } = render(<CopyableContent content=\"source\" />);\n\n expect(screen.getByRole('button', { name: 'Teilen' })).toBeInTheDocument();\n expect(container.querySelector('[data-copy-action=\"false\"]')).toBeInTheDocument();\n expect(container.querySelector('[data-calling-code-action=\"false\"]')).toBeInTheDocument();\n });\n});\n"],"mappings":"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","ignoreList":[]}
@@ -5,19 +5,47 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.copyableContentToClipboard = void 0;
7
7
  var _format = require("@chayns-components/format");
8
- const RICH_MIME_TYPES = ['text/plain', 'text/markdown', 'text/html'];
9
- const createClipboardItem = data => new ClipboardItem(data);
10
- const supportsRichMimeTypes = () => {
11
- if (typeof ClipboardItem === 'undefined' || typeof ClipboardItem.supports !== 'function') {
12
- return true;
13
- }
14
- return RICH_MIME_TYPES.every(mimeType => ClipboardItem.supports(mimeType));
8
+ const getPlainTextFromHtml = html => {
9
+ const document = new DOMParser().parseFromString(html, 'text/html');
10
+ return Array.from(document.body.children).map(element => {
11
+ var _element$textContent;
12
+ if (element.tagName === 'UL' || element.tagName === 'OL') {
13
+ return Array.from(element.children).map(item => {
14
+ var _item$textContent;
15
+ return `• ${((_item$textContent = item.textContent) === null || _item$textContent === void 0 ? void 0 : _item$textContent.trim()) ?? ''}`;
16
+ }).join('\n');
17
+ }
18
+ return ((_element$textContent = element.textContent) === null || _element$textContent === void 0 ? void 0 : _element$textContent.trim()) ?? '';
19
+ }).filter(Boolean).join('\n\n');
20
+ };
21
+ const createClipboardContent = source => {
22
+ const {
23
+ html
24
+ } = (0, _format.formatStringToHtml)(source);
25
+ return {
26
+ html,
27
+ plainText: getPlainTextFromHtml(html)
28
+ };
29
+ };
30
+ const copyWithClipboardItem = async ({
31
+ html,
32
+ plainText
33
+ }) => {
34
+ const clipboardData = new ClipboardItem({
35
+ 'text/plain': new Blob([plainText], {
36
+ type: 'text/plain'
37
+ }),
38
+ 'text/html': new Blob([html], {
39
+ type: 'text/html'
40
+ })
41
+ });
42
+ await navigator.clipboard.write([clipboardData]);
15
43
  };
16
- const copyPlainText = async source => {
44
+ const copyPlainText = async plainText => {
17
45
  if (typeof ClipboardItem !== 'undefined') {
18
46
  try {
19
- await navigator.clipboard.write([createClipboardItem({
20
- 'text/plain': new Blob([source], {
47
+ await navigator.clipboard.write([new ClipboardItem({
48
+ 'text/plain': new Blob([plainText], {
21
49
  type: 'text/plain'
22
50
  })
23
51
  })]);
@@ -26,33 +54,22 @@ const copyPlainText = async source => {
26
54
  // Use writeText as the final browser-compatible fallback.
27
55
  }
28
56
  }
29
- await navigator.clipboard.writeText(source);
57
+ await navigator.clipboard.writeText(plainText);
30
58
  };
31
59
  const copyableContentToClipboard = async source => {
60
+ const clipboardContent = createClipboardContent(source);
32
61
  if (!navigator.clipboard) {
33
62
  throw new Error('Clipboard API is not available.');
34
63
  }
35
- if (typeof ClipboardItem === 'undefined' || !supportsRichMimeTypes()) {
36
- await copyPlainText(source);
64
+ if (typeof ClipboardItem === 'undefined') {
65
+ await copyPlainText(clipboardContent.plainText);
37
66
  return;
38
67
  }
39
- const {
40
- html
41
- } = (0, _format.formatStringToHtml)(source);
42
68
  try {
43
- await navigator.clipboard.write([createClipboardItem({
44
- 'text/plain': new Blob([source], {
45
- type: 'text/plain'
46
- }),
47
- 'text/markdown': new Blob([source], {
48
- type: 'text/markdown'
49
- }),
50
- 'text/html': new Blob([html], {
51
- type: 'text/html'
52
- })
53
- })]);
69
+ await copyWithClipboardItem(clipboardContent);
54
70
  } catch {
55
- await copyPlainText(source);
71
+ // Use the plain-text fallback when the browser rejects rich MIME types.
72
+ await copyPlainText(clipboardContent.plainText);
56
73
  }
57
74
  };
58
75
  exports.copyableContentToClipboard = copyableContentToClipboard;
@@ -1 +1 @@
1
- {"version":3,"file":"copyableContentClipboard.js","names":["_format","require","RICH_MIME_TYPES","createClipboardItem","data","ClipboardItem","supportsRichMimeTypes","supports","every","mimeType","copyPlainText","source","navigator","clipboard","write","Blob","type","writeText","copyableContentToClipboard","Error","html","formatStringToHtml","exports"],"sources":["../../../../src/components/copyable-content/copyableContentClipboard.ts"],"sourcesContent":["import { formatStringToHtml } from '@chayns-components/format';\n\nconst RICH_MIME_TYPES = ['text/plain', 'text/markdown', 'text/html'] as const;\n\nconst createClipboardItem = (data: Record<string, Blob>) => new ClipboardItem(data);\n\nconst supportsRichMimeTypes = () => {\n if (typeof ClipboardItem === 'undefined' || typeof ClipboardItem.supports !== 'function') {\n return true;\n }\n\n return RICH_MIME_TYPES.every((mimeType) => ClipboardItem.supports(mimeType));\n};\n\nconst copyPlainText = async (source: string) => {\n if (typeof ClipboardItem !== 'undefined') {\n try {\n await navigator.clipboard.write([\n createClipboardItem({ 'text/plain': new Blob([source], { type: 'text/plain' }) }),\n ]);\n return;\n } catch {\n // Use writeText as the final browser-compatible fallback.\n }\n }\n\n await navigator.clipboard.writeText(source);\n};\n\nexport const copyableContentToClipboard = async (source: string) => {\n if (!navigator.clipboard) {\n throw new Error('Clipboard API is not available.');\n }\n\n if (typeof ClipboardItem === 'undefined' || !supportsRichMimeTypes()) {\n await copyPlainText(source);\n return;\n }\n\n const { html } = formatStringToHtml(source);\n\n try {\n await navigator.clipboard.write([\n createClipboardItem({\n 'text/plain': new Blob([source], { type: 'text/plain' }),\n 'text/markdown': new Blob([source], { type: 'text/markdown' }),\n 'text/html': new Blob([html], { type: 'text/html' }),\n }),\n ]);\n } catch {\n await copyPlainText(source);\n }\n};\n"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAEA,MAAMC,eAAe,GAAG,CAAC,YAAY,EAAE,eAAe,EAAE,WAAW,CAAU;AAE7E,MAAMC,mBAAmB,GAAIC,IAA0B,IAAK,IAAIC,aAAa,CAACD,IAAI,CAAC;AAEnF,MAAME,qBAAqB,GAAGA,CAAA,KAAM;EAChC,IAAI,OAAOD,aAAa,KAAK,WAAW,IAAI,OAAOA,aAAa,CAACE,QAAQ,KAAK,UAAU,EAAE;IACtF,OAAO,IAAI;EACf;EAEA,OAAOL,eAAe,CAACM,KAAK,CAAEC,QAAQ,IAAKJ,aAAa,CAACE,QAAQ,CAACE,QAAQ,CAAC,CAAC;AAChF,CAAC;AAED,MAAMC,aAAa,GAAG,MAAOC,MAAc,IAAK;EAC5C,IAAI,OAAON,aAAa,KAAK,WAAW,EAAE;IACtC,IAAI;MACA,MAAMO,SAAS,CAACC,SAAS,CAACC,KAAK,CAAC,CAC5BX,mBAAmB,CAAC;QAAE,YAAY,EAAE,IAAIY,IAAI,CAAC,CAACJ,MAAM,CAAC,EAAE;UAAEK,IAAI,EAAE;QAAa,CAAC;MAAE,CAAC,CAAC,CACpF,CAAC;MACF;IACJ,CAAC,CAAC,MAAM;MACJ;IAAA;EAER;EAEA,MAAMJ,SAAS,CAACC,SAAS,CAACI,SAAS,CAACN,MAAM,CAAC;AAC/C,CAAC;AAEM,MAAMO,0BAA0B,GAAG,MAAOP,MAAc,IAAK;EAChE,IAAI,CAACC,SAAS,CAACC,SAAS,EAAE;IACtB,MAAM,IAAIM,KAAK,CAAC,iCAAiC,CAAC;EACtD;EAEA,IAAI,OAAOd,aAAa,KAAK,WAAW,IAAI,CAACC,qBAAqB,CAAC,CAAC,EAAE;IAClE,MAAMI,aAAa,CAACC,MAAM,CAAC;IAC3B;EACJ;EAEA,MAAM;IAAES;EAAK,CAAC,GAAG,IAAAC,0BAAkB,EAACV,MAAM,CAAC;EAE3C,IAAI;IACA,MAAMC,SAAS,CAACC,SAAS,CAACC,KAAK,CAAC,CAC5BX,mBAAmB,CAAC;MAChB,YAAY,EAAE,IAAIY,IAAI,CAAC,CAACJ,MAAM,CAAC,EAAE;QAAEK,IAAI,EAAE;MAAa,CAAC,CAAC;MACxD,eAAe,EAAE,IAAID,IAAI,CAAC,CAACJ,MAAM,CAAC,EAAE;QAAEK,IAAI,EAAE;MAAgB,CAAC,CAAC;MAC9D,WAAW,EAAE,IAAID,IAAI,CAAC,CAACK,IAAI,CAAC,EAAE;QAAEJ,IAAI,EAAE;MAAY,CAAC;IACvD,CAAC,CAAC,CACL,CAAC;EACN,CAAC,CAAC,MAAM;IACJ,MAAMN,aAAa,CAACC,MAAM,CAAC;EAC/B;AACJ,CAAC;AAACW,OAAA,CAAAJ,0BAAA,GAAAA,0BAAA","ignoreList":[]}
1
+ {"version":3,"file":"copyableContentClipboard.js","names":["_format","require","getPlainTextFromHtml","html","document","DOMParser","parseFromString","Array","from","body","children","map","element","_element$textContent","tagName","item","_item$textContent","textContent","trim","join","filter","Boolean","createClipboardContent","source","formatStringToHtml","plainText","copyWithClipboardItem","clipboardData","ClipboardItem","Blob","type","navigator","clipboard","write","copyPlainText","writeText","copyableContentToClipboard","clipboardContent","Error","exports"],"sources":["../../../../src/components/copyable-content/copyableContentClipboard.ts"],"sourcesContent":["import { formatStringToHtml } from '@chayns-components/format';\n\ninterface ClipboardContent {\n html: string;\n plainText: string;\n}\n\nconst getPlainTextFromHtml = (html: string) => {\n const document = new DOMParser().parseFromString(html, 'text/html');\n\n return Array.from(document.body.children)\n .map((element) => {\n if (element.tagName === 'UL' || element.tagName === 'OL') {\n return Array.from(element.children)\n .map((item) => `• ${item.textContent?.trim() ?? ''}`)\n .join('\\n');\n }\n\n return element.textContent?.trim() ?? '';\n })\n .filter(Boolean)\n .join('\\n\\n');\n};\n\nconst createClipboardContent = (source: string): ClipboardContent => {\n const { html } = formatStringToHtml(source);\n return { html, plainText: getPlainTextFromHtml(html) };\n};\n\nconst copyWithClipboardItem = async ({ html, plainText }: ClipboardContent) => {\n const clipboardData = new ClipboardItem({\n 'text/plain': new Blob([plainText], { type: 'text/plain' }),\n 'text/html': new Blob([html], { type: 'text/html' }),\n });\n\n await navigator.clipboard.write([clipboardData]);\n};\n\nconst copyPlainText = async (plainText: string) => {\n if (typeof ClipboardItem !== 'undefined') {\n try {\n await navigator.clipboard.write([\n new ClipboardItem({\n 'text/plain': new Blob([plainText], { type: 'text/plain' }),\n }),\n ]);\n return;\n } catch {\n // Use writeText as the final browser-compatible fallback.\n }\n }\n\n await navigator.clipboard.writeText(plainText);\n};\n\nexport const copyableContentToClipboard = async (source: string) => {\n const clipboardContent = createClipboardContent(source);\n\n if (!navigator.clipboard) {\n throw new Error('Clipboard API is not available.');\n }\n\n if (typeof ClipboardItem === 'undefined') {\n await copyPlainText(clipboardContent.plainText);\n return;\n }\n\n try {\n await copyWithClipboardItem(clipboardContent);\n } catch {\n // Use the plain-text fallback when the browser rejects rich MIME types.\n await copyPlainText(clipboardContent.plainText);\n }\n};\n"],"mappings":"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","ignoreList":[]}
@@ -14,27 +14,29 @@ const readBlob = blob => new Promise((resolve, reject) => {
14
14
  (0, _vitest.afterEach)(() => {
15
15
  _vitest.vi.restoreAllMocks();
16
16
  });
17
- (0, _vitest.it)('writes exact source as plain text and markdown with safe HTML', async () => {
17
+ (0, _vitest.it)('writes readable plain text first and safe HTML second', async () => {
18
18
  const write = _vitest.vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();
19
19
  await (0, _copyableContentClipboard.copyableContentToClipboard)(source);
20
20
  const item = write.mock.calls[0][0][0];
21
- await (0, _vitest.expect)(readBlob(await item.getType('text/plain'))).resolves.toBe(source);
22
- await (0, _vitest.expect)(readBlob(await item.getType('text/markdown'))).resolves.toBe(source);
21
+ (0, _vitest.expect)(Object.keys(item.items)).toEqual(['text/plain', 'text/html']);
22
+ await (0, _vitest.expect)(readBlob(await item.getType('text/plain'))).resolves.toBe('Heading\n\nLink');
23
23
  await (0, _vitest.expect)(readBlob(await item.getType('text/html'))).resolves.toBe((0, _format.formatStringToHtml)(source).html);
24
24
  });
25
- (0, _vitest.it)('uses a plain ClipboardItem when rich MIME types are unsupported', async () => {
26
- _vitest.vi.stubGlobal('ClipboardItem', Object.assign(class {}, {
27
- supports: () => false
28
- }));
29
- const write = _vitest.vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();
25
+ (0, _vitest.it)('uses a plain ClipboardItem after a rejected rich write', async () => {
26
+ const write = _vitest.vi.spyOn(navigator.clipboard, 'write').mockRejectedValueOnce(new Error('denied')).mockResolvedValueOnce();
27
+ const writeText = _vitest.vi.spyOn(navigator.clipboard, 'writeText').mockResolvedValue();
30
28
  await (0, _copyableContentClipboard.copyableContentToClipboard)(source);
31
- (0, _vitest.expect)(write).toHaveBeenCalledTimes(1);
29
+ (0, _vitest.expect)(write).toHaveBeenCalledTimes(2);
30
+ (0, _vitest.expect)(writeText).not.toHaveBeenCalled();
31
+ const item = write.mock.calls[1][0][0];
32
+ (0, _vitest.expect)(Object.keys(item.items)).toEqual(['text/plain']);
33
+ await (0, _vitest.expect)(readBlob(await item.getType('text/plain'))).resolves.toBe('Heading\n\nLink');
32
34
  });
33
- (0, _vitest.it)('uses writeText after ClipboardItem writes fail', async () => {
35
+ (0, _vitest.it)('uses writeText after all ClipboardItem writes fail', async () => {
34
36
  _vitest.vi.spyOn(navigator.clipboard, 'write').mockRejectedValue(new Error('denied'));
35
37
  const writeText = _vitest.vi.spyOn(navigator.clipboard, 'writeText').mockResolvedValue();
36
38
  await (0, _copyableContentClipboard.copyableContentToClipboard)(source);
37
- (0, _vitest.expect)(writeText).toHaveBeenCalledWith(source);
39
+ (0, _vitest.expect)(writeText).toHaveBeenCalledWith('Heading\n\nLink');
38
40
  });
39
41
  });
40
42
  //# sourceMappingURL=copyableContentClipboard.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"copyableContentClipboard.test.js","names":["_format","require","_vitest","_copyableContentClipboard","source","readBlob","blob","Promise","resolve","reject","reader","FileReader","onerror","error","onload","result","readAsText","describe","afterEach","vi","restoreAllMocks","it","write","spyOn","navigator","clipboard","mockResolvedValue","copyableContentToClipboard","item","mock","calls","expect","getType","resolves","toBe","formatStringToHtml","html","stubGlobal","Object","assign","supports","toHaveBeenCalledTimes","mockRejectedValue","Error","writeText","toHaveBeenCalledWith"],"sources":["../../../../src/components/copyable-content/copyableContentClipboard.test.ts"],"sourcesContent":["import { formatStringToHtml } from '@chayns-components/format';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport { copyableContentToClipboard } from './copyableContentClipboard';\n\nconst source = '# Heading\\n\\n[Link](https://example.com)';\n\nconst readBlob = (blob: Blob) =>\n new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error);\n reader.onload = () => resolve(reader.result as string);\n reader.readAsText(blob);\n });\n\ndescribe('copyableContentToClipboard', () => {\n afterEach(() => {\n vi.restoreAllMocks();\n });\n\n it('writes exact source as plain text and markdown with safe HTML', async () => {\n const write = vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n\n await copyableContentToClipboard(source);\n\n const item = write.mock.calls[0][0][0] as unknown as ClipboardItem;\n await expect(readBlob(await item.getType('text/plain'))).resolves.toBe(source);\n await expect(readBlob(await item.getType('text/markdown'))).resolves.toBe(source);\n await expect(readBlob(await item.getType('text/html'))).resolves.toBe(\n formatStringToHtml(source).html,\n );\n });\n\n it('uses a plain ClipboardItem when rich MIME types are unsupported', async () => {\n vi.stubGlobal('ClipboardItem', Object.assign(class {}, { supports: () => false }));\n const write = vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n\n await copyableContentToClipboard(source);\n\n expect(write).toHaveBeenCalledTimes(1);\n });\n\n it('uses writeText after ClipboardItem writes fail', async () => {\n vi.spyOn(navigator.clipboard, 'write').mockRejectedValue(new Error('denied'));\n const writeText = vi.spyOn(navigator.clipboard, 'writeText').mockResolvedValue();\n\n await copyableContentToClipboard(source);\n\n expect(writeText).toHaveBeenCalledWith(source);\n });\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"copyableContentClipboard.test.js","names":["_format","require","_vitest","_copyableContentClipboard","source","readBlob","blob","Promise","resolve","reject","reader","FileReader","onerror","error","onload","result","readAsText","describe","afterEach","vi","restoreAllMocks","it","write","spyOn","navigator","clipboard","mockResolvedValue","copyableContentToClipboard","item","mock","calls","expect","Object","keys","items","toEqual","getType","resolves","toBe","formatStringToHtml","html","mockRejectedValueOnce","Error","mockResolvedValueOnce","writeText","toHaveBeenCalledTimes","not","toHaveBeenCalled","mockRejectedValue","toHaveBeenCalledWith"],"sources":["../../../../src/components/copyable-content/copyableContentClipboard.test.ts"],"sourcesContent":["import { formatStringToHtml } from '@chayns-components/format';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport { copyableContentToClipboard } from './copyableContentClipboard';\n\nconst source = '# Heading\\n\\n[Link](https://example.com)';\n\nconst readBlob = (blob: Blob) =>\n new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error);\n reader.onload = () => resolve(reader.result as string);\n reader.readAsText(blob);\n });\n\ndescribe('copyableContentToClipboard', () => {\n afterEach(() => {\n vi.restoreAllMocks();\n });\n\n it('writes readable plain text first and safe HTML second', async () => {\n const write = vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n\n await copyableContentToClipboard(source);\n\n const item = write.mock.calls[0][0][0] as unknown as ClipboardItem & {\n items: Record<string, Blob>;\n };\n expect(Object.keys(item.items)).toEqual(['text/plain', 'text/html']);\n await expect(readBlob(await item.getType('text/plain'))).resolves.toBe('Heading\\n\\nLink');\n await expect(readBlob(await item.getType('text/html'))).resolves.toBe(\n formatStringToHtml(source).html,\n );\n });\n\n it('uses a plain ClipboardItem after a rejected rich write', async () => {\n const write = vi\n .spyOn(navigator.clipboard, 'write')\n .mockRejectedValueOnce(new Error('denied'))\n .mockResolvedValueOnce();\n const writeText = vi.spyOn(navigator.clipboard, 'writeText').mockResolvedValue();\n\n await copyableContentToClipboard(source);\n\n expect(write).toHaveBeenCalledTimes(2);\n expect(writeText).not.toHaveBeenCalled();\n const item = write.mock.calls[1][0][0] as unknown as ClipboardItem & {\n items: Record<string, Blob>;\n };\n expect(Object.keys(item.items)).toEqual(['text/plain']);\n await expect(readBlob(await item.getType('text/plain'))).resolves.toBe('Heading\\n\\nLink');\n });\n\n it('uses writeText after all ClipboardItem writes fail', async () => {\n vi.spyOn(navigator.clipboard, 'write').mockRejectedValue(new Error('denied'));\n const writeText = vi.spyOn(navigator.clipboard, 'writeText').mockResolvedValue();\n\n await copyableContentToClipboard(source);\n\n expect(writeText).toHaveBeenCalledWith('Heading\\n\\nLink');\n });\n});\n"],"mappings":"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","ignoreList":[]}
@@ -17,6 +17,8 @@ const SharingContextMenu = /*#__PURE__*/(0, _react.forwardRef)(({
17
17
  link,
18
18
  children,
19
19
  shouldEnableKeyboardHighlighting,
20
+ shouldShowCallingCodeAction = true,
21
+ shouldShowCopyAction = true,
20
22
  ...contextMenuProps
21
23
  }, ref) => {
22
24
  const isTouch = (0, _environment.useIsTouch)();
@@ -63,12 +65,12 @@ const SharingContextMenu = /*#__PURE__*/(0, _react.forwardRef)(({
63
65
  break;
64
66
  }
65
67
  }, [link, isTouch]);
66
- const contextMenuItems = [{
68
+ const contextMenuItems = [...(shouldShowCopyAction ? [{
67
69
  icons: ['fa fa-copy'],
68
70
  key: 'copy',
69
71
  onClick: () => handleShare('copy'),
70
72
  text: 'Zwischenablage'
71
- }, {
73
+ }] : []), {
72
74
  icons: ['fa-solid fa-brands fa-whatsapp'],
73
75
  key: 'whatsapp',
74
76
  onClick: () => handleShare('whatsapp'),
@@ -88,21 +90,18 @@ const SharingContextMenu = /*#__PURE__*/(0, _react.forwardRef)(({
88
90
  key: 'mail',
89
91
  onClick: () => handleShare('mail'),
90
92
  text: 'Mail'
91
- }, {
93
+ }, ...(shouldShowCallingCodeAction ? [{
92
94
  icons: ['fa fa-qrcode'],
93
95
  key: 'callingCode',
94
96
  onClick: handleImageDownload,
95
97
  text: 'Calling Code herunterladen'
96
- }];
97
- return (
98
- /*#__PURE__*/
98
+ }] : [])];
99
+ return /*#__PURE__*/_react.default.createElement(_ContextMenu.default, _extends({
100
+ items: contextMenuItems,
101
+ ref: ref,
102
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting
99
103
  // eslint-disable-next-line react/jsx-props-no-spreading
100
- _react.default.createElement(_ContextMenu.default, _extends({
101
- items: contextMenuItems,
102
- ref: ref,
103
- shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting
104
- }, contextMenuProps), children)
105
- );
104
+ }, contextMenuProps), children);
106
105
  });
107
106
  SharingContextMenu.displayName = 'SharingContextMenu';
108
107
  var _default = exports.default = SharingContextMenu;