@linagora/twake-mui 15.2.0 → 16.0.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/components/Dialog/Dialog.stories.d.ts +1 -1
  3. package/dist/components/Dialog/Dialog.stories.js +1 -1
  4. package/dist/components/Dialog/index.d.ts +1 -1
  5. package/dist/components/Dialog/index.js +1 -1
  6. package/dist/components/Dialogs/ConfirmDialog.d.ts +8 -0
  7. package/dist/components/Dialogs/ConfirmDialog.js +16 -0
  8. package/dist/components/Dialogs/DialogBackButton.d.ts +8 -0
  9. package/dist/components/Dialogs/DialogBackButton.js +14 -0
  10. package/dist/components/Dialogs/DialogCloseButton.d.ts +8 -0
  11. package/dist/components/Dialogs/DialogCloseButton.js +14 -0
  12. package/dist/components/Dialogs/DialogFluidContent.d.ts +12 -0
  13. package/dist/components/Dialogs/DialogFluidContent.js +11 -0
  14. package/dist/components/Dialogs/DialogNavButtons.d.ts +9 -0
  15. package/dist/components/Dialogs/DialogNavButtons.js +14 -0
  16. package/dist/components/Dialogs/Dialogs.stories.d.ts +33 -0
  17. package/dist/components/Dialogs/Dialogs.stories.js +177 -0
  18. package/dist/components/Dialogs/FixedActionsDialog.d.ts +8 -0
  19. package/dist/components/Dialogs/FixedActionsDialog.js +20 -0
  20. package/dist/components/Dialogs/FixedDialog.d.ts +8 -0
  21. package/dist/components/Dialogs/FixedDialog.js +20 -0
  22. package/dist/components/Dialogs/IllustrationDialog.d.ts +8 -0
  23. package/dist/components/Dialogs/IllustrationDialog.js +21 -0
  24. package/dist/components/Dialogs/InstallFlagshipAppDialog.d.ts +13 -0
  25. package/dist/components/Dialogs/InstallFlagshipAppDialog.js +26 -0
  26. package/dist/components/Dialogs/PermissionDialog.d.ts +11 -0
  27. package/dist/components/Dialogs/PermissionDialog.js +15 -0
  28. package/dist/components/Dialogs/PermissionDialogIcon.d.ts +3 -0
  29. package/dist/components/Dialogs/PermissionDialogIcon.js +8 -0
  30. package/dist/components/Dialogs/ShortcutDialog.d.ts +15 -0
  31. package/dist/components/Dialogs/ShortcutDialog.js +41 -0
  32. package/dist/components/Dialogs/SlideUpTransition.d.ts +5 -0
  33. package/dist/components/Dialogs/SlideUpTransition.js +6 -0
  34. package/dist/components/Dialogs/SpecificDialogs.stories.d.ts +7 -0
  35. package/dist/components/Dialogs/SpecificDialogs.stories.js +43 -0
  36. package/dist/components/Dialogs/StandardDialog.d.ts +11 -0
  37. package/dist/components/Dialogs/StandardDialog.js +21 -0
  38. package/dist/components/Dialogs/images/appStore.png +0 -0
  39. package/dist/components/Dialogs/images/installFlagshipAppQrCode.png +0 -0
  40. package/dist/components/Dialogs/images/playStore.png +0 -0
  41. package/dist/components/Dialogs/locales/de.json +25 -0
  42. package/dist/components/Dialogs/locales/en.json +25 -0
  43. package/dist/components/Dialogs/locales/es.json +25 -0
  44. package/dist/components/Dialogs/locales/fr.json +25 -0
  45. package/dist/components/Dialogs/locales/index.d.ts +177 -0
  46. package/dist/components/Dialogs/locales/index.js +8 -0
  47. package/dist/components/Dialogs/locales/it.json +25 -0
  48. package/dist/components/Dialogs/locales/ru.json +25 -0
  49. package/dist/components/Dialogs/locales/vi.json +25 -0
  50. package/dist/components/Dialogs/shortcutHelpers.d.ts +19 -0
  51. package/dist/components/Dialogs/shortcutHelpers.js +49 -0
  52. package/dist/components/Dialogs/types.d.ts +7 -0
  53. package/dist/components/Dialogs/types.js +1 -0
  54. package/dist/components/Dialogs/useDialogLayout.d.ts +40 -0
  55. package/dist/components/Dialogs/useDialogLayout.js +63 -0
  56. package/dist/index.d.ts +24 -1
  57. package/dist/index.js +12 -1
  58. package/dist/lib/overrides.js +71 -6
  59. package/package.json +2 -2
