@weni/unnnic-system 3.31.1 → 3.32.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 (34) hide show
  1. package/dist/index.d.ts +1518 -4106
  2. package/dist/style.css +1 -1
  3. package/dist/unnnic.mjs +12879 -13865
  4. package/dist/unnnic.umd.js +36 -36
  5. package/package.json +1 -1
  6. package/src/components/index.ts +1 -41
  7. package/src/stories/PageHeader.stories.js +11 -5
  8. package/src/types/index.d.ts +0 -1
  9. package/src/components/Button/ButtonIcon.vue +0 -106
  10. package/src/components/Button/__tests__/ButtonIcon.spec.js +0 -56
  11. package/src/components/Carousel/Carousel.vue +0 -59
  12. package/src/components/Carousel/TagCarousel.vue +0 -209
  13. package/src/components/Carousel/__tests__/TagCarousel.spec.js +0 -258
  14. package/src/components/ChatText/ChatText.vue +0 -179
  15. package/src/components/CircleProgressBar/CircleProgressBar.vue +0 -150
  16. package/src/components/Indicator/Indicator.vue +0 -110
  17. package/src/components/InputNext/InputNext.vue +0 -282
  18. package/src/components/ModalUpload/ModalUpload.vue +0 -181
  19. package/src/components/MoodRating/MoodRating.vue +0 -130
  20. package/src/components/Slider/Slider.vue +0 -438
  21. package/src/components/Slider/__tests__/Slider.spec.js +0 -321
  22. package/src/components/StarRating/StarRating.vue +0 -76
  23. package/src/components/TransitionRipple/TransitionRipple.vue +0 -126
  24. package/src/stories/ButtonIcon.stories.js +0 -31
  25. package/src/stories/Carousel.stories.js +0 -45
  26. package/src/stories/ChatText.stories.js +0 -57
  27. package/src/stories/CircleProgressBar.stories.js +0 -15
  28. package/src/stories/Indicator.stories.js +0 -18
  29. package/src/stories/InputNext.stories.js +0 -92
  30. package/src/stories/ModalUpload.stories.js +0 -25
  31. package/src/stories/MoodRating.stories.js +0 -33
  32. package/src/stories/Slider.stories.js +0 -23
  33. package/src/stories/StarRating.stories.js +0 -38
  34. package/src/stories/TransitionRipple.stories.js +0 -35
