@weni/unnnic-system 3.12.8-alpha.0 → 3.13.0

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 (71) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/{es-52edeb71.mjs → es-41fceca9.mjs} +1 -1
  3. package/dist/{index-756fe685.mjs → index-cca96b43.mjs} +26458 -29323
  4. package/dist/index.d.ts +1652 -4902
  5. package/dist/{pt-br-24583c8c.mjs → pt-br-a3088529.mjs} +1 -1
  6. package/dist/style.css +1 -1
  7. package/dist/unnnic.mjs +204 -232
  8. package/dist/unnnic.umd.js +44 -48
  9. package/package.json +2 -3
  10. package/src/assets/scss/scheme-colors.scss +223 -223
  11. package/src/assets/scss/tailwind.scss +0 -8
  12. package/src/components/Alert/__tests__/__snapshots__/Alert.spec.js.snap +1 -1
  13. package/src/components/Checkbox/Checkbox.vue +1 -1
  14. package/src/components/Drawer/Drawer.vue +269 -190
  15. package/src/components/Drawer/__tests__/Drawer.spec.js +46 -37
  16. package/src/components/Drawer/__tests__/__snapshots__/Drawer.spec.js.snap +19 -18
  17. package/src/components/FormElement/FormElement.vue +1 -1
  18. package/src/components/Input/Input.scss +2 -0
  19. package/src/components/ModalDialog/ModalDialog.vue +148 -64
  20. package/src/components/ModalDialog/__tests__/ModalDialog.spec.js +221 -11
  21. package/src/components/ModalDialog/__tests__/__snapshots__/ModalDialog.spec.js.snap +22 -1
  22. package/src/components/MultiSelect/MultiSelect.vue +297 -0
  23. package/src/components/Radio/Radio.vue +1 -1
  24. package/src/components/Select/index.vue +3 -3
  25. package/src/components/Switch/Switch.vue +1 -1
  26. package/src/components/Tab/__test__/__snapshots__/Tab.spec.js.snap +1 -3
  27. package/src/components/TemplatePreview/TemplatePreview.vue +2 -2
  28. package/src/components/TemplatePreview/TemplatePreviewModal.vue +1 -1
  29. package/src/components/Toast/Toast.vue +9 -16
  30. package/src/components/ToolTip/ToolTip.vue +177 -25
  31. package/src/components/ToolTip/__tests__/ToolTip.spec.js +61 -339
  32. package/src/components/index.ts +2 -58
  33. package/src/components/ui/popover/PopoverContent.vue +4 -5
  34. package/src/components/ui/popover/PopoverTrigger.vue +1 -5
  35. package/src/stories/Drawer.stories.js +1 -1
  36. package/src/stories/ModalDialog.mdx +0 -3
  37. package/src/stories/ModalDialog.stories.js +1 -1
  38. package/src/stories/MultiSelect.stories.js +45 -143
  39. package/src/components/MultiSelect/MultSelectOption.vue +0 -49
  40. package/src/components/MultiSelect/__tests__/MultiSelect.spec.js +0 -557
  41. package/src/components/MultiSelect/__tests__/MultiSelectOption.spec.js +0 -229
  42. package/src/components/MultiSelect/__tests__/__snapshots__/MultiSelect.spec.js.snap +0 -87
  43. package/src/components/MultiSelect/__tests__/__snapshots__/MultiSelectOption.spec.js.snap +0 -51
  44. package/src/components/MultiSelect/index.vue +0 -265
  45. package/src/components/ui/dialog/Dialog.vue +0 -19
  46. package/src/components/ui/dialog/DialogClose.vue +0 -29
  47. package/src/components/ui/dialog/DialogContent.vue +0 -140
  48. package/src/components/ui/dialog/DialogFooter.vue +0 -50
  49. package/src/components/ui/dialog/DialogHeader.vue +0 -83
  50. package/src/components/ui/dialog/DialogTitle.vue +0 -38
  51. package/src/components/ui/dialog/DialogTrigger.vue +0 -16
  52. package/src/components/ui/dialog/index.ts +0 -7
  53. package/src/components/ui/drawer/Drawer.vue +0 -27
  54. package/src/components/ui/drawer/DrawerClose.vue +0 -31
  55. package/src/components/ui/drawer/DrawerContent.vue +0 -111
  56. package/src/components/ui/drawer/DrawerDescription.vue +0 -40
  57. package/src/components/ui/drawer/DrawerFooter.vue +0 -38
  58. package/src/components/ui/drawer/DrawerHeader.vue +0 -57
  59. package/src/components/ui/drawer/DrawerOverlay.vue +0 -33
  60. package/src/components/ui/drawer/DrawerTitle.vue +0 -37
  61. package/src/components/ui/drawer/DrawerTrigger.vue +0 -31
  62. package/src/components/ui/drawer/index.ts +0 -10
  63. package/src/components/ui/tooltip/Tooltip.vue +0 -21
  64. package/src/components/ui/tooltip/TooltipContent.vue +0 -74
  65. package/src/components/ui/tooltip/TooltipTrigger.vue +0 -26
  66. package/src/components/ui/tooltip/index.ts +0 -3
  67. package/src/lib/layer-manager.ts +0 -92
  68. package/src/stories/Dialog.stories.js +0 -832
  69. package/src/stories/DrawerNext.stories.js +0 -611
  70. package/src/stories/LayerManager.docs.mdx +0 -40
  71. package/src/stories/LayerManager.stories.js +0 -364
