@webitel/ui-sdk 26.8.104 → 26.8.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/{clients-BZ1QzRFi.js → clients-Dm3JLACL.js} +2 -2
- package/dist/{components-oyMSmFwI.js → components-CRmvV0ze.js} +21 -17
- package/dist/{composables-OP5kSvlh.js → composables-Vg-QfE_2.js} +112 -86
- package/dist/{convertDuration-CGW5IDMW.js → convertDuration-heRoQzks.js} +8 -8
- package/dist/{enums-Bd-8yrmg.js → enums-BDtfwdQu.js} +1 -0
- package/dist/ui-sdk.css +1 -1
- package/dist/ui-sdk.js +19 -3
- package/dist/ui-sdk.umd.cjs +342 -341
- package/dist/{useValidation-CtEfmUkB.js → useValidation-B4q8qUvG.js} +1 -1
- package/dist/{utils-B_8uwL9P.js → utils-DaacyMAw.js} +1 -1
- package/dist/{wt-action-bar-B4rcG26w.js → wt-action-bar-ChLl_-jR.js} +2 -2
- package/dist/{wt-badge-lFnfK2an.js → wt-badge-C8O4Oarp.js} +1 -1
- package/dist/{wt-button-BzYDkfhK.js → wt-button-C-BRwWdy.js} +2 -2
- package/dist/{wt-chat-emoji-CdNBvJez.js → wt-chat-emoji-DUYgD7x0.js} +4 -4
- package/dist/{wt-datepicker-D_O49-Ab.js → wt-datepicker-C1kACub3.js} +2 -2
- package/dist/{wt-display-chip-items-1uWroA2z.js → wt-display-chip-items-Dm6I2JFC.js} +2 -2
- package/dist/{wt-dual-panel-B0inNxRm.js → wt-dual-panel-D5TCilWN.js} +1 -1
- package/dist/{wt-expansion-card-CJjtuFDk.js → wt-expansion-card-2wdr_Hpi.js} +2 -2
- package/dist/{wt-expansion-panel-tqCCM3go.js → wt-expansion-panel-DP8zz2tS.js} +1 -1
- package/dist/{wt-galleria-CmaNfz7E.js → wt-galleria-iRpRiDc6.js} +1 -1
- package/dist/{wt-icon-DFtSR4bO.js → wt-icon-B8nQuJZu.js} +1 -1
- package/dist/{wt-icon-action-DUAnoMrj.js → wt-icon-action-g26vM7fD.js} +1 -1
- package/dist/{wt-icon-btn-CeGGT2PO.js → wt-icon-btn-BFRfANYh.js} +1 -1
- package/dist/{wt-notifications-bar-DWME3pmb.js → wt-notifications-bar-BnCbODMe.js} +2 -2
- package/dist/{wt-player-DXCQLKch.js → wt-player-DnoC6Gci.js} +3 -3
- package/dist/{wt-screen-recordings-action-Cx7-2gDE.js → wt-screen-recordings-action-biHVl6lR.js} +1 -1
- package/dist/{wt-search-bar-BkopW1qp.js → wt-search-bar-ByF2Wjsg.js} +1 -1
- package/dist/{wt-send-message-popup-C3qRY8Lk.js → wt-send-message-popup-afA26_0Q.js} +3 -3
- package/dist/{wt-status-select-DnaJ04Gw.js → wt-status-select-BOmAd__4.js} +2 -2
- package/dist/{wt-table-xmGhfp4p.js → wt-table-C_91bkNX.js} +5 -5
- package/dist/{wt-timepicker-C0DHJSeR.js → wt-timepicker-C4kMPkNd.js} +2 -2
- package/dist/{wt-toast-Lge1Y6IO.js → wt-toast-CBQIP-YS.js} +2 -2
- package/dist/{wt-tree-table-BTHxl_MY.js → wt-tree-table-DMK0J0Jx.js} +1 -1
- package/dist/{wt-type-extension-value-input-CkBr5oPm.js → wt-type-extension-value-input-CEX06xVC.js} +3 -3
- package/dist/{wt-vidstack-player-P4fT1R6k.js → wt-vidstack-player-1Z1fEhkA.js} +5 -5
- package/package.json +1 -1
- package/src/components/_internals/composables/useSelect/__tests__/useSelectAutoOpen.spec.ts +206 -0
- package/src/components/_internals/composables/useSelect/types.ts +1 -0
- package/src/components/_internals/composables/useSelect/useSelect.ts +6 -2
- package/src/components/_internals/composables/useSelect/useSelectAutoOpen.ts +106 -0
- package/src/components/_internals/types/PrimevueInstance.ts +1 -0
- package/src/components/wt-chip/wt-chip.vue +4 -2
- package/src/components/wt-multi-select/wt-multi-select.vue +2 -0
- package/src/components/wt-single-select/wt-single-select.vue +2 -0
- package/src/components/wt-table/wt-table.vue +6 -0
- package/src/enums/ChipColor/ChipColor.ts +1 -0
- package/src/modules/UploadCsvPopup/components/wt-upload-csv-popup.vue +27 -27
- package/src/modules/UploadCsvPopup/composable/__tests__/useUploadCsv.spec.js +1 -1
- package/src/modules/UploadCsvPopup/composable/useUploadCsv.ts +3 -1
- package/src/plugins/primevue/theme/components/chip/chip.js +4 -0
- package/src/scripts/__tests__/convertDuration.spec.js +32 -0
- package/types/.tsbuildinfo +1 -1
- package/types/components/_internals/composables/useSelect/types.d.ts +1 -0
- package/types/components/_internals/composables/useSelect/useSelect.d.ts +1 -1
- package/types/components/_internals/composables/useSelect/useSelectAutoOpen.d.ts +15 -0
- package/types/components/_internals/types/PrimevueInstance.d.ts +1 -0
- package/types/components/wt-chip/wt-chip.vue.d.ts +4 -2
- package/types/components/wt-datepicker/wt-datepicker.vue.d.ts +2 -2
- package/types/components/wt-multi-select/wt-multi-select.vue.d.ts +1 -0
- package/types/components/wt-popover/wt-popover.vue.d.ts +2 -2
- package/types/components/wt-single-select/wt-single-select.vue.d.ts +1 -0
- package/types/components/wt-tooltip/_internals/wt-tooltip-floating.vue.d.ts +2 -2
- package/types/enums/ChipColor/ChipColor.d.ts +1 -0
- package/types/plugins/primevue/theme/components/chip/chip.d.ts +12 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { onBeforeUnmount, type Ref } from 'vue';
|
|
2
|
+
|
|
3
|
+
import type { SelectComponentRef } from './types';
|
|
4
|
+
|
|
5
|
+
/** ~500ms at 60fps — opens anyway if something animates without end. */
|
|
6
|
+
const MAX_SETTLE_FRAMES = 30;
|
|
7
|
+
|
|
8
|
+
/** `getAnimations()` marks the real end; polling geometry reads a lull mid-animation as one. */
|
|
9
|
+
const waitForAncestorAnimations = async (el: HTMLElement) => {
|
|
10
|
+
const animations: Animation[] = [];
|
|
11
|
+
let node: HTMLElement | null = el;
|
|
12
|
+
|
|
13
|
+
while (node) {
|
|
14
|
+
if (typeof node.getAnimations === 'function') {
|
|
15
|
+
animations.push(...node.getAnimations());
|
|
16
|
+
}
|
|
17
|
+
node = node.parentElement;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!animations.length) return;
|
|
21
|
+
|
|
22
|
+
await Promise.all(
|
|
23
|
+
animations.map((animation) => animation.finished.catch(() => undefined)),
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Opens the dropdown (`autoOpen`) only once the select has stopped moving.
|
|
29
|
+
*
|
|
30
|
+
* In a popover the trigger keeps shifting through the 300ms enter animation,
|
|
31
|
+
* and primevue aligns the overlay to the trigger's rect — open too early and
|
|
32
|
+
* the dropdown sits in the wrong place until it snaps. The options half is the
|
|
33
|
+
* caller's: `useSelect` calls this after the first fetch resolves.
|
|
34
|
+
*
|
|
35
|
+
* [WTEL-10353](https://webitel.atlassian.net/browse/WTEL-10353)
|
|
36
|
+
*/
|
|
37
|
+
export const useSelectAutoOpen = (
|
|
38
|
+
autoOpen: (() => boolean | undefined) | undefined,
|
|
39
|
+
selectRef: Ref<SelectComponentRef | undefined>,
|
|
40
|
+
) => {
|
|
41
|
+
let rafId: number | null = null;
|
|
42
|
+
let isCancelled = false;
|
|
43
|
+
|
|
44
|
+
const cancel = () => {
|
|
45
|
+
isCancelled = true;
|
|
46
|
+
if (rafId !== null) {
|
|
47
|
+
cancelAnimationFrame(rafId);
|
|
48
|
+
rafId = null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const waitForSettledRect = () =>
|
|
53
|
+
new Promise<void>((resolve) => {
|
|
54
|
+
let previousRect: DOMRect | undefined;
|
|
55
|
+
let frames = 0;
|
|
56
|
+
|
|
57
|
+
const step = () => {
|
|
58
|
+
rafId = null;
|
|
59
|
+
if (isCancelled) return;
|
|
60
|
+
|
|
61
|
+
const el = selectRef.value?.$el;
|
|
62
|
+
if (!el) return;
|
|
63
|
+
|
|
64
|
+
const rect = el.getBoundingClientRect();
|
|
65
|
+
const isSettled =
|
|
66
|
+
!!previousRect &&
|
|
67
|
+
rect.top === previousRect.top &&
|
|
68
|
+
rect.left === previousRect.left &&
|
|
69
|
+
rect.width === previousRect.width &&
|
|
70
|
+
rect.height === previousRect.height;
|
|
71
|
+
|
|
72
|
+
if (isSettled || ++frames >= MAX_SETTLE_FRAMES) {
|
|
73
|
+
resolve();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
previousRect = rect;
|
|
78
|
+
rafId = requestAnimationFrame(step);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
rafId = requestAnimationFrame(step);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const openWhenSettled = async () => {
|
|
85
|
+
if (!autoOpen?.()) return;
|
|
86
|
+
|
|
87
|
+
const el = selectRef.value?.$el;
|
|
88
|
+
if (!el) return;
|
|
89
|
+
|
|
90
|
+
isCancelled = false;
|
|
91
|
+
|
|
92
|
+
await waitForAncestorAnimations(el);
|
|
93
|
+
if (isCancelled) return;
|
|
94
|
+
|
|
95
|
+
await waitForSettledRect();
|
|
96
|
+
if (isCancelled) return;
|
|
97
|
+
|
|
98
|
+
selectRef.value?.show?.();
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
onBeforeUnmount(cancel);
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
openWhenSettled,
|
|
105
|
+
};
|
|
106
|
+
};
|
|
@@ -31,10 +31,12 @@ import { ChipColor, ComponentSize } from '../../enums';
|
|
|
31
31
|
|
|
32
32
|
interface WtProps extends ChipProps {
|
|
33
33
|
/**
|
|
34
|
-
* Chip color. "main" and "
|
|
34
|
+
* Chip color. "main" and "transfer" are chip-specific colors; the rest follow
|
|
35
|
+
* the semantic scheme. "info" renders as a light tint with dark text, like
|
|
36
|
+
* "main", rather than a solid fill.
|
|
35
37
|
* @type {ChipColor}
|
|
36
38
|
* @default ChipColor.MAIN
|
|
37
|
-
* @options ['main', '
|
|
39
|
+
* @options ['main', 'primary', 'on-primary', 'secondary', 'success', 'warning', 'error', 'info', 'transfer']
|
|
38
40
|
*/
|
|
39
41
|
color?: ChipColor;
|
|
40
42
|
/**
|
|
@@ -167,6 +167,7 @@ interface Props extends Omit<SelectProps, 'options'> {
|
|
|
167
167
|
* false disables options search
|
|
168
168
|
*/
|
|
169
169
|
filterable?: boolean;
|
|
170
|
+
autoOpen?: boolean;
|
|
170
171
|
/**
|
|
171
172
|
* true shows the clear button
|
|
172
173
|
*/
|
|
@@ -260,6 +261,7 @@ const {
|
|
|
260
261
|
searchMethod: computed(() => props.searchMethod),
|
|
261
262
|
selectId: computed(() => selectId),
|
|
262
263
|
isSingle: false,
|
|
264
|
+
autoOpen: () => props.autoOpen,
|
|
263
265
|
strictApiOptions: computed(() => props.strictApiOptions),
|
|
264
266
|
emit,
|
|
265
267
|
});
|
|
@@ -140,6 +140,7 @@ interface Props extends Omit<SelectProps, 'size' | 'options'> {
|
|
|
140
140
|
* false disables options search
|
|
141
141
|
*/
|
|
142
142
|
filterable?: boolean;
|
|
143
|
+
autoOpen?: boolean;
|
|
143
144
|
/**
|
|
144
145
|
* true shows the clear button
|
|
145
146
|
*/
|
|
@@ -227,6 +228,7 @@ const {
|
|
|
227
228
|
searchMethod: computed(() => props.searchMethod),
|
|
228
229
|
selectId: computed(() => selectId),
|
|
229
230
|
isSingle: true,
|
|
231
|
+
autoOpen: () => props.autoOpen,
|
|
230
232
|
strictApiOptions: computed(() => props.strictApiOptions),
|
|
231
233
|
emit,
|
|
232
234
|
});
|
|
@@ -673,7 +673,13 @@ onUnmounted(() => {
|
|
|
673
673
|
.wt-table__empty {
|
|
674
674
|
position: absolute;
|
|
675
675
|
inset: 0;
|
|
676
|
+
z-index: 1;
|
|
676
677
|
display: flex;
|
|
678
|
+
pointer-events: none;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
.wt-table__empty > * {
|
|
682
|
+
pointer-events: auto;
|
|
677
683
|
}
|
|
678
684
|
|
|
679
685
|
.wt-table :deep(.wt-table__wrapper--overlay tr.p-datatable-empty-message) {
|
|
@@ -139,63 +139,63 @@ import { ref, toRefs } from 'vue';
|
|
|
139
139
|
import { useI18n } from 'vue-i18n';
|
|
140
140
|
|
|
141
141
|
import useUploadCsv, {
|
|
142
|
-
|
|
142
|
+
type UseUploadCsvProps,
|
|
143
143
|
} from '../composable/useUploadCsv';
|
|
144
144
|
import type { CsvMappingField } from '../scripts/normalizeCSVData';
|
|
145
145
|
import HandlingCSVMode from '../types/WtUploadCSVHandlingMode.enum';
|
|
146
146
|
|
|
147
147
|
interface CharsetOption {
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
name: string;
|
|
149
|
+
value: string;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
interface Props extends UseUploadCsvProps {
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
file: File | null;
|
|
154
|
+
mappingFields: CsvMappingField[];
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
const props = withDefaults(defineProps<Props>(), {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
file: null,
|
|
159
|
+
mappingFields: () => [],
|
|
160
|
+
handlingMode: HandlingCSVMode.PROCESS,
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
const emit = defineEmits<{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
(e: 'changeMappingFields', value: unknown[]): void;
|
|
165
|
+
(e: 'save'): void;
|
|
166
|
+
(e: 'close'): void;
|
|
167
167
|
}>();
|
|
168
168
|
|
|
169
169
|
const { t } = useI18n();
|
|
170
170
|
|
|
171
171
|
const getFieldLabel = (field: CsvMappingField) =>
|
|
172
|
-
|
|
172
|
+
field.locale ? t(field.locale) : field.name;
|
|
173
173
|
|
|
174
174
|
const skipHeaders = ref(true);
|
|
175
175
|
const separator = ref(',');
|
|
176
176
|
const charsetOptions = ref<CharsetOption[]>([]);
|
|
177
177
|
const charset = ref<CharsetOption>({
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
name: 'UTF-8',
|
|
179
|
+
value: 'utf-8',
|
|
180
180
|
});
|
|
181
181
|
|
|
182
182
|
const { file, mappingFields } = toRefs(props);
|
|
183
183
|
|
|
184
184
|
const {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
185
|
+
isReadingFile,
|
|
186
|
+
isParsingCSV,
|
|
187
|
+
isParsingPreview,
|
|
188
|
+
csvPreviewTableData,
|
|
189
|
+
csvPreviewTableHeaders,
|
|
190
|
+
csvColumns,
|
|
191
|
+
allowSaveAction,
|
|
192
|
+
processCSV,
|
|
193
|
+
close,
|
|
194
194
|
} = useUploadCsv({
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
195
|
+
props,
|
|
196
|
+
emit,
|
|
197
|
+
skipHeaders,
|
|
198
|
+
separator,
|
|
199
199
|
});
|
|
200
200
|
</script>
|
|
201
201
|
|
|
@@ -18,4 +18,36 @@ describe('Case converters', () => {
|
|
|
18
18
|
const duration = '00:00:00';
|
|
19
19
|
expect(convertDuration(time)).toBe(duration);
|
|
20
20
|
});
|
|
21
|
+
|
|
22
|
+
describe('alwaysShowHours: false', () => {
|
|
23
|
+
it('drops the hours segment below an hour', () => {
|
|
24
|
+
expect(
|
|
25
|
+
convertDuration(111, {
|
|
26
|
+
alwaysShowHours: false,
|
|
27
|
+
}),
|
|
28
|
+
).toBe('01:51');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('keeps the hours segment once there are hours to show', () => {
|
|
32
|
+
expect(
|
|
33
|
+
convertDuration(3725, {
|
|
34
|
+
alwaysShowHours: false,
|
|
35
|
+
}),
|
|
36
|
+
).toBe('01:02:05');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('drops the hours segment for a false value too', () => {
|
|
40
|
+
expect(
|
|
41
|
+
convertDuration(null, {
|
|
42
|
+
alwaysShowHours: false,
|
|
43
|
+
}),
|
|
44
|
+
).toBe('00:00');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// live timers rely on the width staying fixed as they tick past an hour
|
|
49
|
+
it('keeps the hours segment by default', () => {
|
|
50
|
+
expect(convertDuration(111)).toBe('00:01:51');
|
|
51
|
+
expect(convertDuration(111, {})).toBe('00:01:51');
|
|
52
|
+
});
|
|
21
53
|
});
|