@payload-enchants/translator 0.0.1-alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/README.md +193 -0
- package/dist/client/api/index.d.ts +8 -0
- package/dist/client/api/index.d.ts.map +1 -0
- package/dist/client/api/index.js +28 -0
- package/dist/client/api/index.js.map +1 -0
- package/dist/client/components/CustomSaveButton/CustomSaveButton.d.ts +4 -0
- package/dist/client/components/CustomSaveButton/CustomSaveButton.d.ts.map +1 -0
- package/dist/client/components/CustomSaveButton/CustomSaveButton.js +22 -0
- package/dist/client/components/CustomSaveButton/CustomSaveButton.js.map +1 -0
- package/dist/client/components/CustomSaveButton/index.d.ts +2 -0
- package/dist/client/components/CustomSaveButton/index.d.ts.map +1 -0
- package/dist/client/components/CustomSaveButton/index.js +3 -0
- package/dist/client/components/CustomSaveButton/index.js.map +1 -0
- package/dist/client/components/CustomSaveButton/styles.scss +5 -0
- package/dist/client/components/LocaleLabel/LocaleLabel.d.ts +6 -0
- package/dist/client/components/LocaleLabel/LocaleLabel.d.ts.map +1 -0
- package/dist/client/components/LocaleLabel/LocaleLabel.js +19 -0
- package/dist/client/components/LocaleLabel/LocaleLabel.js.map +1 -0
- package/dist/client/components/LocaleLabel/index.d.ts +2 -0
- package/dist/client/components/LocaleLabel/index.d.ts.map +1 -0
- package/dist/client/components/LocaleLabel/index.js +3 -0
- package/dist/client/components/LocaleLabel/index.js.map +1 -0
- package/dist/client/components/ResolverButton/ResolverButton.d.ts +6 -0
- package/dist/client/components/ResolverButton/ResolverButton.d.ts.map +1 -0
- package/dist/client/components/ResolverButton/ResolverButton.js +16 -0
- package/dist/client/components/ResolverButton/ResolverButton.js.map +1 -0
- package/dist/client/components/ResolverButton/index.d.ts +2 -0
- package/dist/client/components/ResolverButton/index.d.ts.map +1 -0
- package/dist/client/components/ResolverButton/index.js +3 -0
- package/dist/client/components/ResolverButton/index.js.map +1 -0
- package/dist/client/components/TranslatorModal/Content.d.ts +3 -0
- package/dist/client/components/TranslatorModal/Content.d.ts.map +1 -0
- package/dist/client/components/TranslatorModal/Content.js +42 -0
- package/dist/client/components/TranslatorModal/Content.js.map +1 -0
- package/dist/client/components/TranslatorModal/TranslatorModal.d.ts +4 -0
- package/dist/client/components/TranslatorModal/TranslatorModal.d.ts.map +1 -0
- package/dist/client/components/TranslatorModal/TranslatorModal.js +21 -0
- package/dist/client/components/TranslatorModal/TranslatorModal.js.map +1 -0
- package/dist/client/components/TranslatorModal/index.d.ts +2 -0
- package/dist/client/components/TranslatorModal/index.d.ts.map +1 -0
- package/dist/client/components/TranslatorModal/index.js +3 -0
- package/dist/client/components/TranslatorModal/index.js.map +1 -0
- package/dist/client/components/TranslatorModal/styles.scss +76 -0
- package/dist/client/providers/Translator/TranslatorProvider.d.ts +5 -0
- package/dist/client/providers/Translator/TranslatorProvider.d.ts.map +1 -0
- package/dist/client/providers/Translator/TranslatorProvider.js +100 -0
- package/dist/client/providers/Translator/TranslatorProvider.js.map +1 -0
- package/dist/client/providers/Translator/context.d.ts +22 -0
- package/dist/client/providers/Translator/context.d.ts.map +1 -0
- package/dist/client/providers/Translator/context.js +9 -0
- package/dist/client/providers/Translator/context.js.map +1 -0
- package/dist/i18n-translations.d.ts +25 -0
- package/dist/i18n-translations.d.ts.map +1 -0
- package/dist/i18n-translations.js +26 -0
- package/dist/i18n-translations.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/resolvers/copy.d.ts +3 -0
- package/dist/resolvers/copy.d.ts.map +1 -0
- package/dist/resolvers/copy.js +14 -0
- package/dist/resolvers/copy.js.map +1 -0
- package/dist/resolvers/google.d.ts +11 -0
- package/dist/resolvers/google.d.ts.map +1 -0
- package/dist/resolvers/google.js +47 -0
- package/dist/resolvers/google.js.map +1 -0
- package/dist/resolvers/openAI.d.ts +21 -0
- package/dist/resolvers/openAI.d.ts.map +1 -0
- package/dist/resolvers/openAI.js +97 -0
- package/dist/resolvers/openAI.js.map +1 -0
- package/dist/resolvers/types.d.ts +20 -0
- package/dist/resolvers/types.d.ts.map +1 -0
- package/dist/resolvers/types.js +3 -0
- package/dist/resolvers/types.js.map +1 -0
- package/dist/translate/endpoint.d.ts +3 -0
- package/dist/translate/endpoint.d.ts.map +1 -0
- package/dist/translate/endpoint.js +22 -0
- package/dist/translate/endpoint.js.map +1 -0
- package/dist/translate/findEntityWithConfig.d.ts +15 -0
- package/dist/translate/findEntityWithConfig.d.ts.map +1 -0
- package/dist/translate/findEntityWithConfig.js +32 -0
- package/dist/translate/findEntityWithConfig.js.map +1 -0
- package/dist/translate/operation.d.ts +9 -0
- package/dist/translate/operation.d.ts.map +1 -0
- package/dist/translate/operation.js +74 -0
- package/dist/translate/operation.js.map +1 -0
- package/dist/translate/traverseFields.d.ts +13 -0
- package/dist/translate/traverseFields.d.ts.map +1 -0
- package/dist/translate/traverseFields.js +160 -0
- package/dist/translate/traverseFields.js.map +1 -0
- package/dist/translate/traverseRichText.d.ts +6 -0
- package/dist/translate/traverseRichText.d.ts.map +1 -0
- package/dist/translate/traverseRichText.js +17 -0
- package/dist/translate/traverseRichText.js.map +1 -0
- package/dist/translate/types.d.ts +25 -0
- package/dist/translate/types.d.ts.map +1 -0
- package/dist/translate/types.js +3 -0
- package/dist/translate/types.js.map +1 -0
- package/dist/translate/updateEntity.d.ts +14 -0
- package/dist/translate/updateEntity.d.ts.map +1 -0
- package/dist/translate/updateEntity.js +26 -0
- package/dist/translate/updateEntity.js.map +1 -0
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/chunkArray.d.ts +2 -0
- package/dist/utils/chunkArray.d.ts.map +1 -0
- package/dist/utils/chunkArray.js +7 -0
- package/dist/utils/chunkArray.js.map +1 -0
- package/dist/utils/isEmpty.d.ts +2 -0
- package/dist/utils/isEmpty.d.ts.map +1 -0
- package/dist/utils/isEmpty.js +8 -0
- package/dist/utils/isEmpty.js.map +1 -0
- package/package.json +75 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Ritsu / Sasha Rakhmatulin
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# Translator plugin for Payload 3.0 (beta)
|
2
|
+
|
3
|
+
## Install
|
4
|
+
|
5
|
+
`pnpm add @payload-enchants/translator`
|
6
|
+
|
7
|
+
## Video
|
8
|
+
|
9
|
+
https://github.com/r1tsuu/payload-plugin-translator/assets/64744993/d39aeba4-bafc-4c3b-838e-9abc5cf1d64a
|
10
|
+
|
11
|
+
## Features:
|
12
|
+
|
13
|
+
1. A flexible structure with [resolvers](https://github.com/r1tsuu/payload-plugin-translator/tree/6d0c8098467f9b5e757bf9fd8cfe63ff5da68d5b/plugin/src/resolvers) that allows you to apply any kind of transformation to your localizated data.
|
14
|
+
2. Can be used not only from the admin panel, but within Local API as well. [Example of the hook](#example-of-the-hook-that-uses-local-operation-to-copy-the-doc-data-to-other-locales) that automatically fills the other locales data on create
|
15
|
+
3. Out of the box supports 3 resolvers - Copy, Google Translate, OpenAI and your own can be written easily.
|
16
|
+
4. Works with any nested document structure and 2 Rich Text editor adapters - Lexical and Slate.
|
17
|
+
|
18
|
+
## Usage:
|
19
|
+
|
20
|
+
```ts
|
21
|
+
import { buildConfig } from 'payload/config';
|
22
|
+
import { translator } from '@payload-enchants/translator';
|
23
|
+
import { copyResolver } from '@payload-enchants/translator/resolvers/copy';
|
24
|
+
import { googleResolver } from '@payload-enchants/translator/resolvers/google';
|
25
|
+
import { openAIResolver } from '@payload-enchants/translator/resolvers/openAI';
|
26
|
+
|
27
|
+
export default buildConfig({
|
28
|
+
plugins: [
|
29
|
+
translator({
|
30
|
+
// collections with the enabled translator in the admin UI
|
31
|
+
collections: ['posts', 'small-posts'],
|
32
|
+
// globals with the enabled translator in the admin UI
|
33
|
+
globals: [],
|
34
|
+
// add resolvers that you want to include, examples on how to write your own in ./plugin/src/resolvers
|
35
|
+
resolvers: [
|
36
|
+
copyResolver(),
|
37
|
+
googleResolver({
|
38
|
+
apiKey: process.env.GOOGLE_API_KEY!,
|
39
|
+
}),
|
40
|
+
openAIResolver({
|
41
|
+
apiKey: process.env.OPENAI_KEY!,
|
42
|
+
}),
|
43
|
+
],
|
44
|
+
}),
|
45
|
+
],
|
46
|
+
});
|
47
|
+
```
|
48
|
+
|
49
|
+
## Resolvers
|
50
|
+
|
51
|
+
### OpenAI
|
52
|
+
|
53
|
+
#### Config:
|
54
|
+
|
55
|
+
```ts
|
56
|
+
export type OpenAIResolverConfig = {
|
57
|
+
apiKey: string; // API key
|
58
|
+
chunkLength?: number; // How many texts to include into 1 request, default: 100
|
59
|
+
model?: string; // model, default: 'gpt-3.5-turbo'
|
60
|
+
promt?: OpenAIPrompt; // custom prompt
|
61
|
+
};
|
62
|
+
```
|
63
|
+
|
64
|
+
### Custom prompt:
|
65
|
+
|
66
|
+
```ts
|
67
|
+
export type OpenAIPrompt = (args: {
|
68
|
+
localeFrom: string;
|
69
|
+
localeTo: string;
|
70
|
+
texts: string[];
|
71
|
+
}) => string;
|
72
|
+
|
73
|
+
// Default
|
74
|
+
const defaultPromt: OpenAIPrompt = ({ localeFrom, localeTo, texts }) => {
|
75
|
+
return `Translate me the following array: ${JSON.stringify(texts)} in locale=${localeFrom} to locale ${localeTo}, respond me with the same array structure`;
|
76
|
+
};
|
77
|
+
```
|
78
|
+
|
79
|
+
### Google
|
80
|
+
|
81
|
+
#### Config:
|
82
|
+
|
83
|
+
```ts
|
84
|
+
export type GoogleResolverConfig = {
|
85
|
+
apiKey: string; // API key
|
86
|
+
chunkLength?: number; / /How many texts to include into 1 request, default: 100
|
87
|
+
};
|
88
|
+
```
|
89
|
+
|
90
|
+
### Writing your own
|
91
|
+
|
92
|
+
```ts
|
93
|
+
import type { TranslateResolver } from '@payload-enchants/translator/resolvers/types';
|
94
|
+
|
95
|
+
const myResolver: TranslateResolver = {
|
96
|
+
key: 'my',
|
97
|
+
resolve: async (args) => {
|
98
|
+
const { localeFrom, localeTo, req, texts } = args;
|
99
|
+
// here you can apply any kind of transformation to incoming texts, could be as well API call to a service.
|
100
|
+
const transformed = texts.map((each) => `${each} translated to ${localeTo}`);
|
101
|
+
|
102
|
+
return {
|
103
|
+
success: true,
|
104
|
+
translatedTexts: transformed,
|
105
|
+
};
|
106
|
+
},
|
107
|
+
};
|
108
|
+
|
109
|
+
export default buildConfig({
|
110
|
+
plugins: [
|
111
|
+
payloadPluginTranslator({
|
112
|
+
collections: ['posts', 'small-posts'],
|
113
|
+
globals: [],
|
114
|
+
resolvers: [myResolver],
|
115
|
+
}),
|
116
|
+
],
|
117
|
+
// apply translations that will be used for your resolver in the admin UI
|
118
|
+
i18n: {
|
119
|
+
supportedLanguages: { en },
|
120
|
+
translations: {
|
121
|
+
en: {
|
122
|
+
'plugin-translator': {
|
123
|
+
resolver_my_buttonLabel: 'Google Translate',
|
124
|
+
resolver_my_errorMessage: 'An error occurred when trying to translate the data',
|
125
|
+
resolver_my_modalTitle: 'Choose the locale to translate from',
|
126
|
+
resolver_my_submitButtonLabelEmpty: 'Translate only empty fields',
|
127
|
+
resolver_my_submitButtonLabelFull: 'Translate all',
|
128
|
+
resolver_my_successMessage: 'Successfully translated. Press "Save" to apply the changes.',
|
129
|
+
},
|
130
|
+
},
|
131
|
+
},
|
132
|
+
},
|
133
|
+
});
|
134
|
+
```
|
135
|
+
|
136
|
+
## Using the Local API
|
137
|
+
|
138
|
+
```ts
|
139
|
+
import { translateOperation } from '@payload-enchants/translator';
|
140
|
+
|
141
|
+
const translateResult = await translateOperation({
|
142
|
+
collectionSlug: 'posts', // or globalSlug if globals,
|
143
|
+
emptyOnly: false, // optional, should translate all the fields values or only fields that are empty, by default false.
|
144
|
+
id: postDefaultLocale.id, // pass the doc id if it's a collection
|
145
|
+
locale: 'de', // locale to translate to
|
146
|
+
localeFrom: 'en', // locale to translate from
|
147
|
+
payload, // payload instance, you can get it with getPayload or req.payload in hooks
|
148
|
+
req, // PayloadRequest, can be used instead of payload, more appreciable than payload if you have it
|
149
|
+
overrideAccess: false, //
|
150
|
+
resolver: 'copy', // pass resolver key
|
151
|
+
update: true, // optional, should update immediately or just return the translated result, default false
|
152
|
+
data: {}, // Optional, if you want to translate from your data passed here instead of the current doc, should be in "localeFrom" locale, for example { title: "Hello" }
|
153
|
+
});
|
154
|
+
```
|
155
|
+
|
156
|
+
### Example of the hook that uses local operation to copy the doc data to other locales
|
157
|
+
|
158
|
+
```ts
|
159
|
+
import type { CollectionAfterChangeHook } from 'payload/types';
|
160
|
+
import { translateOperation } from '@payload-enchants/translator';
|
161
|
+
|
162
|
+
export const copyOtherLocales: CollectionAfterChangeHook = async ({
|
163
|
+
collection,
|
164
|
+
doc,
|
165
|
+
operation,
|
166
|
+
req,
|
167
|
+
}) => {
|
168
|
+
if (operation !== 'create') return;
|
169
|
+
|
170
|
+
const locale = req.locale;
|
171
|
+
|
172
|
+
if (!locale || !req.payload.config.localization) return;
|
173
|
+
|
174
|
+
const otherLocales = req.payload.config.localization.locales.filter(
|
175
|
+
(each) => each.code !== locale,
|
176
|
+
);
|
177
|
+
|
178
|
+
const { id } = doc;
|
179
|
+
|
180
|
+
for (const { code } of otherLocales) {
|
181
|
+
await translateOperation({
|
182
|
+
collectionSlug: collection.slug,
|
183
|
+
data: doc,
|
184
|
+
id,
|
185
|
+
locale: code,
|
186
|
+
localeFrom: locale,
|
187
|
+
req,
|
188
|
+
resolver: 'copy',
|
189
|
+
update: true,
|
190
|
+
});
|
191
|
+
}
|
192
|
+
};
|
193
|
+
```
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import type { TranslateEndpointArgs, TranslateResult } from '../../translate/types';
|
2
|
+
export declare const createClient: ({ api, serverURL }: {
|
3
|
+
api: string;
|
4
|
+
serverURL: string;
|
5
|
+
}) => {
|
6
|
+
translate: (args: TranslateEndpointArgs) => Promise<TranslateResult>;
|
7
|
+
};
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEpF,eAAO,MAAM,YAAY,uBAAwB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;sBAClD,qBAAqB,KAAG,QAAQ,eAAe,CAAC;CAwBhF,CAAC"}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
export const createClient = ({ api, serverURL })=>{
|
2
|
+
const translate = async (args)=>{
|
3
|
+
try {
|
4
|
+
const response = await fetch(`${serverURL}${api}/translator/translate`, {
|
5
|
+
body: JSON.stringify(args),
|
6
|
+
credentials: 'include',
|
7
|
+
headers: {
|
8
|
+
'Content-Type': 'application/json'
|
9
|
+
},
|
10
|
+
method: 'POST'
|
11
|
+
});
|
12
|
+
if (!response.ok) return {
|
13
|
+
success: false
|
14
|
+
};
|
15
|
+
return response.json();
|
16
|
+
} catch (e) {
|
17
|
+
if (e instanceof Error) console.error(e.message);
|
18
|
+
return {
|
19
|
+
success: false
|
20
|
+
};
|
21
|
+
}
|
22
|
+
};
|
23
|
+
return {
|
24
|
+
translate
|
25
|
+
};
|
26
|
+
};
|
27
|
+
|
28
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../src/client/api/index.ts"],"sourcesContent":["import type { TranslateEndpointArgs, TranslateResult } from '../../translate/types';\r\n\r\nexport const createClient = ({ api, serverURL }: { api: string; serverURL: string }) => {\r\n const translate = async (args: TranslateEndpointArgs): Promise<TranslateResult> => {\r\n try {\r\n const response = await fetch(`${serverURL}${api}/translator/translate`, {\r\n body: JSON.stringify(args),\r\n credentials: 'include',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n method: 'POST',\r\n });\r\n\r\n if (!response.ok) return { success: false };\r\n\r\n return response.json();\r\n } catch (e) {\r\n if (e instanceof Error) console.error(e.message);\r\n\r\n return { success: false };\r\n }\r\n };\r\n\r\n return {\r\n translate,\r\n };\r\n};\r\n"],"names":["createClient","api","serverURL","translate","args","response","fetch","body","JSON","stringify","credentials","headers","method","ok","success","json","e","Error","console","error","message"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAEA,OAAO,MAAMA,eAAe,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAsC;IACjF,MAAMC,YAAY,OAAOC;QACvB,IAAI;YACF,MAAMC,WAAW,MAAMC,MAAM,CAAC,EAAEJ,UAAU,EAAED,IAAI,qBAAqB,CAAC,EAAE;gBACtEM,MAAMC,KAAKC,SAAS,CAACL;gBACrBM,aAAa;gBACbC,SAAS;oBACP,gBAAgB;gBAClB;gBACAC,QAAQ;YACV;YAEA,IAAI,CAACP,SAASQ,EAAE,EAAE,OAAO;gBAAEC,SAAS;YAAM;YAE1C,OAAOT,SAASU,IAAI;QACtB,EAAE,OAAOC,GAAG;YACV,IAAIA,aAAaC,OAAOC,QAAQC,KAAK,CAACH,EAAEI,OAAO;YAE/C,OAAO;gBAAEN,SAAS;YAAM;QAC1B;IACF;IAEA,OAAO;QACLX;IACF;AACF,EAAE"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CustomSaveButton.d.ts","sourceRoot":"","sources":["../../../../src/client/components/CustomSaveButton/CustomSaveButton.tsx"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC;AAWvB,eAAO,MAAM,gBAAgB,mCAoB5B,CAAC"}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
'use client';
|
2
|
+
import './styles.scss';
|
3
|
+
import { DefaultSaveButton } from '@payloadcms/ui/elements/Save';
|
4
|
+
import { useConfig } from '@payloadcms/ui/providers/Config';
|
5
|
+
import { useDocumentInfo } from '@payloadcms/ui/providers/DocumentInfo';
|
6
|
+
import { TranslatorProvider } from '../../providers/Translator/TranslatorProvider';
|
7
|
+
import { ResolverButton } from '../ResolverButton';
|
8
|
+
import { TranslatorModal } from '../TranslatorModal';
|
9
|
+
export const CustomSaveButton = ()=>{
|
10
|
+
const config = useConfig();
|
11
|
+
const { globalSlug, id } = useDocumentInfo();
|
12
|
+
const resolvers = config.admin?.custom?.translator?.resolvers ?? [];
|
13
|
+
if (!id && !globalSlug) return /*#__PURE__*/ React.createElement(DefaultSaveButton, null);
|
14
|
+
return /*#__PURE__*/ React.createElement(TranslatorProvider, null, /*#__PURE__*/ React.createElement("div", {
|
15
|
+
className: 'translator__custom-save-button'
|
16
|
+
}, /*#__PURE__*/ React.createElement(TranslatorModal, null), resolvers.map((resolver)=>/*#__PURE__*/ React.createElement(ResolverButton, {
|
17
|
+
key: resolver.key,
|
18
|
+
resolver: resolver
|
19
|
+
})), /*#__PURE__*/ React.createElement(DefaultSaveButton, null)));
|
20
|
+
};
|
21
|
+
|
22
|
+
//# sourceMappingURL=CustomSaveButton.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/CustomSaveButton/CustomSaveButton.tsx"],"sourcesContent":["'use client';\r\n\r\nimport './styles.scss';\r\n\r\nimport { DefaultSaveButton } from '@payloadcms/ui/elements/Save';\r\nimport { useConfig } from '@payloadcms/ui/providers/Config';\r\nimport { useDocumentInfo } from '@payloadcms/ui/providers/DocumentInfo';\r\n\r\nimport type { TranslateResolver } from '../../../resolvers/types';\r\nimport { TranslatorProvider } from '../../providers/Translator/TranslatorProvider';\r\nimport { ResolverButton } from '../ResolverButton';\r\nimport { TranslatorModal } from '../TranslatorModal';\r\n\r\nexport const CustomSaveButton = () => {\r\n const config = useConfig();\r\n\r\n const { globalSlug, id } = useDocumentInfo();\r\n\r\n const resolvers = (config.admin?.custom?.translator?.resolvers as TranslateResolver[]) ?? [];\r\n\r\n if (!id && !globalSlug) return <DefaultSaveButton />;\r\n\r\n return (\r\n <TranslatorProvider>\r\n <div className={'translator__custom-save-button'}>\r\n <TranslatorModal />\r\n {resolvers.map((resolver) => (\r\n <ResolverButton key={resolver.key} resolver={resolver} />\r\n ))}\r\n <DefaultSaveButton />\r\n </div>\r\n </TranslatorProvider>\r\n );\r\n};\r\n"],"names":["DefaultSaveButton","useConfig","useDocumentInfo","TranslatorProvider","ResolverButton","TranslatorModal","CustomSaveButton","config","globalSlug","id","resolvers","admin","custom","translator","div","className","map","resolver","key"],"rangeMappings":";;;;;;;;;;;;;;;;;;;","mappings":"AAAA;AAEA,OAAO,gBAAgB;AAEvB,SAASA,iBAAiB,QAAQ,+BAA+B;AACjE,SAASC,SAAS,QAAQ,kCAAkC;AAC5D,SAASC,eAAe,QAAQ,wCAAwC;AAGxE,SAASC,kBAAkB,QAAQ,gDAAgD;AACnF,SAASC,cAAc,QAAQ,oBAAoB;AACnD,SAASC,eAAe,QAAQ,qBAAqB;AAErD,OAAO,MAAMC,mBAAmB;IAC9B,MAAMC,SAASN;IAEf,MAAM,EAAEO,UAAU,EAAEC,EAAE,EAAE,GAAGP;IAE3B,MAAMQ,YAAY,AAACH,OAAOI,KAAK,EAAEC,QAAQC,YAAYH,aAAqC,EAAE;IAE5F,IAAI,CAACD,MAAM,CAACD,YAAY,qBAAO,oBAACR;IAEhC,qBACE,oBAACG,wCACC,oBAACW;QAAIC,WAAW;qBACd,oBAACV,wBACAK,UAAUM,GAAG,CAAC,CAACC,yBACd,oBAACb;YAAec,KAAKD,SAASC,GAAG;YAAED,UAAUA;2BAE/C,oBAACjB;AAIT,EAAE"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/components/CustomSaveButton/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/CustomSaveButton/index.ts"],"sourcesContent":["export * from './CustomSaveButton';\r\n"],"names":[],"rangeMappings":"","mappings":"AAAA,cAAc,qBAAqB"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"LocaleLabel.d.ts","sourceRoot":"","sources":["../../../../src/client/components/LocaleLabel/LocaleLabel.tsx"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI7C,eAAO,MAAM,WAAW,eAAgB;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,gCAczD,CAAC"}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { getTranslation } from '@payloadcms/translations';
|
2
|
+
import { Chevron } from '@payloadcms/ui/icons/Chevron';
|
3
|
+
import { useTranslation } from '@payloadcms/ui/providers/Translation';
|
4
|
+
const baseClass = 'localizer-button';
|
5
|
+
export const LocaleLabel = ({ locale })=>{
|
6
|
+
const { i18n, t } = useTranslation();
|
7
|
+
return /*#__PURE__*/ React.createElement("div", {
|
8
|
+
"aria-label": t('general:locale'),
|
9
|
+
className: baseClass
|
10
|
+
}, /*#__PURE__*/ React.createElement("div", {
|
11
|
+
className: `${baseClass}__label`
|
12
|
+
}, `${t('general:locale')}:`), " ", /*#__PURE__*/ React.createElement("span", {
|
13
|
+
className: `${baseClass}__current-label`
|
14
|
+
}, `${getTranslation(locale.label, i18n)}`), " ", /*#__PURE__*/ React.createElement(Chevron, {
|
15
|
+
className: `${baseClass}__chevron`
|
16
|
+
}));
|
17
|
+
};
|
18
|
+
|
19
|
+
//# sourceMappingURL=LocaleLabel.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/LocaleLabel/LocaleLabel.tsx"],"sourcesContent":["import { getTranslation } from '@payloadcms/translations';\r\nimport { Chevron } from '@payloadcms/ui/icons/Chevron';\r\nimport { useTranslation } from '@payloadcms/ui/providers/Translation';\r\nimport type { Locale } from 'payload/config';\r\n\r\nconst baseClass = 'localizer-button';\r\n\r\nexport const LocaleLabel = ({ locale }: { locale: Locale }) => {\r\n const { i18n, t } = useTranslation();\r\n\r\n return (\r\n <div aria-label={t('general:locale')} className={baseClass}>\r\n <div className={`${baseClass}__label`}>{`${t('general:locale')}:`}</div>\r\n \r\n <span className={`${baseClass}__current-label`}>\r\n {`${getTranslation(locale.label, i18n)}`}\r\n </span>\r\n \r\n <Chevron className={`${baseClass}__chevron`} />\r\n </div>\r\n );\r\n};\r\n"],"names":["getTranslation","Chevron","useTranslation","baseClass","LocaleLabel","locale","i18n","t","div","aria-label","className","span","label"],"rangeMappings":";;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,cAAc,QAAQ,2BAA2B;AAC1D,SAASC,OAAO,QAAQ,+BAA+B;AACvD,SAASC,cAAc,QAAQ,uCAAuC;AAGtE,MAAMC,YAAY;AAElB,OAAO,MAAMC,cAAc,CAAC,EAAEC,MAAM,EAAsB;IACxD,MAAM,EAAEC,IAAI,EAAEC,CAAC,EAAE,GAAGL;IAEpB,qBACE,oBAACM;QAAIC,cAAYF,EAAE;QAAmBG,WAAWP;qBAC/C,oBAACK;QAAIE,WAAW,CAAC,EAAEP,UAAU,OAAO,CAAC;OAAG,CAAC,EAAEI,EAAE,kBAAkB,CAAC,CAAC,GAAO,oBAExE,oBAACI;QAAKD,WAAW,CAAC,EAAEP,UAAU,eAAe,CAAC;OAC3C,CAAC,EAAEH,eAAeK,OAAOO,KAAK,EAAEN,MAAM,CAAC,GACnC,mBAEP,oBAACL;QAAQS,WAAW,CAAC,EAAEP,UAAU,SAAS,CAAC;;AAGjD,EAAE"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/components/LocaleLabel/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/LocaleLabel/index.ts"],"sourcesContent":["export * from './LocaleLabel';\r\n"],"names":[],"rangeMappings":"","mappings":"AAAA,cAAc,gBAAgB"}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
/// <reference types="react" resolution-mode="require"/>
|
2
|
+
import type { TranslateResolver } from '../../../resolvers/types';
|
3
|
+
export declare const ResolverButton: ({ resolver: { key: resolverKey }, }: {
|
4
|
+
resolver: TranslateResolver;
|
5
|
+
}) => import("react").JSX.Element;
|
6
|
+
//# sourceMappingURL=ResolverButton.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ResolverButton.d.ts","sourceRoot":"","sources":["../../../../src/client/components/ResolverButton/ResolverButton.tsx"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,eAAO,MAAM,cAAc,wCAExB;IACD,QAAQ,EAAE,iBAAiB,CAAC;CAC7B,gCAYA,CAAC"}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { Button } from '@payloadcms/ui/elements';
|
2
|
+
import { useTranslation } from '@payloadcms/ui/providers/Translation';
|
3
|
+
import { useTranslator } from '../../providers/Translator/context';
|
4
|
+
export const ResolverButton = ({ resolver: { key: resolverKey } })=>{
|
5
|
+
const { openTranslator } = useTranslator();
|
6
|
+
const { t } = useTranslation();
|
7
|
+
const handleClick = ()=>openTranslator({
|
8
|
+
resolverKey
|
9
|
+
});
|
10
|
+
return /*#__PURE__*/ React.createElement(Button, {
|
11
|
+
onClick: handleClick,
|
12
|
+
size: "small"
|
13
|
+
}, t(`plugin-translator:resolver_${resolverKey}_buttonLabel`));
|
14
|
+
};
|
15
|
+
|
16
|
+
//# sourceMappingURL=ResolverButton.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/ResolverButton/ResolverButton.tsx"],"sourcesContent":["import { Button } from '@payloadcms/ui/elements';\r\nimport { useTranslation } from '@payloadcms/ui/providers/Translation';\r\n\r\nimport type { TranslateResolver } from '../../../resolvers/types';\r\nimport { useTranslator } from '../../providers/Translator/context';\r\n\r\nexport const ResolverButton = ({\r\n resolver: { key: resolverKey },\r\n}: {\r\n resolver: TranslateResolver;\r\n}) => {\r\n const { openTranslator } = useTranslator();\r\n\r\n const { t } = useTranslation();\r\n\r\n const handleClick = () => openTranslator({ resolverKey });\r\n\r\n return (\r\n <Button onClick={handleClick} size='small'>\r\n {t(`plugin-translator:resolver_${resolverKey}_buttonLabel`)}\r\n </Button>\r\n );\r\n};\r\n"],"names":["Button","useTranslation","useTranslator","ResolverButton","resolver","key","resolverKey","openTranslator","t","handleClick","onClick","size"],"rangeMappings":";;;;;;;;;;;;;","mappings":"AAAA,SAASA,MAAM,QAAQ,0BAA0B;AACjD,SAASC,cAAc,QAAQ,uCAAuC;AAGtE,SAASC,aAAa,QAAQ,qCAAqC;AAEnE,OAAO,MAAMC,iBAAiB,CAAC,EAC7BC,UAAU,EAAEC,KAAKC,WAAW,EAAE,EAG/B;IACC,MAAM,EAAEC,cAAc,EAAE,GAAGL;IAE3B,MAAM,EAAEM,CAAC,EAAE,GAAGP;IAEd,MAAMQ,cAAc,IAAMF,eAAe;YAAED;QAAY;IAEvD,qBACE,oBAACN;QAAOU,SAASD;QAAaE,MAAK;OAChCH,EAAE,CAAC,2BAA2B,EAAEF,YAAY,YAAY,CAAC;AAGhE,EAAE"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/components/ResolverButton/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/ResolverButton/index.ts"],"sourcesContent":["export * from './ResolverButton';\r\n"],"names":[],"rangeMappings":"","mappings":"AAAA,cAAc,mBAAmB"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"Content.d.ts","sourceRoot":"","sources":["../../../../src/client/components/TranslatorModal/Content.tsx"],"names":[],"mappings":";AAOA,eAAO,MAAM,OAAO,mCAwDnB,CAAC"}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import { getTranslation } from '@payloadcms/translations';
|
2
|
+
import { Button, Popup, PopupList } from '@payloadcms/ui/elements';
|
3
|
+
import { useTranslation } from '@payloadcms/ui/providers/Translation';
|
4
|
+
import { useTranslator } from '../../providers/Translator/context';
|
5
|
+
import { LocaleLabel } from '../LocaleLabel';
|
6
|
+
export const Content = ()=>{
|
7
|
+
const { localeToTranslateFrom: localeCodeToTranslateFrom, localesOptions, resolverT, setLocaleToTranslateFrom, submit } = useTranslator();
|
8
|
+
const { i18n } = useTranslation();
|
9
|
+
const localeToTranslateFrom = localesOptions.find((each)=>each.code === localeCodeToTranslateFrom);
|
10
|
+
return /*#__PURE__*/ React.createElement("div", {
|
11
|
+
className: 'translator__content'
|
12
|
+
}, /*#__PURE__*/ React.createElement("h2", null, resolverT('modalTitle')), localeToTranslateFrom && /*#__PURE__*/ React.createElement(Popup, {
|
13
|
+
button: /*#__PURE__*/ React.createElement(LocaleLabel, {
|
14
|
+
locale: localeToTranslateFrom
|
15
|
+
}),
|
16
|
+
horizontalAlign: "center",
|
17
|
+
render: ({ close })=>/*#__PURE__*/ React.createElement(PopupList.ButtonGroup, null, localesOptions.map((option)=>{
|
18
|
+
const label = getTranslation(option.label, i18n);
|
19
|
+
return /*#__PURE__*/ React.createElement(PopupList.Button, {
|
20
|
+
active: option.code === localeCodeToTranslateFrom,
|
21
|
+
key: option.code,
|
22
|
+
onClick: ()=>{
|
23
|
+
setLocaleToTranslateFrom(option.code);
|
24
|
+
close();
|
25
|
+
}
|
26
|
+
}, label, label !== option.code && ` (${option.code})`);
|
27
|
+
})),
|
28
|
+
verticalAlign: "bottom"
|
29
|
+
}), /*#__PURE__*/ React.createElement("div", {
|
30
|
+
className: 'translator__buttons'
|
31
|
+
}, /*#__PURE__*/ React.createElement(Button, {
|
32
|
+
onClick: ()=>submit({
|
33
|
+
emptyOnly: false
|
34
|
+
})
|
35
|
+
}, resolverT('submitButtonLabelFull')), /*#__PURE__*/ React.createElement(Button, {
|
36
|
+
onClick: ()=>submit({
|
37
|
+
emptyOnly: true
|
38
|
+
})
|
39
|
+
}, resolverT('submitButtonLabelEmpty'))));
|
40
|
+
};
|
41
|
+
|
42
|
+
//# sourceMappingURL=Content.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/Content.tsx"],"sourcesContent":["import { getTranslation } from '@payloadcms/translations';\r\nimport { Button, Popup, PopupList } from '@payloadcms/ui/elements';\r\nimport { useTranslation } from '@payloadcms/ui/providers/Translation';\r\n\r\nimport { useTranslator } from '../../providers/Translator/context';\r\nimport { LocaleLabel } from '../LocaleLabel';\r\n\r\nexport const Content = () => {\r\n const {\r\n localeToTranslateFrom: localeCodeToTranslateFrom,\r\n localesOptions,\r\n resolverT,\r\n setLocaleToTranslateFrom,\r\n submit,\r\n } = useTranslator();\r\n\r\n const { i18n } = useTranslation();\r\n\r\n const localeToTranslateFrom = localesOptions.find(\r\n (each) => each.code === localeCodeToTranslateFrom,\r\n );\r\n\r\n return (\r\n <div className={'translator__content'}>\r\n <h2>{resolverT('modalTitle')}</h2>\r\n {localeToTranslateFrom && (\r\n <Popup\r\n button={<LocaleLabel locale={localeToTranslateFrom} />}\r\n horizontalAlign='center'\r\n render={({ close }) => (\r\n <PopupList.ButtonGroup>\r\n {localesOptions.map((option) => {\r\n const label = getTranslation(option.label, i18n);\r\n\r\n return (\r\n <PopupList.Button\r\n active={option.code === localeCodeToTranslateFrom}\r\n key={option.code}\r\n onClick={() => {\r\n setLocaleToTranslateFrom(option.code);\r\n close();\r\n }}\r\n >\r\n {label}\r\n {label !== option.code && ` (${option.code})`}\r\n </PopupList.Button>\r\n );\r\n })}\r\n </PopupList.ButtonGroup>\r\n )}\r\n verticalAlign='bottom'\r\n />\r\n )}\r\n <div className={'translator__buttons'}>\r\n <Button onClick={() => submit({ emptyOnly: false })}>\r\n {resolverT('submitButtonLabelFull')}\r\n </Button>\r\n <Button onClick={() => submit({ emptyOnly: true })}>\r\n {resolverT('submitButtonLabelEmpty')}\r\n </Button>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"names":["getTranslation","Button","Popup","PopupList","useTranslation","useTranslator","LocaleLabel","Content","localeToTranslateFrom","localeCodeToTranslateFrom","localesOptions","resolverT","setLocaleToTranslateFrom","submit","i18n","find","each","code","div","className","h2","button","locale","horizontalAlign","render","close","ButtonGroup","map","option","label","active","key","onClick","verticalAlign","emptyOnly"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,cAAc,QAAQ,2BAA2B;AAC1D,SAASC,MAAM,EAAEC,KAAK,EAAEC,SAAS,QAAQ,0BAA0B;AACnE,SAASC,cAAc,QAAQ,uCAAuC;AAEtE,SAASC,aAAa,QAAQ,qCAAqC;AACnE,SAASC,WAAW,QAAQ,iBAAiB;AAE7C,OAAO,MAAMC,UAAU;IACrB,MAAM,EACJC,uBAAuBC,yBAAyB,EAChDC,cAAc,EACdC,SAAS,EACTC,wBAAwB,EACxBC,MAAM,EACP,GAAGR;IAEJ,MAAM,EAAES,IAAI,EAAE,GAAGV;IAEjB,MAAMI,wBAAwBE,eAAeK,IAAI,CAC/C,CAACC,OAASA,KAAKC,IAAI,KAAKR;IAG1B,qBACE,oBAACS;QAAIC,WAAW;qBACd,oBAACC,YAAIT,UAAU,gBACdH,uCACC,oBAACN;QACCmB,sBAAQ,oBAACf;YAAYgB,QAAQd;;QAC7Be,iBAAgB;QAChBC,QAAQ,CAAC,EAAEC,KAAK,EAAE,iBAChB,oBAACtB,UAAUuB,WAAW,QACnBhB,eAAeiB,GAAG,CAAC,CAACC;gBACnB,MAAMC,QAAQ7B,eAAe4B,OAAOC,KAAK,EAAEf;gBAE3C,qBACE,oBAACX,UAAUF,MAAM;oBACf6B,QAAQF,OAAOX,IAAI,KAAKR;oBACxBsB,KAAKH,OAAOX,IAAI;oBAChBe,SAAS;wBACPpB,yBAAyBgB,OAAOX,IAAI;wBACpCQ;oBACF;mBAECI,OACAA,UAAUD,OAAOX,IAAI,IAAI,CAAC,EAAE,EAAEW,OAAOX,IAAI,CAAC,CAAC,CAAC;YAGnD;QAGJgB,eAAc;sBAGlB,oBAACf;QAAIC,WAAW;qBACd,oBAAClB;QAAO+B,SAAS,IAAMnB,OAAO;gBAAEqB,WAAW;YAAM;OAC9CvB,UAAU,yCAEb,oBAACV;QAAO+B,SAAS,IAAMnB,OAAO;gBAAEqB,WAAW;YAAK;OAC7CvB,UAAU;AAKrB,EAAE"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"TranslatorModal.d.ts","sourceRoot":"","sources":["../../../../src/client/components/TranslatorModal/TranslatorModal.tsx"],"names":[],"mappings":";AAAA,OAAO,eAAe,CAAC;AAOvB,eAAO,MAAM,eAAe,+CAkB3B,CAAC"}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import './styles.scss';
|
2
|
+
import { Modal } from '@payloadcms/ui/elements';
|
3
|
+
import { useTranslator } from '../../providers/Translator/context';
|
4
|
+
import { Content } from './Content';
|
5
|
+
export const TranslatorModal = ()=>{
|
6
|
+
const { closeTranslator, modalSlug, resolver } = useTranslator();
|
7
|
+
if (!resolver) return;
|
8
|
+
return /*#__PURE__*/ React.createElement(Modal, {
|
9
|
+
className: 'translator__modal',
|
10
|
+
slug: modalSlug
|
11
|
+
}, /*#__PURE__*/ React.createElement("div", {
|
12
|
+
className: 'translator__wrapper'
|
13
|
+
}, /*#__PURE__*/ React.createElement("span", {
|
14
|
+
"aria-label": "Close",
|
15
|
+
className: 'translator__close',
|
16
|
+
onClick: closeTranslator,
|
17
|
+
role: "button"
|
18
|
+
}), /*#__PURE__*/ React.createElement(Content, null)));
|
19
|
+
};
|
20
|
+
|
21
|
+
//# sourceMappingURL=TranslatorModal.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/TranslatorModal.tsx"],"sourcesContent":["import './styles.scss';\r\n\r\nimport { Modal } from '@payloadcms/ui/elements';\r\n\r\nimport { useTranslator } from '../../providers/Translator/context';\r\nimport { Content } from './Content';\r\n\r\nexport const TranslatorModal = () => {\r\n const { closeTranslator, modalSlug, resolver } = useTranslator();\r\n\r\n if (!resolver) return;\r\n\r\n return (\r\n <Modal className={'translator__modal'} slug={modalSlug}>\r\n <div className={'translator__wrapper'}>\r\n <span\r\n aria-label='Close'\r\n className={'translator__close'}\r\n onClick={closeTranslator}\r\n role='button'\r\n />\r\n <Content />\r\n </div>\r\n </Modal>\r\n );\r\n};\r\n"],"names":["Modal","useTranslator","Content","TranslatorModal","closeTranslator","modalSlug","resolver","className","slug","div","span","aria-label","onClick","role"],"rangeMappings":";;;;;;;;;;;;;;;;;;","mappings":"AAAA,OAAO,gBAAgB;AAEvB,SAASA,KAAK,QAAQ,0BAA0B;AAEhD,SAASC,aAAa,QAAQ,qCAAqC;AACnE,SAASC,OAAO,QAAQ,YAAY;AAEpC,OAAO,MAAMC,kBAAkB;IAC7B,MAAM,EAAEC,eAAe,EAAEC,SAAS,EAAEC,QAAQ,EAAE,GAAGL;IAEjD,IAAI,CAACK,UAAU;IAEf,qBACE,oBAACN;QAAMO,WAAW;QAAqBC,MAAMH;qBAC3C,oBAACI;QAAIF,WAAW;qBACd,oBAACG;QACCC,cAAW;QACXJ,WAAW;QACXK,SAASR;QACTS,MAAK;sBAEP,oBAACX;AAIT,EAAE"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/components/TranslatorModal/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/TranslatorModal/index.ts"],"sourcesContent":["export * from './TranslatorModal';\r\n"],"names":[],"rangeMappings":"","mappings":"AAAA,cAAc,oBAAoB"}
|
@@ -0,0 +1,76 @@
|
|
1
|
+
.translator {
|
2
|
+
&__modal {
|
3
|
+
display: flex;
|
4
|
+
position: relative;
|
5
|
+
justify-content: center;
|
6
|
+
align-items: center;
|
7
|
+
width: fit-content;
|
8
|
+
height: fit-content;
|
9
|
+
}
|
10
|
+
|
11
|
+
&__wrapper {
|
12
|
+
display: flex;
|
13
|
+
position: relative;
|
14
|
+
flex-direction: column;
|
15
|
+
gap: var(--base);
|
16
|
+
z-index: 1;
|
17
|
+
background: var(--theme-elevation-50);
|
18
|
+
padding: 50px;
|
19
|
+
}
|
20
|
+
|
21
|
+
&__content {
|
22
|
+
display: flex;
|
23
|
+
flex-direction: column;
|
24
|
+
align-items: center;
|
25
|
+
gap: var(--base);
|
26
|
+
max-width: 400px;
|
27
|
+
|
28
|
+
h2 {
|
29
|
+
margin: 0;
|
30
|
+
text-align: center;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
&__buttons {
|
35
|
+
display: flex;
|
36
|
+
justify-content: center;
|
37
|
+
gap: 10px;
|
38
|
+
width: 100%;
|
39
|
+
|
40
|
+
button {
|
41
|
+
margin: 0;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
&__close {
|
46
|
+
position: absolute;
|
47
|
+
top: 10px;
|
48
|
+
right: 10px;
|
49
|
+
transition: 0.25s;
|
50
|
+
cursor: pointer;
|
51
|
+
width: 32px;
|
52
|
+
height: 32px;
|
53
|
+
|
54
|
+
&:hover {
|
55
|
+
opacity: 0.6;
|
56
|
+
}
|
57
|
+
|
58
|
+
&:before,
|
59
|
+
&:after {
|
60
|
+
position: absolute;
|
61
|
+
left: 15px;
|
62
|
+
background-color: var(--theme-elevation-800);
|
63
|
+
width: 2px;
|
64
|
+
height: 33px;
|
65
|
+
content: ' ';
|
66
|
+
}
|
67
|
+
|
68
|
+
&:before {
|
69
|
+
transform: rotate(45deg);
|
70
|
+
}
|
71
|
+
|
72
|
+
&:after {
|
73
|
+
transform: rotate(-45deg);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|