@v1nt1248/3nclient-lib 0.1.88 → 0.1.90

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
@@ -2,7 +2,7 @@
2
2
  "name": "@v1nt1248/3nclient-lib",
3
3
  "license": "AGPL-3.0-or-later",
4
4
  "author": "v1nt1248",
5
- "version": "0.1.88",
5
+ "version": "0.1.90",
6
6
  "description": "Library for 3NWeb clients",
7
7
  "type": "module",
8
8
  "files": [
@@ -0,0 +1,198 @@
1
+ <script lang="ts" setup>
2
+ import { computed, ref, watch } from 'vue';
3
+ import { useFloating, offset, autoUpdate, arrow } from '@floating-ui/vue';
4
+ import type { Ui3nTooltipEmits, Ui3nTooltipProps, Ui3nTooltipSlots } from './types';
5
+
6
+ const baseOffset = 5;
7
+
8
+ const props = withDefaults(defineProps<Ui3nTooltipProps>(), {
9
+ color: 'var(--color-bg-control-secondary-default)',
10
+ textColor: 'var(--color-text-control-primary-default)',
11
+ placement: 'top',
12
+ positionStrategy: 'absolute',
13
+ offsetX: 0,
14
+ offsetY: 0,
15
+ trigger: 'hover',
16
+ });
17
+
18
+ const emits = defineEmits<Ui3nTooltipEmits>();
19
+ defineSlots<Ui3nTooltipSlots>();
20
+
21
+ const referenceElEventHandler = {
22
+ ...(props.trigger === 'hover' &&
23
+ !props.disabled && {
24
+ mouseenter: () => handleMouseEvents(true),
25
+ mouseleave: () => handleMouseEvents(false),
26
+ }),
27
+ ...(props.trigger === 'click' &&
28
+ !props.disabled && {
29
+ click: () => handleMouseEvents(!showTooltip.value),
30
+ }),
31
+ };
32
+
33
+ const showTooltip = ref(false);
34
+ const referenceEl = ref(null);
35
+ const floatingEl = ref(null);
36
+ const floatingArrowEl = ref(null);
37
+
38
+ const baseOffsetCssValue = computed(() => `${-baseOffset}px`);
39
+ const arrowSizeCssValue = computed(() => `${baseOffset}px`);
40
+ const mainPlacement = computed(() => {
41
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
42
+ const [part1, _] = props.placement.split('-');
43
+ return part1;
44
+ });
45
+ const offsetOptions = computed(() => {
46
+ const options = {
47
+ mainAxis: 0,
48
+ crossAxis: 0,
49
+ };
50
+ switch (mainPlacement.value) {
51
+ case 'top':
52
+ options.mainAxis = -1 * Number(props.offsetY) + baseOffset;
53
+ options.crossAxis = Number(props.offsetX);
54
+ break;
55
+ case 'bottom':
56
+ options.mainAxis = Number(props.offsetY) + baseOffset;
57
+ options.crossAxis = Number(props.offsetX);
58
+ break;
59
+ case 'left':
60
+ options.mainAxis = -1 * Number(props.offsetX) + baseOffset;
61
+ options.crossAxis = Number(props.offsetY);
62
+ break;
63
+ case 'right':
64
+ options.mainAxis = Number(props.offsetX) + baseOffset;
65
+ options.crossAxis = Number(props.offsetY);
66
+ break;
67
+ }
68
+ return options;
69
+ });
70
+
71
+ const { floatingStyles, isPositioned, middlewareData } = useFloating(referenceEl, floatingEl, {
72
+ open: showTooltip,
73
+ placement: props.placement,
74
+ strategy: props.positionStrategy,
75
+ middleware: [offset(offsetOptions.value), arrow({ element: floatingArrowEl, padding: 8 })],
76
+ whileElementsMounted: props.positionStrategy === 'fixed' ? autoUpdate : undefined,
77
+ });
78
+
79
+ function handleMouseEvents(val: boolean) {
80
+ showTooltip.value = val;
81
+ val ? emits('open') : emits('close');
82
+ emits('update:modelValue', val);
83
+ }
84
+
85
+ watch(
86
+ () => props.modelValue,
87
+ val => props.trigger === 'manual' && (showTooltip.value = val),
88
+ { immediate: true },
89
+ );
90
+
91
+ watch(isPositioned, val => {
92
+ val ? emits('opened') : emits('closed');
93
+ });
94
+ </script>
95
+
96
+ <template>
97
+ <div :class="$style.ui3nTooltip">
98
+ <div
99
+ ref="referenceEl"
100
+ :class="$style.reference"
101
+ v-on="referenceElEventHandler"
102
+ >
103
+ <slot name="default" />
104
+ </div>
105
+
106
+ <div
107
+ v-if="showTooltip"
108
+ ref="floatingEl"
109
+ :class="$style.floating"
110
+ :style="floatingStyles"
111
+ >
112
+ <slot name="content">
113
+ <div :class="$style.content">
114
+ {{ content }}
115
+ <div
116
+ ref="floatingArrowEl"
117
+ :class="[$style.arrow, $style[`arrow-${mainPlacement}`]]"
118
+ :style="{
119
+ left: middlewareData.arrow?.x != null ? `${middlewareData.arrow?.x}px` : '',
120
+ top: middlewareData.arrow?.y != null ? `${middlewareData.arrow?.y}px` : '',
121
+ }"
122
+ />
123
+ </div>
124
+ </slot>
125
+ </div>
126
+ </div>
127
+ </template>
128
+
129
+ <style lang="scss" module>
130
+ .ui3nTooltip {
131
+ --ui3n-tooltip-bg-color: v-bind(color);
132
+ --ui3n-tooltip-text-color: v-bind(textColor);
133
+
134
+ position: relative;
135
+ width: max-content;
136
+ }
137
+
138
+ .reference {
139
+ position: relative;
140
+ }
141
+
142
+ .floating {
143
+ width: max-content;
144
+ z-index: 5;
145
+ }
146
+
147
+ .arrow {
148
+ position: absolute;
149
+ width: 0;
150
+ height: 0;
151
+
152
+ &-top,
153
+ &-bottom {
154
+ border-style: solid;
155
+ border-width: 0 v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue);
156
+ border-color: transparent transparent var(--ui3n-tooltip-bg-color) transparent;
157
+ }
158
+
159
+ &-top {
160
+ bottom: v-bind(baseOffsetCssValue);
161
+ transform: rotate(180deg);
162
+ }
163
+
164
+ &-bottom {
165
+ top: v-bind(baseOffsetCssValue);
166
+ transform: rotate(0deg);
167
+ }
168
+
169
+ &-left,
170
+ &-right {
171
+ border-style: solid;
172
+ border-width: v-bind(arrowSizeCssValue) 0 v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue);
173
+ border-color: transparent transparent transparent var(--ui3n-tooltip-bg-color);
174
+ }
175
+
176
+ &-left {
177
+ right: v-bind(baseOffsetCssValue);
178
+ transform: rotate(0deg);
179
+ }
180
+
181
+ &-right {
182
+ left: v-bind(baseOffsetCssValue);
183
+ transform: rotate(180deg);
184
+ }
185
+ }
186
+
187
+ .content {
188
+ position: relative;
189
+ max-width: 400px;
190
+ padding: var(--spacing-xs) var(--spacing-s);
191
+ border-radius: var(--spacing-xs);
192
+ font-size: var(--font-11);
193
+ line-height: var(--font-12);
194
+ font-weight: 400;
195
+ background-color: var(--ui3n-tooltip-bg-color);
196
+ color: var(--ui3n-tooltip-text-color);
197
+ }
198
+ </style>
@@ -1,197 +1,212 @@
1
1
  <script lang="ts" setup>
