From cbef0f921c289a5be807990aea09fdf1c8ce7a6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=9C=D0=B0?=
 =?UTF-8?q?=D0=BB=D1=8E=D0=B3=D0=B8=D0=BD?= <d.malygin@iqdev.digital>
Date: Sun, 26 Jan 2025 10:50:29 +0500
Subject: [PATCH] refactor: 'Checkbox', 'Knob', 'ProgressBar', 'Rating' and
 'Select' for 'Table' work

---
 src/components/Checkbox/Checkbox.vue       | 13 ++++++++-----
 src/components/Knob/Knob.vue               | 14 +++++++++++---
 src/components/ProgressBar/ProgressBar.vue |  5 ++++-
 src/components/Rating/Rating.vue           |  8 +++++++-
 src/components/Select/Select.vue           | 10 +++++++---
 5 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/src/components/Checkbox/Checkbox.vue b/src/components/Checkbox/Checkbox.vue
index a351908..49378d4 100644
--- a/src/components/Checkbox/Checkbox.vue
+++ b/src/components/Checkbox/Checkbox.vue
@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import type { ICheckboxProps } from '@interfaces/componentsProps';
-import { computed } from 'vue';
+import { computed, watch } from 'vue';
 import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common';
 import CheckMarkIcon from '@icons/Mono/CheckMarkIcon.vue';
 
@@ -19,6 +19,13 @@ const props = withDefaults(defineProps<ICheckboxProps>(), {
   darknessBorder: '500',
 });
 const active = defineModel();
+const emit = defineEmits(['update']);
+
+if (props.active) {
+  active.value = props.active;
+}
+
+watch(active, () => emit('update', active));
 
 const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme));
 const activeThemeColor = computed(() => convertThemeToColor(props.activeTheme, props.darknessActiveTheme));
@@ -46,10 +53,6 @@ const gap = computed(() => {
 });
 const borderWidth = computed(() => (props.size === 'large' || props.size === 'huge' ? 2 : 1));
 const borderRadius = computed(() => `${elSize.value / 7 - borderWidth.value}px`);
-
-if (props.active) {
-  active.value = props.active;
-}
 </script>
 
 <template>
diff --git a/src/components/Knob/Knob.vue b/src/components/Knob/Knob.vue
index f941d70..6d0ac1d 100644
--- a/src/components/Knob/Knob.vue
+++ b/src/components/Knob/Knob.vue
@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import type { IKnobProps } from '@interfaces/componentsProps';
-import { computed, ref, type Ref } from 'vue';
+import { computed, ref, type Ref, watch } from 'vue';
 import { convertThemeToColor } from '@helpers/common';
 import { calcCenter, calcStart, calcNewValue, calcThemeColor, calcContainerSize } from '@components/Knob/helpers';
 import Button from '@components/Button/Button.vue';
@@ -25,13 +25,20 @@ const props = withDefaults(defineProps<IKnobProps>(), {
 const value = defineModel<number>({
   default: 0,
 }) as Ref<number>;
+const emit = defineEmits(['update']);
+
+if (props.value) {
+  value.value = props.value;
+}
+watch(value, () => emit('update', value));
 
 const isClickHold = ref<boolean>(false);
+const container = ref();
 
 const degreesTotal = computed(() => 360 - 90);
 const length = computed(() => props.max - props.min);
-const center = computed(() => calcCenter(document.querySelector('.container')!));
-const start = computed(() => calcStart(document.querySelector('.container')!));
+const center = computed(() => calcCenter(container.value));
+const start = computed(() => calcStart(container.value));
 const containerSize = computed(() => calcContainerSize(props.size));
 const buttonSize = computed(() => {
   const size = props.size;
@@ -95,6 +102,7 @@ const onPointerDown = ($event: MouseEvent) => {
     @pointermove="isClickHold ? setNewValue($event) : ''"
     @pointerup="isClickHold = false"
     class="container containerSize"
+    ref="container"
   >
     <div class="background"></div>
     <span
diff --git a/src/components/ProgressBar/ProgressBar.vue b/src/components/ProgressBar/ProgressBar.vue
index f515341..769b298 100644
--- a/src/components/ProgressBar/ProgressBar.vue
+++ b/src/components/ProgressBar/ProgressBar.vue
@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import type { IProgressBarProps } from '@interfaces/componentsProps';
-import { computed, ref, type Ref } from 'vue';
+import { computed, ref, type Ref, watch } from 'vue';
 import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common';
 
 const props = withDefaults(defineProps<IProgressBarProps>(), {
@@ -15,10 +15,13 @@ const props = withDefaults(defineProps<IProgressBarProps>(), {
   labelAfter: '%',
 });
 const value = defineModel() as Ref<number>;
+const emit = defineEmits(['update']);
 
 if (props.value) {
   value.value = props.value;
 }
+watch(value, () => emit('update', value));
+
 const active = computed(() => `${(value.value / props.max) * 100}%`);
 const activeColor = computed(() => {
   if (props.gradient) return `linear-gradient(to right, ${props.gradient.join(',')})`;
diff --git a/src/components/Rating/Rating.vue b/src/components/Rating/Rating.vue
index 453a9d2..df733be 100644
--- a/src/components/Rating/Rating.vue
+++ b/src/components/Rating/Rating.vue
@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import type { IRatingProps } from '@interfaces/componentsProps';
-import { computed, type Ref, ref } from 'vue';
+import { computed, type Ref, ref, watch } from 'vue';
 import { iconsSet } from '@/common/constants/icons';
 import StarFilledIcon from '@icons/Mono/StarFilledIcon.vue';
 import { convertThemeToColor } from '@helpers/common';
@@ -16,6 +16,12 @@ const props = withDefaults(defineProps<IRatingProps>(), {
 const value = defineModel({
   default: 0,
 }) as Ref<number>;
+const emit = defineEmits(['update']);
+
+if (props.value) {
+  value.value = props.value;
+}
+watch(value, () => emit('update', value));
 
 const onHoverIndex = ref();
 
diff --git a/src/components/Select/Select.vue b/src/components/Select/Select.vue
index 1dfeaaa..d916605 100644
--- a/src/components/Select/Select.vue
+++ b/src/components/Select/Select.vue
@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import type { ISelectProps } from '@interfaces/componentsProps';
-import { computed, ref } from 'vue';
+import { computed, ref, watch } from 'vue';
 import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common';
 import { iconsSet } from '@/common/constants/icons';
 import type { TThemeColor } from '@interfaces/common';
@@ -20,13 +20,17 @@ const props = withDefaults(defineProps<ISelectProps>(), {
   openIcon: 'ArrowShortDown',
 });
 const selected = defineModel();
-const isOpen = ref<boolean>(false);
-const filter = ref<string>('');
+const emit = defineEmits(['update']);
 
 if (props.selected) {
   selected.value = props.selected;
 }
 
+watch(selected, () => emit('update', selected));
+
+const isOpen = ref<boolean>(false);
+const filter = ref<string>('');
+
 const optionsGroups = computed(() => getOptionsGroups(props.options, props.groups, filter.value));
 const optionsNoGroup = computed(() =>
   props.options.filter(
-- 
GitLab