@v1nt1248/3nclient-lib 0.3.27 → 0.3.29

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.
Files changed (115) hide show
  1. package/dist/chunks/ui3n-notification-Dr_3Td9N.js +279 -0
  2. package/dist/components/index.d.ts +12 -12
  3. package/dist/components/ui3n-autocomplete/types.d.ts +8 -0
  4. package/dist/components/ui3n-autocomplete/ui3n-autocomplete.d.ts +2 -2
  5. package/dist/components/ui3n-badge/types.d.ts +12 -0
  6. package/dist/components/ui3n-badge/ui3n-badge-simple.d.ts +1 -1
  7. package/dist/components/ui3n-badge/ui3n-badge.d.ts +1 -1
  8. package/dist/components/ui3n-breadcrumbs/types.d.ts +1 -1
  9. package/dist/components/ui3n-breadcrumbs/ui3n-breadcrumb.d.ts +2 -2
  10. package/dist/components/ui3n-button/types.d.ts +4 -2
  11. package/dist/components/ui3n-checkbox/types.d.ts +11 -0
  12. package/dist/components/ui3n-checkbox/ui3n-checkbox.d.ts +4 -1
  13. package/dist/components/ui3n-chip/types.d.ts +6 -1
  14. package/dist/components/ui3n-chip/ui3n-chip.d.ts +2 -0
  15. package/dist/components/ui3n-drop-files/types.d.ts +7 -0
  16. package/dist/components/ui3n-drop-files/ui3n-drop-files.d.ts +7 -1
  17. package/dist/components/ui3n-editable/types.d.ts +11 -0
  18. package/dist/components/ui3n-editable/ui3n-editable.d.ts +4 -2
  19. package/dist/components/ui3n-icon/types.d.ts +5 -1
  20. package/dist/components/ui3n-icon/ui3n-icon.d.ts +2 -2
  21. package/dist/components/ui3n-input/types.d.ts +4 -0
  22. package/dist/components/ui3n-input/ui3n-input.d.ts +4 -1
  23. package/dist/components/ui3n-input-file/types.d.ts +11 -0
  24. package/dist/components/ui3n-input-file/ui3n-input-file.d.ts +4 -1
  25. package/dist/components/ui3n-list/types.d.ts +4 -0
  26. package/dist/components/ui3n-menu/types.d.ts +4 -0
  27. package/dist/components/ui3n-menu/ui3n-menu.d.ts +1 -1
  28. package/dist/components/ui3n-notification/ui3n-notification.d.ts +2 -2
  29. package/dist/components/ui3n-progress/ui3n-progress-circular.d.ts +1 -1
  30. package/dist/components/ui3n-progress/ui3n-progress-linear.d.ts +1 -1
  31. package/dist/components/ui3n-radio-group/types.d.ts +18 -0
  32. package/dist/components/ui3n-radio-group/ui3n-radio-group.d.ts +3 -1
  33. package/dist/components/ui3n-radio-group/ui3n-radio.d.ts +6 -7
  34. package/dist/components/ui3n-scrollbar-horizontal/types.d.ts +1 -0
  35. package/dist/components/ui3n-scrollbar-horizontal/ui3n-scroolbar-horizontal.d.ts +1 -0
  36. package/dist/components/ui3n-scrollbar-vertical/types.d.ts +3 -0
  37. package/dist/components/ui3n-scrollbar-vertical/ui3n-scrollbar-vertical.d.ts +3 -0
  38. package/dist/components/ui3n-selector/types.d.ts +11 -0
  39. package/dist/components/ui3n-selector/ui3n-selector.d.ts +2 -2
  40. package/dist/components/ui3n-slider/types.d.ts +11 -0
  41. package/dist/components/ui3n-slider/ui3n-slider.d.ts +4 -1
  42. package/dist/components/ui3n-step-line-bar/types.d.ts +4 -0
  43. package/dist/components/ui3n-switch/types.d.ts +11 -0
  44. package/dist/components/ui3n-switch/ui3n-switch.d.ts +4 -1
  45. package/dist/components/ui3n-table/composables/useTable.d.ts +1 -0
  46. package/dist/components/ui3n-table/types.d.ts +4 -0
  47. package/dist/components/ui3n-table/ui3n-table-sort-icon.d.ts +4 -1
  48. package/dist/components/ui3n-tabs/types.d.ts +4 -0
  49. package/dist/components/ui3n-text/types.d.ts +11 -0
  50. package/dist/components/ui3n-text/ui3n-text.d.ts +4 -1
  51. package/dist/components/ui3n-tooltip/types.d.ts +4 -0
  52. package/dist/components/ui3n-tooltip/ui3n-tooltip.d.ts +4 -2
  53. package/dist/style.css +1 -1
  54. package/dist/ui3n-components.js +2083 -1697
  55. package/dist/ui3n-plugins.js +1 -1
  56. package/package.json +1 -1
  57. package/src/components/index.ts +29 -7
  58. package/src/components/ui3n-autocomplete/types.ts +9 -1
  59. package/src/components/ui3n-autocomplete/ui3n-autocomplete.vue +182 -51
  60. package/src/components/ui3n-badge/types.ts +10 -0
  61. package/src/components/ui3n-badge/ui3n-badge-simple.vue +54 -55
  62. package/src/components/ui3n-badge/ui3n-badge.vue +4 -0
  63. package/src/components/ui3n-breadcrumbs/types.ts +1 -1
  64. package/src/components/ui3n-breadcrumbs/ui3n-breadcrumb.vue +7 -5
  65. package/src/components/ui3n-button/types.ts +4 -2
  66. package/src/components/ui3n-button/ui3n-button.vue +24 -19
  67. package/src/components/ui3n-checkbox/types.ts +12 -0
  68. package/src/components/ui3n-checkbox/ui3n-checkbox.vue +79 -29
  69. package/src/components/ui3n-chip/types.ts +6 -1
  70. package/src/components/ui3n-chip/ui3n-chip.vue +64 -61
  71. package/src/components/ui3n-dialog/ui3n-dialog.vue +3 -3
  72. package/src/components/ui3n-drop-files/types.ts +8 -0
  73. package/src/components/ui3n-drop-files/ui3n-drop-files.vue +73 -29
  74. package/src/components/ui3n-editable/types.ts +12 -0
  75. package/src/components/ui3n-editable/ui3n-editable.vue +56 -24
  76. package/src/components/ui3n-icon/types.ts +5 -1
  77. package/src/components/ui3n-icon/ui3n-icon.vue +45 -50
  78. package/src/components/ui3n-input/types.ts +4 -0
  79. package/src/components/ui3n-input/ui3n-input.vue +14 -1
  80. package/src/components/ui3n-input-file/types.ts +12 -0
  81. package/src/components/ui3n-input-file/ui3n-input-file.vue +33 -16
  82. package/src/components/ui3n-list/types.ts +4 -0
  83. package/src/components/ui3n-list/ui3n-list.vue +3 -1
  84. package/src/components/ui3n-menu/types.ts +4 -0
  85. package/src/components/ui3n-menu/ui3n-menu.vue +43 -32
  86. package/src/components/ui3n-notification/ui3n-notification.vue +190 -175
  87. package/src/components/ui3n-progress/ui3n-progress-circular.vue +40 -22
  88. package/src/components/ui3n-progress/ui3n-progress-linear.vue +14 -7
  89. package/src/components/ui3n-radio-group/types.ts +20 -0
  90. package/src/components/ui3n-radio-group/ui3n-radio-group.vue +61 -48
  91. package/src/components/ui3n-radio-group/ui3n-radio.vue +60 -65
  92. package/src/components/ui3n-scrollbar-horizontal/types.ts +1 -0
  93. package/src/components/ui3n-scrollbar-horizontal/ui3n-scroolbar-horizontal.vue +8 -1
  94. package/src/components/ui3n-scrollbar-vertical/types.ts +3 -0
  95. package/src/components/ui3n-scrollbar-vertical/ui3n-scrollbar-vertical.vue +12 -5
  96. package/src/components/ui3n-selector/types.ts +12 -0
  97. package/src/components/ui3n-selector/ui3n-selector.vue +63 -40
  98. package/src/components/ui3n-slider/types.ts +12 -0
  99. package/src/components/ui3n-slider/ui3n-slider.vue +88 -39
  100. package/src/components/ui3n-step-line-bar/types.ts +4 -0
  101. package/src/components/ui3n-step-line-bar/ui3n-step-line-bar.vue +8 -10
  102. package/src/components/ui3n-switch/types.ts +12 -0
  103. package/src/components/ui3n-switch/ui3n-switch.vue +57 -25
  104. package/src/components/ui3n-table/composables/useTable.ts +17 -0
  105. package/src/components/ui3n-table/types.ts +4 -0
  106. package/src/components/ui3n-table/ui3n-table-sort-icon.vue +9 -8
  107. package/src/components/ui3n-table/ui3n-table.vue +48 -17
  108. package/src/components/ui3n-tabs/types.ts +4 -0
  109. package/src/components/ui3n-tabs/ui3n-tabs.vue +146 -108
  110. package/src/components/ui3n-text/types.ts +12 -0
  111. package/src/components/ui3n-text/ui3n-text.vue +56 -15
  112. package/src/components/ui3n-tooltip/types.ts +4 -0
  113. package/src/components/ui3n-tooltip/ui3n-tooltip.vue +61 -43
  114. package/src/components/ui3n-virtual-scroll/ui3n-virtual-scroll.vue +201 -17
  115. package/dist/chunks/ui3n-notification-DlDM-u-R.js +0 -276