2
- import { computed, ref, watch } from 'vue';
3
- import { useFloating, offset, autoUpdate, arrow } from '@floating-ui/vue';
4
- import type { Ui3nTooltipEmits, Ui3nTooltipProps, Ui3nTooltipSlots } from './types';
5
-
6
- const baseOffset = 5;
7
-
8
- const props = withDefaults(defineProps<Ui3nTooltipProps>(), {
9
- color: 'var(--color-bg-control-secondary-default)',
10
- textColor: 'var(--color-text-control-primary-default)',
11
- placement: 'top',
12
- positionStrategy: 'absolute',
13
- offsetX: 0,
14
- offsetY: 0,
15
- trigger: 'hover',
16
- });
17
-
18
- const emits = defineEmits<Ui3nTooltipEmits>();
19
- defineSlots<Ui3nTooltipSlots>();
20
-
21
- const referenceElEventHandler = {
22
- ...(props.trigger === 'hover' &&
23
- !props.disabled && {
24
- mouseenter: () => handleMouseEvents(true),
25
- mouseleave: () => handleMouseEvents(false),
26
- }),
27
- ...(props.trigger === 'click' &&
28
- !props.disabled && {
29
- click: () => handleMouseEvents(!showTooltip.value),
30
- }),
31
- };
32
-
33
- const showTooltip = ref(false);
34
- const referenceEl = ref(null);
35
- const floatingEl = ref(null);
36
- const floatingArrowEl = ref(null);
37
-
38
- const baseOffsetCssValue = computed(() => `${-baseOffset}px`);
39
- const arrowSizeCssValue = computed(() => `${baseOffset}px`);
40
- const mainPlacement = computed(() => {
41
- const [part1, _] = props.placement.split('-');
42
- return part1;
43
- });
44
- const offsetOptions = computed(() => {
45
- const options = {
46
- mainAxis: 0,
47
- crossAxis: 0,
48
- };
49
- switch (mainPlacement.value) {
50
- case 'top':
51
- options.mainAxis = -1 * Number(props.offsetY) + baseOffset;
52
- options.crossAxis = Number(props.offsetX);
53
- break;
54
- case 'bottom':
55
- options.mainAxis = Number(props.offsetY) + baseOffset;
56
- options.crossAxis = Number(props.offsetX);
57
- break;
58
- case 'left':
59
- options.mainAxis = -1 * Number(props.offsetX) + baseOffset;
60
- options.crossAxis = Number(props.offsetY);
61
- break;
62
- case 'right':
63
- options.mainAxis = Number(props.offsetX) + baseOffset;
64
- options.crossAxis = Number(props.offsetY);
65
- break;
2
+ /* eslint-disable vue/no-multiple-template-root */
3
+ import { computed, getCurrentInstance, onBeforeUnmount, onMounted, ref, watch } from 'vue';
4
+ import type { Nullable } from '@/components/types';
5
+ import type { Ui3nTooltipProps, Ui3nTooltipEmits, Ui3nTooltipSlots } from './types';
6
+ import { arrow, autoUpdate, offset, useFloating } from '@floating-ui/vue';
7
+
8
+ const baseOffset = 5;
9
+
10
+ const props = withDefaults(defineProps<Ui3nTooltipProps>(), {
11
+ color: 'var(--color-bg-block-tritery-default)',
12
+ textColor: 'var(--color-text-block-darkery-default)',
13
+ placement: 'top',
14
+ positionStrategy: 'absolute',
15
+ offsetX: 0,
16
+ offsetY: 0,
17
+ trigger: 'hover',
18
+ });
19
+ const emits = defineEmits<Ui3nTooltipEmits>();
20
+ defineSlots<Ui3nTooltipSlots>();
21
+
22
+ const showTooltip = ref(false);
23
+ const referenceEl = ref<Nullable<HTMLElement>>(null);
24
+ const floatingEl = ref<Nullable<HTMLElement>>(null);
25
+ const floatingArrowEl = ref<Nullable<HTMLElement>>(null);
26
+
27
+ const baseOffsetCssValue = computed(() => `${-baseOffset}px`);
28
+ const arrowSizeCssValue = computed(() => `${baseOffset}px`);
29
+ const mainPlacement = computed(() => {
30
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
31
+ const [part1, _] = props.placement.split('-');
32
+ return part1;
33
+ });
34
+ const offsetOptions = computed(() => {
35
+ const options = {
36
+ mainAxis: 0,
37
+ crossAxis: 0,
38
+ };
39
+ switch (mainPlacement.value) {
40
+ case 'top':
41
+ options.mainAxis = -1 * Number(props.offsetY) + baseOffset;
42
+ options.crossAxis = Number(props.offsetX);
43
+ break;
44
+ case 'bottom':
45
+ options.mainAxis = Number(props.offsetY) + baseOffset;
46
+ options.crossAxis = Number(props.offsetX);
47
+ break;
48
+ case 'left':
49
+ options.mainAxis = -1 * Number(props.offsetX) + baseOffset;
50
+ options.crossAxis = Number(props.offsetY);
51
+ break;
52
+ case 'right':
53
+ options.mainAxis = Number(props.offsetX) + baseOffset;
54
+ options.crossAxis = Number(props.offsetY);
55
+ break;
56
+ }
57
+ return options;
58
+ });
59
+
60
+ const { floatingStyles, isPositioned, middlewareData } = useFloating(referenceEl, floatingEl, {
61
+ open: showTooltip,
62
+ placement: props.placement,
63
+ strategy: props.positionStrategy,
64
+ middleware: [offset(offsetOptions.value), arrow({ element: floatingArrowEl, padding: 8 })],
65
+ whileElementsMounted: props.positionStrategy === 'fixed' ? autoUpdate : undefined,
66
+ });
67
+
68
+ function onMouseenter() {
69
+ showTooltip.value = true;
70
+ emits('open');
71
+ emits('update:modelValue', true);
66
72
  }
67
- return options;
68
- });
69
-
70
- const { floatingStyles, isPositioned, middlewareData } = useFloating(referenceEl, floatingEl, {
71
- open: showTooltip,
72
- placement: props.placement,
73
- strategy: props.positionStrategy,
74
- middleware: [offset(offsetOptions.value), arrow({ element: floatingArrowEl, padding: 8 })],
75
- whileElementsMounted: props.positionStrategy === 'fixed' ? autoUpdate : undefined,
76
- });
77
-
78
- function handleMouseEvents(val: boolean) {
79
- showTooltip.value = val;
80
- val ? emits('open') : emits('close');
81
- emits('update:modelValue', val);
82
- }
83
-
84
- watch(
85
- () => props.modelValue,
86
- val => props.trigger === 'manual' && (showTooltip.value = val),
87
- { immediate: true },
88
- );
89
-
90
- watch(isPositioned, val => {
91
- val ? emits('opened') : emits('closed');
92
- });
73
+
74
+ function onMouseleave() {
75
+ showTooltip.value = false;
76
+ emits('close');
77
+ emits('update:modelValue', false);
78
+ }
79
+
80
+ function onClick() {
81
+ if (showTooltip.value) {
82
+ onMouseleave();
83
+ } else {
84
+ onMouseenter();
85
+ }
86
+ }
87
+
88
+ onMounted(() => {
89
+ if (props.disabled) return;
90
+
91
+ const inst = getCurrentInstance();
92
+ const el = inst?.vnode?.el;
93
+ if (!el) {
94
+ throw new Error('[ui3n-tooltip] A reference element is absent.');
95
+ }
96
+
97
+ referenceEl.value = el.nodeName === '#text' ? el.nextElementSibling : el;
98
+
99
+ if (props.trigger === 'hover') {
100
+ referenceEl.value!.addEventListener('mouseenter', onMouseenter);
101
+ referenceEl.value!.addEventListener('mouseleave', onMouseleave);
102
+ } else if (props.trigger === 'click') {
103
+ referenceEl.value!.addEventListener('click', onClick);
104
+ }
105
+ });
106
+
107
+ onBeforeUnmount(() => {
108
+ if (props.trigger === 'hover') {
109
+ referenceEl.value!.removeEventListener('mouseenter', onMouseenter);
110
+ referenceEl.value!.removeEventListener('mouseleave', onMouseleave);
111
+ } else if (props.trigger === 'click') {
112
+ referenceEl.value!.removeEventListener('click', onClick);
113
+ }
114
+ });
115
+
116
+ watch(
117
+ () => props.modelValue,
118
+ val => props.trigger === 'manual' && (showTooltip.value = val),
119
+ { immediate: true },
120
+ );
121
+
122
+ watch(isPositioned, val => {
123
+ val ? emits('opened') : emits('closed');
124
+ });
93
125
  </script>
94
126
 
95
127
  <template>
96
- <div :class="$style.ui3nTooltip">
97
- <div
98
- ref="referenceEl"
99
- :class="$style.reference"
100
- v-on="referenceElEventHandler"
101
- >
102
- <slot name="default" />
103
- </div>
104
-
105
- <div
106
- v-if="showTooltip"
107
- ref="floatingEl"
108
- :class="$style.floating"
109
- :style="floatingStyles"
110
- >
111
- <slot name="content">
112
- <div :class="$style.content">
113
- {{ content }}
114
- <div
115
- ref="floatingArrowEl"
116
- :class="[$style.arrow, $style[`arrow-${mainPlacement}`]]"
117
- :style="{
128
+ <slot />
129
+
130
+ <div
131
+ v-if="showTooltip"
132
+ ref="floatingEl"
133
+ :class="$style.floating"
134
+ :style="floatingStyles"
135
+ >
136
+ <slot name="content">
137
+ <div :class="$style.content">
138
+ {{ content }}
139
+ <div
140
+ ref="floatingArrowEl"
141
+ :class="[$style.arrow, $style[`arrow-${mainPlacement}`]]"
142
+ :style="{
118
143
  left: middlewareData.arrow?.x != null ? `${middlewareData.arrow?.x}px` : '',
119
144
  top: middlewareData.arrow?.y != null ? `${middlewareData.arrow?.y}px` : '',
120
145
  }"
