@weni/unnnic-system 3.12.3-alpha-teleports.1 → 3.12.3-alpha.1
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/dist/components/ChartFunnel/DefaultFunnel/ChartDefaultFunnelBase.vue.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.vue.d.ts.map +1 -1
- package/dist/components/CheckboxGroup/CheckboxGroup.vue.d.ts.map +1 -1
- package/dist/components/DateFilter/DateFilter.vue.d.ts +81 -2
- package/dist/components/Drawer/Drawer.vue.d.ts.map +1 -1
- package/dist/components/FormElement/FormElement.vue.d.ts.map +1 -1
- package/dist/components/Input/BaseInput.vue.d.ts +22 -0
- package/dist/components/Input/BaseInput.vue.d.ts.map +1 -1
- package/dist/components/Input/Input.vue.d.ts +81 -2
- package/dist/components/Input/Input.vue.d.ts.map +1 -1
- package/dist/components/Input/TextInput.vue.d.ts +52 -1
- package/dist/components/Input/TextInput.vue.d.ts.map +1 -1
- package/dist/components/InputNext/InputNext.vue.d.ts +1 -1
- package/dist/components/ModalNext/ModalNext.vue.d.ts +81 -2
- package/dist/components/MultiSelect/MultSelectOption.vue.d.ts +17 -0
- package/dist/components/MultiSelect/MultSelectOption.vue.d.ts.map +1 -0
- package/dist/components/MultiSelect/index.vue.d.ts +44 -0
- package/dist/components/MultiSelect/index.vue.d.ts.map +1 -0
- package/dist/components/Radio/Radio.vue.d.ts.map +1 -1
- package/dist/components/Select/index.vue.d.ts +44 -0
- package/dist/components/Select/index.vue.d.ts.map +1 -0
- package/dist/components/SelectSmart/SelectSmart.vue.d.ts +52 -1
- package/dist/components/SelectTime/index.vue.d.ts +52 -1
- package/dist/components/Switch/Switch.vue.d.ts.map +1 -1
- package/dist/components/TemplatePreview/TemplatePreview.vue.d.ts.map +1 -1
- package/dist/components/Toast/Toast.vue.d.ts.map +1 -1
- package/dist/components/index.d.ts +23720 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/ui/popover/PopoverOption.vue.d.ts +18 -0
- package/dist/components/ui/popover/PopoverOption.vue.d.ts.map +1 -0
- package/dist/components/ui/popover/index.d.ts +1 -0
- package/dist/components/ui/popover/index.d.ts.map +1 -1
- package/dist/{es-4aa88754.mjs → es-239c29c2.mjs} +1 -1
- package/dist/{index-ec96f88a.mjs → index-40e176e4.mjs} +9498 -9233
- package/dist/lib/layer-manager.d.ts.map +1 -1
- package/dist/locales/en.json.d.ts +2 -1
- package/dist/locales/es.json.d.ts +2 -1
- package/dist/locales/pt_br.json.d.ts +2 -1
- package/dist/{pt-br-ec1ec185.mjs → pt-br-5004a35e.mjs} +1 -1
- package/dist/style.css +1 -1
- package/dist/unnnic.mjs +176 -172
- package/dist/unnnic.umd.js +33 -33
- package/package.json +1 -1
- package/src/assets/scss/scheme-colors.scss +223 -223
- package/src/components/ChartFunnel/DefaultFunnel/ChartDefaultFunnelBase.vue +1 -2
- package/src/components/ChartFunnel/SvgFunnel/ChartFunnelTwoRows.vue +60 -61
- package/src/components/Checkbox/Checkbox.vue +9 -3
- package/src/components/CheckboxGroup/CheckboxGroup.vue +7 -5
- package/src/components/Chip/Chip.vue +1 -1
- package/src/components/Drawer/Drawer.vue +20 -9
- package/src/components/Drawer/__tests__/Drawer.spec.js +11 -9
- package/src/components/Drawer/__tests__/__snapshots__/Drawer.spec.js.snap +9 -9
- package/src/components/FormElement/FormElement.vue +96 -87
- package/src/components/Input/BaseInput.vue +21 -2
- package/src/components/Input/Input.scss +2 -3
- package/src/components/Input/Input.vue +21 -3
- package/src/components/Input/TextInput.vue +58 -22
- package/src/components/Input/__test__/__snapshots__/Input.spec.js.snap +5 -1
- package/src/components/Input/__test__/__snapshots__/TextInput.spec.js.snap +7 -1
- package/src/components/ModalDialog/ModalDialog.vue +2 -2
- package/src/components/MultiSelect/MultSelectOption.vue +49 -0
- package/src/components/MultiSelect/__tests__/MultiSelect.spec.js +556 -0
- package/src/components/MultiSelect/__tests__/MultiSelectOption.spec.js +229 -0
- package/src/components/MultiSelect/__tests__/__snapshots__/MultiSelect.spec.js.snap +81 -0
- package/src/components/MultiSelect/__tests__/__snapshots__/MultiSelectOption.spec.js.snap +51 -0
- package/src/components/MultiSelect/index.vue +224 -0
- package/src/components/Radio/Radio.vue +12 -6
- package/src/components/Radio/__test__/Radio.spec.js +3 -1
- package/src/components/RadioGroup/RadioGroup.vue +18 -10
- package/src/components/Select/__tests__/Select.spec.js +422 -0
- package/src/components/Select/__tests__/SelectItem.spec.js +330 -0
- package/src/components/Select/__tests__/__snapshots__/Popover.spec.js.snap +8 -0
- package/src/components/Select/__tests__/__snapshots__/Select.spec.js.snap +65 -0
- package/src/components/Select/__tests__/__snapshots__/SelectItem.spec.js.snap +15 -0
- package/src/components/Select/__tests__/__snapshots__/SelectOption.spec.js.snap +25 -0
- package/src/components/Select/__tests__/__snapshots__/SelectPopover.spec.js.snap +8 -0
- package/src/components/Select/index.vue +261 -0
- package/src/components/Switch/Switch.vue +10 -3
- package/src/components/TemplatePreview/TemplatePreview.vue +28 -25
- package/src/components/TemplatePreview/TemplatePreviewModal.vue +10 -10
- package/src/components/TemplatePreview/types.d.ts +3 -3
- package/src/components/Toast/Toast.vue +12 -8
- package/src/components/index.ts +7 -7
- package/src/components/ui/dialog/DialogClose.vue +3 -3
- package/src/components/ui/drawer/DrawerClose.vue +9 -3
- package/src/components/ui/popover/PopoverOption.vue +4 -0
- package/src/lib/layer-manager.ts +12 -20
- package/src/locales/en.json +2 -1
- package/src/locales/es.json +2 -1
- package/src/locales/pt_br.json +2 -1
- package/src/stories/MultiSelect.stories.js +142 -46
- package/src/stories/Select.stories.js +158 -0
- package/src/stories/TemplatePreview.stories.js +27 -27
- package/src/stories/TemplatePreviewModal.stories.js +31 -31
- package/dist/components/MultiSelect/MultiSelect.vue.d.ts +0 -163
- package/dist/components/MultiSelect/MultiSelect.vue.d.ts.map +0 -1
- package/src/components/MultiSelect/MultiSelect.vue +0 -297
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="unnnic-select"
|
|
4
|
+
@keydown="handleKeyDown"
|
|
5
|
+
>
|
|
6
|
+
<Popover
|
|
7
|
+
:open="openPopover"
|
|
8
|
+
@update:open="openPopover = $event"
|
|
9
|
+
>
|
|
10
|
+
<PopoverTrigger>
|
|
11
|
+
<UnnnicInput
|
|
12
|
+
:modelValue="inputValue"
|
|
13
|
+
class="unnnic-select__input"
|
|
14
|
+
readonly
|
|
15
|
+
:forceActiveStatus="openPopover"
|
|
16
|
+
:size="props.size"
|
|
17
|
+
:placeholder="props.placeholder"
|
|
18
|
+
:label="props.label"
|
|
19
|
+
:errors="props.errors"
|
|
20
|
+
:message="props.message"
|
|
21
|
+
:iconRight="openPopover ? 'keyboard_arrow_up' : 'keyboard_arrow_down'"
|
|
22
|
+
:disabled="props.disabled"
|
|
23
|
+
showClear
|
|
24
|
+
@clear="emit('update:modelValue', '')"
|
|
25
|
+
/>
|
|
26
|
+
</PopoverTrigger>
|
|
27
|
+
<PopoverContent
|
|
28
|
+
align="start"
|
|
29
|
+
:style="{
|
|
30
|
+
maxHeight: calculatedMaxHeight,
|
|
31
|
+
overflow: 'auto',
|
|
32
|
+
}"
|
|
33
|
+
>
|
|
34
|
+
<div class="unnnic-select__content">
|
|
35
|
+
<UnnnicInput
|
|
36
|
+
v-if="props.enableSearch"
|
|
37
|
+
class="unnnic-select__input-search"
|
|
38
|
+
:modelValue="props.search"
|
|
39
|
+
:placeholder="$t('search')"
|
|
40
|
+
iconLeft="search"
|
|
41
|
+
@update:model-value="handleSearch"
|
|
42
|
+
/>
|
|
43
|
+
<PopoverOption
|
|
44
|
+
v-for="(option, index) in filteredOptions"
|
|
45
|
+
:key="option[props.itemValue]"
|
|
46
|
+
:data-option-index="index"
|
|
47
|
+
data-testid="select-option"
|
|
48
|
+
:label="option[props.itemLabel]"
|
|
49
|
+
:active="
|
|
50
|
+
option[props.itemValue] === selectedItem?.[props.itemValue]
|
|
51
|
+
"
|
|
52
|
+
:focused="focusedOptionIndex === index"
|
|
53
|
+
:disabled="option.disabled"
|
|
54
|
+
@click="handleSelectOption(option)"
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
</PopoverContent>
|
|
58
|
+
</Popover>
|
|
59
|
+
</div>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<script setup lang="ts">
|
|
63
|
+
import { computed, ref, watch, nextTick } from 'vue';
|
|
64
|
+
import UnnnicInput from '../Input/Input.vue';
|
|
65
|
+
|
|
66
|
+
import {
|
|
67
|
+
Popover,
|
|
68
|
+
PopoverTrigger,
|
|
69
|
+
PopoverContent,
|
|
70
|
+
PopoverOption,
|
|
71
|
+
} from '../ui/popover/index';
|
|
72
|
+
import UnnnicI18n from '../../mixins/i18n';
|
|
73
|
+
|
|
74
|
+
defineOptions({
|
|
75
|
+
name: 'UnnnicSelect',
|
|
76
|
+
mixins: [UnnnicI18n],
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
interface SelectProps {
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
81
|
+
options: Array<{ [key: string]: any }>;
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
+
modelValue: any;
|
|
84
|
+
returnObject?: boolean;
|
|
85
|
+
itemLabel?: string;
|
|
86
|
+
itemValue?: string;
|
|
87
|
+
placeholder?: string;
|
|
88
|
+
label?: string;
|
|
89
|
+
type?: 'normal' | 'error';
|
|
90
|
+
errors?: string | Array<string>;
|
|
91
|
+
message?: string;
|
|
92
|
+
size?: 'sm' | 'md';
|
|
93
|
+
optionsLines?: number;
|
|
94
|
+
enableSearch?: boolean;
|
|
95
|
+
search?: string;
|
|
96
|
+
locale?: string;
|
|
97
|
+
disabled?: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const props = withDefaults(defineProps<SelectProps>(), {
|
|
101
|
+
size: 'md',
|
|
102
|
+
type: 'normal',
|
|
103
|
+
placeholder: '',
|
|
104
|
+
optionsLines: 5,
|
|
105
|
+
returnObject: false,
|
|
106
|
+
itemLabel: 'label',
|
|
107
|
+
itemValue: 'value',
|
|
108
|
+
locale: 'en',
|
|
109
|
+
enableSearch: false,
|
|
110
|
+
disabled: false,
|
|
111
|
+
label: '',
|
|
112
|
+
errors: '',
|
|
113
|
+
message: '',
|
|
114
|
+
search: '',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const emit = defineEmits<{
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
119
|
+
'update:modelValue': [value: any];
|
|
120
|
+
'update:search': [value: string];
|
|
121
|
+
}>();
|
|
122
|
+
|
|
123
|
+
const openPopover = ref(false);
|
|
124
|
+
|
|
125
|
+
watch(openPopover, () => {
|
|
126
|
+
if (!openPopover.value) {
|
|
127
|
+
handleSearch('');
|
|
128
|
+
} else {
|
|
129
|
+
focusedOptionIndex.value = -1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (openPopover.value && props.modelValue) {
|
|
133
|
+
const selectedOptionIndex = props.options.findIndex(
|
|
134
|
+
(option) =>
|
|
135
|
+
option[props.itemValue] === selectedItem.value?.[props.itemValue],
|
|
136
|
+
);
|
|
137
|
+
scrollToOption(selectedOptionIndex, 'instant', 'center');
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const handleKeyDown = (event) => {
|
|
142
|
+
const { key } = event;
|
|
143
|
+
const validKeys = ['ArrowUp', 'ArrowDown', 'Enter'];
|
|
144
|
+
if (validKeys.includes(key)) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
if (key === 'ArrowUp') {
|
|
147
|
+
if (focusedOptionIndex.value === 0) return;
|
|
148
|
+
focusedOptionIndex.value--;
|
|
149
|
+
scrollToOption(focusedOptionIndex.value);
|
|
150
|
+
}
|
|
151
|
+
if (key === 'ArrowDown') {
|
|
152
|
+
if (focusedOptionIndex.value === filteredOptions.value.length - 1) return;
|
|
153
|
+
focusedOptionIndex.value++;
|
|
154
|
+
scrollToOption(focusedOptionIndex.value);
|
|
155
|
+
}
|
|
156
|
+
if (key === 'Enter') {
|
|
157
|
+
handleSelectOption(filteredOptions.value[focusedOptionIndex.value]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const focusedOptionIndex = ref<number>(-1);
|
|
163
|
+
|
|
164
|
+
const scrollToOption = (
|
|
165
|
+
index: number,
|
|
166
|
+
behavior: 'smooth' | 'instant' = 'smooth',
|
|
167
|
+
block: 'center' | 'start' | 'end' | 'nearest' = 'center',
|
|
168
|
+
) => {
|
|
169
|
+
nextTick(() => {
|
|
170
|
+
const option = document.querySelector(`[data-option-index="${index}"]`);
|
|
171
|
+
if (option) {
|
|
172
|
+
option.scrollIntoView?.({ behavior, block });
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const calculatedMaxHeight = computed(() => {
|
|
178
|
+
if (!props.options || props.options.length === 0) return 'unset';
|
|
179
|
+
const popoverPadding = 32;
|
|
180
|
+
const popoverGap = 4;
|
|
181
|
+
// 37 = 21px (height) + 16px (padding)
|
|
182
|
+
const fieldsHeight = 37 * props.optionsLines;
|
|
183
|
+
const size =
|
|
184
|
+
fieldsHeight + popoverPadding + (popoverGap * props.optionsLines - 2);
|
|
185
|
+
return `${props.enableSearch ? size + 54 : size}px`;
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const selectedItem = computed(() => {
|
|
189
|
+
if (props.returnObject) return props.modelValue;
|
|
190
|
+
|
|
191
|
+
return props.options.find(
|
|
192
|
+
(option) => option[props.itemValue] === props.modelValue,
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const inputValue = computed(() => {
|
|
197
|
+
return selectedItem.value?.[props.itemLabel];
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const handleSelectOption = (option) => {
|
|
201
|
+
if (
|
|
202
|
+
option[props.itemValue] === selectedItem.value?.[props.itemValue] ||
|
|
203
|
+
option.disabled
|
|
204
|
+
)
|
|
205
|
+
return;
|
|
206
|
+
|
|
207
|
+
emit(
|
|
208
|
+
'update:modelValue',
|
|
209
|
+
props.returnObject ? option : option[props.itemValue],
|
|
210
|
+
);
|
|
211
|
+
openPopover.value = false;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const handleSearch = (value: string) => {
|
|
215
|
+
emit('update:search', value);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const filteredOptions = computed(() => {
|
|
219
|
+
if (!props.enableSearch || !props.search) return props.options;
|
|
220
|
+
|
|
221
|
+
return props.options.filter(
|
|
222
|
+
(option) =>
|
|
223
|
+
option[props.itemLabel]
|
|
224
|
+
.toLowerCase()
|
|
225
|
+
.includes(props.search?.toLowerCase()) ||
|
|
226
|
+
option[props.itemValue]
|
|
227
|
+
.toLowerCase()
|
|
228
|
+
.includes(props.search?.toLowerCase()),
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
</script>
|
|
232
|
+
|
|
233
|
+
<style lang="scss" scoped>
|
|
234
|
+
@use '@/assets/scss/unnnic' as *;
|
|
235
|
+
|
|
236
|
+
:deep(.unnnic-select__input) {
|
|
237
|
+
cursor: pointer;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
:deep(.unnnic-select__input-search) {
|
|
241
|
+
> .icon-left {
|
|
242
|
+
color: $unnnic-color-fg-base;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
:deep(.unnnic-select__input) {
|
|
247
|
+
> .icon-right {
|
|
248
|
+
color: $unnnic-color-fg-base;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.unnnic-select {
|
|
253
|
+
&__content {
|
|
254
|
+
display: flex;
|
|
255
|
+
flex-direction: column;
|
|
256
|
+
padding: 0;
|
|
257
|
+
margin: 0;
|
|
258
|
+
gap: $unnnic-space-1;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
</style>
|
|
@@ -8,7 +8,12 @@
|
|
|
8
8
|
class="unnnic-switch__label"
|
|
9
9
|
/>
|
|
10
10
|
|
|
11
|
-
<label
|
|
11
|
+
<label
|
|
12
|
+
:class="[
|
|
13
|
+
'unnnic-switch__input-wrapper',
|
|
14
|
+
{ 'unnnic-switch__input-wrapper--disabled': disabled },
|
|
15
|
+
]"
|
|
16
|
+
>
|
|
12
17
|
<input
|
|
13
18
|
class="unnnic-switch__input"
|
|
14
19
|
type="checkbox"
|
|
@@ -78,7 +83,7 @@ export default {
|
|
|
78
83
|
type: String,
|
|
79
84
|
default: '',
|
|
80
85
|
},
|
|
81
|
-
|
|
86
|
+
|
|
82
87
|
helper: {
|
|
83
88
|
type: String,
|
|
84
89
|
default: '',
|
|
@@ -176,7 +181,9 @@ $switch-height: 20px;
|
|
|
176
181
|
background-repeat: no-repeat;
|
|
177
182
|
background-position: 4px center;
|
|
178
183
|
|
|
179
|
-
transition:
|
|
184
|
+
transition:
|
|
185
|
+
120ms linear background-position,
|
|
186
|
+
120ms linear background-color;
|
|
180
187
|
|
|
181
188
|
cursor: pointer;
|
|
182
189
|
|
|
@@ -75,7 +75,10 @@
|
|
|
75
75
|
{{ template?.footer }}
|
|
76
76
|
</footer>
|
|
77
77
|
</section>
|
|
78
|
-
<footer
|
|
78
|
+
<footer
|
|
79
|
+
v-if="hasButtons"
|
|
80
|
+
class="unnnic-template-preview__buttons"
|
|
81
|
+
>
|
|
79
82
|
<section
|
|
80
83
|
v-for="(button, index) in template?.buttons"
|
|
81
84
|
:key="`button-${index}`"
|
|
@@ -96,15 +99,15 @@
|
|
|
96
99
|
</template>
|
|
97
100
|
|
|
98
101
|
<script lang="ts" setup>
|
|
99
|
-
import { computed } from
|
|
102
|
+
import { computed } from 'vue';
|
|
100
103
|
|
|
101
|
-
import type { Template } from
|
|
104
|
+
import type { Template } from './types';
|
|
102
105
|
|
|
103
|
-
import imagePreview from
|
|
104
|
-
import documentPreview from
|
|
105
|
-
import videoPreview from
|
|
106
|
+
import imagePreview from '../../assets/img/previews/image-preview.png';
|
|
107
|
+
import documentPreview from '../../assets/img/previews/doc-preview.png';
|
|
108
|
+
import videoPreview from '../../assets/img/previews/video-preview.png';
|
|
106
109
|
|
|
107
|
-
import UnnnicIcon from
|
|
110
|
+
import UnnnicIcon from '../Icon.vue';
|
|
108
111
|
|
|
109
112
|
interface Props {
|
|
110
113
|
template?: Template | null;
|
|
@@ -115,30 +118,30 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
115
118
|
});
|
|
116
119
|
|
|
117
120
|
const hasHeader = computed(
|
|
118
|
-
() => props.template?.header && props.template.header.type
|
|
121
|
+
() => props.template?.header && props.template.header.type,
|
|
119
122
|
);
|
|
120
123
|
const hasHeaderMedia = computed(
|
|
121
|
-
() => !!props.template?.header && props.template.header.type ===
|
|
124
|
+
() => !!props.template?.header && props.template.header.type === 'MEDIA',
|
|
122
125
|
);
|
|
123
126
|
const hasBody = computed(
|
|
124
|
-
() => !!props.template?.body && props.template.body.length > 0
|
|
127
|
+
() => !!props.template?.body && props.template.body.length > 0,
|
|
125
128
|
);
|
|
126
129
|
const hasFooter = computed(
|
|
127
|
-
() => !!props.template?.footer && props.template.footer.length > 0
|
|
130
|
+
() => !!props.template?.footer && props.template.footer.length > 0,
|
|
128
131
|
);
|
|
129
132
|
const hasButtons = computed(
|
|
130
|
-
() => !!props.template?.buttons && props.template.buttons.length > 0
|
|
133
|
+
() => !!props.template?.buttons && props.template.buttons.length > 0,
|
|
131
134
|
);
|
|
132
135
|
const parsedBody = computed(() => {
|
|
133
|
-
if (!hasBody.value) return
|
|
136
|
+
if (!hasBody.value) return '';
|
|
134
137
|
|
|
135
138
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
136
139
|
const result = props
|
|
137
|
-
.template!.body!.replaceAll(
|
|
138
|
-
.replaceAll(/(?:\*)([^*<\n]+)(?:\*)/g,
|
|
139
|
-
.replaceAll(/(?:_)([^_<\n]+)(?:_)/g,
|
|
140
|
-
.replaceAll(/(?:~)([^~<\n]+)(?:~)/g,
|
|
141
|
-
.replaceAll(/(?:```)([^```<\n]+)(?:```)/g,
|
|
140
|
+
.template!.body!.replaceAll('\n', '<br/>')
|
|
141
|
+
.replaceAll(/(?:\*)([^*<\n]+)(?:\*)/g, '<strong>$1</strong>')
|
|
142
|
+
.replaceAll(/(?:_)([^_<\n]+)(?:_)/g, '<i>$1</i>')
|
|
143
|
+
.replaceAll(/(?:~)([^~<\n]+)(?:~)/g, '<s>$1</s>')
|
|
144
|
+
.replaceAll(/(?:```)([^```<\n]+)(?:```)/g, '<tt>$1</tt>')
|
|
142
145
|
.replaceAll(/{{.*?}}/g, (match) => `<strong>${match}</strong>`);
|
|
143
146
|
|
|
144
147
|
return result;
|
|
@@ -146,19 +149,19 @@ const parsedBody = computed(() => {
|
|
|
146
149
|
|
|
147
150
|
const getButtonIcon = (buttonType) => {
|
|
148
151
|
const buttonMapper = {
|
|
149
|
-
PHONE_NUMBER:
|
|
150
|
-
URL:
|
|
151
|
-
COPY_CODE:
|
|
152
|
-
FLOW:
|
|
153
|
-
QUICK_REPLY:
|
|
152
|
+
PHONE_NUMBER: 'phone',
|
|
153
|
+
URL: 'open_in_new',
|
|
154
|
+
COPY_CODE: 'content_copy',
|
|
155
|
+
FLOW: '',
|
|
156
|
+
QUICK_REPLY: 'reply',
|
|
154
157
|
};
|
|
155
158
|
|
|
156
|
-
return buttonMapper[buttonType] ||
|
|
159
|
+
return buttonMapper[buttonType] || '';
|
|
157
160
|
};
|
|
158
161
|
</script>
|
|
159
162
|
|
|
160
163
|
<style lang="scss" scoped>
|
|
161
|
-
@use
|
|
164
|
+
@use '@/assets/scss/unnnic' as *;
|
|
162
165
|
|
|
163
166
|
.unnnic-template-preview {
|
|
164
167
|
display: flex;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<UnnnicModalDialog
|
|
3
|
-
:
|
|
3
|
+
:modelValue="modelValue"
|
|
4
4
|
@update:modelValue="$event === false && $emit('close')"
|
|
5
5
|
:title="defaultTranslations.title[props.locale]"
|
|
6
|
-
:
|
|
6
|
+
:showCloseIcon="true"
|
|
7
7
|
class="unnnic-template-preview-modal"
|
|
8
8
|
>
|
|
9
9
|
<UnnnicTemplatePreview :template="template" />
|
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
13
|
<script lang="ts" setup>
|
|
14
|
-
import UnnnicTemplatePreview from
|
|
15
|
-
import UnnnicModalDialog from
|
|
14
|
+
import UnnnicTemplatePreview from './TemplatePreview.vue';
|
|
15
|
+
import UnnnicModalDialog from '../ModalDialog/ModalDialog.vue';
|
|
16
16
|
|
|
17
|
-
import type { Template } from
|
|
17
|
+
import type { Template } from './types';
|
|
18
18
|
|
|
19
19
|
const defaultTranslations = {
|
|
20
20
|
title: {
|
|
21
|
-
|
|
22
|
-
en:
|
|
23
|
-
es:
|
|
21
|
+
'pt-br': 'Visualizar modelo',
|
|
22
|
+
en: 'Template preview',
|
|
23
|
+
es: 'Vista previa de plantilla',
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
26
|
|
|
@@ -31,7 +31,7 @@ interface Props {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const props = withDefaults(defineProps<Props>(), {
|
|
34
|
-
locale:
|
|
34
|
+
locale: 'en',
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
defineEmits<{
|
|
@@ -40,7 +40,7 @@ defineEmits<{
|
|
|
40
40
|
</script>
|
|
41
41
|
|
|
42
42
|
<style lang="scss" scoped>
|
|
43
|
-
@use
|
|
43
|
+
@use '@/assets/scss/unnnic' as *;
|
|
44
44
|
|
|
45
45
|
:deep(.unnnic-modal-dialog__container__content) {
|
|
46
46
|
display: flex;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
export interface Template {
|
|
2
2
|
header: {
|
|
3
|
-
type:
|
|
4
|
-
mediaType?:
|
|
3
|
+
type: 'TEXT' | 'MEDIA';
|
|
4
|
+
mediaType?: 'IMAGE' | 'VIDEO' | 'DOCUMENT';
|
|
5
5
|
text?: string | null;
|
|
6
6
|
src?: string | null;
|
|
7
7
|
};
|
|
8
8
|
body?: string;
|
|
9
9
|
footer?: string;
|
|
10
10
|
buttons?: Array<{
|
|
11
|
-
type:
|
|
11
|
+
type: 'QUICK_REPLY' | 'PHONE_NUMBER';
|
|
12
12
|
text: string;
|
|
13
13
|
countryCode?: string;
|
|
14
14
|
phoneNumber?: string;
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
>
|
|
8
8
|
<aside
|
|
9
9
|
v-if="isVisible"
|
|
10
|
-
:class="['unnnic-toast', `unnnic-toast--${
|
|
11
|
-
:role="
|
|
12
|
-
:aria-live="
|
|
10
|
+
:class="['unnnic-toast', `unnnic-toast--${validType}`]"
|
|
11
|
+
:role="validType === 'error' ? 'alert' : 'status'"
|
|
12
|
+
:aria-live="validType === 'error' ? 'assertive' : 'polite'"
|
|
13
13
|
data-testid="toast"
|
|
14
14
|
:style="{ zIndex: toastZIndex }"
|
|
15
15
|
>
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
>
|
|
24
24
|
<UnnnicIcon
|
|
25
25
|
:icon="typeConfig.icon"
|
|
26
|
-
:scheme="typeConfig.scheme"
|
|
26
|
+
:scheme="typeConfig.scheme as SchemeColor"
|
|
27
27
|
size="ant"
|
|
28
28
|
data-testid="toast-type-icon"
|
|
29
29
|
/>
|
|
@@ -97,6 +97,13 @@ const emit = defineEmits<ToastEmits>();
|
|
|
97
97
|
const isVisible = ref(false);
|
|
98
98
|
let timeoutId: number | null = null;
|
|
99
99
|
|
|
100
|
+
const validType = computed(() => {
|
|
101
|
+
if (['informational', 'attention', 'success', 'error'].includes(props.type)) {
|
|
102
|
+
return props.type;
|
|
103
|
+
}
|
|
104
|
+
return 'informational';
|
|
105
|
+
});
|
|
106
|
+
|
|
100
107
|
const typeConfig = computed(() => {
|
|
101
108
|
const configMap = {
|
|
102
109
|
informational: { icon: 'info', scheme: 'blue-500' },
|
|
@@ -105,10 +112,7 @@ const typeConfig = computed(() => {
|
|
|
105
112
|
error: { icon: 'cancel', scheme: 'red-500' },
|
|
106
113
|
};
|
|
107
114
|
|
|
108
|
-
return configMap[
|
|
109
|
-
icon: string;
|
|
110
|
-
scheme: SchemeColor;
|
|
111
|
-
};
|
|
115
|
+
return configMap[validType.value];
|
|
112
116
|
});
|
|
113
117
|
|
|
114
118
|
const toastZIndex = useLayerZIndex('toast');
|
package/src/components/index.ts
CHANGED
|
@@ -33,10 +33,10 @@ import modal from './Modal/Modal.vue';
|
|
|
33
33
|
import modalUpload from './ModalUpload/ModalUpload.vue';
|
|
34
34
|
import { callAlert, callModal } from '../utils/call';
|
|
35
35
|
import selectSmart from './SelectSmart/SelectSmart.vue';
|
|
36
|
-
|
|
36
|
+
import select from './Select/index.vue';
|
|
37
37
|
import selectItem from './Select/SelectItem.vue';
|
|
38
38
|
// import selectListItem from './SelectListItem/SelectListItem.vue';
|
|
39
|
-
import multiSelect from './MultiSelect/
|
|
39
|
+
import multiSelect from './MultiSelect/index.vue';
|
|
40
40
|
import alert from './Alert/Alert.vue';
|
|
41
41
|
// import autocomplete from './Input/Autocomplete.vue';
|
|
42
42
|
// import autocompleteSelect from './AutocompleteSelect/AutocompleteSelect.vue';
|
|
@@ -168,10 +168,10 @@ export const components: ComponentsMap = {
|
|
|
168
168
|
unnnicModalDialog: ModalDialog,
|
|
169
169
|
unnnicModalUpload: modalUpload,
|
|
170
170
|
unnnicSelectSmart: selectSmart,
|
|
171
|
-
|
|
171
|
+
unnnicSelect: select,
|
|
172
172
|
unnnicSelectItem: selectItem,
|
|
173
173
|
// unnnicSelectListItem: selectListItem,
|
|
174
|
-
unnnicMultiSelect: multiSelect,
|
|
174
|
+
unnnicMultiSelect: multiSelect as VueComponent,
|
|
175
175
|
unnnicAlert: alert,
|
|
176
176
|
unnnicCallAlert: callAlert,
|
|
177
177
|
unnnicCallModal: callModal,
|
|
@@ -264,7 +264,7 @@ export const unnnicFontSize = fontSize;
|
|
|
264
264
|
export const unnnicFormElement = formElement;
|
|
265
265
|
export const unnnicInput = input;
|
|
266
266
|
export const unnnicInputNext = inputNext;
|
|
267
|
-
export const unnnicInputDatePicker = inputDatePicker;
|
|
267
|
+
export const unnnicInputDatePicker = inputDatePicker as VueComponent;
|
|
268
268
|
export const unnnicButton = button;
|
|
269
269
|
export const unnnicButtonIcon = buttonIcon;
|
|
270
270
|
export const unnnicSidebar = sidebar;
|
|
@@ -296,7 +296,7 @@ export const unnnicModalDialog = ModalDialog;
|
|
|
296
296
|
export const unnnicModalNext = ModalNext;
|
|
297
297
|
export const unnnicModalUpload = modalUpload;
|
|
298
298
|
export const unnnicSelectSmart = selectSmart as VueComponent;
|
|
299
|
-
|
|
299
|
+
export const unnnicSelect = select as VueComponent;
|
|
300
300
|
export const unnnicSelectItem = selectItem;
|
|
301
301
|
// export const unnnicSelectListItem = selectListItem;
|
|
302
302
|
export const unnnicMultiSelect = multiSelect as VueComponent;
|
|
@@ -423,7 +423,7 @@ export const UnnnicModalDialog = ModalDialog;
|
|
|
423
423
|
export const UnnnicModalNext = ModalNext;
|
|
424
424
|
export const UnnnicModalUpload = modalUpload;
|
|
425
425
|
export const UnnnicSelectSmart = selectSmart as VueComponent;
|
|
426
|
-
|
|
426
|
+
export const UnnnicSelect = select as VueComponent;
|
|
427
427
|
export const UnnnicSelectItem = selectItem;
|
|
428
428
|
// export const UnnnicSelectListItem = selectListItem;
|
|
429
429
|
export const UnnnicMultiSelect = multiSelect as VueComponent;
|
|
@@ -6,9 +6,7 @@ defineOptions({
|
|
|
6
6
|
name: 'UnnnicDialogClose',
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
const props =
|
|
10
|
-
asChild: true,
|
|
11
|
-
});
|
|
9
|
+
const props = defineProps<DialogCloseProps>();
|
|
12
10
|
</script>
|
|
13
11
|
|
|
14
12
|
<template>
|
|
@@ -21,6 +19,8 @@ const props = withDefaults(defineProps<DialogCloseProps>(), {
|
|
|
21
19
|
</template>
|
|
22
20
|
|
|
23
21
|
<style lang="scss" scoped>
|
|
22
|
+
@use '@/assets/scss/unnnic' as *;
|
|
23
|
+
|
|
24
24
|
.unnnic-dialog-close {
|
|
25
25
|
> * {
|
|
26
26
|
width: 100%;
|
|
@@ -6,9 +6,7 @@ defineOptions({
|
|
|
6
6
|
name: 'UnnnicDrawerClose',
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
const props =
|
|
10
|
-
asChild: true,
|
|
11
|
-
});
|
|
9
|
+
const props = defineProps<DrawerCloseProps>();
|
|
12
10
|
</script>
|
|
13
11
|
|
|
14
12
|
<template>
|
|
@@ -24,6 +22,14 @@ const props = withDefaults(defineProps<DrawerCloseProps>(), {
|
|
|
24
22
|
@use '@/assets/scss/unnnic' as *;
|
|
25
23
|
|
|
26
24
|
.unnnic-drawer__close {
|
|
25
|
+
display: flex;
|
|
26
|
+
|
|
27
|
+
border: none;
|
|
28
|
+
background: none;
|
|
29
|
+
padding: 0;
|
|
30
|
+
margin: 0;
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
|
|
27
33
|
> * {
|
|
28
34
|
width: 100%;
|
|
29
35
|
}
|
|
@@ -98,6 +98,10 @@ const schemeColor = computed(() => {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
&__label {
|
|
101
|
+
overflow: hidden;
|
|
102
|
+
text-overflow: ellipsis;
|
|
103
|
+
white-space: nowrap;
|
|
104
|
+
|
|
101
105
|
@each $name, $color in $unnnic-scheme-colors {
|
|
102
106
|
&.unnnic-popover-option__label--#{$name} {
|
|
103
107
|
color: $color;
|
package/src/lib/layer-manager.ts
CHANGED
|
@@ -14,14 +14,14 @@ export type LayerToken = keyof typeof layerScale;
|
|
|
14
14
|
|
|
15
15
|
const DEFAULT_STEP = 5;
|
|
16
16
|
|
|
17
|
-
const
|
|
18
|
-
hide:
|
|
19
|
-
base:
|
|
20
|
-
drawer:
|
|
21
|
-
modal:
|
|
22
|
-
popover:
|
|
23
|
-
tooltip:
|
|
24
|
-
toast:
|
|
17
|
+
const counters: Record<LayerToken, number> = {
|
|
18
|
+
hide: 0,
|
|
19
|
+
base: 0,
|
|
20
|
+
drawer: 0,
|
|
21
|
+
modal: 0,
|
|
22
|
+
popover: 0,
|
|
23
|
+
tooltip: 0,
|
|
24
|
+
toast: 0,
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
interface Allocation {
|
|
@@ -34,14 +34,10 @@ const allocations = new Map<symbol, Allocation>();
|
|
|
34
34
|
|
|
35
35
|
function acquire(type: LayerToken): Allocation {
|
|
36
36
|
const id = Symbol('layer');
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
const value = lastValue + DEFAULT_STEP;
|
|
37
|
+
counters[type] = (counters[type] ?? 0) + 1;
|
|
38
|
+
const value = layerScale[type] + counters[type] * DEFAULT_STEP;
|
|
40
39
|
const allocation: Allocation = { id, type, value };
|
|
41
|
-
|
|
42
|
-
list.push(value);
|
|
43
40
|
allocations.set(id, allocation);
|
|
44
|
-
|
|
45
41
|
return allocation;
|
|
46
42
|
}
|
|
47
43
|
|
|
@@ -52,12 +48,8 @@ function release(id: symbol) {
|
|
|
52
48
|
}
|
|
53
49
|
|
|
54
50
|
allocations.delete(id);
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (index !== -1) {
|
|
59
|
-
list.splice(index, 1);
|
|
60
|
-
}
|
|
51
|
+
const current = Math.max((counters[allocation.type] ?? 1) - 1, 0);
|
|
52
|
+
counters[allocation.type] = current;
|
|
61
53
|
}
|
|
62
54
|
|
|
63
55
|
export interface LayerZIndexOptions {
|