@kubex/zinc 1.0.105 → 1.0.106
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/dist/custom-elements.json +204 -74
- package/dist/vscode.html-custom-data.json +13 -11
- package/dist/web-types.json +30 -23
- package/dist/zn.d.ts +21 -0
- package/dist/zn.min.js +274 -241
- package/docs/pages/components/translation-group.md +25 -0
- package/docs/pages/components/translations.md +17 -1
- package/package.json +1 -1
- package/src/components/inline-edit/inline-edit.component.ts +2 -1
- package/src/components/inline-edit/inline-edit.scss +9 -11
- package/src/components/textarea/textarea.component.ts +1 -1
- package/src/components/translation-group/translation-group.component.ts +113 -2
- package/src/components/translations/translations.component.ts +120 -3
|
@@ -89,6 +89,31 @@ The group scales well with multiple translation inputs under a single toggle.
|
|
|
89
89
|
</zn-translation-group>
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
+
### Language Overflow
|
|
93
|
+
|
|
94
|
+
When there are more languages than will fit across the header, the extras collapse into a chevron dropdown beside the
|
|
95
|
+
visible buttons. The dropdown sits before the `+` add-language dropdown and selects the same way — picking a language
|
|
96
|
+
switches every child translation input in the group.
|
|
97
|
+
|
|
98
|
+
```html:preview
|
|
99
|
+
<div style="max-width: 480px;">
|
|
100
|
+
<zn-translation-group
|
|
101
|
+
label="Release Notes"
|
|
102
|
+
languages='{"en":"English","ar":"Arabic","de":"German","es":"Spanish","fr":"French","it":"Italian","ja":"Japanese","ko":"Korean","pt":"Portuguese","ru":"Russian","tr":"Turkish","zh-hans":"Simplified Chinese"}'>
|
|
103
|
+
<zn-translations
|
|
104
|
+
label="Headline"
|
|
105
|
+
name="headline"
|
|
106
|
+
values='{"en":"Now shipping","ar":"متاح الآن","de":"Jetzt verfügbar","es":"Ya disponible","fr":"Disponible dès maintenant","it":"Disponibile ora","ja":"発売開始","ko":"출시됨","pt":"Disponível agora","ru":"Уже в продаже","tr":"Şimdi mevcut","zh-hans":"现已发布"}'
|
|
107
|
+
></zn-translations>
|
|
108
|
+
<zn-translations
|
|
109
|
+
label="Summary"
|
|
110
|
+
name="summary"
|
|
111
|
+
values='{"en":"Tap through the release highlights.","ar":"تصفح أبرز ميزات الإصدار.","de":"Highlights der Version ansehen.","es":"Consulta lo más destacado.","fr":"Découvrez les nouveautés.","it":"Scopri le novità.","ja":"リリースのハイライトをご覧ください。","ko":"업데이트 주요 내용 보기.","pt":"Veja os destaques.","ru":"Ознакомьтесь с обновлениями.","tr":"Sürüm önemli noktaları.","zh-hans":"浏览版本亮点。"}'
|
|
112
|
+
></zn-translations>
|
|
113
|
+
</zn-translation-group>
|
|
114
|
+
</div>
|
|
115
|
+
```
|
|
116
|
+
|
|
92
117
|
### Flush Layout
|
|
93
118
|
|
|
94
119
|
Remove body padding for a more compact appearance using the `flush` attribute.
|
|
@@ -141,7 +141,8 @@ Use the `expand` slot to add custom buttons or actions.
|
|
|
141
141
|
|
|
142
142
|
### Many Languages
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
When the language buttons don't all fit on one line, the overflow collapses into a chevron dropdown so the row stays a
|
|
145
|
+
single line. Resizing the container re-measures and expands the buttons back out when space allows.
|
|
145
146
|
|
|
146
147
|
```html:preview
|
|
147
148
|
<zn-translations
|
|
@@ -151,6 +152,21 @@ The component handles many languages gracefully with scrollable tabs.
|
|
|
151
152
|
></zn-translations>
|
|
152
153
|
```
|
|
153
154
|
|
|
155
|
+
### Constrained Width
|
|
156
|
+
|
|
157
|
+
Placing the component in a narrow container forces the chevron overflow to kick in. Selecting a language from the
|
|
158
|
+
dropdown switches the active language just like clicking a visible button.
|
|
159
|
+
|
|
160
|
+
```html:preview
|
|
161
|
+
<div style="max-width: 320px;">
|
|
162
|
+
<zn-translations
|
|
163
|
+
label="Narrow Container"
|
|
164
|
+
languages='{"en":"English","fr":"French","de":"German","es":"Spanish","it":"Italian","pt":"Portuguese","ja":"Japanese","ko":"Korean","zh-hans":"Simplified Chinese"}'
|
|
165
|
+
values='{"en":"Hello","fr":"Bonjour","de":"Hallo","es":"Hola","it":"Ciao","pt":"Olá","ja":"こんにちは","ko":"안녕하세요","zh-hans":"你好"}'
|
|
166
|
+
></zn-translations>
|
|
167
|
+
</div>
|
|
168
|
+
```
|
|
169
|
+
|
|
154
170
|
### RTL Language Support
|
|
155
171
|
|
|
156
172
|
The component automatically detects and applies right-to-left text direction for Arabic and Hebrew languages.
|
package/package.json
CHANGED
|
@@ -79,6 +79,7 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
79
79
|
@property() step: number | 'any';
|
|
80
80
|
|
|
81
81
|
@property({ attribute: "input-type" }) inputType: 'select' | 'text' | 'data-select' | 'number' | 'textarea' = 'text';
|
|
82
|
+
@property({ attribute: "textarea-rows", type: Number }) textareaRows: 1;
|
|
82
83
|
|
|
83
84
|
@property({ type: Object }) options: { [key: string]: string } = {};
|
|
84
85
|
|
|
@@ -387,7 +388,7 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
|
|
|
387
388
|
name="${this.name}"
|
|
388
389
|
size="${this.size}"
|
|
389
390
|
resize="auto"
|
|
390
|
-
rows="
|
|
391
|
+
rows="${this.textareaRows}"
|
|
391
392
|
.value="${this.value}"
|
|
392
393
|
placeholder="${this.placeholder}"
|
|
393
394
|
pattern=${ifDefined(this.pattern)}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
gap: 10px;
|
|
15
15
|
|
|
16
16
|
&:not(.ai--editing) {
|
|
17
|
-
.ai__input::part(base), .ai__input::part(combobox) {
|
|
17
|
+
.ai__input::part(base), .ai__input::part(combobox), .ai__input::part(textarea) {
|
|
18
18
|
background-color: transparent;
|
|
19
19
|
border-color: transparent;
|
|
20
20
|
box-shadow: none;
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
color: rgb(var(--zn-text));
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
.ai__input::part(input), .ai__input::part(combobox) {
|
|
33
|
+
.ai__input::part(input), .ai__input::part(combobox), .ai__input::part(textarea) {
|
|
34
34
|
padding: 0;
|
|
35
35
|
color: rgb(var(--zn-text));
|
|
36
36
|
text-decoration: underline;
|
|
@@ -39,6 +39,12 @@
|
|
|
39
39
|
text-underline-offset: 3px;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
.ai__input::part(textarea) {
|
|
43
|
+
padding-top: 8px;
|
|
44
|
+
box-shadow: none;
|
|
45
|
+
text-decoration:none;
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
.ai__input::part(expand-icon) {
|
|
43
49
|
display: none;
|
|
44
50
|
}
|
|
@@ -150,7 +156,7 @@
|
|
|
150
156
|
}
|
|
151
157
|
|
|
152
158
|
&--disabled:not(.ai--editing) {
|
|
153
|
-
.ai__input::part(input), .ai__input::part(combobox) {
|
|
159
|
+
.ai__input::part(input), .ai__input::part(combobox), .ai__input::part(textarea) {
|
|
154
160
|
text-decoration: none;
|
|
155
161
|
caret-color: transparent;
|
|
156
162
|
border-radius: 0;
|
|
@@ -170,12 +176,4 @@ zn-textarea::part(textarea) {
|
|
|
170
176
|
resize: none;
|
|
171
177
|
}
|
|
172
178
|
|
|
173
|
-
.ai:not(.ai--editing) {
|
|
174
|
-
zn-textarea::part(textarea) {
|
|
175
|
-
box-shadow: none;
|
|
176
|
-
padding-left: 0;
|
|
177
|
-
padding-right: 0;
|
|
178
|
-
min-height: 35px;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
179
|
|
|
@@ -78,7 +78,7 @@ export default class ZnTextarea extends ZincElement implements ZincFormControl {
|
|
|
78
78
|
@property() placeholder = '';
|
|
79
79
|
|
|
80
80
|
/** The number of rows to display by default. */
|
|
81
|
-
@property({type: Number}) rows = 4;
|
|
81
|
+
@property({attribute: 'rows',type: Number}) rows = 4;
|
|
82
82
|
|
|
83
83
|
/** Controls how the textarea can be resized. */
|
|
84
84
|
@property() resize: 'none' | 'vertical' | 'auto' = 'vertical';
|
|
@@ -54,9 +54,39 @@ export default class ZnTranslationGroup extends ZnPanel {
|
|
|
54
54
|
/** Tracks all language codes that have been activated across children. */
|
|
55
55
|
@state() private _activatedLanguages: string[] = ['en'];
|
|
56
56
|
|
|
57
|
+
@state() private _overflowIndex = -1;
|
|
58
|
+
|
|
59
|
+
private _resizeObserver?: ResizeObserver;
|
|
60
|
+
private _lastObservedWidth = 0;
|
|
61
|
+
private _measureRafId = 0;
|
|
62
|
+
|
|
63
|
+
connectedCallback() {
|
|
64
|
+
super.connectedCallback();
|
|
65
|
+
this._resizeObserver = new ResizeObserver(entries => {
|
|
66
|
+
const width = entries[0]?.contentRect.width ?? 0;
|
|
67
|
+
if (Math.abs(width - this._lastObservedWidth) < 1) return;
|
|
68
|
+
this._lastObservedWidth = width;
|
|
69
|
+
if (this._overflowIndex !== -1) {
|
|
70
|
+
this._overflowIndex = -1;
|
|
71
|
+
} else {
|
|
72
|
+
this._scheduleLangOverflow();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
disconnectedCallback() {
|
|
78
|
+
super.disconnectedCallback();
|
|
79
|
+
this._resizeObserver?.disconnect();
|
|
80
|
+
if (this._measureRafId) {
|
|
81
|
+
cancelAnimationFrame(this._measureRafId);
|
|
82
|
+
this._measureRafId = 0;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
57
86
|
protected firstUpdated(_changedProperties: PropertyValues) {
|
|
58
87
|
super.firstUpdated(_changedProperties);
|
|
59
88
|
this.syncChildren();
|
|
89
|
+
this._resizeObserver?.observe(this);
|
|
60
90
|
}
|
|
61
91
|
|
|
62
92
|
protected updated(changedProperties: PropertyValues) {
|
|
@@ -64,6 +94,52 @@ export default class ZnTranslationGroup extends ZnPanel {
|
|
|
64
94
|
if (changedProperties.has('languages')) {
|
|
65
95
|
this.syncChildLanguages();
|
|
66
96
|
}
|
|
97
|
+
this._scheduleLangOverflow();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private _scheduleLangOverflow() {
|
|
101
|
+
if (this._measureRafId) return;
|
|
102
|
+
this._measureRafId = requestAnimationFrame(() => {
|
|
103
|
+
this._measureRafId = 0;
|
|
104
|
+
this._computeLangOverflow();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private _computeLangOverflow() {
|
|
109
|
+
const group = this.shadowRoot?.querySelector<HTMLElement>('.translation-group__languages zn-button-group');
|
|
110
|
+
if (!group) return;
|
|
111
|
+
|
|
112
|
+
const buttons = Array.from(group.querySelectorAll<HTMLElement>('zn-button[data-lang-btn]'));
|
|
113
|
+
if (buttons.length < 2) {
|
|
114
|
+
if (this._overflowIndex !== -1) this._overflowIndex = -1;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const firstTop = buttons[0].getBoundingClientRect().top;
|
|
119
|
+
let wrapAt = -1;
|
|
120
|
+
for (let i = 1; i < buttons.length; i++) {
|
|
121
|
+
if (buttons[i].getBoundingClientRect().top > firstTop + 1) {
|
|
122
|
+
wrapAt = i;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (wrapAt === -1) {
|
|
128
|
+
const trailing = group.querySelector<HTMLElement>('[data-lang-overflow], [data-lang-add]');
|
|
129
|
+
if (trailing && trailing.getBoundingClientRect().top > firstTop + 1) {
|
|
130
|
+
wrapAt = buttons.length;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (wrapAt === -1) return;
|
|
135
|
+
|
|
136
|
+
const newIndex = this._overflowIndex === -1
|
|
137
|
+
? wrapAt
|
|
138
|
+
: Math.max(1, Math.min(wrapAt, this._overflowIndex - 1));
|
|
139
|
+
|
|
140
|
+
if (newIndex !== this._overflowIndex) {
|
|
141
|
+
this._overflowIndex = newIndex;
|
|
142
|
+
}
|
|
67
143
|
}
|
|
68
144
|
|
|
69
145
|
private getAllTranslations(): ZnTranslations[] {
|
|
@@ -124,6 +200,15 @@ export default class ZnTranslationGroup extends ZnPanel {
|
|
|
124
200
|
}
|
|
125
201
|
};
|
|
126
202
|
|
|
203
|
+
private handleOverflowSelect = (e: ZnMenuSelectEvent) => {
|
|
204
|
+
e.stopPropagation();
|
|
205
|
+
const element = e.detail.element as HTMLElement;
|
|
206
|
+
const languageCode = element.getAttribute('data-path');
|
|
207
|
+
if (languageCode) {
|
|
208
|
+
this.switchLanguage(languageCode);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
127
212
|
render() {
|
|
128
213
|
const hasActionSlot = this._slotController.test('actions');
|
|
129
214
|
const hasFooterSlot = this._slotController.test('footer');
|
|
@@ -142,6 +227,16 @@ export default class ZnTranslationGroup extends ZnPanel {
|
|
|
142
227
|
visibleTabs.unshift('en');
|
|
143
228
|
}
|
|
144
229
|
|
|
230
|
+
const overflowCutoff = this._overflowIndex === -1 ? visibleTabs.length : this._overflowIndex;
|
|
231
|
+
const visibleLangTabs = visibleTabs.slice(0, overflowCutoff);
|
|
232
|
+
const overflowLangTabs = visibleTabs.slice(overflowCutoff);
|
|
233
|
+
const overflowActions = overflowLangTabs.map(code => ({
|
|
234
|
+
title: code.toUpperCase(),
|
|
235
|
+
type: 'dropdown',
|
|
236
|
+
path: code,
|
|
237
|
+
icon: code === this._activeLanguage ? 'check' : ''
|
|
238
|
+
}));
|
|
239
|
+
|
|
145
240
|
const hasMultipleLanguages = Object.keys(this.languages).length > 1;
|
|
146
241
|
const hasHeader = headerCaption || hasMultipleLanguages || hasActionSlot;
|
|
147
242
|
|
|
@@ -163,8 +258,9 @@ export default class ZnTranslationGroup extends ZnPanel {
|
|
|
163
258
|
${hasMultipleLanguages ? html`
|
|
164
259
|
<div slot="actions" class="translation-group__languages">
|
|
165
260
|
<zn-button-group>
|
|
166
|
-
${
|
|
261
|
+
${visibleLangTabs.map(code => html`
|
|
167
262
|
<zn-button
|
|
263
|
+
data-lang-btn
|
|
168
264
|
size="x-small"
|
|
169
265
|
color="default"
|
|
170
266
|
?outline="${code !== this._activeLanguage}"
|
|
@@ -172,8 +268,23 @@ export default class ZnTranslationGroup extends ZnPanel {
|
|
|
172
268
|
>${code.toUpperCase()}
|
|
173
269
|
</zn-button>
|
|
174
270
|
`)}
|
|
271
|
+
${overflowActions.length > 0 ? html`
|
|
272
|
+
<zn-dropdown placement="bottom-end" data-lang-overflow>
|
|
273
|
+
<zn-button
|
|
274
|
+
slot="trigger"
|
|
275
|
+
size="x-small"
|
|
276
|
+
color="default"
|
|
277
|
+
icon="keyboard_arrow_down"
|
|
278
|
+
?outline="${!overflowLangTabs.includes(this._activeLanguage)}"
|
|
279
|
+
></zn-button>
|
|
280
|
+
<zn-menu
|
|
281
|
+
.actions=${overflowActions}
|
|
282
|
+
@zn-menu-select="${this.handleOverflowSelect}"
|
|
283
|
+
></zn-menu>
|
|
284
|
+
</zn-dropdown>
|
|
285
|
+
` : nothing}
|
|
175
286
|
${availableLanguages.length > 0 ? html`
|
|
176
|
-
<zn-dropdown placement="bottom-end">
|
|
287
|
+
<zn-dropdown placement="bottom-end" data-lang-add>
|
|
177
288
|
<zn-button
|
|
178
289
|
slot="trigger"
|
|
179
290
|
size="x-small"
|
|
@@ -2,6 +2,7 @@ import {classMap} from 'lit/directives/class-map.js';
|
|
|
2
2
|
import {FormControlController, validValidityState} from '../../internal/form';
|
|
3
3
|
import {HasSlotController} from '../../internal/slot';
|
|
4
4
|
import {html, nothing, unsafeCSS} from 'lit';
|
|
5
|
+
import {ifDefined} from 'lit/directives/if-defined.js';
|
|
5
6
|
import {keyed} from 'lit/directives/keyed.js';
|
|
6
7
|
import {live} from 'lit/directives/live.js';
|
|
7
8
|
import {property, state} from 'lit/decorators.js';
|
|
@@ -39,6 +40,7 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
|
|
|
39
40
|
@property({type: Boolean, reflect: true}) required = false;
|
|
40
41
|
@property({type: Boolean, reflect: true}) flush = false;
|
|
41
42
|
@property({attribute: "input-type"}) inputType: 'select' | 'text' | 'number' | 'textarea' = 'text';
|
|
43
|
+
@property({attribute: "textarea-rows", type: Number}) textareaRows: number | undefined;
|
|
42
44
|
|
|
43
45
|
/** When true, hides the individual language navbar and defers language control to a parent zn-translation-group. */
|
|
44
46
|
@property({type: Boolean, reflect: true}) grouped = false;
|
|
@@ -49,6 +51,11 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
|
|
|
49
51
|
@property({type: Object}) values: Record<string, string> = {};
|
|
50
52
|
|
|
51
53
|
@state() private _activeLanguage = 'en';
|
|
54
|
+
@state() private _overflowIndex = -1;
|
|
55
|
+
|
|
56
|
+
private _resizeObserver?: ResizeObserver;
|
|
57
|
+
private _lastObservedWidth = 0;
|
|
58
|
+
private _measureRafId = 0;
|
|
52
59
|
|
|
53
60
|
get validity(): ValidityState {
|
|
54
61
|
return validValidityState;
|
|
@@ -99,8 +106,82 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
|
|
|
99
106
|
return Object.keys(this.values);
|
|
100
107
|
}
|
|
101
108
|
|
|
109
|
+
connectedCallback() {
|
|
110
|
+
super.connectedCallback();
|
|
111
|
+
this._resizeObserver = new ResizeObserver(entries => {
|
|
112
|
+
const width = entries[0]?.contentRect.width ?? 0;
|
|
113
|
+
if (Math.abs(width - this._lastObservedWidth) < 1) return;
|
|
114
|
+
this._lastObservedWidth = width;
|
|
115
|
+
if (this._overflowIndex !== -1) {
|
|
116
|
+
this._overflowIndex = -1;
|
|
117
|
+
} else {
|
|
118
|
+
this._scheduleLangOverflow();
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
disconnectedCallback() {
|
|
124
|
+
super.disconnectedCallback();
|
|
125
|
+
this._resizeObserver?.disconnect();
|
|
126
|
+
if (this._measureRafId) {
|
|
127
|
+
cancelAnimationFrame(this._measureRafId);
|
|
128
|
+
this._measureRafId = 0;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
102
132
|
protected firstUpdated() {
|
|
103
133
|
this.formControlController.updateValidity();
|
|
134
|
+
this._resizeObserver?.observe(this);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
protected updated(changedProperties: PropertyValues) {
|
|
138
|
+
super.updated(changedProperties);
|
|
139
|
+
this._scheduleLangOverflow();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private _scheduleLangOverflow() {
|
|
143
|
+
if (this._measureRafId) return;
|
|
144
|
+
this._measureRafId = requestAnimationFrame(() => {
|
|
145
|
+
this._measureRafId = 0;
|
|
146
|
+
this._computeLangOverflow();
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private _computeLangOverflow() {
|
|
151
|
+
const group = this.shadowRoot?.querySelector<HTMLElement>('.translations__language-group');
|
|
152
|
+
if (!group) return;
|
|
153
|
+
|
|
154
|
+
const buttons = Array.from(group.querySelectorAll<HTMLElement>('zn-button[data-lang-btn]'));
|
|
155
|
+
if (buttons.length < 2) {
|
|
156
|
+
if (this._overflowIndex !== -1) this._overflowIndex = -1;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const firstTop = buttons[0].getBoundingClientRect().top;
|
|
161
|
+
let wrapAt = -1;
|
|
162
|
+
for (let i = 1; i < buttons.length; i++) {
|
|
163
|
+
if (buttons[i].getBoundingClientRect().top > firstTop + 1) {
|
|
164
|
+
wrapAt = i;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (wrapAt === -1) {
|
|
170
|
+
const trailing = group.querySelector<HTMLElement>('[data-lang-overflow], [data-lang-add]');
|
|
171
|
+
if (trailing && trailing.getBoundingClientRect().top > firstTop + 1) {
|
|
172
|
+
wrapAt = buttons.length;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (wrapAt === -1) return;
|
|
177
|
+
|
|
178
|
+
const newIndex = this._overflowIndex === -1
|
|
179
|
+
? wrapAt
|
|
180
|
+
: Math.max(1, Math.min(wrapAt, this._overflowIndex - 1));
|
|
181
|
+
|
|
182
|
+
if (newIndex !== this._overflowIndex) {
|
|
183
|
+
this._overflowIndex = newIndex;
|
|
184
|
+
}
|
|
104
185
|
}
|
|
105
186
|
|
|
106
187
|
willUpdate(changedProperties: PropertyValues) {
|
|
@@ -164,6 +245,15 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
|
|
|
164
245
|
}
|
|
165
246
|
};
|
|
166
247
|
|
|
248
|
+
private handleOverflowSelect = (e: ZnMenuSelectEvent) => {
|
|
249
|
+
e.stopPropagation();
|
|
250
|
+
const element = e.detail.element as HTMLElement;
|
|
251
|
+
const languageCode = element.getAttribute('data-path');
|
|
252
|
+
if (languageCode) {
|
|
253
|
+
this.switchLanguage(languageCode);
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
167
257
|
private switchLanguage = (lang: string) => {
|
|
168
258
|
this._activeLanguage = lang;
|
|
169
259
|
this.requestUpdate();
|
|
@@ -223,6 +313,16 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
|
|
|
223
313
|
visibleTabs.unshift('en');
|
|
224
314
|
}
|
|
225
315
|
|
|
316
|
+
const overflowCutoff = this._overflowIndex === -1 ? visibleTabs.length : this._overflowIndex;
|
|
317
|
+
const visibleLangTabs = visibleTabs.slice(0, overflowCutoff);
|
|
318
|
+
const overflowLangTabs = visibleTabs.slice(overflowCutoff);
|
|
319
|
+
const overflowActions = overflowLangTabs.map(code => ({
|
|
320
|
+
title: code.toUpperCase(),
|
|
321
|
+
type: 'dropdown',
|
|
322
|
+
path: code,
|
|
323
|
+
icon: code === this._activeLanguage ? 'check' : ''
|
|
324
|
+
}));
|
|
325
|
+
|
|
226
326
|
const currentTranslation = this.values[this._activeLanguage] ?? '';
|
|
227
327
|
const isRTL = this.isRTLLanguage(this._activeLanguage);
|
|
228
328
|
|
|
@@ -252,9 +352,10 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
|
|
|
252
352
|
<div class="translations__actions">
|
|
253
353
|
${hasExpandSlot ? html`<slot name="expand"></slot>` : nothing}
|
|
254
354
|
${hasMultipleLanguages ? html`
|
|
255
|
-
<zn-button-group>
|
|
256
|
-
${
|
|
355
|
+
<zn-button-group class="translations__language-group">
|
|
356
|
+
${visibleLangTabs.map(code => html`
|
|
257
357
|
<zn-button
|
|
358
|
+
data-lang-btn
|
|
258
359
|
size="x-small"
|
|
259
360
|
color="default"
|
|
260
361
|
?outline="${code !== this._activeLanguage}"
|
|
@@ -262,8 +363,23 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
|
|
|
262
363
|
>${code.toUpperCase()}
|
|
263
364
|
</zn-button>
|
|
264
365
|
`)}
|
|
366
|
+
${overflowActions.length > 0 ? html`
|
|
367
|
+
<zn-dropdown placement="bottom-end" data-lang-overflow>
|
|
368
|
+
<zn-button
|
|
369
|
+
slot="trigger"
|
|
370
|
+
size="x-small"
|
|
371
|
+
color="default"
|
|
372
|
+
icon="keyboard_arrow_down"
|
|
373
|
+
?outline="${!overflowLangTabs.includes(this._activeLanguage)}"
|
|
374
|
+
></zn-button>
|
|
375
|
+
<zn-menu
|
|
376
|
+
.actions=${overflowActions}
|
|
377
|
+
@zn-menu-select="${this.handleOverflowSelect}"
|
|
378
|
+
></zn-menu>
|
|
379
|
+
</zn-dropdown>
|
|
380
|
+
` : nothing}
|
|
265
381
|
${availableLanguages.length > 0 ? html`
|
|
266
|
-
<zn-dropdown placement="bottom-end">
|
|
382
|
+
<zn-dropdown placement="bottom-end" data-lang-add>
|
|
267
383
|
<zn-button
|
|
268
384
|
slot="trigger"
|
|
269
385
|
size="x-small"
|
|
@@ -287,6 +403,7 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
|
|
|
287
403
|
${keyed(this._activeLanguage, html`
|
|
288
404
|
<zn-inline-edit
|
|
289
405
|
input-type=${this.inputType}
|
|
406
|
+
textarea-rows=${ifDefined(this.textareaRows)}
|
|
290
407
|
.value=${live(currentTranslation)}
|
|
291
408
|
name="${this.name}"
|
|
292
409
|
placeholder="Enter translation..."
|