@@ -1,19 +1,3 @@
1
- <!--
2
- Copyright (C) 2026 3NSoft Inc.
3
-
4
- This program is free software: you can redistribute it and/or modify it under
5
- the terms of the GNU General Public License as published by the Free Software
6
- Foundation, either version 3 of the License, or (at your option) any later
7
- version.
8
-
9
- This program is distributed in the hope that it will be useful, but
10
- WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
- See the GNU General Public License for more details.
13
-
14
- You should have received a copy of the GNU General Public License along with
15
- this program. If not, see <http://www.gnu.org/licenses/>.
16
- -->
17
1
  <script setup lang="ts" generic="T extends Ui3nSelectorOptionBase">
18
2
  import { ref, computed, type ComputedRef, useTemplateRef, watch } from 'vue';
19
3
  import isEmpty from 'lodash/isEmpty';
@@ -25,6 +9,7 @@
25
9
  Ui3nSelectorProps,
26
10
  Ui3nSelectorEmits,
27
11
  Ui3nSelectorSlots,
12
+ Ui3nSelectorExpose,
28
13
  Ui3nSelectorItemDisplayingFunction,
29
14
  } from './types';
30
15
  import Ui3nButton from '../ui3n-button/ui3n-button.vue';
@@ -32,6 +17,7 @@
32
17
  import Ui3nMenu from '../ui3n-menu/ui3n-menu.vue';
