@kubex/zinc 1.0.104 → 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 +604 -115
- package/dist/vscode.html-custom-data.json +33 -13
- package/dist/web-types.json +73 -26
- package/dist/zn.d.ts +24 -3
- package/dist/zn.min.js +347 -294
- 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/markdown-editor/markdown-editor.component.ts +107 -64
- package/src/components/markdown-editor/markdown-editor.scss +23 -24
- 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
|
@@ -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..."
|