@schukai/monster 4.38.9 → 4.39.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 +16 -0
- package/package.json +1 -1
- package/source/components/accessibility/locale-picker.mjs +561 -551
- package/source/components/accessibility/locale-select.mjs +270 -0
- package/source/components/form/select.mjs +2854 -2851
- package/source/i18n/util.mjs +149 -142
@@ -0,0 +1,270 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
|
3
|
+
* Node module: @schukai/monster
|
4
|
+
*
|
5
|
+
* This source code is licensed under the GNU Affero General Public License Version 3 (AGPLv3).
|
6
|
+
* The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.de.html
|
7
|
+
*
|
8
|
+
* For those who do not wish to adhere to the AGPLv3, a commercial license is available.
|
9
|
+
* For more information about purchasing a commercial license, please contact schukai GmbH.
|
10
|
+
*/
|
11
|
+
|
12
|
+
import { instanceSymbol } from "../../constants.mjs";
|
13
|
+
import { ATTRIBUTE_ROLE } from "../../dom/constants.mjs";
|
14
|
+
import { CustomElement } from "../../dom/customelement.mjs";
|
15
|
+
import {
|
16
|
+
assembleMethodSymbol,
|
17
|
+
registerCustomElement,
|
18
|
+
} from "../../dom/customelement.mjs";
|
19
|
+
import { isFunction, isObject } from "../../types/is.mjs";
|
20
|
+
import { LocalePickerStyleSheet } from "./stylesheet/locale-picker.mjs";
|
21
|
+
import { detectUserLanguagePreference } from "../../i18n/util.mjs";
|
22
|
+
|
23
|
+
import "../form/select.mjs";
|
24
|
+
|
25
|
+
export { LocaleSelect as LocalSelector };
|
26
|
+
|
27
|
+
/**
|
28
|
+
* @private
|
29
|
+
* @type {symbol}
|
30
|
+
* Reference to the select element
|
31
|
+
*/
|
32
|
+
const selectElementSymbol = Symbol("selectElement");
|
33
|
+
|
34
|
+
/**
|
35
|
+
* @private
|
36
|
+
* @type {symbol}
|
37
|
+
* Stores detected languages
|
38
|
+
*/
|
39
|
+
const detectedLanguagesSymbol = Symbol("detectedLanguages");
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Returns the localized label for the language selection.
|
43
|
+
* @return {string}
|
44
|
+
*/
|
45
|
+
function getLocalizedLabel() {
|
46
|
+
const lang = document.documentElement.lang || navigator.language || "en";
|
47
|
+
switch (lang.split("-")[0]) {
|
48
|
+
case "de":
|
49
|
+
return "Sprache wählen";
|
50
|
+
case "fr":
|
51
|
+
return "Sélectionnez une langue";
|
52
|
+
case "es":
|
53
|
+
return "Seleccione un idioma";
|
54
|
+
case "it":
|
55
|
+
return "Seleziona una lingua";
|
56
|
+
case "pt":
|
57
|
+
return "Selecione um idioma";
|
58
|
+
case "nl":
|
59
|
+
return "Selecteer een taal";
|
60
|
+
case "pl":
|
61
|
+
return "Wybierz język";
|
62
|
+
case "ru":
|
63
|
+
return "Выберите язык";
|
64
|
+
case "cs":
|
65
|
+
return "Vyberte jazyk";
|
66
|
+
case "sk":
|
67
|
+
return "Vyberte jazyk";
|
68
|
+
case "bg":
|
69
|
+
return "Изберете език";
|
70
|
+
case "hr":
|
71
|
+
return "Odaberite jezik";
|
72
|
+
case "fi":
|
73
|
+
return "Valitse kieli";
|
74
|
+
case "sv":
|
75
|
+
return "Välj ett språk";
|
76
|
+
case "el":
|
77
|
+
return "Επιλέξτε γλώσσα";
|
78
|
+
case "hu":
|
79
|
+
return "Válasszon egy nyelvet";
|
80
|
+
case "ro":
|
81
|
+
return "Selectați o limbă";
|
82
|
+
case "da":
|
83
|
+
return "Vælg et sprog";
|
84
|
+
case "no":
|
85
|
+
return "Velg et språk";
|
86
|
+
case "hi":
|
87
|
+
return "एक भाषा चुनें";
|
88
|
+
case "bn":
|
89
|
+
return "একটি ভাষা নির্বাচন করুন";
|
90
|
+
case "ta":
|
91
|
+
return "ஒரு மொழியைத் தேர்ந்தெடுக்கவும்";
|
92
|
+
case "te":
|
93
|
+
return "భాషను ఎంచుకోండి";
|
94
|
+
case "mr":
|
95
|
+
return "एक भाषा निवडा";
|
96
|
+
case "zh":
|
97
|
+
return "选择一种语言";
|
98
|
+
case "ja":
|
99
|
+
return "言語を選択してください";
|
100
|
+
default:
|
101
|
+
return "Select a language";
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* LocaleSelect component
|
107
|
+
*
|
108
|
+
* Displays a monster-select with all available languages except the current document language.
|
109
|
+
*
|
110
|
+
* @since 3.97.0
|
111
|
+
* @copyright schukai GmbH
|
112
|
+
* @summary A simple language switcher as a select.
|
113
|
+
*/
|
114
|
+
class LocaleSelect extends CustomElement {
|
115
|
+
/**
|
116
|
+
* Used by the instanceof operator.
|
117
|
+
* @returns {symbol}
|
118
|
+
*/
|
119
|
+
static get [instanceSymbol]() {
|
120
|
+
return Symbol.for(
|
121
|
+
"@schukai/monster/components/accessibility/local-selector@@instance",
|
122
|
+
);
|
123
|
+
}
|
124
|
+
|
125
|
+
/**
|
126
|
+
* Initializes the component.
|
127
|
+
* @return {LocaleSelect}
|
128
|
+
*/
|
129
|
+
[assembleMethodSymbol]() {
|
130
|
+
super[assembleMethodSymbol]();
|
131
|
+
initControlReferences.call(this);
|
132
|
+
initSelectOptions.call(this);
|
133
|
+
initEventHandler.call(this);
|
134
|
+
return this;
|
135
|
+
}
|
136
|
+
|
137
|
+
/**
|
138
|
+
* Default options
|
139
|
+
*/
|
140
|
+
get defaults() {
|
141
|
+
return Object.assign({}, super.defaults, {
|
142
|
+
templates: {
|
143
|
+
main: getTemplate(),
|
144
|
+
},
|
145
|
+
labels: {
|
146
|
+
"select-an-option": getLocalizedLabel(),
|
147
|
+
},
|
148
|
+
callbacks: {},
|
149
|
+
disabled: false,
|
150
|
+
});
|
151
|
+
}
|
152
|
+
|
153
|
+
/**
|
154
|
+
* connectedCallback
|
155
|
+
*/
|
156
|
+
connectedCallback() {
|
157
|
+
super.connectedCallback();
|
158
|
+
this[detectedLanguagesSymbol] = detectUserLanguagePreference();
|
159
|
+
initSelectOptions.call(this);
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
* @return {string}
|
164
|
+
*/
|
165
|
+
static getTag() {
|
166
|
+
return "monster-locale-select";
|
167
|
+
}
|
168
|
+
|
169
|
+
/**
|
170
|
+
* @return {CSSStyleSheet[]}
|
171
|
+
*/
|
172
|
+
static getCSSStyleSheet() {
|
173
|
+
return [LocalePickerStyleSheet];
|
174
|
+
}
|
175
|
+
|
176
|
+
/**
|
177
|
+
* Export parts from monster-select to make them available for styling outside.
|
178
|
+
*/
|
179
|
+
static get exportparts() {
|
180
|
+
// The parts from monster-select, as defined in source/components/form/select.mjs:
|
181
|
+
return [
|
182
|
+
"control",
|
183
|
+
"container",
|
184
|
+
"popper",
|
185
|
+
"option",
|
186
|
+
"option-label",
|
187
|
+
"option-control",
|
188
|
+
"badge",
|
189
|
+
"badge-label",
|
190
|
+
"remove-badge",
|
191
|
+
"summary",
|
192
|
+
"status-or-remove-badges",
|
193
|
+
"remote-info",
|
194
|
+
"no-options",
|
195
|
+
"selection",
|
196
|
+
"inline-filter",
|
197
|
+
"popper-filter",
|
198
|
+
"content"
|
199
|
+
].join(",");
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* Initializes the reference to the select element.
|
205
|
+
* @private
|
206
|
+
*/
|
207
|
+
function initControlReferences() {
|
208
|
+
this[selectElementSymbol] = this.shadowRoot.querySelector(
|
209
|
+
`[${ATTRIBUTE_ROLE}="select"]`,
|
210
|
+
);
|
211
|
+
}
|
212
|
+
|
213
|
+
/**
|
214
|
+
* Initializes the options of the select element.
|
215
|
+
* @private
|
216
|
+
*/
|
217
|
+
function initSelectOptions() {
|
218
|
+
const detected =
|
219
|
+
this[detectedLanguagesSymbol] || detectUserLanguagePreference();
|
220
|
+
|
221
|
+
let options = [];
|
222
|
+
if (Array.isArray(detected.available)) {
|
223
|
+
const currentLang = detected.current;
|
224
|
+
options = detected.available.filter(
|
225
|
+
(lang) => lang.baseLang !== currentLang && lang.fullLang !== currentLang,
|
226
|
+
);
|
227
|
+
} else if (Array.isArray(detected.allOfferable)) {
|
228
|
+
options = detected.allOfferable;
|
229
|
+
}
|
230
|
+
|
231
|
+
options = detected.allOfferable;
|
232
|
+
if (this[selectElementSymbol]) {
|
233
|
+
this[selectElementSymbol].setOption("mapping.labelTemplate", "${label}");
|
234
|
+
this[selectElementSymbol].setOption("mapping.valueTemplate", "${href}");
|
235
|
+
this[selectElementSymbol].setOption(
|
236
|
+
"labels.select-an-option",
|
237
|
+
this.getOption("labels.select-an-option"),
|
238
|
+
);
|
239
|
+
this[selectElementSymbol].importOptions(options);
|
240
|
+
}
|
241
|
+
}
|
242
|
+
|
243
|
+
/**
|
244
|
+
* Initializes the event handler for the select element.
|
245
|
+
* @private
|
246
|
+
*/
|
247
|
+
function initEventHandler() {
|
248
|
+
if (!this[selectElementSymbol]) return;
|
249
|
+
|
250
|
+
this[selectElementSymbol].addEventListener("change", (event) => {
|
251
|
+
const selected = event.target?.value;
|
252
|
+
if (selected) {
|
253
|
+
window.location.href = selected;
|
254
|
+
}
|
255
|
+
});
|
256
|
+
}
|
257
|
+
|
258
|
+
/**
|
259
|
+
* Returns the template for the component.
|
260
|
+
* @private
|
261
|
+
* @return {string}
|
262
|
+
*/
|
263
|
+
function getTemplate() {
|
264
|
+
// language=HTML
|
265
|
+
return `
|
266
|
+
<monster-select exportparts="control,container,popper,option,option-label,option-control,badge,badge-label,remove-badge,summary,status-or-remove-badges,remote-info,no-options,selection,inline-filter,popper-filter,content" data-monster-role="select"></monster-select>
|
267
|
+
`;
|
268
|
+
}
|
269
|
+
|
270
|
+
registerCustomElement(LocaleSelect);
|