33
18
 
34
19
  const props = withDefaults(defineProps<Ui3nSelectorProps<T>>(), {
20
+ name: undefined,
35
21
  label: '',
36
22
  items: () => [] as T[],
37
23
  itemValue: 'id',
@@ -219,6 +205,23 @@
219
205
  }
220
206
  }
221
207
 
208
+ function clear() {
209
+ resetValue();
210
+ }
211
+
212
+ defineExpose<Ui3nSelectorExpose>({
213
+ clear,
214
+ });
215
+
216
+ watch(
217
+ () => props.name,
218
+ newName => {
219
+ if (!newName) {
220
+ clear();
221
+ }
222
+ },
223
+ );
224
+
222
225
  watch(
223
226
  () => isMenuOpen.value,
224
227
  (val, oVal) => {
@@ -245,7 +248,17 @@
245
248
  </script>
246
249
 
247
250
  <template>
248
- <div :class="$style.ui3nSelector">
251
+ <div
252
+ :id="id"
253
+ :class="$style.ui3nSelector"
254
+ >
255
+ <input
256
+ v-if="name && modelValue"
257
+ type="hidden"
258
+ :name="name"
259
+ :value="typeof modelValue === 'object' ? JSON.stringify(modelValue) : String(modelValue)"
260
+ />
261
+
249
262
  <label
250
263
  v-if="label"
251
264
  :class="$style.label"
@@ -362,7 +375,15 @@
362
375
  @use '@/assets/styles/mixins' as mixins;
363
376
 
364
377
  .ui3nSelector {
365
- --selector-activator-height: 32px;
378
+ --ui3n-selector-activator-height: 32px;
379
+ --ui3n-selector-border-radius: calc(var(--ui3n-selector-activator-height) / 2.5);
380
+ --ui3n-selector-font-size: 12px;
381
+ --ui3n-selector-trigger-padding: 0 24px 0 8px;
382
+ --ui3n-selector-trigger-font-size: 13px;
383
+ --ui3n-selector-item-min-height: 32px;
384
+ --ui3n-selector-item-padding: 4px;
385
+ --ui3n-selector-item-font-size: 13px;
386
+ --ui3n-selector-item-border-radius: 4px;
366
387
 
367
388
  position: relative;
368
389
  width: 100%;
@@ -371,35 +392,37 @@
371
392
  .label {
372
393
  display: block;
373
394
  width: 100%;
374
- font-size: var(--font-12);
395
+ font-size: var(--ui3n-selector-font-size);
375
396
  font-weight: 500;
376
- line-height: var(--font-16);
397
+ line-height: 1.33;
377
398
  color: var(--color-text-control-primary-default);
378
- margin-bottom: var(--spacing-xs);
399
+ margin-bottom: 4px;
379
400
  }
380
401
 
381
402
  .menu {
382
403
  width: 100%;
383
404
  max-width: 100% !important;
405
+ border-radius: var(--ui3n-selector-border-radius);
384
406
 
385
407
  & > div {
386
408
  max-width: 100% !important;
409
+ border-radius: var(--ui3n-selector-border-radius);
387
410
  }
388
411
  }
389
412
 
390
413
  .trigger {
391
414
  display: flex;
392
415
  width: 100%;
393
- height: var(--selector-activator-height);
394
- padding: 0 var(--spacing-ml) 0 var(--spacing-s);
416
+ height: var(--ui3n-selector-activator-height);
417
+ padding: var(--ui3n-selector-trigger-padding);
395
418
  justify-content: flex-start;
396
419
  align-items: center;
397
420
  background-color: var(--color-bg-control-secondary-default);
398
- border-radius: var(--spacing-xs);
421
+ border-radius: var(--ui3n-selector-border-radius);
399
422
  color: var(--color-text-control-primary-default);
400
- font-size: var(--font-13);
423
+ font-size: var(--ui3n-selector-trigger-font-size);
401
424
  font-weight: 400;
402
- line-height: var(--font-16);
425
+ line-height: 1.23;
403
426
  transition: all 0.2s ease-in-out;
404
427
  cursor: pointer;
405
428
  @include mixins.text-overflow-ellipsis();
@@ -423,13 +446,13 @@
423
446
  }
424
447
 
425
448
  &.clearable {
426
- padding-right: calc(var(--spacing-xxl) + var(--spacing-xs));
449
+ padding-right: 52px;
427
450
  }
428
451
 
429
452
  .clearBtn {
430
453
  position: absolute;
431
- top: var(--spacing-xs);
432
- right: var(--spacing-ml);
454
+ top: 4px;
455
+ right: 24px;
433
456
  }
434
457
 
435
458
  &.triggerFocused {
@@ -442,32 +465,32 @@
442
465
  position: relative;
443
466
  width: 100%;
444
467
  background-color: var(--color-bg-block-primary-default);
445
- padding: var(--spacing-xs);
468
+ padding: var(--ui3n-selector-body-padding);
446
469
 
447
470
  .noData {
448
471
  display: flex;
449
- min-height: var(--spacing-l);
472
+ min-height: var(--ui3n-selector-item-min-height);
450
473
  justify-content: flex-start;
451
474
  align-items: center;
452
- padding: var(--spacing-xs) var(--spacing-s);
453
- font-size: var(--font-13);
454
- line-height: var(--font-16);
475
+ padding: var(--ui3n-selector-item-padding) calc(var(--ui3n-selector-item-padding) * 2);
476
+ font-size: var(--ui3n-selector-item-font-size);
477
+ line-height: 1.33;
455
478
  font-weight: 500;
456
479
  color: var(--color-text-control-primary-default);
457
- border-radius: var(--spacing-xs);
480
+ border-radius: var(--ui3n-selector-item-border-radius);
458
481
  }
459
482
 
460
483
  .item {
461
484
  display: flex;
462
- min-height: var(--spacing-l);
485
+ min-height: var(--ui3n-selector-item-min-height);
463
486
  justify-content: flex-start;
464
487
  align-items: center;
465
- padding: var(--spacing-xs) var(--spacing-s);
466
- font-size: var(--font-13);
467
- line-height: var(--font-16);
488
+ padding: var(--ui3n-selector-item-padding) calc(var(--ui3n-selector-item-padding) * 2);
489
+ font-size: var(--ui3n-selector-item-font-size);
490
+ line-height: 1.33;
468
491
  font-weight: 500;
469
492
  color: var(--color-text-control-primary-default);
470
- border-radius: var(--spacing-xs);
493
+ border-radius: var(--ui3n-selector-item-border-radius);
471
494
  user-select: none;
472
495
  cursor: pointer;
473
496
 
@@ -1,4 +1,12 @@
1
1
  export interface UI3nSliderProps {
2
+ /**
3
+ * Root element id
4
+ */
5
+ id?: string;
6
+ /**
7
+ * HTML name attribute for form submission
8
+ */
9
+ name?: string;
2
10
  /**
3
11
  * Current slider value
4
12
  */
@@ -70,3 +78,7 @@ export interface UI3nSliderEmits {
70
78
  */
71
79
  (event: 'update:modelValue', value: number | [number, number]): void;
72
80
  }
81
+
82
+ export interface UI3nSliderExpose {
83
+ clear: () => void;
84
+ }
@@ -4,9 +4,10 @@
4
4
  import Ui3nTooltip from '../ui3n-tooltip/ui3n-tooltip.vue';
5
5
  import { round } from '@/utils';
6
6
  import type { Nullable } from '@/types';
7
- import type { UI3nSliderProps, UI3nSliderEmits } from './types';
7
+ import type { UI3nSliderProps, UI3nSliderEmits, UI3nSliderExpose } from './types';
8
8
 
9
9
  const props = withDefaults(defineProps<UI3nSliderProps>(), {
10
+ name: undefined,
10
11
  min: 0,
11
12
  max: 100,
12
13
  labelVisible: 'normal',
@@ -34,14 +35,9 @@
34
35
  const innerValue = ref<number | [number, number]>(0);
35
36
  const selectedPointer = ref<Nullable<1 | 2>>(null);
36
37
 
37
- const sliderHeight = computed(() => {
38
- const height = Math.max(Number(props.trackHeight), Number(props.thumbSize));
39
- return `${height}px`;
40
- });
41
- const trackHeightCss = computed(() => `${props.trackHeight}px`);
42
38
  const thumbSizeCss = computed(() => `${props.thumbSize}px`);
43
39
  const diff = computed(() => Number(props.max) - Number(props.min));
44
- const innerStep = computed(() => props.step ? Number(props.step) : diff.value / 100);
40
+ const innerStep = computed(() => (props.step ? Number(props.step) : diff.value / 100));
45
41
 
46
42
  const activeBlockStyle = computed(() => {
47
43
  const style = {} as Record<'left' | 'width', string>;
@@ -51,15 +47,14 @@
51
47
  if (minVal <= Number(props.min)) {
52
48
  style.left = '0px';
53
49
  } else if (minVal < Number(props.max)) {
54
- style.left = `${round((minVal - Number(props.min)) / diff.value * 100, 0)}%`;
50
+ style.left = `${round(((minVal - Number(props.min)) / diff.value) * 100, 0)}%`;
55
51
  }
56
52
 
57
53
  if (maxVal >= Number(props.max)) {
58
- style.width = minVal <= Number(props.min)
59
- ? '100%'
60
- : `${round((Number(props.max) - minVal) / diff.value * 100, 0)}%`;
54
+ style.width =
55
+ minVal <= Number(props.min) ? '100%' : `${round(((Number(props.max) - minVal) / diff.value) * 100, 0)}%`;
61
56
  } else if (maxVal > Number(props.min)) {
62
- style.width = `${round((maxVal - minVal) / diff.value * 100, 0)}%`;
57
+ style.width = `${round(((maxVal - minVal) / diff.value) * 100, 0)}%`;
63
58
  }
64
59
 
65
60
  return style;
@@ -73,30 +68,32 @@
73
68
  style.width = '100%';
74
69
  } else {
75
70
  style.left = '0px';
76
- style.width = `${round(((innerValue.value as number) - Number(props.min)) / diff.value * 100, 0)}%`;
71
+ style.width = `${round((((innerValue.value as number) - Number(props.min)) / diff.value) * 100, 0)}%`;
77
72
  }
78
73
 
79
74
  return style;
80
75
  }) as ComputedRef<Record<string, string>>;
81
76
 
82
- const pointer1PositionCss = computed(() => props.range
83
- ? `calc(${activeBlockStyle.value.left} - calc(${thumbSizeCss.value} / 2))`
84
- : `calc(${activeBlockStyle.value.width} - calc(${thumbSizeCss.value} / 2))`,
77
+ const pointer1PositionCss = computed(() =>
78
+ props.range
79
+ ? `calc(${activeBlockStyle.value.left} - calc(${thumbSizeCss.value} / 2))`
80
+ : `calc(${activeBlockStyle.value.width} - calc(${thumbSizeCss.value} / 2))`,
85
81
  );
86
- const pointer2PositionCss = computed(() => props.range
87
- ? `calc(${activeBlockStyle.value.width} + ${activeBlockStyle.value.left} - calc(${thumbSizeCss.value} / 2))`
88
- : '200%',
82
+ const pointer2PositionCss = computed(() =>
83
+ props.range
84
+ ? `calc(${activeBlockStyle.value.width} + ${activeBlockStyle.value.left} - calc(${thumbSizeCss.value} / 2))`
85
+ : '200%',
89
86
  );
90
87
 
91
88
  const label1Text = computed(() => {
92
89
  if (props.range) {
93
90
  const val = (innerValue.value as [number, number])[0];
94
- return props.transformValueMethod
95
- ? props.transformValueMethod(val)
96
- : `${val}`;
91
+ return props.transformValueMethod ? props.transformValueMethod(val) : `${val}`;
97
92
  }
98
93
 
99
- return props.transformValueMethod ? props.transformValueMethod(innerValue.value as number) : `${innerValue.value}`;
94
+ return props.transformValueMethod
95
+ ? props.transformValueMethod(innerValue.value as number)
96
+ : `${innerValue.value}`;
100
97
  });
101
98
  const label2Text = computed(() => {
102
99
  if (!props.range) {
@@ -104,7 +101,23 @@
104
101
  }
105
102
 
106
103
  const val = (innerValue.value as [number, number])[1];
107
- return props.transformValueMethod ? props.transformValueMethod(val) : `${val}`;
104
+ return props.transformValueMethod ? props.transformValueMethod(val) : `${val}`;
105
+ });
106
+
107
+ const sliderStyle = computed(() => {
108
+ const height = Math.max(Number(props.trackHeight), Number(props.thumbSize));
109
+ return {
110
+ '--ui3n-slider-height': `${height}px`,
111
+ '--ui3n-slider-label-color': props.labelColor,
112
+ '--ui3n-slider-label-text-color': props.labelTextColor,
113
+ '--ui3n-slider-active-color': props.activeColor,
114
+ '--ui3n-slider-track-color': props.trackColor,
115
+ '--ui3n-slider-track-height': `${props.trackHeight}px`,
116
+ '--ui3n-slider-thumb-size': `${props.thumbSize}px`,
117
+ '--ui3n-slider-thumb-color': props.thumbColor,
118
+ '--ui3n-slider-pointer1-position': pointer1PositionCss.value,
119
+ '--ui3n-slider-pointer2-position': pointer2PositionCss.value,
120
+ };
108
121
  });
109
122
 
110
123
  function onMouseenter(pointer: 1 | 2) {
@@ -152,7 +165,8 @@
152
165
  }
153
166
 
154
167
  const sliderRefClientRect = sliderRef.value!.getBoundingClientRect();
155
- const getValue = (leftPosition: number): number => Math.round(leftPosition / sliderRefClientRect.width * diff.value) + Number(props.min);
168
+ const getValue = (leftPosition: number): number =>
169
+ Math.round((leftPosition / sliderRefClientRect.width) * diff.value) + Number(props.min);
156
170
 
157
171
  let newLeft = event.clientX - shiftX.value[`${selectedPointer.value}`] - sliderRefClientRect.left;
158
172
  if (newLeft < 0) {
@@ -187,7 +201,7 @@
187
201
  function onTimelineClick(event: MouseEvent) {
188
202
  const { x } = event;
189
203
  const { x: sliderElStart, width: sliderElWidth } = sliderRef.value!.getBoundingClientRect();
190
- const selectedValue = Math.round((x - sliderElStart) / sliderElWidth * diff.value) + Number(props.min);
204
+ const selectedValue = Math.round(((x - sliderElStart) / sliderElWidth) * diff.value) + Number(props.min);
191
205
 
192
206
  if (props.range) {
193
207
  const [minVal, maxVal] = innerValue.value as [number, number];
@@ -204,9 +218,30 @@
204
218
  emits('update:modelValue', innerValue.value);
205
219
  }
206
220
 
221
+ function clear() {
222
+ const resetValue = props.range
223
+ ? ([Number(props.min), Number(props.min)] as [number, number])
224
+ : Number(props.min);
225
+ innerValue.value = resetValue;
226
+ emits('update:modelValue', resetValue);
227
+ }
228
+
229
+ defineExpose<UI3nSliderExpose>({
230
+ clear,
231
+ });
232
+
233
+ watch(
234
+ () => props.name,
235
+ newName => {
236
+ if (!newName) {
237
+ clear();
238
+ }
239
+ },
240
+ );
241
+
207
242
  watch(
208
243
  () => JSON.stringify(props.modelValue),
209
- (val) => {
244
+ val => {
210
245
  if (props.range) {
211
246
  if (val !== JSON.stringify(innerValue.value)) {
212
247
  innerValue.value = cloneDeep(props.modelValue);
@@ -220,7 +255,8 @@
220
255
  if (newVal !== innerValue.value) {
221
256
  innerValue.value = newVal;
222
257
  }
223
- }, {
258
+ },
259
+ {
224
260
  immediate: true,
225
261
  },
226
262
  );
@@ -229,9 +265,33 @@
229
265
  <template>
230
266
  <div
231
267
  ref="sliderEl"
268
+ :id="id"
269
+ :style="sliderStyle"
232
270
  :class="[$style.ui3nSlider, disabled && $style.disabled]"
233
271
  @click.stop.prevent="onTimelineClick"
234
272
  >
273
+ <template v-if="name">
274
+ <template v-if="range">
275
+ <input
276
+ type="hidden"
277
+ :name="`${name}_min`"
278
+ :value="(innerValue as [number, number])[0]"
279
+ />
280
+ <input
281
+ type="hidden"
282
+ :name="`${name}_max`"
283
+ :value="(innerValue as [number, number])[1]"
284
+ />
285
+ </template>
286
+ <template v-else>
287
+ <input
288
+ type="hidden"
289
+ :name="name"
290
+ :value="innerValue as number"
291
+ />
292
+ </template>
293
+ </template>
294
+
235
295
  <div :class="$style.track">
236
296
  <div
237
297
  :class="$style.active"
@@ -290,17 +350,6 @@
290
350
 
291
351
  <style lang="scss" module>
292
352
  .ui3nSlider {
293
- --ui3n-slider-height: v-bind(sliderHeight);
294
- --ui3n-slider-label-color: v-bind(labelColor);
295
- --ui3n-slider-label-text-color: v-bind(labelTextColor);
296
- --ui3n-slider-active-color: v-bind(activeColor);
297
- --ui3n-slider-track-color: v-bind(trackColor);
298
- --ui3n-slider-track-height: v-bind(trackHeightCss);
299
- --ui3n-slider-thumb-size: v-bind(thumbSizeCss);
300
- --ui3n-slider-thumb-color: v-bind(thumbColor);
301
- --ui3n-slider-pointer1-position: v-bind(pointer1PositionCss);
302
- --ui3n-slider-pointer2-position: v-bind(pointer2PositionCss);
303
-
304
353
  position: relative;
305
354
  width: 100%;
306
355
  height: var(--ui3n-slider-height);
@@ -2,6 +2,10 @@
2
2
  * Step line bar component properties
3
3
  */
4
4
  export interface Ui3nStepLineBarProps {
5
+ /**
6
+ * Root element id
7
+ */
8
+ id?: string;
5
9
  /**
6
10
  * Step label
7
11
  */
@@ -1,16 +1,16 @@
1
1
  <script lang="ts" setup>
2
2
  import type { Ui3nStepLineBarProps } from './types';
3
3
 
4
- withDefaults(
5
- defineProps<Ui3nStepLineBarProps>(),
6
- {
7
- current: 1,
8
- },
9
- );
4
+ const props = withDefaults(defineProps<Ui3nStepLineBarProps>(), {
5
+ current: 1,
6
+ });
10
7
  </script>
11
8
 
12
9
  <template>
13
- <div :class="$style.ui3nStepLineBar">
10
+ <div
11
+ :id="id"
12
+ :class="$style.ui3nStepLineBar"
13
+ >
14
14
  <div :class="$style.label">
15
15
  {{ label }}
16
16
  </div>
@@ -27,8 +27,6 @@
27
27
 
28
28
  <style lang="scss" module>
29
29
  .ui3nStepLineBar {
30
- --ui3n-step-line-bar-steps: v-bind(steps);
31
-
32
30
  position: relative;
33
31
  width: 100%;
34
32
  }
@@ -54,7 +52,7 @@
54
52
 
55
53
  .step {
56
54
  position: relative;
57
- width: calc((100% - (calc(var(--ui3n-step-line-bar-steps) - 1) * var(--spacing-s))) / var(--ui3n-step-line-bar-steps));
55
+ flex: 1;
58
56
  height: var(--spacing-xs);
59
57
  border-radius: var(--spacing-xs);
60
58
  background-color: var(--color-bg-control-secondary-default);
@@ -4,6 +4,14 @@ import { VNode } from 'vue';
4
4
  * Switch component properties
5
5
  */
6
6
  export interface Ui3nSwitchProps {
7
+ /**
8
+ * Root element id
9
+ */
10
+ id?: string;
11
+ /**
12
+ * HTML name attribute for form submission
13
+ */
14
+ name?: string;
7
15
  /**
8
16
  * Current switch value
9
17
  */
@@ -46,3 +54,7 @@ export interface Ui3nSwitchSlots {
46
54
  */
47
55
  default: () => VNode;
48
56
  }
57
+
58
+ export interface Ui3nSwitchExpose {
59
+ clear: () => void;
60
+ }
@@ -1,15 +1,13 @@
1
1
  <script lang="ts" setup>
2
- import { onMounted, ref, watch, useSlots } from 'vue';
3
- import type { Ui3nSwitchEmits, Ui3nSwitchProps, Ui3nSwitchSlots } from './types';
4
-
5
- const props = withDefaults(
6
- defineProps<Ui3nSwitchProps>(),
7
- {
8
- size: 16,
9
- color: 'var(--color-icon-control-accent-default)',
10
- disabled: false,
11
- },
12
- );
2
+ import { computed, ref, watch, useSlots } from 'vue';
3
+ import type { Ui3nSwitchEmits, Ui3nSwitchProps, Ui3nSwitchSlots, Ui3nSwitchExpose } from './types';
4
+
5
+ const props = withDefaults(defineProps<Ui3nSwitchProps>(), {
6
+ name: undefined,
7
+ size: 16,
8
+ color: 'var(--color-icon-control-accent-default)',
9
+ disabled: false,
10
+ });
13
11
 
14
12
  const emits = defineEmits<Ui3nSwitchEmits>();
15
13
 
@@ -19,18 +17,10 @@
19
17
  const switchEl = ref<HTMLDivElement | null>(null);
20
18
  const val = ref<boolean>(false);
21
19
 
22
- onMounted(() => {
23
- if (switchEl.value) {
24
- switchEl.value.style.setProperty('--ui3n-switch-color', `${props.color}`);
25
- props.size && switchEl.value.style.setProperty('--ui3n-switch-size', `${props.size}px`);
26
- }
27
- });
28
-
29
- watch(
30
- () => props.modelValue,
31
- newValue => val.value = newValue,
32
- { immediate: true },
33
- );
20
+ const switchStyle = computed(() => ({
21
+ '--ui3n-switch-color': props.color,
22
+ '--ui3n-switch-size': `${props.size}px`,
23
+ }));
34
24
 
35
25
  function change(ev: Event) {
36
26
  ev.preventDefault();
@@ -39,13 +29,55 @@
39
29
  emits('change', val.value);
40
30
  emits('update:modelValue', val.value);
41
31
  }
32
+
33
+ function clear() {
34
+ val.value = false;
35
+ emits('change', false);
36
+ emits('update:modelValue', false);
37
+ }
38
+
39
+ defineExpose<Ui3nSwitchExpose>({
40
+ clear,
41
+ });
42
+
43
+ watch(
44
+ () => props.name,
45
+ newName => {
46
+ if (!newName) {
47
+ clear();
48
+ }
49
+ },
50
+ );
51
+
52
+ watch(
53
+ () => props.modelValue,
54
+ newValue => (val.value = newValue),
55
+ { immediate: true },
56
+ );
42
57
  </script>
43
58
 
44
59
  <template>
45
60
  <div
46
61
  ref="switchEl"
47
- :class="[$style.ui3nSwitch, val && $style.checked, !slots.default && $style.noLabel, disabled && $style.disabled]"
62
+ :id="id"
63
+ :style="switchStyle"
64
+ :class="[
65
+ $style.ui3nSwitch,
66
+ val && $style.checked,
67
+ !slots.default && $style.noLabel,
68
+ disabled && $style.disabled,
69
+ ]"
48
70
  >
71
+ <input
72
+ v-if="name"
73
+ type="checkbox"
74
+ hidden
75
+ :name="name"
76
+ :checked="val"
77
+ :disabled="disabled"
78
+ :value="val ? 'on' : ''"
79
+ />
80
+
49
81
  <div
50
82
  :class="$style.body"
51
83
  :tabindex="disabled ? -1 : 0"
@@ -75,7 +107,7 @@
75
107
  display: flex;
76
108
  justify-content: flex-start;
77
109
  align-items: center;
78
- gap: var(--spacing-s);
110
+ gap: 8px;
79
111
  }
80
112
 
81
113
  .body {
@@ -199,6 +199,22 @@ export function useTable<T extends Ui3nTableBodyBaseItem>(props: Ui3nTableProps<
199
199
  emits('change:sort', currentConfig.value.sortOrder as Ui3nTableSort<T>);
200
200
  }
201
201
 
202
+ function clear() {
203
+ isRowKeyUsed.value && ((selectedRows.value as Array<T[keyof T]>) = []);
204
+ !isRowKeyUsed.value && (selectedRows.value as Set<T>).clear();
205
+ hasGroupActionsRow.value = false;
206
+ emits('select:row', []);
207
+ }
208
+
209
+ watch(
210
+ () => props.config?.tableName,
211
+ newTableName => {
212
+ if (!newTableName) {
213
+ clear();
214
+ }
215
+ },
216
+ );
217
+
202
218
  watch(
203
219
  tableColumnWidth,
204
220
  (val, oVal) => {
@@ -237,5 +253,6 @@ export function useTable<T extends Ui3nTableBodyBaseItem>(props: Ui3nTableProps<
237
253
  processSelection,
238
254
  toggleSelectedRows,
239
255
  changeSortOrder,
256
+ clear,
240
257
  };
241
258
  }
@@ -309,4 +309,8 @@ export type Ui3nTableExpose<T extends Ui3nTableBodyBaseItem> = {
309
309
  * Close group actions row
310
310
  */
311
311
  closeGroupActionsRow: () => void;
312
+ /**
313
+ * Clear all selected rows
314
+ */
315
+ clear: () => void;
312
316
  };