@transferwise/components 46.160.6 → 46.160.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/Prompt/InfoPrompt/InfoPrompt.js +13 -6
- package/build/Prompt/InfoPrompt/InfoPrompt.js.map +1 -1
- package/build/Prompt/InfoPrompt/InfoPrompt.mjs +13 -6
- package/build/Prompt/InfoPrompt/InfoPrompt.mjs.map +1 -1
- package/build/Prompt/PrimitivePrompt/PrimitivePrompt.js +1 -0
- package/build/Prompt/PrimitivePrompt/PrimitivePrompt.js.map +1 -1
- package/build/Prompt/PrimitivePrompt/PrimitivePrompt.mjs +1 -0
- package/build/Prompt/PrimitivePrompt/PrimitivePrompt.mjs.map +1 -1
- package/build/main.css +17 -0
- package/build/styles/Prompt/PrimitivePrompt/PrimitivePrompt.css +17 -0
- package/build/styles/main.css +17 -0
- package/build/types/Prompt/InfoPrompt/InfoPrompt.d.ts.map +1 -1
- package/build/types/Prompt/PrimitivePrompt/PrimitivePrompt.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Prompt/InfoPrompt/InfoPrompt.test.tsx +56 -2
- package/src/Prompt/InfoPrompt/InfoPrompt.tsx +14 -7
- package/src/Prompt/InfoPrompt/_stories/InfoPrompt.story.tsx +6 -1
- package/src/Prompt/PrimitivePrompt/PrimitivePrompt.css +17 -0
- package/src/Prompt/PrimitivePrompt/PrimitivePrompt.less +15 -0
- package/src/Prompt/PrimitivePrompt/PrimitivePrompt.tsx +1 -0
- package/src/main.css +17 -0
|
@@ -47,15 +47,22 @@ const InfoPrompt = ({
|
|
|
47
47
|
const [shouldFire, setShouldFire] = React.useState();
|
|
48
48
|
const announceOnChange = [title, React.Children.toArray(description).map(child => /*#__PURE__*/React.isValidElement(child) ? child.props.children : child).join(''), action?.label].filter(Boolean).join('|');
|
|
49
49
|
const statusIconSentiment = sentiment$1 === 'success' ? sentiment.Sentiment.POSITIVE : sentiment$1;
|
|
50
|
-
const handleTouchStart =
|
|
50
|
+
const handleTouchStart = event => {
|
|
51
|
+
const target = event.target;
|
|
52
|
+
if (target.closest('.wds-prompt__dismiss') || target.closest('.wds-info-prompt__action')) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
51
55
|
setShouldFire(true);
|
|
52
56
|
};
|
|
53
57
|
const handleTouchEnd = () => {
|
|
54
|
-
if (shouldFire && action
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
if (shouldFire && action) {
|
|
59
|
+
action.onClick?.();
|
|
60
|
+
if (action.href) {
|
|
61
|
+
if (action.target === '_blank') {
|
|
62
|
+
window.top?.open(action.href, '_blank', 'noopener, noreferrer');
|
|
63
|
+
} else {
|
|
64
|
+
window.top?.location.assign(action.href);
|
|
65
|
+
}
|
|
59
66
|
}
|
|
60
67
|
}
|
|
61
68
|
setShouldFire(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoPrompt.js","sources":["../../../src/Prompt/InfoPrompt/InfoPrompt.tsx"],"sourcesContent":["import { Children, HTMLAttributes, ReactNode, isValidElement, useState } from 'react';\nimport { LiveRegion, Sentiment, Typography } from '../../common';\nimport type { AriaLive } from '../../common';\nimport { GiftBox } from '@transferwise/icons';\nimport type { Sentiment as SurfaceSentiment } from '../../SentimentSurface';\nimport StatusIcon from '../../StatusIcon';\nimport { clsx } from 'clsx';\nimport Body from '../../Body';\nimport Link, { LinkProps } from '../../Link';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nexport type InfoPromptAction = Pick<LinkProps, 'href' | 'target' | 'onClick'> & {\n /**\n * The label text for the action link\n */\n label: string;\n};\n\nexport type InfoPromptMedia = {\n /**\n * The icon/image asset to display.\n * The asset should include its own accessibility attributes (e.g. title, aria-label) if it conveys meaning.\n */\n asset: ReactNode;\n};\n\nexport type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'aria-live' | 'role'> &\n Pick<PrimitivePromptProps, 'data-testid'> & {\n /**\n * The sentiment determines the colour scheme\n * @default 'neutral'\n */\n sentiment?: SurfaceSentiment;\n /**\n * Handler called when the close button is clicked.\n * If not provided, the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Custom media to override the default status icon.\n * Success and proposition sentiments support 2 status variations: standard checkmark & confetti.\n */\n media?: InfoPromptMedia;\n /**\n * Action link to be displayed below the description\n */\n action?: InfoPromptAction;\n /**\n * Title content for the prompt\n */\n title?: string;\n /**\n * Description content for the prompt (required). Accepts plain text or rich content (ReactNode).\n * If the description contains an interactive element, the `action` prop must not be used simultaneously.\n */\n description: ReactNode;\n className?: string;\n /**\n * Sets the ARIA live region politeness level.\n * - `'polite'` — announced after the current speech (default)\n * - `'assertive'` — interrupts the current speech immediately\n * - `'off'` — disables the live region entirely\n * @default 'polite'\n */\n 'aria-live'?: AriaLive;\n };\n\n/**\n * `InfoPrompt` displays important contextual messages to users within a screen.\n * It provides a visually distinct way to communicate information, warnings, errors,\n * or positive feedback with optional actions and dismissal capabilities.\n *\n * Use this component to replace the deprecated `Alert` component (run codemod to migrate: **`npx \\@wise/wds-codemods@latest info-prompt`**).\n *\n * Guidance can be found in the [design system](https://docs.wise.design/components/info-prompt).\n */\nexport const InfoPrompt = ({\n sentiment = 'neutral',\n onDismiss,\n media,\n action,\n title,\n description,\n className,\n 'aria-live': ariaLive = 'polite',\n 'data-testid': dataTestId,\n ...restProps\n}: InfoPromptProps) => {\n const [shouldFire, setShouldFire] = useState<boolean>();\n const announceOnChange = [\n title,\n Children.toArray(description)\n .map((child) =>\n isValidElement<{ children?: ReactNode }>(child) ? child.props.children : child,\n )\n .join(''),\n action?.label,\n ]\n .filter(Boolean)\n .join('|');\n const statusIconSentiment =\n sentiment === 'success'\n ? Sentiment.POSITIVE\n : (sentiment as Exclude<SurfaceSentiment, 'proposition'>);\n\n const handleTouchStart = () => {\n setShouldFire(true);\n };\n\n const handleTouchEnd = () => {\n if (shouldFire && action?.href) {\n
|
|
1
|
+
{"version":3,"file":"InfoPrompt.js","sources":["../../../src/Prompt/InfoPrompt/InfoPrompt.tsx"],"sourcesContent":["import { Children, HTMLAttributes, ReactNode, TouchEvent, isValidElement, useState } from 'react';\nimport { LiveRegion, Sentiment, Typography } from '../../common';\nimport type { AriaLive } from '../../common';\nimport { GiftBox } from '@transferwise/icons';\nimport type { Sentiment as SurfaceSentiment } from '../../SentimentSurface';\nimport StatusIcon from '../../StatusIcon';\nimport { clsx } from 'clsx';\nimport Body from '../../Body';\nimport Link, { LinkProps } from '../../Link';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nexport type InfoPromptAction = Pick<LinkProps, 'href' | 'target' | 'onClick'> & {\n /**\n * The label text for the action link\n */\n label: string;\n};\n\nexport type InfoPromptMedia = {\n /**\n * The icon/image asset to display.\n * The asset should include its own accessibility attributes (e.g. title, aria-label) if it conveys meaning.\n */\n asset: ReactNode;\n};\n\nexport type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'aria-live' | 'role'> &\n Pick<PrimitivePromptProps, 'data-testid'> & {\n /**\n * The sentiment determines the colour scheme\n * @default 'neutral'\n */\n sentiment?: SurfaceSentiment;\n /**\n * Handler called when the close button is clicked.\n * If not provided, the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Custom media to override the default status icon.\n * Success and proposition sentiments support 2 status variations: standard checkmark & confetti.\n */\n media?: InfoPromptMedia;\n /**\n * Action link to be displayed below the description\n */\n action?: InfoPromptAction;\n /**\n * Title content for the prompt\n */\n title?: string;\n /**\n * Description content for the prompt (required). Accepts plain text or rich content (ReactNode).\n * If the description contains an interactive element, the `action` prop must not be used simultaneously.\n */\n description: ReactNode;\n className?: string;\n /**\n * Sets the ARIA live region politeness level.\n * - `'polite'` — announced after the current speech (default)\n * - `'assertive'` — interrupts the current speech immediately\n * - `'off'` — disables the live region entirely\n * @default 'polite'\n */\n 'aria-live'?: AriaLive;\n };\n\n/**\n * `InfoPrompt` displays important contextual messages to users within a screen.\n * It provides a visually distinct way to communicate information, warnings, errors,\n * or positive feedback with optional actions and dismissal capabilities.\n *\n * Use this component to replace the deprecated `Alert` component (run codemod to migrate: **`npx \\@wise/wds-codemods@latest info-prompt`**).\n *\n * Guidance can be found in the [design system](https://docs.wise.design/components/info-prompt).\n */\nexport const InfoPrompt = ({\n sentiment = 'neutral',\n onDismiss,\n media,\n action,\n title,\n description,\n className,\n 'aria-live': ariaLive = 'polite',\n 'data-testid': dataTestId,\n ...restProps\n}: InfoPromptProps) => {\n const [shouldFire, setShouldFire] = useState<boolean>();\n const announceOnChange = [\n title,\n Children.toArray(description)\n .map((child) =>\n isValidElement<{ children?: ReactNode }>(child) ? child.props.children : child,\n )\n .join(''),\n action?.label,\n ]\n .filter(Boolean)\n .join('|');\n const statusIconSentiment =\n sentiment === 'success'\n ? Sentiment.POSITIVE\n : (sentiment as Exclude<SurfaceSentiment, 'proposition'>);\n\n const handleTouchStart = (event: TouchEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n if (target.closest('.wds-prompt__dismiss') || target.closest('.wds-info-prompt__action')) {\n return;\n }\n setShouldFire(true);\n };\n\n const handleTouchEnd = () => {\n if (shouldFire && action) {\n (action.onClick as (() => void) | undefined)?.();\n if (action.href) {\n if (action.target === '_blank') {\n window.top?.open(action.href, '_blank', 'noopener, noreferrer');\n } else {\n window.top?.location.assign(action.href);\n }\n }\n }\n setShouldFire(false);\n };\n\n const handleTouchMove = () => {\n setShouldFire(false);\n };\n\n const renderMedia = () => {\n if (media) {\n return <span className=\"wds-info-prompt__media\">{media.asset}</span>;\n }\n\n if (sentiment === 'proposition') {\n return (\n <span className=\"wds-info-prompt__media\">\n <GiftBox />\n </span>\n );\n }\n\n return <StatusIcon size={24} sentiment={statusIconSentiment} />;\n };\n\n // Render content directly in LiveRegion\n return (\n <LiveRegion aria-live={ariaLive} announceOnChange={announceOnChange}>\n <PrimitivePrompt\n sentiment={sentiment}\n media={renderMedia()}\n data-testid={dataTestId}\n className={clsx('wds-info-prompt', className)}\n {...restProps}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchMove={handleTouchMove}\n onDismiss={onDismiss}\n >\n <div className=\"wds-info-prompt__content\">\n {title && (\n <Body className=\"wds-info-prompt__title\" type={Typography.BODY_LARGE_BOLD} as=\"span\">\n {title}\n </Body>\n )}\n <Body as=\"span\" className=\"wds-info-prompt__description\">\n {description}\n </Body>\n {action && (\n <Link\n href={action.href}\n target={action.target}\n type={Typography.LINK_DEFAULT}\n className=\"wds-info-prompt__action\"\n onClick={action.onClick}\n >\n {action.label}\n </Link>\n )}\n </div>\n </PrimitivePrompt>\n </LiveRegion>\n );\n};\n"],"names":["InfoPrompt","sentiment","onDismiss","media","action","title","description","className","ariaLive","dataTestId","restProps","shouldFire","setShouldFire","useState","announceOnChange","Children","toArray","map","child","isValidElement","props","children","join","label","filter","Boolean","statusIconSentiment","Sentiment","POSITIVE","handleTouchStart","event","target","closest","handleTouchEnd","onClick","href","window","top","open","location","assign","handleTouchMove","renderMedia","_jsx","asset","GiftBox","StatusIcon","size","LiveRegion","PrimitivePrompt","clsx","onTouchStart","onTouchEnd","onTouchMove","_jsxs","Body","type","Typography","BODY_LARGE_BOLD","as","Link","LINK_DEFAULT"],"mappings":"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"}
|
|
@@ -45,15 +45,22 @@ const InfoPrompt = ({
|
|
|
45
45
|
const [shouldFire, setShouldFire] = useState();
|
|
46
46
|
const announceOnChange = [title, Children.toArray(description).map(child => /*#__PURE__*/isValidElement(child) ? child.props.children : child).join(''), action?.label].filter(Boolean).join('|');
|
|
47
47
|
const statusIconSentiment = sentiment === 'success' ? Sentiment.POSITIVE : sentiment;
|
|
48
|
-
const handleTouchStart =
|
|
48
|
+
const handleTouchStart = event => {
|
|
49
|
+
const target = event.target;
|
|
50
|
+
if (target.closest('.wds-prompt__dismiss') || target.closest('.wds-info-prompt__action')) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
49
53
|
setShouldFire(true);
|
|
50
54
|
};
|
|
51
55
|
const handleTouchEnd = () => {
|
|
52
|
-
if (shouldFire && action
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
if (shouldFire && action) {
|
|
57
|
+
action.onClick?.();
|
|
58
|
+
if (action.href) {
|
|
59
|
+
if (action.target === '_blank') {
|
|
60
|
+
window.top?.open(action.href, '_blank', 'noopener, noreferrer');
|
|
61
|
+
} else {
|
|
62
|
+
window.top?.location.assign(action.href);
|
|
63
|
+
}
|
|
57
64
|
}
|
|
58
65
|
}
|
|
59
66
|
setShouldFire(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoPrompt.mjs","sources":["../../../src/Prompt/InfoPrompt/InfoPrompt.tsx"],"sourcesContent":["import { Children, HTMLAttributes, ReactNode, isValidElement, useState } from 'react';\nimport { LiveRegion, Sentiment, Typography } from '../../common';\nimport type { AriaLive } from '../../common';\nimport { GiftBox } from '@transferwise/icons';\nimport type { Sentiment as SurfaceSentiment } from '../../SentimentSurface';\nimport StatusIcon from '../../StatusIcon';\nimport { clsx } from 'clsx';\nimport Body from '../../Body';\nimport Link, { LinkProps } from '../../Link';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nexport type InfoPromptAction = Pick<LinkProps, 'href' | 'target' | 'onClick'> & {\n /**\n * The label text for the action link\n */\n label: string;\n};\n\nexport type InfoPromptMedia = {\n /**\n * The icon/image asset to display.\n * The asset should include its own accessibility attributes (e.g. title, aria-label) if it conveys meaning.\n */\n asset: ReactNode;\n};\n\nexport type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'aria-live' | 'role'> &\n Pick<PrimitivePromptProps, 'data-testid'> & {\n /**\n * The sentiment determines the colour scheme\n * @default 'neutral'\n */\n sentiment?: SurfaceSentiment;\n /**\n * Handler called when the close button is clicked.\n * If not provided, the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Custom media to override the default status icon.\n * Success and proposition sentiments support 2 status variations: standard checkmark & confetti.\n */\n media?: InfoPromptMedia;\n /**\n * Action link to be displayed below the description\n */\n action?: InfoPromptAction;\n /**\n * Title content for the prompt\n */\n title?: string;\n /**\n * Description content for the prompt (required). Accepts plain text or rich content (ReactNode).\n * If the description contains an interactive element, the `action` prop must not be used simultaneously.\n */\n description: ReactNode;\n className?: string;\n /**\n * Sets the ARIA live region politeness level.\n * - `'polite'` — announced after the current speech (default)\n * - `'assertive'` — interrupts the current speech immediately\n * - `'off'` — disables the live region entirely\n * @default 'polite'\n */\n 'aria-live'?: AriaLive;\n };\n\n/**\n * `InfoPrompt` displays important contextual messages to users within a screen.\n * It provides a visually distinct way to communicate information, warnings, errors,\n * or positive feedback with optional actions and dismissal capabilities.\n *\n * Use this component to replace the deprecated `Alert` component (run codemod to migrate: **`npx \\@wise/wds-codemods@latest info-prompt`**).\n *\n * Guidance can be found in the [design system](https://docs.wise.design/components/info-prompt).\n */\nexport const InfoPrompt = ({\n sentiment = 'neutral',\n onDismiss,\n media,\n action,\n title,\n description,\n className,\n 'aria-live': ariaLive = 'polite',\n 'data-testid': dataTestId,\n ...restProps\n}: InfoPromptProps) => {\n const [shouldFire, setShouldFire] = useState<boolean>();\n const announceOnChange = [\n title,\n Children.toArray(description)\n .map((child) =>\n isValidElement<{ children?: ReactNode }>(child) ? child.props.children : child,\n )\n .join(''),\n action?.label,\n ]\n .filter(Boolean)\n .join('|');\n const statusIconSentiment =\n sentiment === 'success'\n ? Sentiment.POSITIVE\n : (sentiment as Exclude<SurfaceSentiment, 'proposition'>);\n\n const handleTouchStart = () => {\n setShouldFire(true);\n };\n\n const handleTouchEnd = () => {\n if (shouldFire && action?.href) {\n
|
|
1
|
+
{"version":3,"file":"InfoPrompt.mjs","sources":["../../../src/Prompt/InfoPrompt/InfoPrompt.tsx"],"sourcesContent":["import { Children, HTMLAttributes, ReactNode, TouchEvent, isValidElement, useState } from 'react';\nimport { LiveRegion, Sentiment, Typography } from '../../common';\nimport type { AriaLive } from '../../common';\nimport { GiftBox } from '@transferwise/icons';\nimport type { Sentiment as SurfaceSentiment } from '../../SentimentSurface';\nimport StatusIcon from '../../StatusIcon';\nimport { clsx } from 'clsx';\nimport Body from '../../Body';\nimport Link, { LinkProps } from '../../Link';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nexport type InfoPromptAction = Pick<LinkProps, 'href' | 'target' | 'onClick'> & {\n /**\n * The label text for the action link\n */\n label: string;\n};\n\nexport type InfoPromptMedia = {\n /**\n * The icon/image asset to display.\n * The asset should include its own accessibility attributes (e.g. title, aria-label) if it conveys meaning.\n */\n asset: ReactNode;\n};\n\nexport type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'aria-live' | 'role'> &\n Pick<PrimitivePromptProps, 'data-testid'> & {\n /**\n * The sentiment determines the colour scheme\n * @default 'neutral'\n */\n sentiment?: SurfaceSentiment;\n /**\n * Handler called when the close button is clicked.\n * If not provided, the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Custom media to override the default status icon.\n * Success and proposition sentiments support 2 status variations: standard checkmark & confetti.\n */\n media?: InfoPromptMedia;\n /**\n * Action link to be displayed below the description\n */\n action?: InfoPromptAction;\n /**\n * Title content for the prompt\n */\n title?: string;\n /**\n * Description content for the prompt (required). Accepts plain text or rich content (ReactNode).\n * If the description contains an interactive element, the `action` prop must not be used simultaneously.\n */\n description: ReactNode;\n className?: string;\n /**\n * Sets the ARIA live region politeness level.\n * - `'polite'` — announced after the current speech (default)\n * - `'assertive'` — interrupts the current speech immediately\n * - `'off'` — disables the live region entirely\n * @default 'polite'\n */\n 'aria-live'?: AriaLive;\n };\n\n/**\n * `InfoPrompt` displays important contextual messages to users within a screen.\n * It provides a visually distinct way to communicate information, warnings, errors,\n * or positive feedback with optional actions and dismissal capabilities.\n *\n * Use this component to replace the deprecated `Alert` component (run codemod to migrate: **`npx \\@wise/wds-codemods@latest info-prompt`**).\n *\n * Guidance can be found in the [design system](https://docs.wise.design/components/info-prompt).\n */\nexport const InfoPrompt = ({\n sentiment = 'neutral',\n onDismiss,\n media,\n action,\n title,\n description,\n className,\n 'aria-live': ariaLive = 'polite',\n 'data-testid': dataTestId,\n ...restProps\n}: InfoPromptProps) => {\n const [shouldFire, setShouldFire] = useState<boolean>();\n const announceOnChange = [\n title,\n Children.toArray(description)\n .map((child) =>\n isValidElement<{ children?: ReactNode }>(child) ? child.props.children : child,\n )\n .join(''),\n action?.label,\n ]\n .filter(Boolean)\n .join('|');\n const statusIconSentiment =\n sentiment === 'success'\n ? Sentiment.POSITIVE\n : (sentiment as Exclude<SurfaceSentiment, 'proposition'>);\n\n const handleTouchStart = (event: TouchEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n if (target.closest('.wds-prompt__dismiss') || target.closest('.wds-info-prompt__action')) {\n return;\n }\n setShouldFire(true);\n };\n\n const handleTouchEnd = () => {\n if (shouldFire && action) {\n (action.onClick as (() => void) | undefined)?.();\n if (action.href) {\n if (action.target === '_blank') {\n window.top?.open(action.href, '_blank', 'noopener, noreferrer');\n } else {\n window.top?.location.assign(action.href);\n }\n }\n }\n setShouldFire(false);\n };\n\n const handleTouchMove = () => {\n setShouldFire(false);\n };\n\n const renderMedia = () => {\n if (media) {\n return <span className=\"wds-info-prompt__media\">{media.asset}</span>;\n }\n\n if (sentiment === 'proposition') {\n return (\n <span className=\"wds-info-prompt__media\">\n <GiftBox />\n </span>\n );\n }\n\n return <StatusIcon size={24} sentiment={statusIconSentiment} />;\n };\n\n // Render content directly in LiveRegion\n return (\n <LiveRegion aria-live={ariaLive} announceOnChange={announceOnChange}>\n <PrimitivePrompt\n sentiment={sentiment}\n media={renderMedia()}\n data-testid={dataTestId}\n className={clsx('wds-info-prompt', className)}\n {...restProps}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchMove={handleTouchMove}\n onDismiss={onDismiss}\n >\n <div className=\"wds-info-prompt__content\">\n {title && (\n <Body className=\"wds-info-prompt__title\" type={Typography.BODY_LARGE_BOLD} as=\"span\">\n {title}\n </Body>\n )}\n <Body as=\"span\" className=\"wds-info-prompt__description\">\n {description}\n </Body>\n {action && (\n <Link\n href={action.href}\n target={action.target}\n type={Typography.LINK_DEFAULT}\n className=\"wds-info-prompt__action\"\n onClick={action.onClick}\n >\n {action.label}\n </Link>\n )}\n </div>\n </PrimitivePrompt>\n </LiveRegion>\n );\n};\n"],"names":["InfoPrompt","sentiment","onDismiss","media","action","title","description","className","ariaLive","dataTestId","restProps","shouldFire","setShouldFire","useState","announceOnChange","Children","toArray","map","child","isValidElement","props","children","join","label","filter","Boolean","statusIconSentiment","Sentiment","POSITIVE","handleTouchStart","event","target","closest","handleTouchEnd","onClick","href","window","top","open","location","assign","handleTouchMove","renderMedia","_jsx","asset","GiftBox","StatusIcon","size","LiveRegion","PrimitivePrompt","clsx","onTouchStart","onTouchEnd","onTouchMove","_jsxs","Body","type","Typography","BODY_LARGE_BOLD","as","Link","LINK_DEFAULT"],"mappings":"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"}
|
|
@@ -39,6 +39,7 @@ const PrimitivePrompt = /*#__PURE__*/React.forwardRef(({
|
|
|
39
39
|
size: 24,
|
|
40
40
|
priority: "secondary",
|
|
41
41
|
"aria-label": intl.formatMessage(CloseButton_messages.default.ariaLabel),
|
|
42
|
+
className: "wds-prompt__dismiss",
|
|
42
43
|
onClick: onDismiss,
|
|
43
44
|
children: /*#__PURE__*/jsxRuntime.jsx(icons.Cross, {})
|
|
44
45
|
}), actions && /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrimitivePrompt.js","sources":["../../../src/Prompt/PrimitivePrompt/PrimitivePrompt.tsx"],"sourcesContent":["import { Cross } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport SentimentSurface, { Emphasis, Sentiment } from '../../SentimentSurface';\nimport IconButton from '../../IconButton';\nimport { useIntl } from 'react-intl';\nimport closeBtnMessages from '../../common/CloseButton/CloseButton.messages';\nimport { forwardRef, HTMLAttributes, ReactNode } from 'react';\n\nexport type PrimitivePromptProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The sentiment determines the colour scheme.\n * @default success\n */\n sentiment?: Sentiment;\n /**\n * The emphasis level affecting background and text contrast.\n * @default 'base'\n */\n emphasis?: Emphasis;\n /**\n * Media to be displayed on the prompt (icon/image/etc).\n */\n media: ReactNode;\n /**\n * Any actions to be displayed on the prompt.\n */\n actions?: ReactNode;\n /**\n * Handler called when the close button is clicked. If not provided, then the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Test ID for testing tools\n */\n 'data-testid'?: string;\n};\n\n/**\n * PrimitivePrompt is a low-level component that provides the structure, sentiment support and styling for various prompts.\n * Uses several css variables to handle styling from within the consuming component, e.g. --Prompt-padding-x. */\nexport const PrimitivePrompt = forwardRef<HTMLDivElement, PrimitivePromptProps>(\n (\n {\n sentiment = 'success',\n emphasis = 'base',\n media,\n actions,\n onDismiss,\n className,\n children,\n ...restProps\n },\n ref,\n ) => {\n const intl = useIntl();\n\n return (\n <SentimentSurface\n // @ts-expect-error - SentimentSurface forwardRef types don't expose ref in props\n ref={ref}\n sentiment={sentiment}\n emphasis={emphasis}\n className={clsx('wds-prompt', `wds-prompt--${sentiment}`, className)}\n {...restProps}\n >\n <div\n className={clsx('wds-prompt__content-wrapper', {\n 'wds-prompt__content-wrapper--with-dismiss': !!onDismiss,\n })}\n >\n <div className={clsx('wds-prompt__media-wrapper')}>{media}</div>\n {children}\n {onDismiss && (\n <IconButton\n size={24}\n priority=\"secondary\"\n aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}\n onClick={onDismiss}\n >\n <Cross />\n </IconButton>\n )}\n {actions && <div className=\"wds-prompt__actions-wrapper\">{actions}</div>}\n </div>\n </SentimentSurface>\n );\n },\n);\n\nPrimitivePrompt.displayName = 'PrimitivePrompt';\n"],"names":["PrimitivePrompt","forwardRef","sentiment","emphasis","media","actions","onDismiss","className","children","restProps","ref","intl","useIntl","_jsx","SentimentSurface","clsx","_jsxs","IconButton","size","priority","formatMessage","closeBtnMessages","ariaLabel","onClick","Cross","displayName"],"mappings":";;;;;;;;;;;AAwCO,MAAMA,eAAe,gBAAGC,gBAAU,CACvC,CACE;AACEC,EAAAA,SAAS,GAAG,SAAS;AACrBC,EAAAA,QAAQ,GAAG,MAAM;EACjBC,KAAK;EACLC,OAAO;EACPC,SAAS;EACTC,SAAS;EACTC,QAAQ;EACR,GAAGC;AAAS,CACb,EACDC,GAAG,KACD;AACF,EAAA,MAAMC,IAAI,GAAGC,iBAAO,EAAE;AAEtB,EAAA,oBACEC,cAAA,CAACC;AACC;AAAA,IAAA;AACAJ,IAAAA,GAAG,EAAEA,GAAI;AACTR,IAAAA,SAAS,EAAEA,SAAU;AACrBC,IAAAA,QAAQ,EAAEA,QAAS;IACnBI,SAAS,EAAEQ,SAAI,CAAC,YAAY,EAAE,eAAeb,SAAS,CAAA,CAAE,EAAEK,SAAS,CAAE;AAAA,IAAA,GACjEE,SAAS;AAAAD,IAAAA,QAAA,eAEbQ,eAAA,CAAA,KAAA,EAAA;AACET,MAAAA,SAAS,EAAEQ,SAAI,CAAC,6BAA6B,EAAE;QAC7C,2CAA2C,EAAE,CAAC,CAACT;AAChD,OAAA,CAAE;AAAAE,MAAAA,QAAA,gBAEHK,cAAA,CAAA,KAAA,EAAA;AAAKN,QAAAA,SAAS,EAAEQ,SAAI,CAAC,2BAA2B,CAAE;AAAAP,QAAAA,QAAA,EAAEJ;OAAW,CAC/D,EAACI,QAAQ,EACRF,SAAS,iBACRO,cAAA,CAACI,kBAAU,EAAA;AACTC,QAAAA,IAAI,EAAE,EAAG;AACTC,QAAAA,QAAQ,EAAC,WAAW;AACpB,QAAA,YAAA,EAAYR,IAAI,CAACS,aAAa,CAACC,4BAAgB,CAACC,SAAS,CAAE;
|
|
1
|
+
{"version":3,"file":"PrimitivePrompt.js","sources":["../../../src/Prompt/PrimitivePrompt/PrimitivePrompt.tsx"],"sourcesContent":["import { Cross } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport SentimentSurface, { Emphasis, Sentiment } from '../../SentimentSurface';\nimport IconButton from '../../IconButton';\nimport { useIntl } from 'react-intl';\nimport closeBtnMessages from '../../common/CloseButton/CloseButton.messages';\nimport { forwardRef, HTMLAttributes, ReactNode } from 'react';\n\nexport type PrimitivePromptProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The sentiment determines the colour scheme.\n * @default success\n */\n sentiment?: Sentiment;\n /**\n * The emphasis level affecting background and text contrast.\n * @default 'base'\n */\n emphasis?: Emphasis;\n /**\n * Media to be displayed on the prompt (icon/image/etc).\n */\n media: ReactNode;\n /**\n * Any actions to be displayed on the prompt.\n */\n actions?: ReactNode;\n /**\n * Handler called when the close button is clicked. If not provided, then the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Test ID for testing tools\n */\n 'data-testid'?: string;\n};\n\n/**\n * PrimitivePrompt is a low-level component that provides the structure, sentiment support and styling for various prompts.\n * Uses several css variables to handle styling from within the consuming component, e.g. --Prompt-padding-x. */\nexport const PrimitivePrompt = forwardRef<HTMLDivElement, PrimitivePromptProps>(\n (\n {\n sentiment = 'success',\n emphasis = 'base',\n media,\n actions,\n onDismiss,\n className,\n children,\n ...restProps\n },\n ref,\n ) => {\n const intl = useIntl();\n\n return (\n <SentimentSurface\n // @ts-expect-error - SentimentSurface forwardRef types don't expose ref in props\n ref={ref}\n sentiment={sentiment}\n emphasis={emphasis}\n className={clsx('wds-prompt', `wds-prompt--${sentiment}`, className)}\n {...restProps}\n >\n <div\n className={clsx('wds-prompt__content-wrapper', {\n 'wds-prompt__content-wrapper--with-dismiss': !!onDismiss,\n })}\n >\n <div className={clsx('wds-prompt__media-wrapper')}>{media}</div>\n {children}\n {onDismiss && (\n <IconButton\n size={24}\n priority=\"secondary\"\n aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}\n className=\"wds-prompt__dismiss\"\n onClick={onDismiss}\n >\n <Cross />\n </IconButton>\n )}\n {actions && <div className=\"wds-prompt__actions-wrapper\">{actions}</div>}\n </div>\n </SentimentSurface>\n );\n },\n);\n\nPrimitivePrompt.displayName = 'PrimitivePrompt';\n"],"names":["PrimitivePrompt","forwardRef","sentiment","emphasis","media","actions","onDismiss","className","children","restProps","ref","intl","useIntl","_jsx","SentimentSurface","clsx","_jsxs","IconButton","size","priority","formatMessage","closeBtnMessages","ariaLabel","onClick","Cross","displayName"],"mappings":";;;;;;;;;;;AAwCO,MAAMA,eAAe,gBAAGC,gBAAU,CACvC,CACE;AACEC,EAAAA,SAAS,GAAG,SAAS;AACrBC,EAAAA,QAAQ,GAAG,MAAM;EACjBC,KAAK;EACLC,OAAO;EACPC,SAAS;EACTC,SAAS;EACTC,QAAQ;EACR,GAAGC;AAAS,CACb,EACDC,GAAG,KACD;AACF,EAAA,MAAMC,IAAI,GAAGC,iBAAO,EAAE;AAEtB,EAAA,oBACEC,cAAA,CAACC;AACC;AAAA,IAAA;AACAJ,IAAAA,GAAG,EAAEA,GAAI;AACTR,IAAAA,SAAS,EAAEA,SAAU;AACrBC,IAAAA,QAAQ,EAAEA,QAAS;IACnBI,SAAS,EAAEQ,SAAI,CAAC,YAAY,EAAE,eAAeb,SAAS,CAAA,CAAE,EAAEK,SAAS,CAAE;AAAA,IAAA,GACjEE,SAAS;AAAAD,IAAAA,QAAA,eAEbQ,eAAA,CAAA,KAAA,EAAA;AACET,MAAAA,SAAS,EAAEQ,SAAI,CAAC,6BAA6B,EAAE;QAC7C,2CAA2C,EAAE,CAAC,CAACT;AAChD,OAAA,CAAE;AAAAE,MAAAA,QAAA,gBAEHK,cAAA,CAAA,KAAA,EAAA;AAAKN,QAAAA,SAAS,EAAEQ,SAAI,CAAC,2BAA2B,CAAE;AAAAP,QAAAA,QAAA,EAAEJ;OAAW,CAC/D,EAACI,QAAQ,EACRF,SAAS,iBACRO,cAAA,CAACI,kBAAU,EAAA;AACTC,QAAAA,IAAI,EAAE,EAAG;AACTC,QAAAA,QAAQ,EAAC,WAAW;AACpB,QAAA,YAAA,EAAYR,IAAI,CAACS,aAAa,CAACC,4BAAgB,CAACC,SAAS,CAAE;AAC3Df,QAAAA,SAAS,EAAC,qBAAqB;AAC/BgB,QAAAA,OAAO,EAAEjB,SAAU;AAAAE,QAAAA,QAAA,eAEnBK,cAAA,CAACW,WAAK,EAAA,EAAA;AACR,OAAY,CACb,EACAnB,OAAO,iBAAIQ,cAAA,CAAA,KAAA,EAAA;AAAKN,QAAAA,SAAS,EAAC,6BAA6B;AAAAC,QAAAA,QAAA,EAAEH;AAAO,OAAM,CAAC;KACrE;AACP,GAAkB,CAAC;AAEvB,CAAC;AAGHL,eAAe,CAACyB,WAAW,GAAG,iBAAiB;;;;"}
|
|
@@ -37,6 +37,7 @@ const PrimitivePrompt = /*#__PURE__*/forwardRef(({
|
|
|
37
37
|
size: 24,
|
|
38
38
|
priority: "secondary",
|
|
39
39
|
"aria-label": intl.formatMessage(closeBtnMessages.ariaLabel),
|
|
40
|
+
className: "wds-prompt__dismiss",
|
|
40
41
|
onClick: onDismiss,
|
|
41
42
|
children: /*#__PURE__*/jsx(Cross, {})
|
|
42
43
|
}), actions && /*#__PURE__*/jsx("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrimitivePrompt.mjs","sources":["../../../src/Prompt/PrimitivePrompt/PrimitivePrompt.tsx"],"sourcesContent":["import { Cross } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport SentimentSurface, { Emphasis, Sentiment } from '../../SentimentSurface';\nimport IconButton from '../../IconButton';\nimport { useIntl } from 'react-intl';\nimport closeBtnMessages from '../../common/CloseButton/CloseButton.messages';\nimport { forwardRef, HTMLAttributes, ReactNode } from 'react';\n\nexport type PrimitivePromptProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The sentiment determines the colour scheme.\n * @default success\n */\n sentiment?: Sentiment;\n /**\n * The emphasis level affecting background and text contrast.\n * @default 'base'\n */\n emphasis?: Emphasis;\n /**\n * Media to be displayed on the prompt (icon/image/etc).\n */\n media: ReactNode;\n /**\n * Any actions to be displayed on the prompt.\n */\n actions?: ReactNode;\n /**\n * Handler called when the close button is clicked. If not provided, then the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Test ID for testing tools\n */\n 'data-testid'?: string;\n};\n\n/**\n * PrimitivePrompt is a low-level component that provides the structure, sentiment support and styling for various prompts.\n * Uses several css variables to handle styling from within the consuming component, e.g. --Prompt-padding-x. */\nexport const PrimitivePrompt = forwardRef<HTMLDivElement, PrimitivePromptProps>(\n (\n {\n sentiment = 'success',\n emphasis = 'base',\n media,\n actions,\n onDismiss,\n className,\n children,\n ...restProps\n },\n ref,\n ) => {\n const intl = useIntl();\n\n return (\n <SentimentSurface\n // @ts-expect-error - SentimentSurface forwardRef types don't expose ref in props\n ref={ref}\n sentiment={sentiment}\n emphasis={emphasis}\n className={clsx('wds-prompt', `wds-prompt--${sentiment}`, className)}\n {...restProps}\n >\n <div\n className={clsx('wds-prompt__content-wrapper', {\n 'wds-prompt__content-wrapper--with-dismiss': !!onDismiss,\n })}\n >\n <div className={clsx('wds-prompt__media-wrapper')}>{media}</div>\n {children}\n {onDismiss && (\n <IconButton\n size={24}\n priority=\"secondary\"\n aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}\n onClick={onDismiss}\n >\n <Cross />\n </IconButton>\n )}\n {actions && <div className=\"wds-prompt__actions-wrapper\">{actions}</div>}\n </div>\n </SentimentSurface>\n );\n },\n);\n\nPrimitivePrompt.displayName = 'PrimitivePrompt';\n"],"names":["PrimitivePrompt","forwardRef","sentiment","emphasis","media","actions","onDismiss","className","children","restProps","ref","intl","useIntl","_jsx","SentimentSurface","clsx","_jsxs","IconButton","size","priority","formatMessage","closeBtnMessages","ariaLabel","onClick","Cross","displayName"],"mappings":";;;;;;;;;AAwCO,MAAMA,eAAe,gBAAGC,UAAU,CACvC,CACE;AACEC,EAAAA,SAAS,GAAG,SAAS;AACrBC,EAAAA,QAAQ,GAAG,MAAM;EACjBC,KAAK;EACLC,OAAO;EACPC,SAAS;EACTC,SAAS;EACTC,QAAQ;EACR,GAAGC;AAAS,CACb,EACDC,GAAG,KACD;AACF,EAAA,MAAMC,IAAI,GAAGC,OAAO,EAAE;AAEtB,EAAA,oBACEC,GAAA,CAACC;AACC;AAAA,IAAA;AACAJ,IAAAA,GAAG,EAAEA,GAAI;AACTR,IAAAA,SAAS,EAAEA,SAAU;AACrBC,IAAAA,QAAQ,EAAEA,QAAS;IACnBI,SAAS,EAAEQ,IAAI,CAAC,YAAY,EAAE,eAAeb,SAAS,CAAA,CAAE,EAAEK,SAAS,CAAE;AAAA,IAAA,GACjEE,SAAS;AAAAD,IAAAA,QAAA,eAEbQ,IAAA,CAAA,KAAA,EAAA;AACET,MAAAA,SAAS,EAAEQ,IAAI,CAAC,6BAA6B,EAAE;QAC7C,2CAA2C,EAAE,CAAC,CAACT;AAChD,OAAA,CAAE;AAAAE,MAAAA,QAAA,gBAEHK,GAAA,CAAA,KAAA,EAAA;AAAKN,QAAAA,SAAS,EAAEQ,IAAI,CAAC,2BAA2B,CAAE;AAAAP,QAAAA,QAAA,EAAEJ;OAAW,CAC/D,EAACI,QAAQ,EACRF,SAAS,iBACRO,GAAA,CAACI,UAAU,EAAA;AACTC,QAAAA,IAAI,EAAE,EAAG;AACTC,QAAAA,QAAQ,EAAC,WAAW;AACpB,QAAA,YAAA,EAAYR,IAAI,CAACS,aAAa,CAACC,gBAAgB,CAACC,SAAS,CAAE;
|
|
1
|
+
{"version":3,"file":"PrimitivePrompt.mjs","sources":["../../../src/Prompt/PrimitivePrompt/PrimitivePrompt.tsx"],"sourcesContent":["import { Cross } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport SentimentSurface, { Emphasis, Sentiment } from '../../SentimentSurface';\nimport IconButton from '../../IconButton';\nimport { useIntl } from 'react-intl';\nimport closeBtnMessages from '../../common/CloseButton/CloseButton.messages';\nimport { forwardRef, HTMLAttributes, ReactNode } from 'react';\n\nexport type PrimitivePromptProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The sentiment determines the colour scheme.\n * @default success\n */\n sentiment?: Sentiment;\n /**\n * The emphasis level affecting background and text contrast.\n * @default 'base'\n */\n emphasis?: Emphasis;\n /**\n * Media to be displayed on the prompt (icon/image/etc).\n */\n media: ReactNode;\n /**\n * Any actions to be displayed on the prompt.\n */\n actions?: ReactNode;\n /**\n * Handler called when the close button is clicked. If not provided, then the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Test ID for testing tools\n */\n 'data-testid'?: string;\n};\n\n/**\n * PrimitivePrompt is a low-level component that provides the structure, sentiment support and styling for various prompts.\n * Uses several css variables to handle styling from within the consuming component, e.g. --Prompt-padding-x. */\nexport const PrimitivePrompt = forwardRef<HTMLDivElement, PrimitivePromptProps>(\n (\n {\n sentiment = 'success',\n emphasis = 'base',\n media,\n actions,\n onDismiss,\n className,\n children,\n ...restProps\n },\n ref,\n ) => {\n const intl = useIntl();\n\n return (\n <SentimentSurface\n // @ts-expect-error - SentimentSurface forwardRef types don't expose ref in props\n ref={ref}\n sentiment={sentiment}\n emphasis={emphasis}\n className={clsx('wds-prompt', `wds-prompt--${sentiment}`, className)}\n {...restProps}\n >\n <div\n className={clsx('wds-prompt__content-wrapper', {\n 'wds-prompt__content-wrapper--with-dismiss': !!onDismiss,\n })}\n >\n <div className={clsx('wds-prompt__media-wrapper')}>{media}</div>\n {children}\n {onDismiss && (\n <IconButton\n size={24}\n priority=\"secondary\"\n aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}\n className=\"wds-prompt__dismiss\"\n onClick={onDismiss}\n >\n <Cross />\n </IconButton>\n )}\n {actions && <div className=\"wds-prompt__actions-wrapper\">{actions}</div>}\n </div>\n </SentimentSurface>\n );\n },\n);\n\nPrimitivePrompt.displayName = 'PrimitivePrompt';\n"],"names":["PrimitivePrompt","forwardRef","sentiment","emphasis","media","actions","onDismiss","className","children","restProps","ref","intl","useIntl","_jsx","SentimentSurface","clsx","_jsxs","IconButton","size","priority","formatMessage","closeBtnMessages","ariaLabel","onClick","Cross","displayName"],"mappings":";;;;;;;;;AAwCO,MAAMA,eAAe,gBAAGC,UAAU,CACvC,CACE;AACEC,EAAAA,SAAS,GAAG,SAAS;AACrBC,EAAAA,QAAQ,GAAG,MAAM;EACjBC,KAAK;EACLC,OAAO;EACPC,SAAS;EACTC,SAAS;EACTC,QAAQ;EACR,GAAGC;AAAS,CACb,EACDC,GAAG,KACD;AACF,EAAA,MAAMC,IAAI,GAAGC,OAAO,EAAE;AAEtB,EAAA,oBACEC,GAAA,CAACC;AACC;AAAA,IAAA;AACAJ,IAAAA,GAAG,EAAEA,GAAI;AACTR,IAAAA,SAAS,EAAEA,SAAU;AACrBC,IAAAA,QAAQ,EAAEA,QAAS;IACnBI,SAAS,EAAEQ,IAAI,CAAC,YAAY,EAAE,eAAeb,SAAS,CAAA,CAAE,EAAEK,SAAS,CAAE;AAAA,IAAA,GACjEE,SAAS;AAAAD,IAAAA,QAAA,eAEbQ,IAAA,CAAA,KAAA,EAAA;AACET,MAAAA,SAAS,EAAEQ,IAAI,CAAC,6BAA6B,EAAE;QAC7C,2CAA2C,EAAE,CAAC,CAACT;AAChD,OAAA,CAAE;AAAAE,MAAAA,QAAA,gBAEHK,GAAA,CAAA,KAAA,EAAA;AAAKN,QAAAA,SAAS,EAAEQ,IAAI,CAAC,2BAA2B,CAAE;AAAAP,QAAAA,QAAA,EAAEJ;OAAW,CAC/D,EAACI,QAAQ,EACRF,SAAS,iBACRO,GAAA,CAACI,UAAU,EAAA;AACTC,QAAAA,IAAI,EAAE,EAAG;AACTC,QAAAA,QAAQ,EAAC,WAAW;AACpB,QAAA,YAAA,EAAYR,IAAI,CAACS,aAAa,CAACC,gBAAgB,CAACC,SAAS,CAAE;AAC3Df,QAAAA,SAAS,EAAC,qBAAqB;AAC/BgB,QAAAA,OAAO,EAAEjB,SAAU;AAAAE,QAAAA,QAAA,eAEnBK,GAAA,CAACW,KAAK,EAAA,EAAA;AACR,OAAY,CACb,EACAnB,OAAO,iBAAIQ,GAAA,CAAA,KAAA,EAAA;AAAKN,QAAAA,SAAS,EAAC,6BAA6B;AAAAC,QAAAA,QAAA,EAAEH;AAAO,OAAM,CAAC;KACrE;AACP,GAAkB,CAAC;AAEvB,CAAC;AAGHL,eAAe,CAACyB,WAAW,GAAG,iBAAiB;;;;"}
|
package/build/main.css
CHANGED
|
@@ -24921,6 +24921,23 @@ button.np-link {
|
|
|
24921
24921
|
grid-column: span 3;
|
|
24922
24922
|
}
|
|
24923
24923
|
}
|
|
24924
|
+
.wds-prompt__dismiss {
|
|
24925
|
+
position: relative;
|
|
24926
|
+
}
|
|
24927
|
+
.wds-prompt__dismiss:before {
|
|
24928
|
+
--size: calc(var(--size-24) + var(--Prompt-padding-x, var(--padding-x-small)) * 2);
|
|
24929
|
+
--offset: calc(-1 * var(--Prompt-padding-x, var(--padding-x-small)));
|
|
24930
|
+
content: "";
|
|
24931
|
+
position: absolute;
|
|
24932
|
+
inset: calc(-1 * 8px);
|
|
24933
|
+
inset: var(--offset);
|
|
24934
|
+
inline-size: calc(24px + 8px * 2);
|
|
24935
|
+
inline-size: var(--size);
|
|
24936
|
+
block-size: calc(24px + 8px * 2);
|
|
24937
|
+
block-size: var(--size);
|
|
24938
|
+
border-radius: 10px;
|
|
24939
|
+
border-radius: var(--Prompt-border-radius, var(--radius-small));
|
|
24940
|
+
}
|
|
24924
24941
|
.wds-inline-prompt {
|
|
24925
24942
|
--Prompt-gap: calc(var(--size-12) / 2);
|
|
24926
24943
|
--Prompt-padding-x: var(--padding-x-small);
|
|
@@ -51,3 +51,20 @@
|
|
|
51
51
|
grid-column: span 3;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
.wds-prompt__dismiss {
|
|
55
|
+
position: relative;
|
|
56
|
+
}
|
|
57
|
+
.wds-prompt__dismiss:before {
|
|
58
|
+
--size: calc(var(--size-24) + var(--Prompt-padding-x, var(--padding-x-small)) * 2);
|
|
59
|
+
--offset: calc(-1 * var(--Prompt-padding-x, var(--padding-x-small)));
|
|
60
|
+
content: "";
|
|
61
|
+
position: absolute;
|
|
62
|
+
inset: calc(-1 * 8px);
|
|
63
|
+
inset: var(--offset);
|
|
64
|
+
inline-size: calc(24px + 8px * 2);
|
|
65
|
+
inline-size: var(--size);
|
|
66
|
+
block-size: calc(24px + 8px * 2);
|
|
67
|
+
block-size: var(--size);
|
|
68
|
+
border-radius: 10px;
|
|
69
|
+
border-radius: var(--Prompt-border-radius, var(--radius-small));
|
|
70
|
+
}
|
package/build/styles/main.css
CHANGED
|
@@ -24921,6 +24921,23 @@ button.np-link {
|
|
|
24921
24921
|
grid-column: span 3;
|
|
24922
24922
|
}
|
|
24923
24923
|
}
|
|
24924
|
+
.wds-prompt__dismiss {
|
|
24925
|
+
position: relative;
|
|
24926
|
+
}
|
|
24927
|
+
.wds-prompt__dismiss:before {
|
|
24928
|
+
--size: calc(var(--size-24) + var(--Prompt-padding-x, var(--padding-x-small)) * 2);
|
|
24929
|
+
--offset: calc(-1 * var(--Prompt-padding-x, var(--padding-x-small)));
|
|
24930
|
+
content: "";
|
|
24931
|
+
position: absolute;
|
|
24932
|
+
inset: calc(-1 * 8px);
|
|
24933
|
+
inset: var(--offset);
|
|
24934
|
+
inline-size: calc(24px + 8px * 2);
|
|
24935
|
+
inline-size: var(--size);
|
|
24936
|
+
block-size: calc(24px + 8px * 2);
|
|
24937
|
+
block-size: var(--size);
|
|
24938
|
+
border-radius: 10px;
|
|
24939
|
+
border-radius: var(--Prompt-border-radius, var(--radius-small));
|
|
24940
|
+
}
|
|
24924
24941
|
.wds-inline-prompt {
|
|
24925
24942
|
--Prompt-gap: calc(var(--size-12) / 2);
|
|
24926
24943
|
--Prompt-padding-x: var(--padding-x-small);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoPrompt.d.ts","sourceRoot":"","sources":["../../../../src/Prompt/InfoPrompt/InfoPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,cAAc,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"InfoPrompt.d.ts","sourceRoot":"","sources":["../../../../src/Prompt/InfoPrompt/InfoPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,cAAc,EAAE,SAAS,EAAwC,MAAM,OAAO,CAAC;AAElG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,SAAS,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI5E,OAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAmB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,GAAG;IAC9E;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC,GAChG,IAAI,CAAC,oBAAoB,EAAE,aAAa,CAAC,GAAG;IAC1C;;;OAGG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;OAGG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,WAAW,EAAE,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC;CACxB,CAAC;AAEJ;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GAAI,wIAWxB,eAAe,gCAkGjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrimitivePrompt.d.ts","sourceRoot":"","sources":["../../../../src/Prompt/PrimitivePrompt/PrimitivePrompt.tsx"],"names":[],"mappings":"AAEA,OAAyB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAI/E,OAAO,EAAc,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IAClE;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;gHAEgH;AAChH,eAAO,MAAM,eAAe;IA/B1B;;;OAGG;gBACS,SAAS;IACrB;;;OAGG;eACQ,QAAQ;IACnB;;OAEG;WACI,SAAS;IAChB;;OAEG;cACO,SAAS;IACnB;;OAEG;gBACS,MAAM,IAAI;IACtB;;OAEG;oBACa,MAAM;
|
|
1
|
+
{"version":3,"file":"PrimitivePrompt.d.ts","sourceRoot":"","sources":["../../../../src/Prompt/PrimitivePrompt/PrimitivePrompt.tsx"],"names":[],"mappings":"AAEA,OAAyB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAI/E,OAAO,EAAc,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IAClE;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;gHAEgH;AAChH,eAAO,MAAM,eAAe;IA/B1B;;;OAGG;gBACS,SAAS;IACrB;;;OAGG;eACQ,QAAQ;IACnB;;OAEG;WACI,SAAS;IAChB;;OAEG;cACO,SAAS;IACnB;;OAEG;gBACS,MAAM,IAAI;IACtB;;OAEG;oBACa,MAAM;kDAsDvB,CAAC"}
|
package/package.json
CHANGED
|
@@ -274,11 +274,12 @@ describe('InfoPrompt', () => {
|
|
|
274
274
|
expect(window.location.assign).not.toHaveBeenCalled();
|
|
275
275
|
});
|
|
276
276
|
|
|
277
|
-
it('should
|
|
277
|
+
it('should call onClick on touch tap when action has no href', () => {
|
|
278
|
+
const onClick = jest.fn();
|
|
278
279
|
render(
|
|
279
280
|
<InfoPrompt
|
|
280
281
|
{...defaultProps}
|
|
281
|
-
action={{ label: 'Click me', onClick
|
|
282
|
+
action={{ label: 'Click me', onClick }}
|
|
282
283
|
data-testid="prompt"
|
|
283
284
|
/>,
|
|
284
285
|
);
|
|
@@ -286,8 +287,61 @@ describe('InfoPrompt', () => {
|
|
|
286
287
|
|
|
287
288
|
fireEvent.touchStart(prompt);
|
|
288
289
|
fireEvent.touchEnd(prompt);
|
|
290
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
289
291
|
expect(window.location.assign).not.toHaveBeenCalled();
|
|
290
292
|
expect(window.open).not.toHaveBeenCalled();
|
|
291
293
|
});
|
|
294
|
+
|
|
295
|
+
it('should call onClick and navigate when action has both href and onClick', () => {
|
|
296
|
+
const onClick = jest.fn();
|
|
297
|
+
render(
|
|
298
|
+
<InfoPrompt
|
|
299
|
+
{...defaultProps}
|
|
300
|
+
action={{ label: 'Learn more', href: '/learn-more', onClick }}
|
|
301
|
+
data-testid="prompt"
|
|
302
|
+
/>,
|
|
303
|
+
);
|
|
304
|
+
const prompt = screen.getByTestId('prompt');
|
|
305
|
+
|
|
306
|
+
fireEvent.touchStart(prompt);
|
|
307
|
+
fireEvent.touchEnd(prompt);
|
|
308
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
309
|
+
expect(window.location.assign).toHaveBeenCalledWith('/learn-more');
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('should not fire action when tapping dismiss button', () => {
|
|
313
|
+
const onClick = jest.fn();
|
|
314
|
+
render(
|
|
315
|
+
<InfoPrompt
|
|
316
|
+
{...defaultProps}
|
|
317
|
+
action={{ label: 'Learn more', href: '/learn-more', onClick }}
|
|
318
|
+
data-testid="prompt"
|
|
319
|
+
onDismiss={jest.fn()}
|
|
320
|
+
/>,
|
|
321
|
+
);
|
|
322
|
+
const dismissButton = screen.getByRole('button', { name: 'Close', hidden: true });
|
|
323
|
+
|
|
324
|
+
fireEvent.touchStart(dismissButton);
|
|
325
|
+
fireEvent.touchEnd(dismissButton);
|
|
326
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
327
|
+
expect(window.location.assign).not.toHaveBeenCalled();
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('should not double-fire onClick when tapping the action element directly', () => {
|
|
331
|
+
const onClick = jest.fn();
|
|
332
|
+
render(
|
|
333
|
+
<InfoPrompt
|
|
334
|
+
{...defaultProps}
|
|
335
|
+
action={{ label: 'Learn more', href: '/learn-more', onClick }}
|
|
336
|
+
data-testid="prompt"
|
|
337
|
+
/>,
|
|
338
|
+
);
|
|
339
|
+
const actionLink = screen.getByRole('link', { name: 'Learn more', hidden: true });
|
|
340
|
+
|
|
341
|
+
fireEvent.touchStart(actionLink);
|
|
342
|
+
fireEvent.touchEnd(actionLink);
|
|
343
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
344
|
+
expect(window.location.assign).not.toHaveBeenCalled();
|
|
345
|
+
});
|
|
292
346
|
});
|
|
293
347
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Children, HTMLAttributes, ReactNode, isValidElement, useState } from 'react';
|
|
1
|
+
import { Children, HTMLAttributes, ReactNode, TouchEvent, isValidElement, useState } from 'react';
|
|
2
2
|
import { LiveRegion, Sentiment, Typography } from '../../common';
|
|
3
3
|
import type { AriaLive } from '../../common';
|
|
4
4
|
import { GiftBox } from '@transferwise/icons';
|
|
@@ -103,16 +103,23 @@ export const InfoPrompt = ({
|
|
|
103
103
|
? Sentiment.POSITIVE
|
|
104
104
|
: (sentiment as Exclude<SurfaceSentiment, 'proposition'>);
|
|
105
105
|
|
|
106
|
-
const handleTouchStart = () => {
|
|
106
|
+
const handleTouchStart = (event: TouchEvent<HTMLDivElement>) => {
|
|
107
|
+
const target = event.target as HTMLElement;
|
|
108
|
+
if (target.closest('.wds-prompt__dismiss') || target.closest('.wds-info-prompt__action')) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
107
111
|
setShouldFire(true);
|
|
108
112
|
};
|
|
109
113
|
|
|
110
114
|
const handleTouchEnd = () => {
|
|
111
|
-
if (shouldFire && action
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
if (shouldFire && action) {
|
|
116
|
+
(action.onClick as (() => void) | undefined)?.();
|
|
117
|
+
if (action.href) {
|
|
118
|
+
if (action.target === '_blank') {
|
|
119
|
+
window.top?.open(action.href, '_blank', 'noopener, noreferrer');
|
|
120
|
+
} else {
|
|
121
|
+
window.top?.location.assign(action.href);
|
|
122
|
+
}
|
|
116
123
|
}
|
|
117
124
|
}
|
|
118
125
|
setShouldFire(false);
|
|
@@ -236,7 +236,11 @@ export const WithTitle: Story = {
|
|
|
236
236
|
|
|
237
237
|
/**
|
|
238
238
|
* Use the `action` prop to add a clickable link below the message.
|
|
239
|
-
* Actions can have an `href` for navigation
|
|
239
|
+
* Actions can have an `href` for navigation, an `onClick` for custom behavior, or both.
|
|
240
|
+
*
|
|
241
|
+
* On touch devices the entire prompt surface acts as a tap target for the action,
|
|
242
|
+
* making it easier to interact with on small screens. A scroll gesture (touch move)
|
|
243
|
+
* cancels the tap. Tapping the dismiss button does not trigger the action.
|
|
240
244
|
*/
|
|
241
245
|
export const WithAction: Story = {
|
|
242
246
|
render: (args: InfoPromptProps) => (
|
|
@@ -322,6 +326,7 @@ export const Dismissible: Story = {
|
|
|
322
326
|
sentiment="success"
|
|
323
327
|
title="Payment successful"
|
|
324
328
|
description="Your payment was successful."
|
|
329
|
+
action={{ label: 'Learn more', href: '#', target: '_blank' }}
|
|
325
330
|
onDismiss={() => setShowPrompt(false)}
|
|
326
331
|
/>
|
|
327
332
|
) : (
|
|
@@ -51,3 +51,20 @@
|
|
|
51
51
|
grid-column: span 3;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
.wds-prompt__dismiss {
|
|
55
|
+
position: relative;
|
|
56
|
+
}
|
|
57
|
+
.wds-prompt__dismiss:before {
|
|
58
|
+
--size: calc(var(--size-24) + var(--Prompt-padding-x, var(--padding-x-small)) * 2);
|
|
59
|
+
--offset: calc(-1 * var(--Prompt-padding-x, var(--padding-x-small)));
|
|
60
|
+
content: "";
|
|
61
|
+
position: absolute;
|
|
62
|
+
inset: calc(-1 * 8px);
|
|
63
|
+
inset: var(--offset);
|
|
64
|
+
inline-size: calc(24px + 8px * 2);
|
|
65
|
+
inline-size: var(--size);
|
|
66
|
+
block-size: calc(24px + 8px * 2);
|
|
67
|
+
block-size: var(--size);
|
|
68
|
+
border-radius: 10px;
|
|
69
|
+
border-radius: var(--Prompt-border-radius, var(--radius-small));
|
|
70
|
+
}
|
|
@@ -46,4 +46,19 @@
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
&__dismiss {
|
|
51
|
+
position: relative;
|
|
52
|
+
|
|
53
|
+
&:before {
|
|
54
|
+
--size: calc(var(--size-24) + var(--Prompt-padding-x, var(--padding-x-small)) * 2);
|
|
55
|
+
--offset: calc(-1 * var(--Prompt-padding-x, var(--padding-x-small)));
|
|
56
|
+
content: "";
|
|
57
|
+
position: absolute;
|
|
58
|
+
inset: var(--offset);
|
|
59
|
+
width: var(--size);
|
|
60
|
+
height: var(--size);
|
|
61
|
+
border-radius: var(--Prompt-border-radius, var(--radius-small));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
49
64
|
}
|
package/src/main.css
CHANGED
|
@@ -24921,6 +24921,23 @@ button.np-link {
|
|
|
24921
24921
|
grid-column: span 3;
|
|
24922
24922
|
}
|
|
24923
24923
|
}
|
|
24924
|
+
.wds-prompt__dismiss {
|
|
24925
|
+
position: relative;
|
|
24926
|
+
}
|
|
24927
|
+
.wds-prompt__dismiss:before {
|
|
24928
|
+
--size: calc(var(--size-24) + var(--Prompt-padding-x, var(--padding-x-small)) * 2);
|
|
24929
|
+
--offset: calc(-1 * var(--Prompt-padding-x, var(--padding-x-small)));
|
|
24930
|
+
content: "";
|
|
24931
|
+
position: absolute;
|
|
24932
|
+
inset: calc(-1 * 8px);
|
|
24933
|
+
inset: var(--offset);
|
|
24934
|
+
inline-size: calc(24px + 8px * 2);
|
|
24935
|
+
inline-size: var(--size);
|
|
24936
|
+
block-size: calc(24px + 8px * 2);
|
|
24937
|
+
block-size: var(--size);
|
|
24938
|
+
border-radius: 10px;
|
|
24939
|
+
border-radius: var(--Prompt-border-radius, var(--radius-small));
|
|
24940
|
+
}
|
|
24924
24941
|
.wds-inline-prompt {
|
|
24925
24942
|
--Prompt-gap: calc(var(--size-12) / 2);
|
|
24926
24943
|
--Prompt-padding-x: var(--padding-x-small);
|