@@ -1,258 +0,0 @@
1
- import { afterEach, describe, expect, it } from 'vitest';
2
- import { mount, flushPromises } from '@vue/test-utils';
3
-
4
- import TagCarousel from '../TagCarousel.vue';
5
-
6
- const tagItems = [
7
- { id: 1, name: 'Tag 1' },
8
- { id: 2, name: 'Tag 2' },
9
- { id: 3, name: 'Tag 3' },
10
- ];
11
-
12
- const mountCarousel = async (props = {}) => {
13
- const wrapper = mount(TagCarousel, {
14
- props: {
15
- modelValue: [],
16
- tagItems,
17
- ...props,
18
- },
19
- attachTo: document.body,
20
- global: {
21
- stubs: {
22
- UnnnicIcon: true,
23
- },
24
- },
25
- });
26
-
27
- await flushPromises();
28
- await wrapper.vm.$nextTick();
29
-
30
- return wrapper;
31
- };
32
-
33
- const mockScrollElement = (
34
- wrapper,
35
- { scrollWidth = 800, clientWidth = 400, scrollLeft = 0 } = {},
36
- ) => {
37
- const element = wrapper.find('#scroll').element;
38
-
39
- Object.defineProperty(element, 'scrollWidth', {
40
- configurable: true,
41
- value: scrollWidth,
42
- });
43
- Object.defineProperty(element, 'clientWidth', {
44
- configurable: true,
45
- value: clientWidth,
46
- });
47
-
48
- let currentScrollLeft = scrollLeft;
49
- Object.defineProperty(element, 'scrollLeft', {
50
- configurable: true,
51
- get: () => currentScrollLeft,
52
- set: (value) => {
53
- currentScrollLeft = value;
54
- },
55
- });
56
-
57
- return element;
58
- };
59
-
60
- describe('TagCarousel', () => {
61
- afterEach(() => {
62
- document.body.innerHTML = '';
63
- });
64
-
65
- it('renders tag slides from tagItems', async () => {
66
- const wrapper = await mountCarousel();
67
-
68
- expect(wrapper.vm.slides).toHaveLength(3);
69
- expect(wrapper.findAll('.chip')).toHaveLength(3);
70
- expect(wrapper.text()).toContain('Tag 1');
71
- });
72
-
73
- it('adds a tag to selection when clicked', async () => {
74
- const wrapper = await mountCarousel();
75
-
76
- await wrapper.findAll('.chip')[0].trigger('click');
77
-
78
- expect(wrapper.emitted('selected')[0]).toEqual([[1]]);
79
- });
80
-
81
- it('removes a tag from selection when already selected', async () => {
82
- const wrapper = await mountCarousel({ modelValue: [1] });
83
-
84
- await wrapper.findAll('.chip')[0].trigger('click');
85
-
86
- expect(wrapper.emitted('selected')[0]).toEqual([[]]);
87
- });
88
-
89
- it('checks whether a tag is included in modelValue', async () => {
90
- const wrapper = await mountCarousel({ modelValue: [2] });
91
-
92
- expect(wrapper.vm.checkIsInclude({ id: 2, name: 'Tag 2' })).toBe(true);
93
- expect(wrapper.vm.checkIsInclude({ id: 1, name: 'Tag 1' })).toBe(false);
94
- });
95
-
96
- it('enables previous button after moving forward', async () => {
97
- const wrapper = await mountCarousel();
98
- mockScrollElement(wrapper, {
99
- scrollWidth: 800,
100
- clientWidth: 400,
101
- scrollLeft: 0,
102
- });
103
-
104
- wrapper.vm.next();
105
-
106
- expect(wrapper.vm.hasPrev).toBe(true);
107
- expect(wrapper.vm.hasNext).toBe(true);
108
- });
109
-
110
- it('disables next button when scrolled to the end', async () => {
111
- const wrapper = await mountCarousel();
112
- mockScrollElement(wrapper, {
113
- scrollWidth: 800,
114
- clientWidth: 400,
115
- scrollLeft: 200,
116
- });
117
-
118
- wrapper.vm.next();
119
-
120
- expect(wrapper.vm.hasNext).toBe(false);
121
- });
122
-
123
- it('disables previous button when scrolled to the start', async () => {
124
- const wrapper = await mountCarousel();
125
- mockScrollElement(wrapper, {
126
- scrollWidth: 800,
127
- clientWidth: 400,
128
- scrollLeft: 200,
129
- });
130
-
131
- wrapper.vm.previous();
132
-
133
- expect(wrapper.vm.hasPrev).toBe(false);
134
- expect(wrapper.vm.hasNext).toBe(true);
135
- });
136
-
137
- it('keeps next enabled when already disabled and not at end', async () => {
138
- const wrapper = await mountCarousel();
139
- mockScrollElement(wrapper, {
140
- scrollWidth: 900,
141
- clientWidth: 400,
142
- scrollLeft: 0,
143
- });
144
- wrapper.vm.hasNext = false;
145
-
146
- wrapper.vm.next();
147
-
148
- expect(wrapper.vm.hasNext).toBe(true);
149
- });
150
-
151
- it('keeps previous enabled when already disabled and not at start', async () => {
152
- const wrapper = await mountCarousel();
153
- mockScrollElement(wrapper, {
154
- scrollWidth: 900,
155
- clientWidth: 400,
156
- scrollLeft: 500,
157
- });
158
-
159
- wrapper.vm.previous();
160
-
161
- expect(wrapper.vm.hasPrev).toBe(true);
162
- expect(wrapper.vm.hasNext).toBe(true);
163
- });
164
-
165
- it('shows blur overlays when navigation is available', async () => {
166
- const wrapper = await mountCarousel();
167
- mockScrollElement(wrapper, {
168
- scrollWidth: 800,
169
- clientWidth: 400,
170
- scrollLeft: 0,
171
- });
172
-
173
- expect(wrapper.vm.hasNext).toBe(true);
174
- expect(wrapper.vm.hasPrev).toBe(false);
175
-
176
- wrapper.vm.next();
177
-
178
- expect(wrapper.vm.hasPrev).toBe(true);
179
- expect(wrapper.vm.hasNext).toBe(true);
180
- });
181
-
182
- it('uses default modelValue when omitted', async () => {
183
- const wrapper = mount(TagCarousel, {
184
- props: { tagItems },
185
- attachTo: document.body,
186
- global: { stubs: { UnnnicIcon: true } },
187
- });
188
-
189
- await flushPromises();
190
- await wrapper.vm.$nextTick();
191
-
192
- expect(wrapper.vm.modelValue).toEqual([]);
193
- expect(wrapper.vm.slides).toHaveLength(3);
194
-
195
- wrapper.unmount();
196
- });
197
-
198
- it('uses default tagItems when omitted', async () => {
199
- const wrapper = mount(TagCarousel, {
200
- props: { modelValue: [] },
201
- attachTo: document.body,
202
- global: { stubs: { UnnnicIcon: true } },
203
- });
204
-
205
- await flushPromises();
206
- await wrapper.vm.$nextTick();
207
-
208
- expect(wrapper.vm.tagItems).toEqual([]);
209
- expect(wrapper.vm.slides).toEqual([]);
210
-
211
- wrapper.unmount();
212
- });
213
-
214
- it('keeps next enabled when it is already enabled', async () => {
215
- const wrapper = await mountCarousel();
216
- mockScrollElement(wrapper, {
217
- scrollWidth: 900,
218
- clientWidth: 400,
219
- scrollLeft: 0,
220
- });
221
- wrapper.vm.hasNext = true;
222
-
223
- wrapper.vm.handleNext();
224
-
225
- expect(wrapper.vm.hasNext).toBe(true);
226
- expect(wrapper.vm.hasPrev).toBe(true);
227
- });
228
-
229
- it('keeps previous enabled when it is already enabled', async () => {
230
- const wrapper = await mountCarousel();
231
- mockScrollElement(wrapper, {
232
- scrollWidth: 900,
233
- clientWidth: 400,
234
- scrollLeft: 500,
235
- });
236
- wrapper.vm.hasPrev = true;
237
-
238
- wrapper.vm.handlePrevious();
239
-
240
- expect(wrapper.vm.hasPrev).toBe(true);
241
- expect(wrapper.vm.hasNext).toBe(true);
242
- });
243
-
244
- it('delegates navigation to next and previous handlers', async () => {
245
- const wrapper = await mountCarousel();
246
- mockScrollElement(wrapper, {
247
- scrollWidth: 800,
248
- clientWidth: 400,
249
- scrollLeft: 0,
250
- });
251
-
252
- wrapper.vm.handleNext();
253
- expect(wrapper.vm.hasPrev).toBe(true);
254
-
255
- wrapper.vm.handlePrevious();
256
- expect(wrapper.vm.hasPrev).toBe(false);
257
- });
258
- });
@@ -1,179 +0,0 @@
1
- <template>
2
- <div :class="['unnnic-chat-text', size]">
3
- <div class="header">
4
- <div :class="['title', titleColor]">
5
- {{ title }}
6
-
7
- <UnnnicToolTip
8
- v-if="info"
9
- side="top"
10
- class="info"
11
- :text="info"
12
- enabled
13
- >
14
- <UnnnicIcon
15
- class="info__icon"
16
- icon="info"
17
- size="sm"
18
- scheme="fg-base"
19
- ></UnnnicIcon>
20
- </UnnnicToolTip>
21
- </div>
22
-
23
- <slot name="actions" />
24
- </div>
25
-
26
- <div
27
- ref="description"
28
- class="description"
29
- >
30
- <slot name="description" />
31
-
32
- <div
33
- v-if="isScrollable"
34
- class="scrollable-gradient"
35
- ></div>
36
- </div>
37
- </div>
38
- </template>
39
-
40
- <script>
41
- import UnnnicToolTip from '../ToolTip/ToolTip.vue';
42
- import UnnnicIcon from '../Icon.vue';
43
-
44
- export default {
45
- components: {
46
- UnnnicToolTip,
47
- UnnnicIcon,
48
- },
49
-
50
- props: {
51
- size: {
52
- type: String,
53
- default: 'normal',
54
- },
55
-
56
- title: {
57
- type: String,
58
- },
59
-
60
- titleColor: {
61
- type: String,
62
- default: 'brand-weni-soft',
63
- },
64
-
65
- info: {
66
- type: String,
67
- },
68
- },
69
-
70
- data() {
71
- return {
72
- isScrollable: false,
73
- };
74
- },
75
-
76
- mounted() {
77
- const areaScrollable =
78
- this.$refs.description.scrollHeight - this.$refs.description.offsetHeight;
79
-
80
- this.isScrollable = areaScrollable;
81
- },
82
- };
83
- </script>
84
-
85
- <style lang="scss" scoped>
86
- @use '@/assets/scss/unnnic' as *;
87
-
88
- .unnnic-chat-text {
89
- border-radius: $unnnic-border-radius-lg;
90
- background-color: $unnnic-color-bg-base;
91
- max-width: 31.25 * $unnnic-font-size;
92
- padding: $unnnic-spacing-inset-md;
93
- box-sizing: border-box;
94
- border: 1px solid $unnnic-color-border-base;
95
- max-height: 15.625 * $unnnic-font-size;
96
- display: flex;
97
- flex-direction: column;
98
-
99
- .header {
100
- margin-bottom: $unnnic-spacing-stack-md;
101
- display: flex;
102
- align-items: center;
103
- justify-content: space-between;
104
-
105
- .title {
106
- display: flex;
107
-
108
- font-family: $unnnic-font-family-secondary;
109
- font-weight: $unnnic-font-weight-black;
110
- font-size: $unnnic-font-size-body-gt;
111
- line-height: $unnnic-font-size-body-gt + $unnnic-line-height-md;
112
- flex: 1;
113
-
114
- .info {
115
- display: flex;
116
- align-items: center;
117
-
118
- &__icon {
119
- margin-left: $unnnic-spacing-inline-nano;
120
- cursor: default;
121
- }
122
- }
123
-
124
- @each $name, $color in $scheme-colors {
125
- &.#{$name} {
126
- color: $color;
127
- }
128
- }
129
- }
130
- }
131
-
132
- .description {
133
- font-family: $unnnic-font-family-primary;
134
- font-weight: $unnnic-font-weight-regular;
135
- font-size: $unnnic-font-size-body-lg;
136
- line-height: $unnnic-font-size-body-lg + $unnnic-line-height-md;
137
- color: $unnnic-color-fg-emphasized;
138
- overflow: hidden;
139
- position: relative;
140
-
141
- .intent {
142
- background-color: rgba(
143
- $unnnic-color-purple-10,
144
- $unnnic-opacity-level-light
145
- );
146
- padding: calc($unnnic-line-height-md / 2) 0;
147
- }
148
-
149
- .scrollable-gradient {
150
- position: absolute;
151
- background-image: linear-gradient(transparent, $unnnic-color-bg-base);
152
- width: 100%;
153
- height: 5 * $unnnic-font-size;
154
- bottom: 0;
155
- left: 0;
156
- pointer-events: none;
157
- }
158
- }
159
-
160
- &.small {
161
- border-radius: $unnnic-border-radius-md;
162
- padding: $unnnic-spacing-inset-sm;
163
- max-height: 7.1875 * $unnnic-font-size;
164
-
165
- .header {
166
- margin-bottom: $unnnic-spacing-stack-xs;
167
- }
168
-
169
- .description {
170
- font-size: $unnnic-font-size-body-md;
171
- line-height: $unnnic-font-size-body-md + $unnnic-line-height-md;
172
-
173
- .scrollable-gradient {
174
- height: 2 * $unnnic-font-size;
175
- }
176
- }
177
- }
178
- }
179
- </style>
@@ -1,150 +0,0 @@
1
- <template>
2
- <div class="unnnic-circle-progress-bar">
3
- <svg
4
- width="46"
5
- height="46"
6
- class="semicircle"
7
- >
8
- <circle
9
- cx="23"
10
- cy="23"
11
- r="21"
12
- stroke="black"
13
- stroke-width="4px"
14
- :class="['background', progress === totalProgress ? 'filled' : '']"
15
- />
16
-
17
- <path
18
- v-show="progress < totalProgress && progress > 0"
19
- id="path"
20
- ref="background"
21
- fill="none"
22
- stroke-linecap="round"
23
- class="front"
24
- stroke-width="4px"
25
- ></path>
26
- </svg>
27
-
28
- <div class="content">{{ progress }}/{{ totalProgress }}</div>
29
- </div>
30
- </template>
31
-
32
- <script>
33
- export default {
34
- components: {},
35
-
36
- props: {
37
- progress: {
38
- type: Number,
39
- },
40
-
41
- totalProgress: {
42
- type: Number,
43
- },
44
- },
45
-
46
- computed: {
47
- progressChange() {
48
- return `${this.progress}-${this.totalProgress}`;
49
- },
50
- },
51
-
52
- watch: {
53
- progressChange: {
54
- immediate: true,
55
- handler() {
56
- function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
57
- const angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0;
58
-
59
- return {
60
- x: centerX + radius * -Math.cos(angleInRadians),
61
- y: centerY + radius * -Math.sin(angleInRadians),
62
- };
63
- }
64
-
65
- function describeArc(
66
- x,
67
- y,
68
- innerRadius,
69
- outerRadius,
70
- startAngle,
71
- endAngle,
72
- ) {
73
- const radius = innerRadius;
74
- const spread = outerRadius - innerRadius;
75
- const outerStart = polarToCartesian(x, y, radius + spread, endAngle);
76
- const outerEnd = polarToCartesian(x, y, radius + spread, startAngle);
77
-
78
- const largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1';
79
-
80
- const d = [
81
- 'M',
82
- outerStart.x,
83
- outerStart.y,
84
- 'A',
85
- radius + spread,
86
- radius + spread,
87
- 0,
88
- largeArcFlag,
89
- 0,
90
- outerEnd.x,
91
- outerEnd.y,
92
- ].join(' ');
93
-
94
- return d;
95
- }
96
-
97
- const value = (this.progress / this.totalProgress) * 360;
98
-
99
- const path = describeArc(23, 23, 0, 21, 180 - value.toFixed(), 180);
100
-
101
- this.$nextTick(() => {
102
- this.$refs.background.setAttribute('d', path);
103
- });
104
- },
105
- },
106
- },
107
- };
108
- </script>
109
-
110
- <style lang="scss" scoped>
111
- @use '@/assets/scss/unnnic' as *;
112
-
113
- .unnnic-circle-progress-bar {
114
- position: relative;
115
- width: fit-content;
116
-
117
- .semicircle {
118
- display: block;
119
- }
120
-
121
- .background {
122
- fill: transparent;
123
- stroke: rgba($unnnic-color-teal-8, $unnnic-opacity-level-extra-light);
124
-
125
- &.filled {
126
- stroke: $unnnic-color-teal-8;
127
- }
128
- }
129
-
130
- .front {
131
- stroke: $unnnic-color-teal-8;
132
- }
133
-
134
- .content {
135
- position: absolute;
136
- text-align: center;
137
- width: 100%;
138
-
139
- top: 50%;
140
- left: 50%;
141
- transform: translate(-50%, -50%);
142
-
143
- color: $unnnic-color-fg-muted;
144
- font-family: $unnnic-font-family-secondary;
145
- font-weight: $unnnic-font-weight-regular;
146
- font-size: $unnnic-font-size-body-gt;
147
- line-height: $unnnic-font-size-body-gt + $unnnic-line-height-md;
148
- }
149
- }
150
- </style>
@@ -1,110 +0,0 @@
1
- <template>
2
- <div class="weni-step-indicator">
3
- <div
4
- v-for="step in numberOfSteps"
5
- :key="step"
6
- :class="{
7
- 'weni-step-indicator__step__wrapper': true,
8
- 'weni-step-indicator--has-separator': step > 1,
9
- }"
10
- >
11
- <div
12
- v-if="step !== 1"
13
- :class="{
14
- 'weni-step-indicator__step__separator': true,
15
- 'weni-step-indicator__step__separator--active': step <= currentStep,
16
- }"
17
- />
18
- <div
19
- :class="{
20
- 'weni-step-indicator__step': true,
21
- 'weni-step-indicator__step--active': step <= currentStep,
22
- }"
23
- >
24
- <span class="weni-step-indicator__label">
25
- {{ titleForStep(step) }}
26
- </span>
27
- </div>
28
- </div>
29
- </div>
30
- </template>
31
-
32
- <script>
33
- export default {
34
- name: 'UnnnicIndicator',
35
- props: {
36
- numberOfSteps: {
37
- type: Number,
38
- required: true,
39
- },
40
- titles: {
41
- type: Array,
42
- default: () => [],
43
- },
44
- currentStep: {
45
- type: Number,
46
- default: 0,
47
- },
48
- },
49
- methods: {
50
- titleForStep(step) {
51
- try {
52
- return this.titles[step - 1];
53
- } catch (e) {
54
- return null;
55
- }
56
- },
57
- },
58
- };
59
- </script>
60
-
61
- <style lang="scss" scoped>
62
- @use '@/assets/scss/unnnic' as *;
63
-
64
- .weni-step-indicator {
65
- display: flex;
66
- align-items: center;
67
- width: 100%;
68
- &--has-separator {
69
- flex: 1;
70
- }
71
- &__step {
72
- border-radius: 50%;
73
- height: $unnnic-avatar-size-nano;
74
- width: $unnnic-avatar-size-nano;
75
- border: $unnnic-border-width-thick solid $unnnic-color-border-muted;
76
- box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
77
- position: relative;
78
- &__wrapper {
79
- display: flex;
80
- align-items: center;
81
- }
82
- &--active {
83
- background-color: $unnnic-color-teal-8;
84
- border: 4px solid rgba(0, 222, 210, 0.24);
85
- background-clip: content-box;
86
- }
87
- &__separator {
88
- border: $unnnic-border-width-thin solid $unnnic-color-border-muted;
89
- margin: 0 $unnnic-inline-xs;
90
- border-radius: 3px;
91
- flex: 1;
92
- &--active {
93
- border: 2px solid $unnnic-color-teal-8;
94
- }
95
- }
96
- }
97
- &__label {
98
- position: absolute;
99
- white-space: nowrap;
100
- text-align: center;
101
- transform: translateX(-50%);
102
- left: 50%;
103
- top: 100%;
104
- margin: $unnnic-inline-xs 0 0 0;
105
- color: $unnnic-color-fg-base;
106
- font-size: $unnnic-font-size-body-gt;
107
- line-height: $unnnic-font-size-body-gt + $unnnic-line-height-medium;
108
- }
109
- }
110
- </style>