@memori.ai/memori-react 2.7.1 → 2.8.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/CHANGELOG.md +14 -0
- package/README.md +49 -28
- package/dist/components/Chat/Chat.d.ts +2 -0
- package/dist/components/Chat/Chat.js +2 -2
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/MediaWidget/MediaItemWidget.d.ts +3 -1
- package/dist/components/MediaWidget/MediaItemWidget.js +8 -4
- package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/dist/components/MediaWidget/MediaItemWidget.test.js +4 -0
- package/dist/components/MediaWidget/MediaItemWidget.test.js.map +1 -1
- package/dist/components/MediaWidget/MediaWidget.d.ts +2 -0
- package/dist/components/MediaWidget/MediaWidget.js +2 -2
- package/dist/components/MediaWidget/MediaWidget.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.d.ts +2 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +2 -1
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.js +6 -9
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/dist/components/ui/Select.css +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/esm/components/Chat/Chat.d.ts +2 -0
- package/esm/components/Chat/Chat.js +2 -2
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/MediaWidget/MediaItemWidget.d.ts +3 -1
- package/esm/components/MediaWidget/MediaItemWidget.js +8 -4
- package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/esm/components/MediaWidget/MediaItemWidget.test.js +4 -0
- package/esm/components/MediaWidget/MediaItemWidget.test.js.map +1 -1
- package/esm/components/MediaWidget/MediaWidget.d.ts +2 -0
- package/esm/components/MediaWidget/MediaWidget.js +2 -2
- package/esm/components/MediaWidget/MediaWidget.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.d.ts +2 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +2 -1
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.js +6 -9
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/ui/Select.css +2 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.js +2 -2
- package/esm/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Chat/Chat.tsx +6 -1
- package/src/components/MediaWidget/MediaItemWidget.stories.tsx +25 -0
- package/src/components/MediaWidget/MediaItemWidget.test.tsx +11 -0
- package/src/components/MediaWidget/MediaItemWidget.tsx +12 -0
- package/src/components/MediaWidget/MediaWidget.tsx +4 -1
- package/src/components/MediaWidget/__snapshots__/MediaItemWidget.test.tsx.snap +12 -0
- package/src/components/MemoriWidget/MemoriWidget.stories.tsx +34 -0
- package/src/components/MemoriWidget/MemoriWidget.tsx +3 -0
- package/src/components/StartPanel/StartPanel.tsx +23 -19
- package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +62 -50
- package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +62 -50
- package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +62 -50
- package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +62 -50
- package/src/components/ui/Select.css +2 -1
- package/src/index.tsx +3 -0
|
@@ -9,7 +9,9 @@ import {
|
|
|
9
9
|
import { hasTouchscreen } from '../../helpers/utils';
|
|
10
10
|
import { getResourceUrl } from '../../helpers/media';
|
|
11
11
|
import ChatBubble from '../ChatBubble/ChatBubble';
|
|
12
|
-
import MediaWidget
|
|
12
|
+
import MediaWidget, {
|
|
13
|
+
Props as MediaWidgetProps,
|
|
14
|
+
} from '../MediaWidget/MediaWidget';
|
|
13
15
|
import Button from '../ui/Button';
|
|
14
16
|
import memoriApiClient from '@memori.ai/memori-api-client';
|
|
15
17
|
import ChatInputs from '../ChatInputs/ChatInputs';
|
|
@@ -51,6 +53,7 @@ export interface Props {
|
|
|
51
53
|
startListening: () => void;
|
|
52
54
|
stopListening: () => void;
|
|
53
55
|
resetTranscript: () => void;
|
|
56
|
+
customMediaRenderer?: MediaWidgetProps['customMediaRenderer'];
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
const Chat: React.FC<Props> = ({
|
|
@@ -87,6 +90,7 @@ const Chat: React.FC<Props> = ({
|
|
|
87
90
|
startListening,
|
|
88
91
|
stopListening,
|
|
89
92
|
resetTranscript,
|
|
93
|
+
customMediaRenderer,
|
|
90
94
|
}) => {
|
|
91
95
|
const scrollToBottom = () => {
|
|
92
96
|
setTimeout(() => {
|
|
@@ -249,6 +253,7 @@ const Chat: React.FC<Props> = ({
|
|
|
249
253
|
baseUrl={baseUrl}
|
|
250
254
|
apiUrl={apiUrl}
|
|
251
255
|
translateTo={translateTo}
|
|
256
|
+
customMediaRenderer={customMediaRenderer}
|
|
252
257
|
/>
|
|
253
258
|
</React.Fragment>
|
|
254
259
|
))}
|
|
@@ -94,3 +94,28 @@ ImagesGrid.args = {
|
|
|
94
94
|
}?random=${i}`,
|
|
95
95
|
})),
|
|
96
96
|
};
|
|
97
|
+
|
|
98
|
+
export const WithCustomMediaRenderer = Template.bind({});
|
|
99
|
+
WithCustomMediaRenderer.args = {
|
|
100
|
+
items: [
|
|
101
|
+
{
|
|
102
|
+
mediumID: '95226d7e-7bae-465e-8b80-995587bb5971',
|
|
103
|
+
mimeType: 'image/png',
|
|
104
|
+
title: 'Image',
|
|
105
|
+
url: 'https://picsum.photos/200/300',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
mediumID: '95226d7e-7bae-465e-8b80-995587bb5973',
|
|
109
|
+
mimeType: 'application/pdf',
|
|
110
|
+
title: 'PDF',
|
|
111
|
+
url: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
|
|
112
|
+
content:
|
|
113
|
+
'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
customMediaRenderer: (mimeType: string) => {
|
|
117
|
+
if (mimeType === 'image/png') {
|
|
118
|
+
return <div>Custom Image Renderer</div>;
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
};
|
|
@@ -118,3 +118,14 @@ it('renders MediaItemWidget unchanged with css snippet to exec', () => {
|
|
|
118
118
|
);
|
|
119
119
|
expect(container).toMatchSnapshot();
|
|
120
120
|
});
|
|
121
|
+
|
|
122
|
+
it('renders MediaItemWidget unchanged with custom media renderer', () => {
|
|
123
|
+
const { container } = render(
|
|
124
|
+
<MediaItemWidget
|
|
125
|
+
items={[]}
|
|
126
|
+
sessionID={sessionID}
|
|
127
|
+
customMediaRenderer={mimeType => <pre>{mimeType}</pre>}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
expect(container).toMatchSnapshot();
|
|
131
|
+
});
|
|
@@ -20,6 +20,7 @@ export interface Props {
|
|
|
20
20
|
translateTo?: string;
|
|
21
21
|
baseURL?: string;
|
|
22
22
|
apiURL?: string;
|
|
23
|
+
customMediaRenderer?: (mimeType: string) => JSX.Element | null;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export const RenderMediaItem = ({
|
|
@@ -31,6 +32,7 @@ export const RenderMediaItem = ({
|
|
|
31
32
|
baseURL,
|
|
32
33
|
apiURL,
|
|
33
34
|
onClick,
|
|
35
|
+
customMediaRenderer,
|
|
34
36
|
}: {
|
|
35
37
|
isChild?: boolean;
|
|
36
38
|
item: Medium;
|
|
@@ -40,6 +42,7 @@ export const RenderMediaItem = ({
|
|
|
40
42
|
baseURL?: string;
|
|
41
43
|
apiURL?: string;
|
|
42
44
|
onClick?: (mediumID: string) => void;
|
|
45
|
+
customMediaRenderer?: (mimeType: string) => JSX.Element | null;
|
|
43
46
|
}) => {
|
|
44
47
|
const url = getResourceUrl({
|
|
45
48
|
resourceURI: item.url,
|
|
@@ -49,6 +52,12 @@ export const RenderMediaItem = ({
|
|
|
49
52
|
apiURL,
|
|
50
53
|
});
|
|
51
54
|
|
|
55
|
+
const customRenderer = customMediaRenderer?.(item.mimeType);
|
|
56
|
+
|
|
57
|
+
if (customRenderer) {
|
|
58
|
+
return customRenderer;
|
|
59
|
+
}
|
|
60
|
+
|
|
52
61
|
switch (item.mimeType) {
|
|
53
62
|
case 'image/jpeg':
|
|
54
63
|
case 'image/png':
|
|
@@ -245,6 +254,7 @@ const MediaItemWidget: React.FC<Props> = ({
|
|
|
245
254
|
translateTo,
|
|
246
255
|
baseURL,
|
|
247
256
|
apiURL,
|
|
257
|
+
customMediaRenderer,
|
|
248
258
|
}: Props) => {
|
|
249
259
|
const [media, setMedia] = useState(items);
|
|
250
260
|
const [openModalMedium, setOpenModalMedium] = useState<Medium>();
|
|
@@ -333,6 +343,7 @@ const MediaItemWidget: React.FC<Props> = ({
|
|
|
333
343
|
url: item.url,
|
|
334
344
|
content: item.content,
|
|
335
345
|
}}
|
|
346
|
+
customMediaRenderer={customMediaRenderer}
|
|
336
347
|
/>
|
|
337
348
|
</Transition.Child>
|
|
338
349
|
))}
|
|
@@ -388,6 +399,7 @@ const MediaItemWidget: React.FC<Props> = ({
|
|
|
388
399
|
url: openModalMedium.url,
|
|
389
400
|
content: openModalMedium.content,
|
|
390
401
|
}}
|
|
402
|
+
customMediaRenderer={customMediaRenderer}
|
|
391
403
|
/>
|
|
392
404
|
</Modal>
|
|
393
405
|
)}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import React, { useEffect, useState } from 'react';
|
|
6
6
|
import Button from '../ui/Button';
|
|
7
7
|
import LinkItemWidget from './LinkItemWidget';
|
|
8
|
-
import MediaItemWidget from './MediaItemWidget';
|
|
8
|
+
import MediaItemWidget, { Props as MediaItemProps } from './MediaItemWidget';
|
|
9
9
|
import { Transition } from '@headlessui/react';
|
|
10
10
|
import cx from 'classnames';
|
|
11
11
|
import { useTranslation } from 'react-i18next';
|
|
@@ -19,6 +19,7 @@ export interface Props {
|
|
|
19
19
|
baseUrl?: string;
|
|
20
20
|
apiUrl?: string;
|
|
21
21
|
translateTo?: string;
|
|
22
|
+
customMediaRenderer?: MediaItemProps['customMediaRenderer'];
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
const MediaWidget: React.FC<Props> = ({
|
|
@@ -30,6 +31,7 @@ const MediaWidget: React.FC<Props> = ({
|
|
|
30
31
|
baseUrl,
|
|
31
32
|
apiUrl,
|
|
32
33
|
translateTo,
|
|
34
|
+
customMediaRenderer,
|
|
33
35
|
}: Props) => {
|
|
34
36
|
const { t } = useTranslation();
|
|
35
37
|
const [showHints, setShowHints] = useState(true);
|
|
@@ -48,6 +50,7 @@ const MediaWidget: React.FC<Props> = ({
|
|
|
48
50
|
translateTo={translateTo}
|
|
49
51
|
baseURL={baseUrl}
|
|
50
52
|
apiURL={apiUrl}
|
|
53
|
+
customMediaRenderer={customMediaRenderer}
|
|
51
54
|
/>
|
|
52
55
|
)}
|
|
53
56
|
{links?.length > 0 && <LinkItemWidget items={links} baseUrl={baseUrl} />}
|
|
@@ -151,6 +151,18 @@ exports[`renders MediaItemWidget unchanged with css snippet to show 1`] = `
|
|
|
151
151
|
</div>
|
|
152
152
|
`;
|
|
153
153
|
|
|
154
|
+
exports[`renders MediaItemWidget unchanged with custom media renderer 1`] = `
|
|
155
|
+
<div>
|
|
156
|
+
<div
|
|
157
|
+
class="memori-media-items"
|
|
158
|
+
>
|
|
159
|
+
<div
|
|
160
|
+
class="memori-media-items--grid"
|
|
161
|
+
/>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
`;
|
|
165
|
+
|
|
154
166
|
exports[`renders MediaItemWidget unchanged with img 1`] = `
|
|
155
167
|
<div>
|
|
156
168
|
<div
|
|
@@ -84,6 +84,19 @@ WithPublicPageIntegrationAndFullbodyAvatar.args = {
|
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
+
export const WithPublicPageIntegrationAndNonDefaultLang = Template.bind({});
|
|
88
|
+
WithPublicPageIntegrationAndNonDefaultLang.args = {
|
|
89
|
+
memori,
|
|
90
|
+
tenant,
|
|
91
|
+
integration: {
|
|
92
|
+
...integration,
|
|
93
|
+
customData: JSON.stringify({
|
|
94
|
+
...JSON.parse(integration.customData ?? '{}'),
|
|
95
|
+
lang: 'es',
|
|
96
|
+
}),
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
87
100
|
export const ShowInstruct = Template.bind({});
|
|
88
101
|
ShowInstruct.args = {
|
|
89
102
|
memori: {
|
|
@@ -114,3 +127,24 @@ WithAzureSpeechKey.args = {
|
|
|
114
127
|
tenant,
|
|
115
128
|
AZURE_COGNITIVE_SERVICES_TTS_KEY: 'provide your key here',
|
|
116
129
|
};
|
|
130
|
+
|
|
131
|
+
export const WithCustomMediaRenderer = Template.bind({});
|
|
132
|
+
WithCustomMediaRenderer.args = {
|
|
133
|
+
memori,
|
|
134
|
+
tenant,
|
|
135
|
+
customMediaRenderer: (mimeType: string) => (
|
|
136
|
+
<div
|
|
137
|
+
style={{
|
|
138
|
+
width: '100%',
|
|
139
|
+
height: '100%',
|
|
140
|
+
backgroundColor: 'black',
|
|
141
|
+
color: 'white',
|
|
142
|
+
display: 'flex',
|
|
143
|
+
justifyContent: 'center',
|
|
144
|
+
alignItems: 'center',
|
|
145
|
+
}}
|
|
146
|
+
>
|
|
147
|
+
{mimeType}
|
|
148
|
+
</div>
|
|
149
|
+
),
|
|
150
|
+
};
|
|
@@ -203,6 +203,7 @@ export interface Props {
|
|
|
203
203
|
AZURE_COGNITIVE_SERVICES_TTS_KEY?: string;
|
|
204
204
|
onStateChange?: (state?: DialogState) => void;
|
|
205
205
|
additionalInfo?: OpenSession['additionalInfo'] & { [key: string]: string };
|
|
206
|
+
customMediaRenderer?: ChatProps['customMediaRenderer'];
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
const MemoriWidget = ({
|
|
@@ -235,6 +236,7 @@ const MemoriWidget = ({
|
|
|
235
236
|
AZURE_COGNITIVE_SERVICES_TTS_KEY,
|
|
236
237
|
onStateChange,
|
|
237
238
|
additionalInfo,
|
|
239
|
+
customMediaRenderer,
|
|
238
240
|
}: Props) => {
|
|
239
241
|
const { t, i18n } = useTranslation();
|
|
240
242
|
|
|
@@ -2312,6 +2314,7 @@ const MemoriWidget = ({
|
|
|
2312
2314
|
resetTranscript,
|
|
2313
2315
|
listening,
|
|
2314
2316
|
isPlayingAudio,
|
|
2317
|
+
customMediaRenderer,
|
|
2315
2318
|
};
|
|
2316
2319
|
|
|
2317
2320
|
const integrationBackground =
|
|
@@ -205,26 +205,30 @@ const StartPanel: React.FC<Props> = ({
|
|
|
205
205
|
|
|
206
206
|
{integrationConfig?.multilanguage && !instruct && (
|
|
207
207
|
<div className="memori--language-chooser">
|
|
208
|
-
<
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
208
|
+
<label id="user-lang-pref-label" htmlFor="user-lang-pref">
|
|
209
|
+
{t('write_and_speak.iWantToTalkToIn', {
|
|
210
|
+
name: memori.name,
|
|
211
|
+
})}
|
|
212
|
+
</label>
|
|
213
|
+
<select
|
|
214
|
+
id="user-lang-pref"
|
|
215
|
+
className="memori-select--button"
|
|
214
216
|
value={(userLang ?? i18n.language).toUpperCase()}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
217
|
+
aria-labelledby="user-lang-pref-label"
|
|
218
|
+
onChange={e => {
|
|
219
|
+
setUserLang(e.target.value);
|
|
220
|
+
}}
|
|
221
|
+
>
|
|
222
|
+
{chatLanguages.map(lang => (
|
|
223
|
+
<option
|
|
224
|
+
key={lang.value}
|
|
225
|
+
value={lang.value}
|
|
226
|
+
aria-label={lang.label}
|
|
227
|
+
>
|
|
228
|
+
{lang.label}
|
|
229
|
+
</option>
|
|
230
|
+
))}
|
|
231
|
+
</select>
|
|
228
232
|
</div>
|
|
229
233
|
)}
|
|
230
234
|
|
|
@@ -537,60 +537,72 @@ exports[`renders StartPanel with integrationConfig unchanged 1`] = `
|
|
|
537
537
|
<div
|
|
538
538
|
class="memori--language-chooser"
|
|
539
539
|
>
|
|
540
|
-
<
|
|
541
|
-
|
|
540
|
+
<label
|
|
541
|
+
for="user-lang-pref"
|
|
542
|
+
id="user-lang-pref-label"
|
|
543
|
+
>
|
|
544
|
+
write_and_speak.iWantToTalkToIn
|
|
545
|
+
</label>
|
|
546
|
+
<select
|
|
547
|
+
aria-labelledby="user-lang-pref-label"
|
|
548
|
+
class="memori-select--button"
|
|
549
|
+
id="user-lang-pref"
|
|
542
550
|
>
|
|
543
|
-
<
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
551
|
+
<option
|
|
552
|
+
aria-label="Italiano"
|
|
553
|
+
value="IT"
|
|
554
|
+
>
|
|
555
|
+
Italiano
|
|
556
|
+
</option>
|
|
557
|
+
<option
|
|
558
|
+
aria-label="English"
|
|
549
559
|
value="EN"
|
|
550
|
-
/>
|
|
551
|
-
<label
|
|
552
|
-
class="memori-select--label"
|
|
553
|
-
data-headlessui-state=""
|
|
554
|
-
id="headlessui-listbox-label-:r0:"
|
|
555
560
|
>
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
aria-haspopup="true"
|
|
562
|
-
aria-label="write_and_speak.iWantToTalkToIn"
|
|
563
|
-
aria-labelledby="headlessui-listbox-label-:r0: headlessui-listbox-button-:r1:"
|
|
564
|
-
class="memori-select--button"
|
|
565
|
-
data-headlessui-state=""
|
|
566
|
-
id="headlessui-listbox-button-:r1:"
|
|
567
|
-
type="button"
|
|
561
|
+
English
|
|
562
|
+
</option>
|
|
563
|
+
<option
|
|
564
|
+
aria-label="Deutsch"
|
|
565
|
+
value="DE"
|
|
568
566
|
>
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
567
|
+
Deutsch
|
|
568
|
+
</option>
|
|
569
|
+
<option
|
|
570
|
+
aria-label="Español"
|
|
571
|
+
value="ES"
|
|
572
|
+
>
|
|
573
|
+
Español
|
|
574
|
+
</option>
|
|
575
|
+
<option
|
|
576
|
+
aria-label="Français"
|
|
577
|
+
value="FR"
|
|
578
|
+
>
|
|
579
|
+
Français
|
|
580
|
+
</option>
|
|
581
|
+
<option
|
|
582
|
+
aria-label="Português"
|
|
583
|
+
value="PT"
|
|
584
|
+
>
|
|
585
|
+
Português
|
|
586
|
+
</option>
|
|
587
|
+
<option
|
|
588
|
+
aria-label="Українська"
|
|
589
|
+
value="UK"
|
|
590
|
+
>
|
|
591
|
+
Українська
|
|
592
|
+
</option>
|
|
593
|
+
<option
|
|
594
|
+
aria-label="Русский"
|
|
595
|
+
value="RU"
|
|
596
|
+
>
|
|
597
|
+
Русский
|
|
598
|
+
</option>
|
|
599
|
+
<option
|
|
600
|
+
aria-label="Polski"
|
|
601
|
+
value="PL"
|
|
602
|
+
>
|
|
603
|
+
Polski
|
|
604
|
+
</option>
|
|
605
|
+
</select>
|
|
594
606
|
</div>
|
|
595
607
|
<button
|
|
596
608
|
class="memori-button memori-button--primary memori-button--rounded memori-button--padded memori--start-button"
|
|
@@ -237,60 +237,72 @@ exports[`renders Chat layout unchanged 1`] = `
|
|
|
237
237
|
<div
|
|
238
238
|
class="memori--language-chooser"
|
|
239
239
|
>
|
|
240
|
-
<
|
|
241
|
-
|
|
240
|
+
<label
|
|
241
|
+
for="user-lang-pref"
|
|
242
|
+
id="user-lang-pref-label"
|
|
243
|
+
>
|
|
244
|
+
write_and_speak.iWantToTalkToIn
|
|
245
|
+
</label>
|
|
246
|
+
<select
|
|
247
|
+
aria-labelledby="user-lang-pref-label"
|
|
248
|
+
class="memori-select--button"
|
|
249
|
+
id="user-lang-pref"
|
|
242
250
|
>
|
|
243
|
-
<
|
|
244
|
-
|
|
245
|
-
name="day"
|
|
246
|
-
readonly=""
|
|
247
|
-
style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px; display: none;"
|
|
248
|
-
type="hidden"
|
|
251
|
+
<option
|
|
252
|
+
aria-label="Italiano"
|
|
249
253
|
value="IT"
|
|
250
|
-
/>
|
|
251
|
-
<label
|
|
252
|
-
class="memori-select--label"
|
|
253
|
-
data-headlessui-state=""
|
|
254
|
-
id="headlessui-listbox-label-:r7:"
|
|
255
254
|
>
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
aria-haspopup="true"
|
|
262
|
-
aria-label="write_and_speak.iWantToTalkToIn"
|
|
263
|
-
aria-labelledby="headlessui-listbox-label-:r7: headlessui-listbox-button-:r8:"
|
|
264
|
-
class="memori-select--button"
|
|
265
|
-
data-headlessui-state=""
|
|
266
|
-
id="headlessui-listbox-button-:r8:"
|
|
267
|
-
type="button"
|
|
255
|
+
Italiano
|
|
256
|
+
</option>
|
|
257
|
+
<option
|
|
258
|
+
aria-label="English"
|
|
259
|
+
value="EN"
|
|
268
260
|
>
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
261
|
+
English
|
|
262
|
+
</option>
|
|
263
|
+
<option
|
|
264
|
+
aria-label="Deutsch"
|
|
265
|
+
value="DE"
|
|
266
|
+
>
|
|
267
|
+
Deutsch
|
|
268
|
+
</option>
|
|
269
|
+
<option
|
|
270
|
+
aria-label="Español"
|
|
271
|
+
value="ES"
|
|
272
|
+
>
|
|
273
|
+
Español
|
|
274
|
+
</option>
|
|
275
|
+
<option
|
|
276
|
+
aria-label="Français"
|
|
277
|
+
value="FR"
|
|
278
|
+
>
|
|
279
|
+
Français
|
|
280
|
+
</option>
|
|
281
|
+
<option
|
|
282
|
+
aria-label="Português"
|
|
283
|
+
value="PT"
|
|
284
|
+
>
|
|
285
|
+
Português
|
|
286
|
+
</option>
|
|
287
|
+
<option
|
|
288
|
+
aria-label="Українська"
|
|
289
|
+
value="UK"
|
|
290
|
+
>
|
|
291
|
+
Українська
|
|
292
|
+
</option>
|
|
293
|
+
<option
|
|
294
|
+
aria-label="Русский"
|
|
295
|
+
value="RU"
|
|
296
|
+
>
|
|
297
|
+
Русский
|
|
298
|
+
</option>
|
|
299
|
+
<option
|
|
300
|
+
aria-label="Polski"
|
|
301
|
+
value="PL"
|
|
302
|
+
>
|
|
303
|
+
Polski
|
|
304
|
+
</option>
|
|
305
|
+
</select>
|
|
294
306
|
</div>
|
|
295
307
|
<button
|
|
296
308
|
class="memori-button memori-button--primary memori-button--rounded memori-button--padded memori--start-button"
|