@telefonica/mistica 17.9.0 → 17.11.0
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/css/blau.css +40 -0
- package/css/community/cyber.css +40 -0
- package/css/esimflag.css +40 -0
- package/css/mistica.css +1 -1
- package/css/movistar.css +40 -0
- package/css/o2.css +41 -0
- package/css/telefonica.css +42 -0
- package/css/vivo-evolution.css +48 -0
- package/css/vivo.css +40 -0
- package/dist/accordion.css-mistica.js +8 -8
- package/dist/align.css-mistica.js +1 -1
- package/dist/autocomplete.css-mistica.js +4 -4
- package/dist/avatar.css-mistica.js +3 -3
- package/dist/badge.css-mistica.js +3 -3
- package/dist/box.css-mistica.js +13 -13
- package/dist/boxed.css-mistica.js +24 -24
- package/dist/button-group.css-mistica.js +3 -3
- package/dist/button-layout.css-mistica.js +15 -15
- package/dist/button.css-mistica.js +64 -64
- package/dist/callout.css-mistica.js +11 -11
- package/dist/card-internal.css-mistica.js +34 -34
- package/dist/carousel.css-mistica.js +35 -35
- package/dist/checkbox.css-mistica.js +15 -15
- package/dist/chip.css-mistica.js +20 -20
- package/dist/circle.css-mistica.js +1 -1
- package/dist/community/advanced-data-card.css-mistica.js +18 -18
- package/dist/community/ai-card.css-mistica.js +9 -9
- package/dist/community/blocks.css-mistica.js +3 -3
- package/dist/community/cyber/example-component.css-mistica.js +1 -1
- package/dist/community/example-component.css-mistica.js +1 -1
- package/dist/community/skins/cyber-skin.js +20 -0
- package/dist/counter.css-mistica.js +7 -7
- package/dist/cover-hero.css-mistica.js +13 -13
- package/dist/credit-card-number-field.css-mistica.js +5 -5
- package/dist/date-field.css-mistica.js +1 -1
- package/dist/date-time-picker.css-mistica.js +1 -1
- package/dist/dialog.css-mistica.js +8 -8
- package/dist/divider.css-mistica.js +5 -5
- package/dist/double-field.css-mistica.js +4 -4
- package/dist/drawer.css-mistica.js +10 -10
- package/dist/drawer.d.ts +5 -1
- package/dist/drawer.js +131 -82
- package/dist/empty-state-card.css-mistica.js +1 -1
- package/dist/empty-state.css-mistica.js +12 -12
- package/dist/fade-in.css-mistica.js +1 -1
- package/dist/fade-out.css-mistica.js +1 -1
- package/dist/feedback.css-mistica.js +3 -3
- package/dist/file-upload.css-mistica.js +12 -12
- package/dist/fixed-footer-layout.css-mistica.js +5 -5
- package/dist/form.css-mistica.js +1 -1
- package/dist/form.d.ts +1 -1
- package/dist/grid-layout.css-mistica.js +3 -3
- package/dist/grid-layout.d.ts +6 -1
- package/dist/grid-layout.js +33 -18
- package/dist/grid.css-mistica.js +120 -120
- package/dist/header.css-mistica.js +1 -1
- package/dist/hero.css-mistica.js +9 -9
- package/dist/horizontal-scroll.css-mistica.js +1 -1
- package/dist/icon-button.css-mistica.js +58 -58
- package/dist/icons/icon-chevron.css-mistica.js +2 -2
- package/dist/icons/icon-error.css-mistica.js +1 -1
- package/dist/image.css-mistica.js +7 -7
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/inline.css-mistica.js +11 -11
- package/dist/list.css-mistica.js +32 -32
- package/dist/loading-bar.css-mistica.js +1 -1
- package/dist/loading-screen.css-mistica.js +9 -9
- package/dist/logo.css-mistica.js +5 -5
- package/dist/menu.css-mistica.js +12 -12
- package/dist/message.css-mistica.js +172 -0
- package/dist/message.css.d.ts +40 -0
- package/dist/message.d.ts +48 -0
- package/dist/message.js +389 -0
- package/dist/mosaic.css-mistica.js +1 -1
- package/dist/navigation-bar.css-mistica.js +20 -20
- package/dist/navigation-breadcrumbs.css-mistica.js +1 -1
- package/dist/navigation-shared.css-mistica.js +18 -18
- package/dist/package-version.js +1 -1
- package/dist/pagination.css-mistica.js +30 -29
- package/dist/pagination.css.d.ts +1 -2
- package/dist/pagination.d.ts +0 -16
- package/dist/pagination.js +108 -115
- package/dist/pin-field.css-mistica.js +8 -8
- package/dist/popover.css-mistica.js +1 -1
- package/dist/progress-bar.css-mistica.js +7 -7
- package/dist/radio-button.css-mistica.js +32 -32
- package/dist/rating.css-mistica.js +4 -4
- package/dist/responsive-layout.css-mistica.js +6 -6
- package/dist/screen-reader-only.css-mistica.js +1 -1
- package/dist/select.css-mistica.js +22 -22
- package/dist/sheet-action-row.css-mistica.js +2 -2
- package/dist/sheet-common.css-mistica.js +9 -9
- package/dist/sheet-info.css-mistica.js +3 -3
- package/dist/sidenav-bar-layout.css-mistica.js +2 -2
- package/dist/sidenav-bar.css-mistica.js +107 -107
- package/dist/skeletons.css-mistica.js +10 -10
- package/dist/skins/blau.js +20 -0
- package/dist/skins/esimflag.js +20 -0
- package/dist/skins/movistar.js +20 -0
- package/dist/skins/o2.d.ts +1 -0
- package/dist/skins/o2.js +21 -0
- package/dist/skins/skin-contract.css-mistica.js +769 -749
- package/dist/skins/skin-contract.css.d.ts +20 -0
- package/dist/skins/telefonica.js +20 -0
- package/dist/skins/types/colors.d.ts +10 -0
- package/dist/skins/vivo-evolution.js +20 -0
- package/dist/skins/vivo.js +20 -0
- package/dist/skip-link.css-mistica.js +2 -2
- package/dist/slider.css-mistica.js +27 -27
- package/dist/snackbar.css-mistica.js +17 -17
- package/dist/spinner.css-mistica.js +5 -5
- package/dist/square.css-mistica.js +1 -1
- package/dist/stack.css-mistica.js +5 -5
- package/dist/stacking-group.css-mistica.js +2 -2
- package/dist/stepper.css-mistica.js +10 -10
- package/dist/switch-component.css-mistica.js +39 -39
- package/dist/table.css-mistica.js +9 -9
- package/dist/tabs.css-mistica.js +19 -19
- package/dist/tag.css-mistica.js +1 -1
- package/dist/text-field-base.css-mistica.js +26 -26
- package/dist/text-field-components.css-mistica.js +12 -12
- package/dist/text-link.css-mistica.js +6 -6
- package/dist/text-tokens.d.ts +2 -0
- package/dist/text-tokens.js +46 -30
- package/dist/text.css-mistica.js +6 -6
- package/dist/timeline.css-mistica.js +13 -13
- package/dist/timer.css-mistica.js +8 -8
- package/dist/tooltip.css-mistica.js +3 -3
- package/dist/tooltip.js +88 -88
- package/dist/touchable.css-mistica.js +5 -5
- package/dist/utils/aspect-ratio-support.css-mistica.js +4 -4
- package/dist/video.css-mistica.js +2 -2
- package/dist/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +1 -1
- package/dist-es/accordion.css-mistica.js +7 -7
- package/dist-es/align.css-mistica.js +1 -1
- package/dist-es/autocomplete.css-mistica.js +2 -2
- package/dist-es/avatar.css-mistica.js +2 -2
- package/dist-es/badge.css-mistica.js +2 -2
- package/dist-es/box.css-mistica.js +13 -13
- package/dist-es/boxed.css-mistica.js +23 -23
- package/dist-es/button-group.css-mistica.js +2 -2
- package/dist-es/button-layout.css-mistica.js +15 -15
- package/dist-es/button.css-mistica.js +43 -43
- package/dist-es/callout.css-mistica.js +11 -11
- package/dist-es/card-internal.css-mistica.js +23 -23
- package/dist-es/carousel.css-mistica.js +10 -10
- package/dist-es/checkbox.css-mistica.js +13 -13
- package/dist-es/chip.css-mistica.js +17 -17
- package/dist-es/circle.css-mistica.js +1 -1
- package/dist-es/community/advanced-data-card.css-mistica.js +9 -9
- package/dist-es/community/ai-card.css-mistica.js +3 -3
- package/dist-es/community/blocks.css-mistica.js +2 -2
- package/dist-es/community/cyber/example-component.css-mistica.js +1 -1
- package/dist-es/community/example-component.css-mistica.js +1 -1
- package/dist-es/community/skins/cyber-skin.js +20 -0
- package/dist-es/counter.css-mistica.js +2 -2
- package/dist-es/cover-hero.css-mistica.js +3 -3
- package/dist-es/credit-card-number-field.css-mistica.js +4 -4
- package/dist-es/date-field.css-mistica.js +1 -1
- package/dist-es/date-time-picker.css-mistica.js +1 -1
- package/dist-es/dialog.css-mistica.js +5 -5
- package/dist-es/divider.css-mistica.js +5 -5
- package/dist-es/double-field.css-mistica.js +4 -4
- package/dist-es/drawer.css-mistica.js +2 -2
- package/dist-es/drawer.js +167 -118
- package/dist-es/empty-state-card.css-mistica.js +1 -1
- package/dist-es/empty-state.css-mistica.js +7 -7
- package/dist-es/fade-in.css-mistica.js +1 -1
- package/dist-es/fade-out.css-mistica.js +1 -1
- package/dist-es/feedback.css-mistica.js +2 -2
- package/dist-es/file-upload.css-mistica.js +8 -8
- package/dist-es/fixed-footer-layout.css-mistica.js +3 -3
- package/dist-es/form.css-mistica.js +1 -1
- package/dist-es/grid-layout.css-mistica.js +3 -3
- package/dist-es/grid-layout.js +37 -22
- package/dist-es/grid.css-mistica.js +120 -120
- package/dist-es/header.css-mistica.js +1 -1
- package/dist-es/hero.css-mistica.js +3 -3
- package/dist-es/horizontal-scroll.css-mistica.js +1 -1
- package/dist-es/icon-button.css-mistica.js +56 -56
- package/dist-es/icons/icon-chevron.css-mistica.js +2 -2
- package/dist-es/icons/icon-error.css-mistica.js +1 -1
- package/dist-es/image.css-mistica.js +4 -4
- package/dist-es/index.js +2355 -2354
- package/dist-es/inline.css-mistica.js +11 -11
- package/dist-es/list.css-mistica.js +8 -8
- package/dist-es/loading-bar.css-mistica.js +1 -1
- package/dist-es/loading-screen.css-mistica.js +5 -5
- package/dist-es/logo.css-mistica.js +5 -5
- package/dist-es/menu.css-mistica.js +12 -12
- package/dist-es/message.css-mistica.js +41 -0
- package/dist-es/message.js +334 -0
- package/dist-es/mosaic.css-mistica.js +1 -1
- package/dist-es/navigation-bar.css-mistica.js +10 -10
- package/dist-es/navigation-breadcrumbs.css-mistica.js +1 -1
- package/dist-es/navigation-shared.css-mistica.js +10 -10
- package/dist-es/package-version.js +1 -1
- package/dist-es/pagination.css-mistica.js +23 -19
- package/dist-es/pagination.js +137 -141
- package/dist-es/pin-field.css-mistica.js +2 -2
- package/dist-es/popover.css-mistica.js +1 -1
- package/dist-es/progress-bar.css-mistica.js +7 -7
- package/dist-es/radio-button.css-mistica.js +24 -24
- package/dist-es/rating.css-mistica.js +4 -4
- package/dist-es/responsive-layout.css-mistica.js +6 -6
- package/dist-es/screen-reader-only.css-mistica.js +1 -1
- package/dist-es/select.css-mistica.js +18 -18
- package/dist-es/sheet-action-row.css-mistica.js +2 -2
- package/dist-es/sheet-common.css-mistica.js +2 -2
- package/dist-es/sheet-info.css-mistica.js +2 -2
- package/dist-es/sidenav-bar-layout.css-mistica.js +2 -2
- package/dist-es/sidenav-bar.css-mistica.js +72 -72
- package/dist-es/skeletons.css-mistica.js +7 -7
- package/dist-es/skins/blau.js +20 -0
- package/dist-es/skins/esimflag.js +20 -0
- package/dist-es/skins/movistar.js +20 -0
- package/dist-es/skins/o2.js +21 -0
- package/dist-es/skins/skin-contract.css-mistica.js +769 -749
- package/dist-es/skins/telefonica.js +20 -0
- package/dist-es/skins/vivo-evolution.js +20 -0
- package/dist-es/skins/vivo.js +20 -0
- package/dist-es/skip-link.css-mistica.js +2 -2
- package/dist-es/slider.css-mistica.js +20 -20
- package/dist-es/snackbar.css-mistica.js +5 -5
- package/dist-es/spinner.css-mistica.js +2 -2
- package/dist-es/square.css-mistica.js +1 -1
- package/dist-es/stack.css-mistica.js +5 -5
- package/dist-es/stacking-group.css-mistica.js +2 -2
- package/dist-es/stepper.css-mistica.js +4 -4
- package/dist-es/style.css +1 -1
- package/dist-es/switch-component.css-mistica.js +37 -37
- package/dist-es/table.css-mistica.js +9 -9
- package/dist-es/tabs.css-mistica.js +18 -18
- package/dist-es/tag.css-mistica.js +1 -1
- package/dist-es/text-field-base.css-mistica.js +17 -17
- package/dist-es/text-field-components.css-mistica.js +4 -4
- package/dist-es/text-link.css-mistica.js +6 -6
- package/dist-es/text-tokens.js +26 -16
- package/dist-es/text.css-mistica.js +6 -6
- package/dist-es/timeline.css-mistica.js +10 -10
- package/dist-es/timer.css-mistica.js +7 -7
- package/dist-es/tooltip.css-mistica.js +2 -2
- package/dist-es/tooltip.js +109 -109
- package/dist-es/touchable.css-mistica.js +2 -2
- package/dist-es/utils/aspect-ratio-support.css-mistica.js +3 -3
- package/dist-es/video.css-mistica.js +2 -2
- package/dist-es/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +1 -1
- package/doc/layout.md +1 -1
- package/doc/llms/figma-mcp.md +1 -0
- package/package.json +1 -1
- package/src/community/skins/cyber-skin.tsx +20 -0
- package/src/drawer.tsx +43 -12
- package/src/form.tsx +1 -1
- package/src/grid-layout.tsx +20 -0
- package/src/index.tsx +2 -0
- package/src/message.css.ts +148 -0
- package/src/message.tsx +303 -0
- package/src/package-version.tsx +1 -1
- package/src/pagination.css.ts +15 -18
- package/src/pagination.tsx +100 -102
- package/src/skins/blau.tsx +20 -0
- package/src/skins/esimflag.tsx +20 -0
- package/src/skins/movistar.tsx +20 -0
- package/src/skins/o2.tsx +21 -0
- package/src/skins/skin-contract.css.ts +10 -0
- package/src/skins/telefonica.tsx +20 -0
- package/src/skins/types/colors.tsx +10 -0
- package/src/skins/vivo-evolution.tsx +20 -0
- package/src/skins/vivo.tsx +20 -0
- package/src/text-tokens.tsx +14 -0
- package/src/tooltip.tsx +5 -2
package/src/drawer.tsx
CHANGED
|
@@ -17,9 +17,13 @@ import {ButtonLink, ButtonPrimary, ButtonSecondary} from './button';
|
|
|
17
17
|
import Divider from './divider';
|
|
18
18
|
import {getPrefixedDataAttributes} from './utils/dom';
|
|
19
19
|
import * as tokens from './text-tokens';
|
|
20
|
+
import Form from './form';
|
|
20
21
|
|
|
22
|
+
import type {FormProps} from './form';
|
|
21
23
|
import type {DataAttributes, HeadingType, TrackingEvent} from './utils/types';
|
|
22
24
|
|
|
25
|
+
type DrawerFormProps = Omit<FormProps, 'children'>;
|
|
26
|
+
|
|
23
27
|
/**
|
|
24
28
|
* Renders divider or a div with transparent border to avoid the small but noticeable layout shift on scroll
|
|
25
29
|
*/
|
|
@@ -31,6 +35,7 @@ type DrawerLayoutProps = {
|
|
|
31
35
|
children: React.ReactNode;
|
|
32
36
|
onClose: () => void;
|
|
33
37
|
onDismiss?: () => void;
|
|
38
|
+
form?: DrawerFormProps;
|
|
34
39
|
};
|
|
35
40
|
|
|
36
41
|
type DrawerPropsRef = {
|
|
@@ -39,7 +44,7 @@ type DrawerPropsRef = {
|
|
|
39
44
|
};
|
|
40
45
|
|
|
41
46
|
const DrawerLayout = React.forwardRef<DrawerPropsRef, DrawerLayoutProps>(
|
|
42
|
-
({width, children, onClose, onDismiss}, ref) => {
|
|
47
|
+
({width, children, onClose, onDismiss, form}, ref) => {
|
|
43
48
|
useSetModalStateEffect();
|
|
44
49
|
const {isMobile} = useScreenSize();
|
|
45
50
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
@@ -79,6 +84,17 @@ const DrawerLayout = React.forwardRef<DrawerPropsRef, DrawerLayoutProps>(
|
|
|
79
84
|
};
|
|
80
85
|
}, [dismiss]);
|
|
81
86
|
|
|
87
|
+
const content = (
|
|
88
|
+
<div
|
|
89
|
+
data-testid="drawerLayout"
|
|
90
|
+
ref={open}
|
|
91
|
+
style={{width: widthStyle}}
|
|
92
|
+
className={classnames(styles.container, isOpen ? styles.open : styles.closed)}
|
|
93
|
+
>
|
|
94
|
+
{children}
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
|
|
82
98
|
return (
|
|
83
99
|
<Portal>
|
|
84
100
|
<FocusTrap>
|
|
@@ -91,14 +107,16 @@ const DrawerLayout = React.forwardRef<DrawerPropsRef, DrawerLayoutProps>(
|
|
|
91
107
|
isOpen ? styles.overlayOpen : styles.overlayClosed
|
|
92
108
|
)}
|
|
93
109
|
/>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
{form ? (
|
|
111
|
+
<Form
|
|
112
|
+
{...form}
|
|
113
|
+
onSubmit={async (...args) => Promise.resolve(form.onSubmit(...args)).then(close)}
|
|
114
|
+
>
|
|
115
|
+
{content}
|
|
116
|
+
</Form>
|
|
117
|
+
) : (
|
|
118
|
+
content
|
|
119
|
+
)}
|
|
102
120
|
</FocusTrap>
|
|
103
121
|
</Portal>
|
|
104
122
|
);
|
|
@@ -140,10 +158,12 @@ type DrawerProps = {
|
|
|
140
158
|
* width is ignored in mobile viewport
|
|
141
159
|
*/
|
|
142
160
|
width?: number;
|
|
161
|
+
/** if form is set, button onPress is ignored. Use form.onSubmit */
|
|
143
162
|
button?: ButtonProps;
|
|
144
163
|
secondaryButton?: ButtonProps;
|
|
145
164
|
buttonLink?: ButtonProps;
|
|
146
165
|
dataAttributes?: DataAttributes;
|
|
166
|
+
form?: DrawerFormProps | undefined;
|
|
147
167
|
};
|
|
148
168
|
|
|
149
169
|
const Drawer = ({
|
|
@@ -160,6 +180,7 @@ const Drawer = ({
|
|
|
160
180
|
secondaryButton,
|
|
161
181
|
buttonLink,
|
|
162
182
|
dataAttributes,
|
|
183
|
+
form,
|
|
163
184
|
}: DrawerProps): JSX.Element => {
|
|
164
185
|
const layoutRef = React.useRef<DrawerPropsRef>(null);
|
|
165
186
|
const hasActions = !!(button || secondaryButton || buttonLink);
|
|
@@ -182,7 +203,7 @@ const Drawer = ({
|
|
|
182
203
|
});
|
|
183
204
|
|
|
184
205
|
return (
|
|
185
|
-
<DrawerLayout width={width} ref={layoutRef} onClose={onClose} onDismiss={onDismiss}>
|
|
206
|
+
<DrawerLayout width={width} ref={layoutRef} onClose={onClose} onDismiss={onDismiss} form={form}>
|
|
186
207
|
<section
|
|
187
208
|
role="dialog"
|
|
188
209
|
aria-modal="true"
|
|
@@ -243,7 +264,17 @@ const Drawer = ({
|
|
|
243
264
|
<div className={styles.buttonsLayoutContainer}>
|
|
244
265
|
<ButtonLayout
|
|
245
266
|
primaryButton={
|
|
246
|
-
button &&
|
|
267
|
+
button &&
|
|
268
|
+
(form ? (
|
|
269
|
+
<ButtonPrimary
|
|
270
|
+
submit
|
|
271
|
+
trackEvent={button.trackEvent}
|
|
272
|
+
trackingEvent={button.trackingEvent}
|
|
273
|
+
disabled={button.disabled}
|
|
274
|
+
>
|
|
275
|
+
{button.text}
|
|
276
|
+
</ButtonPrimary>
|
|
277
|
+
) : (
|
|
247
278
|
<ButtonPrimary
|
|
248
279
|
trackEvent={button.trackEvent}
|
|
249
280
|
trackingEvent={button.trackingEvent}
|
|
@@ -252,7 +283,7 @@ const Drawer = ({
|
|
|
252
283
|
>
|
|
253
284
|
{button.text}
|
|
254
285
|
</ButtonPrimary>
|
|
255
|
-
)
|
|
286
|
+
))
|
|
256
287
|
}
|
|
257
288
|
secondaryButton={
|
|
258
289
|
secondaryButton && (
|
package/src/form.tsx
CHANGED
|
@@ -26,7 +26,7 @@ export type FormValues = {[name: string]: any};
|
|
|
26
26
|
|
|
27
27
|
type HTMLFieldElement = HTMLSelectElement | HTMLInputElement;
|
|
28
28
|
|
|
29
|
-
type FormProps = {
|
|
29
|
+
export type FormProps = {
|
|
30
30
|
id?: string;
|
|
31
31
|
onSubmit: (values: FormValues, rawValues: FormValues) => Promise<void> | void;
|
|
32
32
|
initialValues?: FormValues;
|
package/src/grid-layout.tsx
CHANGED
|
@@ -32,6 +32,12 @@ type PropsTemplate8plus4 = {
|
|
|
32
32
|
right: React.ReactNode;
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
type PropsTemplate7plus5 = {
|
|
36
|
+
template: '7+5';
|
|
37
|
+
left: React.ReactNode;
|
|
38
|
+
right: React.ReactNode;
|
|
39
|
+
};
|
|
40
|
+
|
|
35
41
|
type PropsTemplate4plus6 = {
|
|
36
42
|
template: '4+6';
|
|
37
43
|
left: React.ReactNode;
|
|
@@ -65,6 +71,7 @@ type Props = CommonProps &
|
|
|
65
71
|
| PropsChildren
|
|
66
72
|
| PropsTemplate6plus6
|
|
67
73
|
| PropsTemplate8plus4
|
|
74
|
+
| PropsTemplate7plus5
|
|
68
75
|
| PropsTemplate4plus6
|
|
69
76
|
| PropsTemplate5plus4
|
|
70
77
|
| PropsTemplate3plus9
|
|
@@ -125,6 +132,19 @@ const GridLayout = ({
|
|
|
125
132
|
);
|
|
126
133
|
}
|
|
127
134
|
|
|
135
|
+
if (template === '7+5') {
|
|
136
|
+
return (
|
|
137
|
+
<div {...gridStyles} {...prefixedDataAttributes}>
|
|
138
|
+
<DesktopContainerTypeContextProvider value="medium">
|
|
139
|
+
<div {...spanStyles(7)}>{left}</div>
|
|
140
|
+
</DesktopContainerTypeContextProvider>
|
|
141
|
+
<DesktopContainerTypeContextProvider value="small">
|
|
142
|
+
<div {...spanStyles(5)}>{right}</div>
|
|
143
|
+
</DesktopContainerTypeContextProvider>
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
128
148
|
if (template === '4+6') {
|
|
129
149
|
return (
|
|
130
150
|
<div {...gridStyles} {...prefixedDataAttributes}>
|
package/src/index.tsx
CHANGED
|
@@ -17,6 +17,8 @@ export {default as ButtonLayout} from './button-layout';
|
|
|
17
17
|
export {default as Counter} from './counter';
|
|
18
18
|
export {default as FixedFooterLayout} from './fixed-footer-layout';
|
|
19
19
|
export {default as ButtonFixedFooterLayout} from './button-fixed-footer-layout';
|
|
20
|
+
export {default as Message} from './message';
|
|
21
|
+
export type {MessageProps} from './message';
|
|
20
22
|
export {default as Snackbar} from './snackbar';
|
|
21
23
|
export {useSnackbar} from './snackbar-context';
|
|
22
24
|
export {Portal} from './portal';
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {globalStyle, style, styleVariants} from '@vanilla-extract/css';
|
|
2
|
+
import {vars} from './skins/skin-contract.css';
|
|
3
|
+
|
|
4
|
+
const bubbleRadius = '4px';
|
|
5
|
+
export const minimumBubbleSize = 48;
|
|
6
|
+
export const bubblePaddingY = 12;
|
|
7
|
+
export const bubblePaddingX = 16;
|
|
8
|
+
export const minimumErrorWidth = 184;
|
|
9
|
+
const boxedErrorInset = 16;
|
|
10
|
+
const actionsGap = 16;
|
|
11
|
+
const actionsInset = 4;
|
|
12
|
+
|
|
13
|
+
export const message = style({display: 'flex', width: 'fit-content', minWidth: 0});
|
|
14
|
+
export const direction = styleVariants({
|
|
15
|
+
incoming: {},
|
|
16
|
+
outgoing: {flexDirection: 'row-reverse', marginLeft: 'auto'},
|
|
17
|
+
});
|
|
18
|
+
export const asset = style({flexShrink: 0});
|
|
19
|
+
export const assetAlignment = styleVariants({
|
|
20
|
+
incoming: {alignSelf: 'flex-start', marginRight: 8},
|
|
21
|
+
outgoing: {alignSelf: 'flex-start', marginLeft: 8},
|
|
22
|
+
});
|
|
23
|
+
export const unboxedAssetSpacing = styleVariants({
|
|
24
|
+
incoming: {marginRight: 12},
|
|
25
|
+
outgoing: {marginLeft: 12},
|
|
26
|
+
});
|
|
27
|
+
export const messageContent = style({display: 'flex', flexDirection: 'column', minWidth: 0});
|
|
28
|
+
export const row = style({display: 'flex', width: '100%', minWidth: 0, alignItems: 'flex-start'});
|
|
29
|
+
export const rowDirection = styleVariants({incoming: {}, outgoing: {flexDirection: 'row-reverse'}});
|
|
30
|
+
export const column = style({display: 'flex', flexDirection: 'column', minWidth: 0});
|
|
31
|
+
export const touchable = style({textAlign: 'left', minWidth: 0, borderRadius: vars.borderRadii.container});
|
|
32
|
+
export const corners = styleVariants({
|
|
33
|
+
'incoming-standalone': {borderTopLeftRadius: bubbleRadius},
|
|
34
|
+
'incoming-first': {borderBottomLeftRadius: bubbleRadius},
|
|
35
|
+
'incoming-middle': {borderTopLeftRadius: bubbleRadius, borderBottomLeftRadius: bubbleRadius},
|
|
36
|
+
'incoming-last': {borderTopLeftRadius: bubbleRadius},
|
|
37
|
+
'outgoing-standalone': {borderBottomRightRadius: bubbleRadius},
|
|
38
|
+
'outgoing-first': {borderBottomRightRadius: bubbleRadius},
|
|
39
|
+
'outgoing-middle': {borderTopRightRadius: bubbleRadius, borderBottomRightRadius: bubbleRadius},
|
|
40
|
+
'outgoing-last': {borderTopRightRadius: bubbleRadius},
|
|
41
|
+
});
|
|
42
|
+
export const bubble = style({
|
|
43
|
+
display: 'flex',
|
|
44
|
+
flexDirection: 'column',
|
|
45
|
+
gap: 4,
|
|
46
|
+
borderRadius: 'inherit',
|
|
47
|
+
overflowWrap: 'anywhere',
|
|
48
|
+
});
|
|
49
|
+
export const boxed = style({
|
|
50
|
+
boxSizing: 'border-box',
|
|
51
|
+
padding: `${bubblePaddingY}px ${bubblePaddingX}px`,
|
|
52
|
+
minWidth: minimumBubbleSize,
|
|
53
|
+
minHeight: minimumBubbleSize,
|
|
54
|
+
});
|
|
55
|
+
export const incomingBackground = styleVariants({
|
|
56
|
+
default: {background: vars.colors.messageBubbleBackgroundIncoming},
|
|
57
|
+
brand: {background: vars.colors.messageBubbleBackgroundIncomingBrand},
|
|
58
|
+
negative: {background: vars.colors.messageBubbleBackgroundIncomingNegative},
|
|
59
|
+
alternative: {background: vars.colors.messageBubbleBackgroundIncomingAlternative},
|
|
60
|
+
media: {background: vars.colors.messageBubbleBackgroundIncomingMedia},
|
|
61
|
+
});
|
|
62
|
+
export const outgoingBackground = styleVariants({
|
|
63
|
+
default: {background: vars.colors.messageBubbleBackgroundOutgoing},
|
|
64
|
+
brand: {background: vars.colors.messageBubbleBackgroundOutgoingBrand},
|
|
65
|
+
negative: {background: vars.colors.messageBubbleBackgroundOutgoingNegative},
|
|
66
|
+
alternative: {background: vars.colors.messageBubbleBackgroundOutgoingAlternative},
|
|
67
|
+
media: {background: vars.colors.messageBubbleBackgroundOutgoingMedia},
|
|
68
|
+
});
|
|
69
|
+
export const errorBackground = style({background: vars.colors.backgroundContainerError});
|
|
70
|
+
export const interactive = style({
|
|
71
|
+
selectors: {
|
|
72
|
+
[`${touchable}:hover &`]: {
|
|
73
|
+
backgroundImage: `linear-gradient(${vars.colors.backgroundContainerHover}, ${vars.colors.backgroundContainerHover})`,
|
|
74
|
+
},
|
|
75
|
+
[`${touchable}:active &`]: {
|
|
76
|
+
backgroundImage: `linear-gradient(${vars.colors.backgroundContainerPressed}, ${vars.colors.backgroundContainerPressed})`,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
export const content = style({
|
|
81
|
+
display: 'flex',
|
|
82
|
+
flexDirection: 'column',
|
|
83
|
+
gap: 4,
|
|
84
|
+
minWidth: 0,
|
|
85
|
+
whiteSpace: 'pre-wrap',
|
|
86
|
+
});
|
|
87
|
+
export const contentSlot = style({minWidth: 0, maxWidth: '100%', overflowX: 'auto', overflowY: 'hidden'});
|
|
88
|
+
globalStyle(`${contentSlot} > *`, {maxWidth: '100%'});
|
|
89
|
+
export const timestamp = style({alignSelf: 'flex-end'});
|
|
90
|
+
export const actions = style({display: 'flex', flexShrink: 0, alignItems: 'center', gap: actionsGap});
|
|
91
|
+
export const footerActions = style({marginTop: actionsInset, flexWrap: 'wrap'});
|
|
92
|
+
export const sideActions = styleVariants({
|
|
93
|
+
incoming: {marginLeft: actionsInset},
|
|
94
|
+
outgoing: {marginRight: actionsInset},
|
|
95
|
+
});
|
|
96
|
+
export const outgoingFooterActions = style({justifyContent: 'flex-end'});
|
|
97
|
+
const maximumSideSlotWidth = '40%';
|
|
98
|
+
export const sideSlot = style({
|
|
99
|
+
display: 'flex',
|
|
100
|
+
flexShrink: 0,
|
|
101
|
+
alignItems: 'center',
|
|
102
|
+
minWidth: 0,
|
|
103
|
+
maxWidth: maximumSideSlotWidth,
|
|
104
|
+
overflowX: 'auto',
|
|
105
|
+
overflowY: 'hidden',
|
|
106
|
+
});
|
|
107
|
+
globalStyle(`${sideSlot} > *`, {maxWidth: '100%'});
|
|
108
|
+
export const unboxedActions = style({marginLeft: -8});
|
|
109
|
+
export const error = style({
|
|
110
|
+
boxSizing: 'border-box',
|
|
111
|
+
display: 'grid',
|
|
112
|
+
gridTemplateColumns: 'auto minmax(0, 1fr)',
|
|
113
|
+
alignItems: 'flex-start',
|
|
114
|
+
gap: 4,
|
|
115
|
+
marginTop: 4,
|
|
116
|
+
minWidth: 0,
|
|
117
|
+
overflowWrap: 'anywhere',
|
|
118
|
+
});
|
|
119
|
+
export const boxedError = style({paddingInline: boxedErrorInset});
|
|
120
|
+
export const errorIcon = style({
|
|
121
|
+
display: 'block',
|
|
122
|
+
width: ['1rem', '1lh'],
|
|
123
|
+
height: ['1rem', '1lh'],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
export const body = style({display: 'flex', flexDirection: 'column', gap: 4});
|
|
127
|
+
export const inlineTimestamp = style({flexDirection: 'row', alignItems: 'baseline', gap: 8});
|
|
128
|
+
export const text = style({display: 'inline-block', maxWidth: '100%'});
|
|
129
|
+
|
|
130
|
+
export const footer = style({
|
|
131
|
+
minWidth: 0,
|
|
132
|
+
maxWidth: '100%',
|
|
133
|
+
overflowWrap: 'anywhere',
|
|
134
|
+
overflowX: 'auto',
|
|
135
|
+
overflowY: 'hidden',
|
|
136
|
+
});
|
|
137
|
+
globalStyle(`${footer} > *`, {maxWidth: '100%'});
|
|
138
|
+
export const errorFooter = style({width: 0, minWidth: '100%', overflowWrap: 'anywhere'});
|
|
139
|
+
export const shortErrorLayout = styleVariants({
|
|
140
|
+
incoming: {display: 'flex', flexDirection: 'column', alignItems: 'flex-start'},
|
|
141
|
+
outgoing: {display: 'flex', flexDirection: 'column', alignItems: 'flex-end'},
|
|
142
|
+
});
|
|
143
|
+
export const shortErrorFooter = style({
|
|
144
|
+
width: 'max-content',
|
|
145
|
+
minWidth: 0,
|
|
146
|
+
maxWidth: `max(100%, ${minimumErrorWidth}px)`,
|
|
147
|
+
flexShrink: 0,
|
|
148
|
+
});
|
package/src/message.tsx
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
import Touchable from './touchable';
|
|
6
|
+
import Avatar from './avatar';
|
|
7
|
+
import {Text1, Text2} from './text';
|
|
8
|
+
import {IconButton} from './icon-button';
|
|
9
|
+
import IconWarningRegular from './generated/mistica-icons/icon-warning-regular';
|
|
10
|
+
import ScreenReaderOnly from './screen-reader-only';
|
|
11
|
+
import {ThemeVariant, useThemeVariant} from './theme-variant-context';
|
|
12
|
+
import {useElementDimensions, useTheme} from './hooks';
|
|
13
|
+
import {vars} from './skins/skin-contract.css';
|
|
14
|
+
import {getPrefixedDataAttributes} from './utils/dom';
|
|
15
|
+
import * as tokens from './text-tokens';
|
|
16
|
+
import * as styles from './message.css';
|
|
17
|
+
|
|
18
|
+
import type {IconButtonProps} from './icon-button';
|
|
19
|
+
import type {PressHandler, TouchableComponentProps} from './touchable';
|
|
20
|
+
import type {ExclusifyUnion} from './utils/utility-types';
|
|
21
|
+
|
|
22
|
+
type MessageAction = IconButtonProps & {
|
|
23
|
+
small?: never;
|
|
24
|
+
type?: never;
|
|
25
|
+
bleedLeft?: never;
|
|
26
|
+
bleedRight?: never;
|
|
27
|
+
bleedY?: never;
|
|
28
|
+
};
|
|
29
|
+
type MessageActions = readonly [MessageAction] | readonly [MessageAction, MessageAction];
|
|
30
|
+
const avatarSize = 40;
|
|
31
|
+
const maximumActions = 2;
|
|
32
|
+
|
|
33
|
+
export type MessageProps = TouchableComponentProps<
|
|
34
|
+
{
|
|
35
|
+
type: 'incoming' | 'outgoing';
|
|
36
|
+
senderName?: string;
|
|
37
|
+
senderNameAs?: 'span' | 'p' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
38
|
+
senderNameLabel?: string;
|
|
39
|
+
timestamp?: string;
|
|
40
|
+
timestampLabel?: string;
|
|
41
|
+
asset?: React.ReactElement;
|
|
42
|
+
boxed?: boolean;
|
|
43
|
+
/** Maximum width of the whole message, including its asset and side actions. Defaults to 80%.
|
|
44
|
+
* Error feedback can exceed this limit up to 184px to avoid illegible wrapping.
|
|
45
|
+
*/
|
|
46
|
+
maxWidth?: number | string;
|
|
47
|
+
position?: 'standalone' | 'first' | 'middle' | 'last';
|
|
48
|
+
} & ExclusifyUnion<
|
|
49
|
+
{onAssetPress: PressHandler; assetLabel: string} | {onAssetPress?: undefined; assetLabel?: undefined}
|
|
50
|
+
> & {
|
|
51
|
+
contentText?: string;
|
|
52
|
+
contentSlot?: React.ReactNode;
|
|
53
|
+
footerSlot?: React.ReactNode;
|
|
54
|
+
sideSlot?: React.ReactNode;
|
|
55
|
+
/** Up to two actions. Extra actions from untyped consumers are ignored. */
|
|
56
|
+
actions?: MessageActions;
|
|
57
|
+
actionsPosition?: 'side' | 'footer';
|
|
58
|
+
} & ExclusifyUnion<{error: true; errorMessage: string} | {error?: false}>
|
|
59
|
+
>;
|
|
60
|
+
|
|
61
|
+
const Message = ({
|
|
62
|
+
type,
|
|
63
|
+
senderName,
|
|
64
|
+
senderNameAs = 'span',
|
|
65
|
+
senderNameLabel,
|
|
66
|
+
timestamp,
|
|
67
|
+
timestampLabel,
|
|
68
|
+
asset,
|
|
69
|
+
onAssetPress,
|
|
70
|
+
assetLabel,
|
|
71
|
+
boxed = true,
|
|
72
|
+
maxWidth = '80%',
|
|
73
|
+
position = 'standalone',
|
|
74
|
+
contentText,
|
|
75
|
+
contentSlot,
|
|
76
|
+
footerSlot,
|
|
77
|
+
sideSlot,
|
|
78
|
+
actions,
|
|
79
|
+
actionsPosition = 'footer',
|
|
80
|
+
error = false,
|
|
81
|
+
errorMessage,
|
|
82
|
+
dataAttributes,
|
|
83
|
+
...touchableProps
|
|
84
|
+
}: MessageProps): JSX.Element => {
|
|
85
|
+
const {t} = useTheme();
|
|
86
|
+
const variant = useThemeVariant();
|
|
87
|
+
const id = React.useId();
|
|
88
|
+
const {width: textWidth, ref: textRef} = useElementDimensions();
|
|
89
|
+
const {width: bubbleContentWidth, height: bubbleContentHeight, ref: bubbleRef} = useElementDimensions();
|
|
90
|
+
const bubbleHeight = bubbleContentHeight + (boxed ? styles.bubblePaddingY * 2 : 0);
|
|
91
|
+
const bubbleWidth = bubbleContentWidth + (boxed ? styles.bubblePaddingX * 2 : 0);
|
|
92
|
+
const shortError = error && bubbleContentWidth > 0 && bubbleWidth < styles.minimumErrorWidth;
|
|
93
|
+
const inlineTimestamp = boxed && !contentSlot && textWidth > 0 && textWidth < styles.minimumBubbleSize;
|
|
94
|
+
const showTimestamp = !!timestamp && !(error && type === 'outgoing');
|
|
95
|
+
const isInteractive = !!(touchableProps.onPress || touchableProps.href || touchableProps.to);
|
|
96
|
+
const directionLabel = t(type === 'incoming' ? tokens.messageIncoming : tokens.messageOutgoing);
|
|
97
|
+
const renderActions = () =>
|
|
98
|
+
actions
|
|
99
|
+
?.slice(0, maximumActions)
|
|
100
|
+
.map((action, index) => <IconButton key={index} {...action} small type="neutral" />);
|
|
101
|
+
|
|
102
|
+
const accessibleIds = [
|
|
103
|
+
`${id}-direction`,
|
|
104
|
+
(senderName || senderNameLabel) && `${id}-sender`,
|
|
105
|
+
`${id}-content`,
|
|
106
|
+
showTimestamp && `${id}-timestamp`,
|
|
107
|
+
error && `${id}-error`,
|
|
108
|
+
]
|
|
109
|
+
.filter(Boolean)
|
|
110
|
+
.join(' ');
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div
|
|
114
|
+
className={classnames(styles.message, styles.direction[type])}
|
|
115
|
+
style={{maxWidth}}
|
|
116
|
+
{...getPrefixedDataAttributes({testid: 'Message', ...dataAttributes})}
|
|
117
|
+
>
|
|
118
|
+
{asset && (
|
|
119
|
+
<div
|
|
120
|
+
className={classnames(styles.asset, styles.assetAlignment[type], {
|
|
121
|
+
[styles.unboxedAssetSpacing[type]]: !boxed,
|
|
122
|
+
})}
|
|
123
|
+
style={
|
|
124
|
+
type === 'outgoing' && bubbleHeight
|
|
125
|
+
? {transform: `translateY(calc(${bubbleHeight}px - 100%))`}
|
|
126
|
+
: undefined
|
|
127
|
+
}
|
|
128
|
+
>
|
|
129
|
+
<Touchable maybe onPress={onAssetPress} aria-label={assetLabel}>
|
|
130
|
+
<span aria-hidden>
|
|
131
|
+
{React.isValidElement<{size: number}>(asset) && asset.type === Avatar
|
|
132
|
+
? React.cloneElement(asset, {size: avatarSize})
|
|
133
|
+
: asset}
|
|
134
|
+
</span>
|
|
135
|
+
</Touchable>
|
|
136
|
+
</div>
|
|
137
|
+
)}
|
|
138
|
+
<div className={classnames(styles.messageContent, {[styles.shortErrorLayout[type]]: shortError})}>
|
|
139
|
+
<div className={classnames(styles.row, styles.rowDirection[type])}>
|
|
140
|
+
<div className={styles.column}>
|
|
141
|
+
<Touchable
|
|
142
|
+
{...touchableProps}
|
|
143
|
+
maybe
|
|
144
|
+
aria-labelledby={
|
|
145
|
+
touchableProps['aria-label']
|
|
146
|
+
? undefined
|
|
147
|
+
: touchableProps['aria-labelledby'] ??
|
|
148
|
+
(isInteractive ? accessibleIds : undefined)
|
|
149
|
+
}
|
|
150
|
+
className={classnames(
|
|
151
|
+
styles.touchable,
|
|
152
|
+
styles.corners[`${type}-${error ? 'standalone' : position}`]
|
|
153
|
+
)}
|
|
154
|
+
>
|
|
155
|
+
<ThemeVariant variant={boxed ? 'default' : variant}>
|
|
156
|
+
<div
|
|
157
|
+
ref={bubbleRef}
|
|
158
|
+
data-testid="MessageBubble"
|
|
159
|
+
className={classnames(styles.bubble, {
|
|
160
|
+
[styles.boxed]: boxed,
|
|
161
|
+
[styles.incomingBackground[variant]]:
|
|
162
|
+
boxed && type === 'incoming' && !error,
|
|
163
|
+
[styles.outgoingBackground[variant]]:
|
|
164
|
+
boxed && type === 'outgoing' && !error,
|
|
165
|
+
[styles.errorBackground]: boxed && error,
|
|
166
|
+
[styles.interactive]: boxed && isInteractive,
|
|
167
|
+
})}
|
|
168
|
+
>
|
|
169
|
+
<ScreenReaderOnly>
|
|
170
|
+
<span id={`${id}-direction`}>{directionLabel}: </span>
|
|
171
|
+
</ScreenReaderOnly>
|
|
172
|
+
{(senderName || senderNameLabel) &&
|
|
173
|
+
(senderName ? (
|
|
174
|
+
<Text1
|
|
175
|
+
medium
|
|
176
|
+
as={senderNameAs}
|
|
177
|
+
id={`${id}-sender`}
|
|
178
|
+
color={
|
|
179
|
+
!boxed &&
|
|
180
|
+
variant !== 'default' &&
|
|
181
|
+
variant !== 'alternative'
|
|
182
|
+
? vars.colors.textPrimary
|
|
183
|
+
: vars.colors.textBrand
|
|
184
|
+
}
|
|
185
|
+
>
|
|
186
|
+
{senderNameLabel ? (
|
|
187
|
+
<>
|
|
188
|
+
<span aria-hidden>{senderName}</span>
|
|
189
|
+
<ScreenReaderOnly>
|
|
190
|
+
<span>{senderNameLabel}</span>
|
|
191
|
+
</ScreenReaderOnly>
|
|
192
|
+
</>
|
|
193
|
+
) : (
|
|
194
|
+
senderName
|
|
195
|
+
)}
|
|
196
|
+
</Text1>
|
|
197
|
+
) : (
|
|
198
|
+
<ScreenReaderOnly>
|
|
199
|
+
<span id={`${id}-sender`}>{senderNameLabel}</span>
|
|
200
|
+
</ScreenReaderOnly>
|
|
201
|
+
))}
|
|
202
|
+
<div
|
|
203
|
+
className={classnames(styles.body, {
|
|
204
|
+
[styles.inlineTimestamp]: inlineTimestamp,
|
|
205
|
+
})}
|
|
206
|
+
>
|
|
207
|
+
<div className={styles.content} id={`${id}-content`}>
|
|
208
|
+
{contentText !== undefined && (
|
|
209
|
+
<Text2 regular as="p">
|
|
210
|
+
<span ref={textRef} className={styles.text}>
|
|
211
|
+
{contentText}
|
|
212
|
+
</span>
|
|
213
|
+
</Text2>
|
|
214
|
+
)}
|
|
215
|
+
{contentSlot !== undefined && (
|
|
216
|
+
<div className={styles.contentSlot}>{contentSlot}</div>
|
|
217
|
+
)}
|
|
218
|
+
</div>
|
|
219
|
+
{showTimestamp && (
|
|
220
|
+
<div className={boxed ? styles.timestamp : undefined}>
|
|
221
|
+
<Text1
|
|
222
|
+
regular
|
|
223
|
+
as="span"
|
|
224
|
+
id={`${id}-timestamp`}
|
|
225
|
+
color={
|
|
226
|
+
boxed
|
|
227
|
+
? type === 'outgoing'
|
|
228
|
+
? vars.colors.textPrimary
|
|
229
|
+
: vars.colors.textSecondary
|
|
230
|
+
: undefined
|
|
231
|
+
}
|
|
232
|
+
>
|
|
233
|
+
{timestampLabel ? (
|
|
234
|
+
<>
|
|
235
|
+
<span aria-hidden>{timestamp}</span>
|
|
236
|
+
<ScreenReaderOnly>
|
|
237
|
+
<span>{timestampLabel}</span>
|
|
238
|
+
</ScreenReaderOnly>
|
|
239
|
+
</>
|
|
240
|
+
) : (
|
|
241
|
+
timestamp
|
|
242
|
+
)}
|
|
243
|
+
</Text1>
|
|
244
|
+
</div>
|
|
245
|
+
)}
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
</ThemeVariant>
|
|
249
|
+
</Touchable>
|
|
250
|
+
{footerSlot && (
|
|
251
|
+
<div className={styles.footer} id={`${id}-footer`}>
|
|
252
|
+
{footerSlot}
|
|
253
|
+
</div>
|
|
254
|
+
)}
|
|
255
|
+
{actions && actionsPosition === 'footer' && (
|
|
256
|
+
<div
|
|
257
|
+
className={classnames(styles.actions, styles.footerActions, {
|
|
258
|
+
[styles.unboxedActions]: !boxed,
|
|
259
|
+
[styles.outgoingFooterActions]: type === 'outgoing',
|
|
260
|
+
})}
|
|
261
|
+
>
|
|
262
|
+
{renderActions()}
|
|
263
|
+
</div>
|
|
264
|
+
)}
|
|
265
|
+
</div>
|
|
266
|
+
{sideSlot && (
|
|
267
|
+
<div className={styles.sideSlot} style={{height: bubbleHeight || undefined}}>
|
|
268
|
+
{sideSlot}
|
|
269
|
+
</div>
|
|
270
|
+
)}
|
|
271
|
+
{actions && actionsPosition === 'side' && (
|
|
272
|
+
<div
|
|
273
|
+
className={classnames(styles.actions, styles.sideActions[type])}
|
|
274
|
+
style={{height: bubbleHeight || undefined}}
|
|
275
|
+
>
|
|
276
|
+
{renderActions()}
|
|
277
|
+
</div>
|
|
278
|
+
)}
|
|
279
|
+
</div>
|
|
280
|
+
{error && (
|
|
281
|
+
<div className={classnames(styles.errorFooter, {[styles.shortErrorFooter]: shortError})}>
|
|
282
|
+
<div
|
|
283
|
+
className={classnames(styles.error, {
|
|
284
|
+
[styles.boxedError]: boxed,
|
|
285
|
+
})}
|
|
286
|
+
role="alert"
|
|
287
|
+
id={`${id}-error`}
|
|
288
|
+
>
|
|
289
|
+
<Text1 regular color={vars.colors.textError}>
|
|
290
|
+
<IconWarningRegular color="currentColor" className={styles.errorIcon} />
|
|
291
|
+
</Text1>
|
|
292
|
+
<Text1 regular color={vars.colors.textError}>
|
|
293
|
+
{errorMessage}
|
|
294
|
+
</Text1>
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
)}
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
);
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
export default Message;
|
package/src/package-version.tsx
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// DO NOT EDIT THIS FILE. It's autogenerated by set-version.js
|
|
2
|
-
export const PACKAGE_VERSION = '17.
|
|
2
|
+
export const PACKAGE_VERSION = '17.11.0' as string;
|