121
- />
122
- </div>
123
- </slot>
124
- </div>
146
+ />
147
+ </div>
148
+ </slot>
125
149
  </div>
126
150
  </template>
127
151
 
128
152
  <style lang="scss" module>
129
- .ui3nTooltip {
130
- --ui3n-tooltip-bg-color: v-bind(color);
131
- --ui3n-tooltip-text-color: v-bind(textColor);
132
-
133
- position: relative;
134
- width: max-content;
135
- }
136
-
137
- .reference {
138
- position: relative;
139
- }
140
-
141
- .floating {
142
- width: max-content;
143
- z-index: 5;
144
- }
145
-
146
- .arrow {
147
- position: absolute;
148
- width: 0;
149
- height: 0;
150
-
151
- &-top,
152
- &-bottom {
153
- border-style: solid;
154
- border-width: 0 v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue);
155
- border-color: transparent transparent var(--ui3n-tooltip-bg-color) transparent;
156
- }
157
-
158
- &-top {
159
- bottom: v-bind(baseOffsetCssValue);
160
- transform: rotate(180deg);
161
- }
162
-
163
- &-bottom {
164
- top: v-bind(baseOffsetCssValue);
165
- transform: rotate(0deg);
166
- }
153
+ .floating {
154
+ --ui3n-tooltip-bg-color: v-bind(color);
155
+ --ui3n-tooltip-text-color: v-bind(textColor);
167
156
 
168
- &-left,
169
- &-right {
170
- border-style: solid;
171
- border-width: v-bind(arrowSizeCssValue) 0 v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue);
172
- border-color: transparent transparent transparent var(--ui3n-tooltip-bg-color);
157
+ width: max-content;
158
+ z-index: 5;
173
159
  }