@@ -0,0 +1,297 @@
1
+ <template>
2
+ <div
3
+ :class="expand ? 'expand-multiselect' : 'normal-multiselect'"
4
+ tabindex="-1"
5
+ >
6
+ <span
7
+ v-if="label"
8
+ class="select-permission-label"
9
+ >{{ label }}</span
10
+ >
11
+ <div
12
+ class="select-permission"
13
+ tabindex="0"
14
+ @keypress="handleIsOpenKeyboard"
15
+ @click="active = !active"
16
+ >
17
+ <h6 class="title noselect">{{ inputTitle }}</h6>
18
+ <UnnnicIcon
19
+ :icon="active ? 'arrow-button-up-1' : 'arrow-button-down-1'"
20
+ size="sm"
21
+ scheme="neutral-dark"
22
+ />
23
+ </div>
24
+ <div
25
+ v-if="active"
26
+ v-on-click-outside="onClickOutside"
27
+ class="select-content"
28
+ tabindex="0"
29
+ >
30
+ <div>
31
+ <template
32
+ v-for="(group, indexGroup) in modelValue"
33
+ :key="`group-${indexGroup}`"
34
+ >
35
+ <h6
36
+ v-if="!hideGroupTitle"
37
+ :key="`title-${indexGroup}`"
38
+ class="title"
39
+ >
40
+ {{ group.title }}
41
+ </h6>
42
+ <section>
43
+ <template
44
+ v-for="(item, indexItem) in group.items"
45
+ :key="`item-${indexItem}`"
46
+ >
47
+ <div
48
+ v-if="hideRadio"
49
+ :key="indexItem + 'input'"
50
+ class="unnnic-radio-container unnnic-radio-container--sm"
51
+ style="cursor: pointer"
52
+ @click="change(indexGroup, indexItem)"
53
+ >
54
+ <strong>{{ item.title }}</strong>
55
+ <span>{{ item.description }}</span>
56
+ </div>
57
+ <UnnnicRadio
58
+ v-else
59
+ id=""
60
+ :key="'else' + indexItem + 'input'"
61
+ name=""
62
+ :modelValue="group.selected"
63
+ :value="indexItem"
64
+ size="sm"
65
+ class=""
66
+ @update:model-value="change(indexGroup, $event)"
67
+ >
68
+ <strong>{{ item.title }}</strong>
69
+ <span>{{ item.description }}</span>
70
+ </UnnnicRadio>
71
+ </template>
72
+ </section>
73
+ </template>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </template>
78
+
79
+ <script>
80
+ import { vOnClickOutside } from '@vueuse/components';
81
+ import UnnnicIcon from '../Icon.vue';
82
+ import UnnnicRadio from '../Radio/Radio.vue';
83
+
84
+ export default {
85
+ name: 'UnnnicMultiSelect',
86
+ components: {
87
+ UnnnicIcon,
88
+ UnnnicRadio,
89
+ },
90
+ directives: {
91
+ onClickOutside: vOnClickOutside,
92
+ },
93
+ props: {
94
+ isOpen: {
95
+ default: false,
96
+ },
97
+ expand: {
98
+ default: false,
99
+ },
100
+ label: {
101
+ type: String,
102
+ default: '',
103
+ },
104
+ modelValue: {
105
+ type: Array,
106
+ default: () => [],
107
+ },
108
+ inputTitle: {
109
+ type: String,
110
+ default: 'Teste',
111
+ },
112
+ hideRadio: {
113
+ type: Boolean,
114
+ default: false,
115
+ },
116
+ hideGroupTitle: {
117
+ type: Boolean,
118
+ default: false,
119
+ },
120
+ unselectable: {
121
+ type: Boolean,
122
+ default: false,
123
+ },
124
+ },
125
+
126
+ data() {
127
+ return {
128
+ active: false,
129
+ };
130
+ },
131
+
132
+ watch: {
133
+ isOpen() {
134
+ this.active = this.open;
135
+ },
136
+ },
137
+ methods: {
138
+ handleIsOpenKeyboard(event) {
139
+ if (
140
+ document.querySelector('.select-permission:focus-visible') &&
141
+ event.keyCode === 32
142
+ ) {
143
+ this.active = !this.active;
144
+ }
145
+ },
146
+
147
+ onClickOutside() {
148
+ if (!this.active) return;
149
+ this.active = false;
150
+ },
151
+
152
+ change(indexGroup, indexSelected) {
153
+ this.$emit(
154
+ 'update:model-value',
155
+ this.modelValue.map((item, index) => {
156
+ if (index === indexGroup) {
157
+ let selected = indexSelected;
158
+ if (this.unselectable && item.selected === indexSelected) {
159
+ selected = -1;
160
+ }
161
+ return { ...item, selected };
162
+ }
163
+
164
+ return item;
165
+ }),
166
+ );
167
+ },
168
+ },
169
+ };
170
+ </script>
171
+
172
+ <style lang="scss" scoped>
173
+ @use '@/assets/scss/unnnic' as *;
174
+
175
+ .normal-multiselect,
176
+ .expand-multiselect {
177
+ user-select: none;
178
+ }
179
+
180
+ .normal-multiselect {
181
+ position: relative;
182
+ max-width: 319px;
183
+
184
+ .select-content {
185
+ max-width: 319px;
186
+ }
187
+ }
188
+
189
+ .expand-multiselect {
190
+ position: relative;
191
+ width: 100%;
192
+
193
+ .select-content {
194
+ width: 100%;
195
+ }
196
+ }
197
+
198
+ .noselect {
199
+ -webkit-touch-callout: none; /* iOS Safari */
200
+ -webkit-user-select: none; /* Safari */
201
+ -khtml-user-select: none; /* Konqueror HTML */
202
+ -moz-user-select: none; /* Old versions of Firefox */
203
+ -ms-user-select: none; /* Internet Explorer/Edge */
204
+ user-select: none; /* Non-prefixed version, currently
205
+ supported by Chrome, Edge, Opera and Firefox */
206
+ }
207
+
208
+ .select-permission,
209
+ .select-content > div {
210
+ padding: $unnnic-squish-xs;
211
+ background-color: $unnnic-color-neutral-snow;
212
+
213
+ border-radius: $unnnic-border-radius-sm;
214
+ border: $unnnic-border-width-thinner solid $unnnic-color-neutral-soft;
215
+ }
216
+ .select-permission {
217
+ display: flex;
218
+ flex-direction: row;
219
+ justify-content: space-between;
220
+ align-items: center;
221
+ line-height: $unnnic-font-size-body-gt + $unnnic-line-height-medium;
222
+
223
+ cursor: pointer;
224
+ .icon {
225
+ margin-left: $unnnic-spacing-inline-xs;
226
+ }
227
+ }
228
+ .select-permission-label {
229
+ display: block;
230
+
231
+ color: $unnnic-color-neutral-cloudy;
232
+ margin-bottom: $unnnic-spacing-stack-xs;
233
+
234
+ font-family: $unnnic-font-family-secondary;
235
+ font-size: $unnnic-font-size-body-gt;
236
+ line-height: $unnnic-font-size-body-gt + $unnnic-line-height-medium;
237
+ }
238
+
239
+ .title {
240
+ font-family: $unnnic-font-family-secondary;
241
+ font-size: $unnnic-font-size-body-gt;
242
+ margin: 0;
243
+ font-weight: $unnnic-font-weight-regular;
244
+ color: $unnnic-color-neutral-dark;
245
+ }
246
+
247
+ .select-content {
248
+ position: absolute;
249
+ margin-top: $unnnic-spacing-stack-xs;
250
+
251
+ > div {
252
+ box-shadow: $unnnic-shadow-level-near;
253
+ .title {
254
+ margin-bottom: $unnnic-spacing-stack-sm;
255
+ }
256
+
257
+ & section {
258
+ display: flex;
259
+ flex-direction: column;
260
+
261
+ & + h6 {
262
+ margin-top: $unnnic-spacing-stack-sm;
263
+ padding-top: $unnnic-spacing-stack-sm;
264
+ border-top: $unnnic-border-width-thinner solid
265
+ $unnnic-color-neutral-darkest;
266
+ }
267
+
268
+ strong,
269
+ span {
270
+ display: block;
271
+ font-family: $unnnic-font-family-secondary;
272
+ font-size: $unnnic-font-size-body-gt;
273
+ }
274
+
275
+ strong {
276
+ font-weight: $unnnic-font-weight-regular;
277
+ }
278
+ span {
279
+ font-weight: $unnnic-font-weight-light;
280
+ }
281
+
282
+ .unnnic-radio-container {
283
+ & + .unnnic-radio-container {
284
+ margin-top: $unnnic-spacing-stack-sm;
285
+ padding-top: $unnnic-spacing-stack-sm;
286
+ border-top: $unnnic-border-width-thinner solid
287
+ $unnnic-color-neutral-lightest;
288
+ }
289
+
290
+ :deep(.unnnic-icon) {
291
+ margin-right: $unnnic-inline-xs;
292
+ }
293
+ }
294
+ }
295
+ }
296
+ }
297
+ </style>
@@ -12,9 +12,9 @@
12
12
  type="radio"