@@ -0,0 +1,41 @@
1
+ import { Button, Stack, TextField } from '@mui/material';
2
+ import React, { useState } from 'react';
3
+ import { useExtendI18n, useI18n } from 'twake-i18n';
4
+ import ConfirmDialog from './ConfirmDialog';
5
+ import { locales } from './locales';
6
+ import { checkAndSaveShortcut, makeHumanReadableFileName } from './shortcutHelpers';
7
+ import { useAlert } from '../../providers/AlertProvider/useAlert';
8
+ /** Creates or edits a shortcut to a URL. Must be rendered within an `AlertProvider` */
9
+ const ShortcutDialog = ({ shortcut, onSave, onClose }) => {
10
+ useExtendI18n(locales);
11
+ const { t } = useI18n();
12
+ const { showAlert } = useAlert();
13
+ const isEditing = Boolean(shortcut);
14
+ const [fileName, setFileName] = useState(makeHumanReadableFileName(shortcut?.name ?? ''));
15
+ const [url, setUrl] = useState(shortcut?.url ?? '');
16
+ const saveShortcut = () => {
17
+ void checkAndSaveShortcut({
18
+ fileName,
19
+ url,
20
+ isEditing,
21
+ onSave,
22
+ onClose,
23
+ showAlert,
24
+ t
25
+ });
26
+ };
27
+ const handleKeyDown = (event) => {
28
+ if (event.key === 'Enter')
29
+ saveShortcut();
30
+ };
31
+ return (React.createElement(ConfirmDialog, { open: true, title: t(isEditing
32
+ ? 'Dialogs.shortcut.editTitle'
33
+ : 'Dialogs.shortcut.createTitle'), onClose: onClose, content: React.createElement(Stack, { spacing: 2 },
34
+ React.createElement("div", null,
35
+ React.createElement(TextField, { label: t('Dialogs.shortcut.url'), value: url, id: "shortcuturl", onChange: event => setUrl(event.target.value), onKeyDown: handleKeyDown, autoComplete: "off", fullWidth: true, margin: "normal", autoFocus: true })),
36
+ React.createElement("div", null,
37
+ React.createElement(TextField, { label: t('Dialogs.shortcut.filename'), value: fileName, id: "shortcutfilename", onChange: event => setFileName(event.target.value), onKeyDown: handleKeyDown, autoComplete: "off", fullWidth: true, margin: "normal" }))), actions: React.createElement(React.Fragment, null,
38
+ React.createElement(Button, { variant: "outlined", onClick: onClose }, t('Dialogs.shortcut.cancel')),
39
+ React.createElement(Button, { onClick: saveShortcut }, t(isEditing ? 'Dialogs.shortcut.edit' : 'Dialogs.shortcut.create'))) }));
40
+ };
41
+ export default ShortcutDialog;
@@ -0,0 +1,5 @@
1
+ import { SlideProps } from '@mui/material';
2
+ import React from 'react';
3
+ /** Slides a full screen dialog in from the bottom of the screen */
4
+ declare const SlideUpTransition: React.ForwardRefExoticComponent<Omit<SlideProps, "ref"> & React.RefAttributes<unknown>>;
5
+ export default SlideUpTransition;
@@ -0,0 +1,6 @@
1
+ import { Slide } from '@mui/material';
2
+ import React, { forwardRef } from 'react';
3
+ /** Slides a full screen dialog in from the bottom of the screen */
4
+ const SlideUpTransition = forwardRef((props, ref) => (React.createElement(Slide, { ref: ref, direction: "up", ...props })));
5
+ SlideUpTransition.displayName = 'SlideUpTransition';
6
+ export default SlideUpTransition;
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ declare const meta: Meta;
3
+ export default meta;
4
+ type Story = StoryObj<typeof meta>;
5
+ export declare const Default: Story;
6
+ export declare const InstallFlagshipAppScreenshot: Story;
7
+ export declare const ShortcutScreenshot: Story;
@@ -0,0 +1,43 @@
1
+ import { Button, Stack } from '@mui/material';
2
+ import React, { useState } from 'react';
3
+ import InstallFlagshipAppDialog from './InstallFlagshipAppDialog';
4
+ import ShortcutDialog from './ShortcutDialog';
5
+ import AlertProvider from '../../providers/AlertProvider';
6
+ const noop = () => undefined;
7
+ const specificDialogs = {
8
+ InstallFlagshipAppDialog,
9
+ ShortcutDialog: ({ onClose }) => (React.createElement(ShortcutDialog, { onClose: onClose, onSave: noop }))
10
+ };
11
+ const Openers = () => {
12
+ const [opened, setOpened] = useState(null);
13
+ const OpenedDialog = opened && specificDialogs[opened];
14
+ return (React.createElement(Stack, { spacing: 1, sx: { alignItems: 'flex-start' } },
15
+ Object.keys(specificDialogs).map(name => (React.createElement(Button, { key: name, onClick: () => setOpened(name) },
16
+ "Open ",
17
+ name))),
18
+ OpenedDialog && React.createElement(OpenedDialog, { onClose: () => setOpened(null) })));
19
+ };
20
+ const meta = {
21
+ title: 'Dialogs/Specific dialogs',
22
+ parameters: { layout: 'centered' },
23
+ tags: ['autodocs'],
24
+ decorators: [
25
+ (Story) => (React.createElement(AlertProvider, null,
26
+ React.createElement(Story, null)))
27
+ ]
28
+ };
29
+ export default meta;
30
+ export const Default = {
31
+ render: () => React.createElement(Openers, null)
32
+ };
33
+ // Visual Regression - one story per dialog, since each one covers the screen
34
+ export const InstallFlagshipAppScreenshot = {
35
+ tags: ['argos'],
36
+ parameters: { layout: 'fullscreen' },
37
+ render: () => React.createElement(InstallFlagshipAppDialog, { onClose: noop })
38
+ };
39
+ export const ShortcutScreenshot = {
40
+ tags: ['argos'],
41
+ parameters: { layout: 'fullscreen' },
42
+ render: () => (React.createElement(ShortcutDialog, { shortcut: { name: 'Twake.url', url: 'https://twake.app' }, onClose: noop, onSave: noop }))
43
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import type { DialogSectionsProps } from './types';
3
+ import { DialogLayoutProps } from './useDialogLayout';
4
+ export interface StandardDialogProps extends DialogLayoutProps, DialogSectionsProps {
5
+ }
6
+ /**
7
+ * Dialog laid out with a title, a content and actions. It is labelled by its
8
+ * title and goes full screen on mobile unless its size is `small`.
9
+ */
10
+ declare const StandardDialog: ({ title, content, actions, actionsLayout, ...props }: StandardDialogProps) => React.ReactElement;
11
+ export default StandardDialog;
@@ -0,0 +1,21 @@
1
+ import { DialogContent, DialogTitle, Divider } from '@mui/material';
2
+ import React from 'react';
3
+ import DialogFluidContent from './DialogFluidContent';
4
+ import DialogNavButtons from './DialogNavButtons';
5
+ import { useDialogLayout } from './useDialogLayout';
6
+ import Dialog from '../Dialog';
7
+ /**
8
+ * Dialog laid out with a title, a content and actions. It is labelled by its
9
+ * title and goes full screen on mobile unless its size is `small`.
10
+ */
11
+ const StandardDialog = ({ title, content, actions, actionsLayout, ...props }) => {
12
+ const { id, fullScreen, dialogProps, dialogTitleProps, dividerProps, dialogActionsProps, dialogContentProps } = useDialogLayout(props);
13
+ return (React.createElement(Dialog, { ...dialogProps },
14
+ React.createElement(DialogNavButtons, { id: id, fullScreen: fullScreen, onClose: props.onClose, onBack: props.onBack }),
15
+ title && (React.createElement(React.Fragment, null,
16
+ React.createElement(DialogTitle, { ...dialogTitleProps }, title),
17
+ React.createElement(Divider, { ...dividerProps }))),
18
+ React.createElement(DialogContent, { ...dialogContentProps },
19
+ React.createElement(DialogFluidContent, { content: content, actions: actions, actionsLayout: actionsLayout, dialogActionsProps: dialogActionsProps }))));
20
+ };
21
+ export default StandardDialog;
@@ -0,0 +1,25 @@
1
+ {
2
+ "Dialogs": {
3
+ "closeButton": "Schließen",
4
+ "backButton": "Zurück",
5
+ "installFlagshipApp": {
6
+ "title": "Scannen Sie den QR-Code",
7
+ "text": "oder öffnen Sie direkt den <img src=%{iosIconSrc} /> <a href='%{iosUrl}' class='u-link' target='_blank' rel='noopener'>App Store</a><br>oder den <img src=%{androidIconSrc} /> <a href='%{androidUrl}' class='u-link' target='_blank' rel='noopener'>Play Store</a>, um die App Twake Workplace zu installieren",
8
+ "linkLabel": "Zur Downloadseite der Anwendung Twake Workplace"
9
+ },
10
+ "shortcut": {
11
+ "createTitle": "Verknüpfung erstellen",
12
+ "editTitle": "Verknüpfung bearbeiten",
13
+ "filename": "Name der Verknüpfung",
14
+ "url": "URL",
15
+ "cancel": "Abbrechen",
16
+ "create": "Erstellen",
17
+ "edit": "Speichern",
18
+ "created": "Die Verknüpfung wurde erstellt",
19
+ "edited": "Die Verknüpfung wurde geändert",
20
+ "errored": "Ein Fehler ist aufgetreten",
21
+ "needsInfo": "Eine Verknüpfung benötigt einen Namen und eine URL",
22
+ "urlBadFormat": "Die eingegebene URL hat nicht das richtige Format"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "Dialogs": {
3
+ "closeButton": "Close",
4
+ "backButton": "Back",
5
+ "installFlagshipApp": {
6
+ "title": "Scan the QR Code",
7
+ "text": "or go directly to the <img src=%{iosIconSrc} /> <a href='%{iosUrl}' class='u-link' target='_blank' rel='noopener'>App Store</a><br>or <img src=%{androidIconSrc} /> <a href='%{androidUrl}' class='u-link' target='_blank' rel='noopener'>Play Store</a> to install the Twake Workplace app",
8
+ "linkLabel": "Go to the Twake Workplace application download page"
9
+ },
10
+ "shortcut": {
11
+ "createTitle": "Create a shortcut",
12
+ "editTitle": "Modify a shortcut",
13
+ "filename": "Shortcut name",
14
+ "url": "URL",
15
+ "cancel": "Cancel",
16
+ "create": "Create",
17
+ "edit": "Save",
18
+ "created": "The shortcut has been created",
19
+ "edited": "The shortcut has been modified",
20
+ "errored": "An error occurred",
21
+ "needsInfo": "A shortcut needs a name and a URL",
22
+ "urlBadFormat": "The entered URL is not in the correct format"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "Dialogs": {
3
+ "closeButton": "Cerrar",
4
+ "backButton": "Atrás",
5
+ "installFlagshipApp": {
6
+ "title": "Escanee el código QR",
7
+ "text": "o vaya directamente a <img src=%{iosIconSrc} /> <a href='%{iosUrl}' class='u-link' target='_blank' rel='noopener'>App Store</a><br>o a <img src=%{androidIconSrc} /> <a href='%{androidUrl}' class='u-link' target='_blank' rel='noopener'>Play Store</a> para instalar la app Twake Workplace",
8
+ "linkLabel": "Ir a la página de descarga de la aplicación Twake Workplace"
9
+ },
10
+ "shortcut": {
11
+ "createTitle": "Crear un acceso directo",
12
+ "editTitle": "Modificar un acceso directo",
13
+ "filename": "Nombre del acceso directo",
14
+ "url": "URL",
15
+ "cancel": "Cancelar",
16
+ "create": "Crear",
17
+ "edit": "Guardar",
18
+ "created": "Se ha creado el acceso directo",
19
+ "edited": "Se ha modificado el acceso directo",
20
+ "errored": "Se ha producido un error",
21
+ "needsInfo": "Un acceso directo necesita un nombre y una URL",
22
+ "urlBadFormat": "La URL introducida no tiene el formato correcto"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "Dialogs": {
3
+ "closeButton": "Fermer",
4
+ "backButton": "Retour",
5
+ "installFlagshipApp": {
6
+ "title": "Scannez le QR Code",
7
+ "text": "ou rendez vous directement sur <img src=%{iosIconSrc} /> <a href='%{iosUrl}' class='u-link' target='_blank' rel='noopener'>l’App Store</a><br>ou sur le <img src=%{androidIconSrc} /> <a href='%{androidUrl}' class='u-link' target='_blank' rel='noopener'>Play Store</a> pour installer l’app Twake Workplace",
8
+ "linkLabel": "Aller sur la page de téléchargement de l'application Twake Workplace"
9
+ },
10
+ "shortcut": {
11
+ "createTitle": "Créer un raccourci",
12
+ "editTitle": "Modifier un raccourci",
13
+ "filename": "Nom du raccourci",
14
+ "url": "URL",
15
+ "cancel": "Annuler",
16
+ "create": "Créer",
17
+ "edit": "Sauvegarder",
18
+ "created": "Le raccourci a été créé",
19
+ "edited": "Le raccourci a été modifié",
20
+ "errored": "Une erreur s'est produite",
21
+ "needsInfo": "Un raccourci a besoin d'un nom et d'une URL",
22
+ "urlBadFormat": "L'URL saisie n'est pas dans le bon format"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,177 @@
1
+ export declare const locales: {
2
+ de: {
3
+ Dialogs: {
4
+ closeButton: string;
5
+ backButton: string;
6
+ installFlagshipApp: {
7
+ title: string;
8
+ text: string;
9
+ linkLabel: string;
10
+ };
11
+ shortcut: {
12
+ createTitle: string;
13
+ editTitle: string;
14
+ filename: string;
15
+ url: string;
16
+ cancel: string;
17
+ create: string;
18
+ edit: string;
19
+ created: string;
20
+ edited: string;
21
+ errored: string;
22
+ needsInfo: string;
23
+ urlBadFormat: string;
24
+ };
25
+ };
26
+ };
27
+ en: {
28
+ Dialogs: {
29
+ closeButton: string;
30
+ backButton: string;
31
+ installFlagshipApp: {
32
+ title: string;
33
+ text: string;
34
+ linkLabel: string;
35
+ };
36
+ shortcut: {
37
+ createTitle: string;
38
+ editTitle: string;
39
+ filename: string;
40
+ url: string;
41
+ cancel: string;
42
+ create: string;
43
+ edit: string;
44
+ created: string;
45
+ edited: string;
46
+ errored: string;
47
+ needsInfo: string;
48
+ urlBadFormat: string;
49
+ };
50
+ };
51
+ };
52
+ es: {
53
+ Dialogs: {
54
+ closeButton: string;
55
+ backButton: string;
56
+ installFlagshipApp: {
57
+ title: string;
58
+ text: string;
59
+ linkLabel: string;
60
+ };
61
+ shortcut: {
62
+ createTitle: string;
63
+ editTitle: string;
64
+ filename: string;
65
+ url: string;
66
+ cancel: string;
67
+ create: string;
68
+ edit: string;
69
+ created: string;
70
+ edited: string;
71
+ errored: string;
72
+ needsInfo: string;
73
+ urlBadFormat: string;
74
+ };
75
+ };
76
+ };
77
+ fr: {
78
+ Dialogs: {
79
+ closeButton: string;
80
+ backButton: string;
81
+ installFlagshipApp: {
82
+ title: string;
83
+ text: string;
84
+ linkLabel: string;
85
+ };
86
+ shortcut: {
87
+ createTitle: string;
88
+ editTitle: string;
89
+ filename: string;
90
+ url: string;
91
+ cancel: string;
92
+ create: string;
93
+ edit: string;
94
+ created: string;
95
+ edited: string;
96
+ errored: string;
97
+ needsInfo: string;
98
+ urlBadFormat: string;
99
+ };
100
+ };
101
+ };
102
+ it: {
103
+ Dialogs: {
104
+ closeButton: string;
105
+ backButton: string;
106
+ installFlagshipApp: {
107
+ title: string;
108
+ text: string;
109
+ linkLabel: string;
110
+ };
111
+ shortcut: {
112
+ createTitle: string;
113
+ editTitle: string;
114
+ filename: string;
115
+ url: string;
116
+ cancel: string;
117
+ create: string;
118
+ edit: string;
119
+ created: string;
120
+ edited: string;
121
+ errored: string;
122
+ needsInfo: string;
123
+ urlBadFormat: string;
124
+ };
125
+ };
126
+ };
127
+ ru: {
128
+ Dialogs: {
129
+ closeButton: string;
130
+ backButton: string;
131
+ installFlagshipApp: {
132
+ title: string;
133
+ text: string;
134
+ linkLabel: string;
135
+ };
136
+ shortcut: {
137
+ createTitle: string;
138
+ editTitle: string;
139
+ filename: string;
140
+ url: string;
141
+ cancel: string;
142
+ create: string;
143
+ edit: string;
144
+ created: string;
145
+ edited: string;
146
+ errored: string;
147
+ needsInfo: string;
148
+ urlBadFormat: string;
149
+ };
150
+ };
151
+ };
152
+ vi: {
153
+ Dialogs: {
154
+ closeButton: string;
155
+ backButton: string;
156
+ installFlagshipApp: {
157
+ title: string;
158
+ text: string;
159
+ linkLabel: string;
160
+ };
161
+ shortcut: {
162
+ createTitle: string;
163
+ editTitle: string;
164
+ filename: string;
165
+ url: string;
166
+ cancel: string;
167
+ create: string;
168
+ edit: string;
169
+ created: string;
170
+ edited: string;
171
+ errored: string;
172
+ needsInfo: string;
173
+ urlBadFormat: string;
174
+ };
175
+ };
176
+ };
177
+ };
@@ -0,0 +1,8 @@
1
+ import de from './de.json';
2
+ import en from './en.json';
3
+ import es from './es.json';
4
+ import fr from './fr.json';
5
+ import it from './it.json';
6
+ import ru from './ru.json';
7
+ import vi from './vi.json';
8
+ export const locales = { de, en, es, fr, it, ru, vi };
@@ -0,0 +1,25 @@
1
+ {
2
+ "Dialogs": {
3
+ "closeButton": "Chiudi",
4
+ "backButton": "Indietro",
5
+ "installFlagshipApp": {
6
+ "title": "Scansiona il codice QR",
7
+ "text": "oppure vai direttamente su <img src=%{iosIconSrc} /> <a href='%{iosUrl}' class='u-link' target='_blank' rel='noopener'>App Store</a><br>o su <img src=%{androidIconSrc} /> <a href='%{androidUrl}' class='u-link' target='_blank' rel='noopener'>Play Store</a> per installare l'app Twake Workplace",
8
+ "linkLabel": "Vai alla pagina di download dell'applicazione Twake Workplace"
9
+ },
10
+ "shortcut": {
11
+ "createTitle": "Crea un collegamento",
12
+ "editTitle": "Modifica un collegamento",
13
+ "filename": "Nome del collegamento",
14
+ "url": "URL",
15
+ "cancel": "Annulla",
16
+ "create": "Crea",
17
+ "edit": "Salva",
18
+ "created": "Il collegamento è stato creato",
19
+ "edited": "Il collegamento è stato modificato",
20
+ "errored": "Si è verificato un errore",
21
+ "needsInfo": "Un collegamento richiede un nome e un URL",
22
+ "urlBadFormat": "L'URL inserito non è nel formato corretto"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "Dialogs": {
3
+ "closeButton": "Закрыть",
4
+ "backButton": "Назад",
5
+ "installFlagshipApp": {
6
+ "title": "Отсканируйте QR-код",
7
+ "text": "или перейдите напрямую в <img src=%{iosIconSrc} /> <a href='%{iosUrl}' class='u-link' target='_blank' rel='noopener'>App Store</a><br>или <img src=%{androidIconSrc} /> <a href='%{androidUrl}' class='u-link' target='_blank' rel='noopener'>Play Store</a> чтобы установить приложение Twake Workplace",
8
+ "linkLabel": "Перейти на страницу загрузки приложения Twake Workplace"
9
+ },
10
+ "shortcut": {
11
+ "createTitle": "Создать ярлык",
12
+ "editTitle": "Изменить ярлык",
13
+ "filename": "Имя ярлыка",
14
+ "url": "URL",
15
+ "cancel": "Отменить",
16
+ "create": "Создать",
17
+ "edit": "Сохранить",
18
+ "created": "Ярлык был создан",
19
+ "edited": "Ярлык был изменен",
20
+ "errored": "Произошла ошибка",
21
+ "needsInfo": "Для ярлыка нужны имя и URL",
22
+ "urlBadFormat": "Введённый URL имеет неверный формат"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "Dialogs": {
3
+ "closeButton": "Đóng",
4
+ "backButton": "Quay lại",
5
+ "installFlagshipApp": {
6
+ "title": "Quét mã QR",
7
+ "text": "hoặc trực tiếp đến <img src=%{iosIconSrc} /> <a href='%{iosUrl}' class='u-link' target='_blank' rel='noopener'>App Store</a><br>hoặc <img src=%{androidIconSrc} /> <a href='%{androidUrl}' class='u-link' target='_blank' rel='noopener'>Play Store</a> để cài đặt ứng dụng Twake Workplace",
8
+ "linkLabel": "Đến trang tải xuống ứng dụng Twake Workplace"
9
+ },
10
+ "shortcut": {
11
+ "createTitle": "Tạo lối tắt",
12
+ "editTitle": "Chỉnh sửa lối tắt",
13
+ "filename": "Tên lối tắt",
14
+ "url": "URL",
15
+ "cancel": "Hủy",
16
+ "create": "Tạo",
17
+ "edit": "Lưu",
18
+ "created": "Lối tắt đã được tạo",
19
+ "edited": "Lối tắt đã được chỉnh sửa",
20
+ "errored": "Đã xảy ra lỗi",
21
+ "needsInfo": "Lối tắt cần có tên và URL",
22
+ "urlBadFormat": "URL đã nhập không đúng định dạng"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,19 @@
1
+ import type { ShowAlert } from '../../providers/AlertProvider/useAlert';
2
+ export declare const isValidUrl: (url: string) => boolean;
3
+ /** Returns the URL, prefixed with `https://` when it lacks a protocol, or `null` when it stays invalid */
4
+ export declare const makeValidUrl: (url: string) => string | null;
5
+ export declare const makeValidFileName: (fileName: string) => string;
6
+ export declare const makeHumanReadableFileName: (fileName: string) => string;
7
+ export type SaveShortcut = (fileName: string, url: string) => void | Promise<void>;
8
+ interface CheckAndSaveShortcutOptions {
9
+ fileName: string;
10
+ url: string;
11
+ isEditing: boolean;
12
+ onSave: SaveShortcut;
13
+ onClose: () => void;
14
+ showAlert: ShowAlert;
15
+ t: (key: string) => string;
16
+ }
17
+ /** Saves the shortcut once its name and URL are valid, and reports the outcome in an alert */
18
+ export declare const checkAndSaveShortcut: ({ fileName, url, isEditing, onSave, onClose, showAlert, t }: CheckAndSaveShortcutOptions) => Promise<void>;
19
+ export {};
@@ -0,0 +1,49 @@
1
+ const SHORTCUT_EXTENSION = '.url';
2
+ export const isValidUrl = (url) => {
3
+ try {
4
+ return Boolean(new URL(url));
5
+ }
6
+ catch {
7
+ return false;
8
+ }
9
+ };
10
+ /** Returns the URL, prefixed with `https://` when it lacks a protocol, or `null` when it stays invalid */
11
+ export const makeValidUrl = (url) => {
12
+ if (isValidUrl(url))
13
+ return url;
14
+ if (isValidUrl(`https://${url}`))
15
+ return `https://${url}`;
16
+ return null;
17
+ };
18
+ export const makeValidFileName = (fileName) => fileName.endsWith(SHORTCUT_EXTENSION)
19
+ ? fileName
20
+ : `${fileName}${SHORTCUT_EXTENSION}`;
21
+ export const makeHumanReadableFileName = (fileName) => fileName.endsWith(SHORTCUT_EXTENSION)
22
+ ? fileName.slice(0, -SHORTCUT_EXTENSION.length)
23
+ : fileName;
24
+ /** Saves the shortcut once its name and URL are valid, and reports the outcome in an alert */
25
+ export const checkAndSaveShortcut = async ({ fileName, url, isEditing, onSave, onClose, showAlert, t }) => {
26
+ if (!fileName || !url) {
27
+ showAlert({ message: t('Dialogs.shortcut.needsInfo'), severity: 'error' });
28
+ return;
29
+ }
30
+ const validUrl = makeValidUrl(url);
31
+ if (!validUrl) {
32
+ showAlert({
33
+ message: t('Dialogs.shortcut.urlBadFormat'),
34
+ severity: 'error'
35
+ });
36
+ return;
37
+ }
38
+ try {
39
+ await onSave(makeValidFileName(fileName), validUrl);
40
+ showAlert({
41
+ message: t(isEditing ? 'Dialogs.shortcut.edited' : 'Dialogs.shortcut.created'),
42
+ severity: 'success'
43
+ });
44
+ }
45
+ catch {
46
+ showAlert({ message: t('Dialogs.shortcut.errored'), severity: 'error' });
47
+ }
48
+ onClose();
49
+ };
@@ -0,0 +1,7 @@
1
+ import type React from 'react';
2
+ export interface DialogSectionsProps {
3
+ title?: React.ReactNode;
4
+ content?: React.ReactNode;
5
+ actions?: React.ReactNode;
6
+ actionsLayout?: 'row' | 'column';
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ import { DialogActionsProps, DialogContentProps, DialogTitleProps, DividerProps } from '@mui/material';
2
+ import React from 'react';
3
+ import type { DialogProps } from '../Dialog';
4
+ export type DialogCloseReason = 'backdropClick' | 'escapeKeyDown';
5
+ export interface DialogLayoutComponentsProps {
6
+ dialogTitle?: DialogTitleProps;
7
+ divider?: DividerProps;
8
+ dialogActions?: DialogActionsProps;
9
+ dialogContent?: DialogContentProps;
10
+ }
11
+ export interface DialogLayoutProps extends Omit<DialogProps, 'title' | 'content' | 'onClose'> {
12
+ /** Called without a reason when the close or back button is clicked */
13
+ onClose?: (event: object, reason?: DialogCloseReason) => void;
14
+ /** Shows a back button. On full screen, it replaces the close button */
15
+ onBack?: React.MouseEventHandler<HTMLButtonElement>;
16
+ align?: 'top' | 'middle';
17
+ /** Lets the title run under the close and back buttons */
18
+ disableTitleAutoPadding?: boolean;
19
+ /** Lets the title wrap and scroll with the content */
20
+ isFluidTitle?: boolean;
21
+ /** Removes the paddings around the content */
22
+ disableGutters?: boolean;
23
+ titleRef?: React.Ref<HTMLHeadingElement>;
24
+ /** CSS `background` of the dialog paper */
25
+ background?: string;
26
+ componentsProps?: DialogLayoutComponentsProps;
27
+ }
28
+ export interface DialogLayout {
29
+ id: string;
30
+ fullScreen: boolean;
31
+ dialogProps: DialogProps;
32
+ dialogTitleProps: DialogTitleProps & {
33
+ ref?: React.Ref<HTMLHeadingElement>;
34
+ };
35
+ dividerProps: DividerProps;
36
+ dialogActionsProps: DialogActionsProps;
37
+ dialogContentProps: DialogContentProps;
38
+ }
39
+ /** Computes the props of a dialog and of its parts, for dialogs laid out with a title, a content and actions */
40
+ export declare const useDialogLayout: ({ size, fullScreen: fullScreenProp, onClose, onBack, align, disableTitleAutoPadding, isFluidTitle, disableGutters, titleRef, background, componentsProps, classes, slots, slotProps, ...props }: DialogLayoutProps) => DialogLayout;