174
160
 
175
- &-left {
176
- right: v-bind(baseOffsetCssValue);
177
- transform: rotate(0deg);
161
+ .arrow {
162
+ position: absolute;
163
+ width: 0;
164
+ height: 0;
165
+
166
+ &-top,
167
+ &-bottom {
168
+ border-style: solid;
169
+ border-width: 0 v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue);
170
+ border-color: transparent transparent var(--ui3n-tooltip-bg-color) transparent;
171
+ }
172
+
173
+ &-top {
174
+ bottom: v-bind(baseOffsetCssValue);
175
+ transform: rotate(180deg);
176
+ }
177
+
178
+ &-bottom {
179
+ top: v-bind(baseOffsetCssValue);
180
+ transform: rotate(0deg);
181
+ }
182
+
183
+ &-left,
184
+ &-right {
185
+ border-style: solid;
186
+ border-width: v-bind(arrowSizeCssValue) 0 v-bind(arrowSizeCssValue) v-bind(arrowSizeCssValue);
187
+ border-color: transparent transparent transparent var(--ui3n-tooltip-bg-color);
188
+ }
189
+
190
+ &-left {
191
+ right: v-bind(baseOffsetCssValue);
192
+ transform: rotate(0deg);
193
+ }
194
+
195
+ &-right {
196
+ left: v-bind(baseOffsetCssValue);
197
+ transform: rotate(180deg);
198
+ }
178
199
  }
179
200
 
180
- &-right {
181
- left: v-bind(baseOffsetCssValue);
182
- transform: rotate(180deg);
201
+ .content {
202
+ position: relative;
203
+ max-width: 400px;
204
+ padding: 6px var(--spacing-s);
205
+ border-radius: 6px;
206
+ font-size: var(--font-11);
207
+ line-height: var(--font-12);
208
+ font-weight: 400;
209
+ background-color: var(--ui3n-tooltip-bg-color);
210
+ color: var(--ui3n-tooltip-text-color);
183
211
  }
184
- }
185
-
186
- .content {
187
- position: relative;
188
- max-width: 400px;
189
- padding: var(--spacing-xs) var(--spacing-s);
190
- border-radius: var(--spacing-xs);
191
- font-size: var(--font-11);
192
- line-height: var(--font-12);
193
- font-weight: 400;
194
- background-color: var(--ui3n-tooltip-bg-color);
195
- color: var(--ui3n-tooltip-text-color);
196
- }
197
212
  </style>