13
13
  :disabled="disabled"
14
14
  :checked="computedModelValue === value"
15
+ @change="click"
15
16
  :name="computedName"
16
17
  v-bind="pick($attrs, ['id'])"
17
- @change="click"
18
18
  />
19
19
 
20
20
  <p
@@ -9,7 +9,7 @@
9
9
  >
10
10
  <PopoverTrigger class="w-full">
11
11
  <UnnnicInput
12
- ref="selectInputRef"
12
+ ref="inputRef"
13
13
  :modelValue="inputValue"
14
14
  class="unnnic-select__input"
15
15
  readonly
@@ -132,8 +132,8 @@ const emit = defineEmits<{
132
132
  }>();
133
133
 
134
134
  const openPopover = ref(false);
135
- const selectInputRef = ref<HTMLInputElement | null>(null);
136
- const { width: inputWidth } = useElementSize(selectInputRef);
135
+ const inputRef = ref<HTMLInputElement | null>(null);
136
+ const { width: inputWidth } = useElementSize(inputRef);
137
137
 
138
138
  const inputWidthString = computed(() => {
139
139
  return `${inputWidth.value}px`;
@@ -19,8 +19,8 @@
19
19
  type="checkbox"
20
20
  :disabled="disabled"
21
21
  :checked="modelValue"
22
- v-bind="pick($attrs, ['id', 'name'])"
23
22
  @change="toggleState"
23
+ v-bind="pick($attrs, ['id', 'name'])"
24
24
  />
25
25
 
26
26
  <p
@@ -4,9 +4,7 @@ exports[`Tab.vue > matches the snapshot 1`] = `
4
4
  "<div data-v-b4e39fac="" class="tab size-md">
5
5
  <header data-v-b4e39fac="" class="tab-header">
6
6
  <ul data-v-b4e39fac="" class="tab-content">
7
- <li data-v-b4e39fac="" class="tab-head">tab1<div data-v-b3d24f2b="" class="unnnic-tooltip-trigger" data-testid="tooltip-trigger" data-state="closed" data-grace-area-trigger=""><span data-v-26446d8e="" data-v-b4e39fac="" class="unnnic-icon material-symbols-rounded unnnic-icon-scheme--fg-base unnnic-icon-size--sm unnnic-icon__size--sm" data-testid="material-icon" translate="no">help</span></div>
8
- <!--teleport start-->
9
- <!--teleport end-->
7
+ <li data-v-b4e39fac="" class="tab-head">tab1<div data-v-bf0cf546="" data-v-b4e39fac="" class="unnnic-tooltip"><span data-v-26446d8e="" data-v-b4e39fac="" class="unnnic-icon material-symbols-rounded unnnic-icon-scheme--fg-base unnnic-icon-size--sm unnnic-icon__size--sm" data-testid="material-icon" translate="no">help</span><span data-v-bf0cf546="" class="unnnic-tooltip-label unnnic-tooltip-label-bottom" data-testid="tooltip-label" style="left: 0px; top: 8px;">Tooltip text <br data-v-bf0cf546=""><!--v-if--></span></div>
10
8
  </li>
11
9
  <li data-v-b4e39fac="" class="tab-head tab-head--active">tab2
12
10
  <!--v-if-->
@@ -13,11 +13,11 @@
13
13
  }`"
14
14
  >
15
15
  <img
16
+ class="unnnic-template-preview__header__media__preview"
16
17
  v-if="
17
18
  template?.header.type === 'MEDIA' &&
18
19
  template?.header.mediaType === 'IMAGE'
19
20
  "
20
- class="unnnic-template-preview__header__media__preview"
21
21
  :src="template.header.src || imagePreview"
22
22
  />
23
23
  <template
@@ -50,8 +50,8 @@
50
50
  />
51
51
  </template>
52
52
  <h1
53
- v-else-if="template?.header.type === 'TEXT'"
54
53
  class="unnnic-template-preview__header__text__preview"
54
+ v-else-if="template?.header.type === 'TEXT'"
55
55
  >
56
56
  {{ template.header.text }}
57
57
  </h1>
@@ -1,10 +1,10 @@
1
1
  <template>
2
2
  <UnnnicModalDialog
3
3
  :modelValue="modelValue"
4
+ @update:modelValue="$event === false && $emit('close')"
4
5
  :title="defaultTranslations.title[props.locale]"
5
6
  :showCloseIcon="true"
6
7
  class="unnnic-template-preview-modal"
7
- @update:model-value="$event === false && $emit('close')"
8
8
  >
9
9
  <UnnnicTemplatePreview :template="template" />
10
10
  </UnnnicModalDialog>
@@ -7,11 +7,10 @@
7
7
  >
8
8
  <aside
9
9
  v-if="isVisible"
10
- :class="['unnnic-toast', `unnnic-toast--${validType}`]"
11
- :role="validType === 'error' ? 'alert' : 'status'"
12
- :aria-live="validType === 'error' ? 'assertive' : 'polite'"
10
+ :class="['unnnic-toast', `unnnic-toast--${type}`]"
11
+ :role="type === 'error' ? 'alert' : 'status'"
12
+ :aria-live="type === 'error' ? 'assertive' : 'polite'"
13
13
  data-testid="toast"
14
- :style="{ zIndex: toastZIndex }"
15
14
  >
16
15
  <section
17
16
  class="unnnic-toast__content"
@@ -23,7 +22,7 @@
23
22
  >
24
23
  <UnnnicIcon
25
24
  :icon="typeConfig.icon"
26
- :scheme="typeConfig.scheme as SchemeColor"
25
+ :scheme="typeConfig.scheme"
27
26
  size="ant"
28
27
  data-testid="toast-type-icon"
29
28
  />
@@ -75,7 +74,6 @@ import { ref, computed, onMounted, onUnmounted } from 'vue';
75
74
 
76
75
  import UnnnicIcon from '@/components/Icon.vue';
77
76
  import UnnnicButton from '@/components/Button/Button.vue';
78
- import { useLayerZIndex } from '@/lib/layer-manager';
79
77
 
80
78
  import type { ToastProps, ToastEmits } from './types';
81
79
  import type { SchemeColor } from '@/types/scheme-colors';
@@ -97,13 +95,6 @@ const emit = defineEmits<ToastEmits>();
97
95
  const isVisible = ref(false);
98
96
  let timeoutId: number | null = null;
99
97
 
100
- const validType = computed(() => {
101
- if (['informational', 'attention', 'success', 'error'].includes(props.type)) {
102
- return props.type;
103
- }
104
- return 'informational';
105
- });
106
-
107
98
  const typeConfig = computed(() => {
108
99
  const configMap = {
109
100
  informational: { icon: 'info', scheme: 'blue-500' },
@@ -112,11 +103,12 @@ const typeConfig = computed(() => {
112
103
  error: { icon: 'cancel', scheme: 'red-500' },
113
104
  };
114
105
 
115
- return configMap[validType.value];
106
+ return configMap[props.type || 'informational'] as {
107
+ icon: string;
108
+ scheme: SchemeColor;
109
+ };
116
110
  });
117
111
 
118
- const toastZIndex = useLayerZIndex('toast');
119
-
120
112
  const handleClose = () => {
121
113
  isVisible.value = false;
122
114
  emit('close');
@@ -160,6 +152,7 @@ onUnmounted(() => {
160
152
  position: fixed;
161
153
  bottom: $unnnic-space-4;
162
154
  right: $unnnic-space-4;
155
+ z-index: 9999;
163
156
 
164
157
  display: flex;
165
158
  align-items: flex-end;
@@ -1,25 +1,23 @@
1
1
  <template>
2
- <Tooltip
3
- :disabled="!(enabled || forceOpen)"
4
- :open="forceOpen || undefined"
5
- data-testid="tooltip-wrapper"
2
+ <div
3
+ ref="tooltip"
4
+ :class="{
5
+ 'unnnic-tooltip': enabled || forceOpen,
6
+ 'force-open': forceOpen,
7
+ }"
8
+ @mouseover="handleResize"
6
9
  >
7
- <TooltipTrigger data-testid="tooltip-trigger">
8
- <slot />
9
- </TooltipTrigger>
10
-
11
- <TooltipContent
10
+ <slot />
11
+ <span
12
+ v-show="enabled || forceOpen"
13
+ ref="label"
12
14
  :class="['unnnic-tooltip-label', `unnnic-tooltip-label-${side}`]"
13
- :style="{ maxWidth: maxWidth }"
14
- :side="side"
15
- data-testid="tooltip-content"
15
+ :style="{ maxWidth: maxWidth, left: leftPos, top: topPos }"
16
+ data-testid="tooltip-label"
16
17
  >
17
18
  <template v-if="enableHtml">
18
19
  <!-- eslint-disable-next-line vue/no-v-html -->
19
- <section
20
- data-testid="tooltip-html-content"
21
- v-html="text"
22
- ></section>
20
+ <section v-html="text"></section>
23
21
  </template>
24
22
  <template
25
23
  v-for="(line, index) in text.split('\n')"
@@ -29,20 +27,22 @@
29
27
  {{ line }}
30
28
  <br />
31
29
  </template>
32
- </TooltipContent>
33
- </Tooltip>
30
+
31
+ <template v-if="shortcutText">
32
+ <span
33
+ class="unnnic-tooltip-label-shortcut"
34
+ data-testid="tooltip-label-shortcut"
35
+ >
36
+ {{ shortcutText }}
37
+ </span>
38
+ </template>
39
+ </span>
40
+ </div>
34
41
  </template>
35
42
 
36
43
  <script>
37
- import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
38
-
39
44
  export default {
40
45
  name: 'UnnnicTooltip',
41
- components: {
42
- Tooltip,
43
- TooltipTrigger,
44
- TooltipContent,
45
- },
46
46
  props: {
47
47
  text: {
48
48
  type: String,
@@ -67,10 +67,162 @@ export default {
67
67
  type: String,
68
68
  default: '',
69
69
  },
70
+ shortcutText: {
71
+ type: String,
72
+ default: null,
73
+ },
70
74
  enableHtml: {
71
75
  type: Boolean,
72
76
  default: false,
73
77
  },
74
78
  },
79
+ data() {
80
+ return {
81
+ topPos: null,
82
+ leftPos: null,
83
+ };
84
+ },
85
+ watch: {
86
+ side() {
87
+ this.getRightPost(this.$refs.tooltip);
88
+ },
89
+ },
90
+ mounted() {
91
+ this.handleResize();
92
+
93
+ window.addEventListener('scroll', this.handleResize);
94
+ window.addEventListener('resize', this.handleResize);
95
+ },
96
+ unmounted() {
97
+ window.removeEventListener('scroll', this.handleResize);
98
+ window.removeEventListener('resize', this.handleResize);
99
+ },
100
+ methods: {
101
+ handleResize() {
102
+ this.getRightPost(this.$refs.tooltip);
103
+ },
104
+ getRightPost(element) {
105
+ const elementPos = element.getBoundingClientRect();
106
+
107
+ if (element && this.$refs.label) {
108
+ if (this.side === 'right') {
109
+ this.leftPos = `${elementPos.x + elementPos.width + 8}px`;
110
+ this.topPos = `${elementPos.y + elementPos.height / 2 - this.$refs.label.offsetHeight / 2}px`;
111
+ } else if (this.side === 'left') {
112
+ this.leftPos = `${elementPos.x - this.$refs.label.offsetWidth - 8}px`;
113
+ this.topPos = `${elementPos.y + elementPos.height / 2 - this.$refs.label.offsetHeight / 2}px`;
114
+ } else if (this.side === 'top') {
115
+ this.leftPos = `${elementPos.x + elementPos.width / 2 - this.$refs.label.clientWidth / 2}px`;
116
+ this.topPos = `${elementPos.y - this.$refs.label.offsetHeight - 8}px`;
117
+ } else if (this.side === 'bottom') {
118
+ this.leftPos = `${elementPos.x + elementPos.width / 2 - this.$refs.label.clientWidth / 2}px`;
119
+ this.topPos = `${elementPos.y + elementPos.height + 8}px`;
120
+ }
121
+ }
122
+ },
123
+ },
75
124
  };
76
125
  </script>
126
+
127
+ <style lang="scss" scoped>
128
+ @use '@/assets/scss/unnnic' as *;
129
+
130
+ .unnnic-tooltip {
131
+ position: relative;
132
+ display: inline-block;
133
+ overflow-wrap: break-word;
134
+ }
135
+
136
+ .unnnic-tooltip-label {
137
+ z-index: 1;
138
+ visibility: hidden;
139
+ text-align: center;
140
+ position: fixed;
141
+ width: max-content;
142
+ min-width: 2 * $unnnic-font-size;
143
+ box-sizing: border-box;
144
+ width: auto;
145
+ display: flex;
146
+ justify-content: center;
147
+ gap: $unnnic-spacing-xs;
148
+ align-items: center;
149
+
150
+ background-color: $unnnic-color-neutral-black;
151
+ color: $unnnic-color-neutral-snow;
152
+ border-radius: $unnnic-border-radius-sm;
153
+ padding: $unnnic-inset-nano;
154
+ box-shadow: $unnnic-shadow-level-near;
155
+ font-size: $unnnic-font-size-body-md;
156
+ font-family: $unnnic-font-family-secondary;
157
+ font-weight: $unnnic-font-weight-regular;
158
+ line-height: ($unnnic-font-size-body-md + $unnnic-line-height-medium);
159
+
160
+ &::after {
161
+ content: '';
162
+ position: absolute;
163
+ border-width: 5px;
164
+ border-style: solid;
165
+ }
166
+
167
+ &-top {
168
+ position: fixed;
169
+ &::after {
170
+ top: 100%;
171
+ left: 50%;
172
+ margin-left: -5px;
173
+ border-color: $unnnic-color-neutral-black transparent transparent
174
+ transparent;
175
+ }
176
+ }
177
+
178
+ &-bottom {
179
+ position: fixed;
180
+ &::after {
181
+ bottom: 100%;
182
+ left: 50%;
183
+ margin-left: -5px;
184
+ border-color: transparent transparent $unnnic-color-neutral-black
185
+ transparent;
186
+ }
187
+ }
188
+ &-right {
189
+ position: fixed;
190
+ &::after {
191
+ top: 50%;
192
+ right: 100%;
193
+ margin-top: -5px;
194
+ border-color: transparent $unnnic-color-neutral-black transparent
195
+ transparent;
196
+ }
197
+ }
198
+ &-left {
199
+ position: fixed;
200
+ &::after {
201
+ top: 50%;
202
+ left: 100%;
203
+ margin-top: -5px;
204
+ border-color: transparent transparent transparent
205
+ $unnnic-color-neutral-black;
206
+ }
207
+ }
208
+
209
+ &-shortcut {
210
+ background-color: $unnnic-color-neutral-darkest;
211
+ border-radius: $unnnic-border-radius-sm;
212
+ padding: calc($unnnic-inset-nano / 2) $unnnic-inset-nano;
213
+ }
214
+ }
215
+
216
+ .unnnic-tooltip.force-open {
217
+ .unnnic-tooltip-label {
218
+ visibility: visible;
219
+ }
220
+ }
221
+
222
+ .unnnic-tooltip:hover {
223
+ .unnnic-tooltip-label {
224
+ visibility: visible;
225
+ width: auto;
226
+ }
227
+ }
228
+ </style>