@milaboratories/uikit 2.2.42 → 2.2.43

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/uikit",
3
- "version": "2.2.42",
3
+ "version": "2.2.43",
4
4
  "type": "module",
5
5
  "main": "dist/pl-uikit.umd.js",
6
6
  "module": "dist/pl-uikit.js",
@@ -32,8 +32,8 @@
32
32
  "vue-tsc": "^2.1.10",
33
33
  "yarpm": "^1.2.0",
34
34
  "svgo": "^3.3.2",
35
- "@platforma-sdk/model": "^1.21.0",
36
35
  "@milaboratories/helpers": "^1.6.11",
36
+ "@platforma-sdk/model": "^1.21.10",
37
37
  "@milaboratories/eslint-config": "^1.0.1"
38
38
  },
39
39
  "scripts": {
@@ -20,6 +20,7 @@ import DropdownListItem from '@/components/DropdownListItem.vue';
20
20
  import { deepEqual, deepIncludes } from '@/helpers/objects';
21
21
  import { normalizeListOptions } from '@/helpers/utils';
22
22
  import DropdownOverlay from '@/utils/DropdownOverlay/DropdownOverlay.vue';
23
+ import { PlMaskIcon24 } from '../PlMaskIcon24';
23
24
 
24
25
  const emit = defineEmits<{
25
26
  (e: 'update:modelValue', v: M[]): void;
@@ -42,7 +43,7 @@ const props = withDefaults(
42
43
  /**
43
44
  * List of available options for the dropdown
44
45
  */
45
- options: Readonly<ListOption<M>[]>;
46
+ options?: Readonly<ListOption<M>[]>;
46
47
  /**
47
48
  * A helper text displayed below the dropdown when there are no errors (optional).
48
49
  */
@@ -98,13 +99,13 @@ const placeholderRef = computed(() => {
98
99
  });
99
100
 
100
101
  const selectedOptionsRef = computed(() => {
101
- return normalizeListOptions(props.options).filter((opt) => deepIncludes(selectedValuesRef.value, opt.value));
102
+ return normalizeListOptions(props.options ?? []).filter((opt) => deepIncludes(selectedValuesRef.value, opt.value));
102
103
  });
103
104
 
104
105
  const filteredOptionsRef = computed(() => {
105
106
  const selectedValues = unref(selectedValuesRef);
106
107
 
107
- const options = normalizeListOptions(props.options);
108
+ const options = normalizeListOptions(props.options ?? []);
108
109
 
109
110
  return (
110
111
  data.search
@@ -128,7 +129,19 @@ const filteredOptionsRef = computed(() => {
128
129
  }));
129
130
  });
130
131
 
131
- const tabindex = computed(() => (props.disabled ? undefined : '0'));
132
+ const isLoadingOptions = computed(() => {
133
+ return props.options === undefined;
134
+ });
135
+
136
+ const isDisabled = computed(() => {
137
+ if (isLoadingOptions.value) {
138
+ return true;
139
+ }
140
+
141
+ return props.disabled;
142
+ });
143
+
144
+ const tabindex = computed(() => (isDisabled.value ? undefined : '0'));
132
145
 
133
146
  const updateActiveOption = () => {
134
147
  data.activeOption = tap(
@@ -223,7 +236,7 @@ watchPostEffect(() => {
223
236
  ref="rootRef"
224
237
  :tabindex="tabindex"
225
238
  class="pl-dropdown-multi"
226
- :class="{ open: data.open, error, disabled }"
239
+ :class="{ open: data.open, error, disabled: isDisabled }"
227
240
  @keydown="handleKeydown"
228
241
  @focusout="onFocusOut"
229
242
  >
@@ -234,7 +247,7 @@ watchPostEffect(() => {
234
247
  v-model="data.search"
235
248
  type="text"
236
249
  tabindex="-1"
237
- :disabled="disabled"
250
+ :disabled="isDisabled"
238
251
  :placeholder="placeholderRef"
239
252
  spellcheck="false"
240
253
  autocomplete="chrome-off"
@@ -245,7 +258,8 @@ watchPostEffect(() => {
245
258
  {{ opt.label || opt.value }}
246
259
  </PlChip>
247
260
  </div>
248
- <div class="arrow" @click.stop="toggleModel" />
261
+ <PlMaskIcon24 v-if="isLoadingOptions" name="loading" />
262
+ <div v-if="!isLoadingOptions" class="arrow" @click.stop="toggleModel" />
249
263
  <div class="pl-dropdown-multi__append">
250
264
  <slot name="append" />
251
265
  </div>
@@ -289,6 +289,11 @@
289
289
  --label-color: var(--color-dis-01);
290
290
  cursor: not-allowed;
291
291
  pointer-events: none;
292
+
293
+ .mask-loading {
294
+ animation: spin 2.5s linear infinite;
295
+ background-color: #07AD3E;
296
+ }
292
297
  }
293
298
 
294
299
  &__open-chips-container {
@@ -0,0 +1,73 @@
1
+ <script lang="ts" setup>
2
+ import type { ModelRef, RefOption } from '@/types';
3
+ import PlDropdownMulti from '../PlDropdownMulti/PlDropdownMulti.vue';
4
+ import { computed } from 'vue';
5
+
6
+ defineEmits<{
7
+ /**
8
+ * Emitted when the model value is updated.
9
+ */
10
+ (e: 'update:modelValue', value: ModelRef[] | undefined): void;
11
+ }>();
12
+
13
+ const props = withDefaults(
14
+ defineProps<{
15
+ /**
16
+ * The current selected values.
17
+ */
18
+ modelValue: ModelRef[] | undefined;
19
+ /**
20
+ * The label text for the dropdown field (optional)
21
+ */
22
+ label?: string;
23
+ /**
24
+ * List of available options for the dropdown
25
+ */
26
+ options?: Readonly<RefOption[]>;
27
+ /**
28
+ * A helper text displayed below the dropdown when there are no errors (optional).
29
+ */
30
+ helper?: string;
31
+ /**
32
+ * Error message displayed below the dropdown (optional)
33
+ */
34
+ error?: string;
35
+ /**
36
+ * Placeholder text shown when no value is selected.
37
+ */
38
+ placeholder?: string;
39
+ /**
40
+ * If `true`, the dropdown component is marked as required.
41
+ */
42
+ required?: boolean;
43
+ /**
44
+ * If `true`, the dropdown component is disabled and cannot be interacted with.
45
+ */
46
+ disabled?: boolean;
47
+ }>(),
48
+ {
49
+ modelValue: () => [],
50
+ label: undefined,
51
+ helper: undefined,
52
+ error: undefined,
53
+ placeholder: '...',
54
+ required: false,
55
+ disabled: false,
56
+ },
57
+ );
58
+
59
+ const options = computed(() =>
60
+ props.options?.map((opt) => ({
61
+ label: opt.label,
62
+ value: opt.ref,
63
+ })),
64
+ );
65
+ </script>
66
+
67
+ <template>
68
+ <PlDropdownMulti
69
+ v-bind="props"
70
+ :options="options"
71
+ @update:model-value="$emit('update:modelValue', $event)"
72
+ />
73
+ </template>
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
3
+ import { mount } from '@vue/test-utils';
4
+ import PlDropdown from '../PlDropdownMultiRef.vue';
5
+ import { delay } from '@milaboratories/helpers';
6
+
7
+ describe('PlDropdownMultiRef', () => {
8
+ it('modelValue', async () => {
9
+ const wrapper = mount(PlDropdown, {
10
+ props: {
11
+ 'modelValue': [
12
+ {
13
+ __isRef: true as const,
14
+ blockId: '2',
15
+ name: 'Block 2 Ref',
16
+ },
17
+ ],
18
+ 'onUpdate:modelValue': (e) => wrapper.setProps({ modelValue: e }),
19
+ 'options': [
20
+ {
21
+ label: 'Block 1 label Ref',
22
+ ref: {
23
+ __isRef: true as const,
24
+ blockId: '1',
25
+ name: 'Block 1 Ref',
26
+ },
27
+ },
28
+ {
29
+ label: 'Block 2 label Ref',
30
+ ref: {
31
+ __isRef: true as const,
32
+ blockId: '2',
33
+ name: 'Block 2 Ref',
34
+ },
35
+ },
36
+ ],
37
+ },
38
+ });
39
+
40
+ await wrapper.find('input').trigger('focus');
41
+
42
+ const getOptions = () => [...document.body.querySelectorAll('.dropdown-list-item')] as HTMLElement[];
43
+
44
+ const options = getOptions();
45
+
46
+ console.log('options', options);
47
+
48
+ expect(options.length).toBe(2);
49
+
50
+ console.log(wrapper.props('modelValue'), 'mv');
51
+ options[0].click();
52
+
53
+ await delay(20);
54
+
55
+ expect(wrapper.props('modelValue')).toEqual([
56
+ {
57
+ __isRef: true,
58
+ blockId: '2',
59
+ name: 'Block 2 Ref',
60
+ },
61
+ {
62
+ __isRef: true,
63
+ blockId: '1',
64
+ name: 'Block 1 Ref',
65
+ },
66
+ ]);
67
+
68
+ expect(getOptions().length).toBe(2); // options are not closed after click
69
+ });
70
+ });
@@ -0,0 +1 @@
1
+ export { default as PlDropdownMultiRef } from './PlDropdownMultiRef.vue';
package/src/index.ts CHANGED
@@ -38,6 +38,7 @@ export * from './components/PlTooltip';
38
38
  export * from './components/PlProgressBar';
39
39
  export * from './components/PlNumberField';
40
40
  export * from './components/PlDropdownMulti';
41
+ export * from './components/PlDropdownMultiRef';
41
42
  export * from './components/PlCheckbox';
42
43
  export * from './components/PlCheckboxGroup';
43
44
  export * from './components/PlChip';