@weni/unnnic-system 3.0.3 → 3.0.4-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.
Files changed (32) hide show
  1. package/dist/components/DataTable/index.vue.d.ts +156 -0
  2. package/dist/components/DataTable/index.vue.d.ts.map +1 -0
  3. package/dist/components/DatePicker/DatePicker.vue.d.ts +2 -2
  4. package/dist/components/InputDatePicker/InputDatePicker.vue.d.ts +3 -3
  5. package/dist/components/ModalDialog/ModalDialog.vue.d.ts +1 -1
  6. package/dist/components/ModalDialog/ModalDialog.vue.d.ts.map +1 -1
  7. package/dist/components/TemplatePreview/TemplatePreview.vue.d.ts +9 -0
  8. package/dist/components/TemplatePreview/TemplatePreview.vue.d.ts.map +1 -0
  9. package/dist/components/TemplatePreview/TemplatePreviewModal.vue.d.ts +15 -0
  10. package/dist/components/TemplatePreview/TemplatePreviewModal.vue.d.ts.map +1 -0
  11. package/dist/components/index.d.ts +263 -6
  12. package/dist/components/index.d.ts.map +1 -1
  13. package/dist/{es-61329267.mjs → es-39b05ec7.mjs} +1 -1
  14. package/dist/{index-0d853377.mjs → index-c43e689f.mjs} +9498 -9163
  15. package/dist/{pt-br-1024c0d5.mjs → pt-br-b70cfbf8.mjs} +1 -1
  16. package/dist/style.css +1 -1
  17. package/dist/unnnic.mjs +61 -58
  18. package/dist/unnnic.umd.js +44 -43
  19. package/package.json +2 -2
  20. package/src/assets/img/previews/doc-preview.png +0 -0
  21. package/src/assets/img/previews/image-preview.png +0 -0
  22. package/src/assets/img/previews/video-preview.png +0 -0
  23. package/src/components/DataTable/index.vue +493 -0
  24. package/src/components/ModalDialog/ModalDialog.vue +27 -29
  25. package/src/components/ModalDialog/__tests__/__snapshots__/ModalDialog.spec.js.snap +1 -1
  26. package/src/components/TemplatePreview/TemplatePreview.vue +249 -0
  27. package/src/components/TemplatePreview/TemplatePreviewModal.vue +51 -0
  28. package/src/components/TemplatePreview/types.d.ts +16 -0
  29. package/src/components/index.ts +9 -0
  30. package/src/stories/DataTable.stories.js +332 -0
  31. package/src/stories/TemplatePreview.stories.js +94 -0
  32. package/src/stories/TemplatePreviewModal.stories.js +110 -0
@@ -0,0 +1,249 @@
1
+ <template>
2
+ <section class="unnnic-template-preview">
3
+ <section
4
+ :class="[
5
+ 'unnnic-template-preview__content',
6
+ { 'unnnic-template-preview__content--has-media': hasHeaderMedia },
7
+ ]"
8
+ >
9
+ <header
10
+ v-if="hasHeader"
11
+ :class="`unnnic-template-preview__header__${
12
+ template?.header.type === 'TEXT' ? 'text' : 'media'
13
+ }`"
14
+ >
15
+ <img
16
+ class="unnnic-template-preview__header__media__preview"
17
+ v-if="
18
+ template?.header.type === 'MEDIA' &&
19
+ template?.header.mediaType === 'IMAGE'
20
+ "
21
+ :src="template.header.src || imagePreview"
22
+ />
23
+ <template
24
+ v-else-if="
25
+ template?.header.type === 'MEDIA' &&
26
+ template?.header.mediaType === 'VIDEO'
27
+ "
28
+ >
29
+ <video
30
+ v-if="template.header.src"
31
+ class="unnnic-template-preview__header__media__preview"
32
+ :src="template.header.src"
33
+ controls
34
+ />
35
+ <img
36
+ v-else
37
+ class="unnnic-template-preview__header__media__preview"
38
+ :src="videoPreview"
39
+ />
40
+ </template>
41
+ <template
42
+ v-else-if="
43
+ template?.header.type === 'MEDIA' &&
44
+ template?.header.mediaType === 'DOCUMENT'
45
+ "
46
+ >
47
+ <img
48
+ class="unnnic-template-preview__header__media__preview"
49
+ :src="documentPreview"
50
+ />
51
+ </template>
52
+ <h1
53
+ class="unnnic-template-preview__header__text__preview"
54
+ v-else-if="template?.header.type === 'TEXT'"
55
+ >
56
+ {{ template.header.text }}
57
+ </h1>
58
+ </header>
59
+ <section
60
+ v-if="hasBody"
61
+ :class="[
62
+ 'unnnic-template-preview__body',
63
+ { 'unnnic-template-preview__body--has-media': hasHeaderMedia },
64
+ ]"
65
+ >
66
+ <section v-html="parsedBody"></section>
67
+ </section>
68
+ <footer
69
+ v-if="hasFooter"
70
+ :class="[
71
+ 'unnnic-template-preview__footer',
72
+ { 'unnnic-template-preview__footer--has-media': hasHeaderMedia },
73
+ ]"
74
+ >
75
+ {{ template?.footer }}
76
+ </footer>
77
+ </section>
78
+ <footer v-if="hasButtons" class="unnnic-template-preview__buttons">
79
+ <section
80
+ v-for="(button, index) in template?.buttons"
81
+ :key="`button-${index}`"
82
+ class="unnnic-template-preview__buttons__button"
83
+ >
84
+ <UnnnicIcon
85
+ class="unnnic-template-preview__buttons__button__icon"
86
+ :icon="getButtonIcon(button.type)"
87
+ scheme="aux-blue-500"
88
+ size="ant"
89
+ />
90
+ <p class="unnnic-template-preview__buttons__button__text">
91
+ {{ button.text }}
92
+ </p>
93
+ </section>
94
+ </footer>
95
+ </section>
96
+ </template>
97
+
98
+ <script lang="ts" setup>
99
+ import { computed } from "vue";
100
+
101
+ import type { Template } from "./types";
102
+
103
+ import imagePreview from "../../assets/img/previews/image-preview.png";
104
+ import documentPreview from "../../assets/img/previews/doc-preview.png";
105
+ import videoPreview from "../../assets/img/previews/video-preview.png";
106
+
107
+ import UnnnicIcon from "../Icon.vue";
108
+
109
+ interface Props {
110
+ template?: Template | null;
111
+ }
112
+
113
+ const props = withDefaults(defineProps<Props>(), {
114
+ template: null,
115
+ });
116
+
117
+ const hasHeader = computed(
118
+ () => props.template?.header && props.template.header.type
119
+ );
120
+ const hasHeaderMedia = computed(
121
+ () => !!props.template?.header && props.template.header.type === "MEDIA"
122
+ );
123
+ const hasBody = computed(
124
+ () => !!props.template?.body && props.template.body.length > 0
125
+ );
126
+ const hasFooter = computed(
127
+ () => !!props.template?.footer && props.template.footer.length > 0
128
+ );
129
+ const hasButtons = computed(
130
+ () => !!props.template?.buttons && props.template.buttons.length > 0
131
+ );
132
+ const parsedBody = computed(() => {
133
+ if (!hasBody.value) return "";
134
+
135
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
136
+ const result = props
137
+ .template!.body!.replaceAll("\n", "<br/>")
138
+ .replaceAll(/(?:\*)([^*<\n]+)(?:\*)/g, "<strong>$1</strong>")
139
+ .replaceAll(/(?:_)([^_<\n]+)(?:_)/g, "<i>$1</i>")
140
+ .replaceAll(/(?:~)([^~<\n]+)(?:~)/g, "<s>$1</s>")
141
+ .replaceAll(/(?:```)([^```<\n]+)(?:```)/g, "<tt>$1</tt>")
142
+ .replaceAll(/{{.*?}}/g, (match) => `<strong>${match}</strong>`);
143
+
144
+ return result;
145
+ });
146
+
147
+ const getButtonIcon = (buttonType) => {
148
+ const buttonMapper = {
149
+ PHONE_NUMBER: "phone",
150
+ URL: "open_in_new",
151
+ COPY_CODE: "content_copy",
152
+ FLOW: "",
153
+ QUICK_REPLY: "reply",
154
+ };
155
+
156
+ return buttonMapper[buttonType] || "";
157
+ };
158
+ </script>
159
+
160
+ <style lang="scss" scoped>
161
+ @use "@/assets/scss/unnnic" as *;
162
+
163
+ .unnnic-template-preview {
164
+ display: flex;
165
+ flex-direction: column;
166
+ box-shadow: $unnnic-shadow-level-near;
167
+ background-color: $unnnic-color-background-white;
168
+ width: 368px;
169
+ border-radius: $unnnic-border-radius-md;
170
+
171
+ &__content {
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: $unnnic-space-3;
175
+ padding: $unnnic-space-4 $unnnic-space-3;
176
+
177
+ &--has-media {
178
+ padding: $unnnic-space-1;
179
+ }
180
+ }
181
+
182
+ &__header {
183
+ &__text {
184
+ &__preview {
185
+ font-family: $unnnic-font-family-secondary;
186
+ font-weight: $unnnic-font-weight-bold;
187
+ font-size: $unnnic-font-size-body-gt;
188
+ line-height: $unnnic-font-size-body-gt + $unnnic-line-height-medium;
189
+ color: $unnnic-color-neutral-dark;
190
+
191
+ margin: $unnnic-space-0;
192
+ }
193
+ }
194
+
195
+ &__media {
196
+ &__preview {
197
+ width: 100%;
198
+ object-fit: cover;
199
+ }
200
+ }
201
+ }
202
+
203
+ &__body {
204
+ font-family: $unnnic-font-family-secondary;
205
+ font-weight: $unnnic-font-weight-regular;
206
+ font-size: $unnnic-font-size-body-gt;
207
+ line-height: $unnnic-font-size-body-gt + $unnnic-line-height-medium;
208
+ color: $unnnic-color-neutral-cloudy;
209
+
210
+ &--has-media {
211
+ padding: $unnnic-space-0 $unnnic-space-2;
212
+ }
213
+ }
214
+
215
+ &__footer {
216
+ font-family: $unnnic-font-family-secondary;
217
+ font-weight: $unnnic-font-weight-regular;
218
+ font-size: $unnnic-font-size-body-md;
219
+ line-height: $unnnic-font-size-body-md + $unnnic-line-height-medium;
220
+ color: $unnnic-color-neutral-clean;
221
+
222
+ &--has-media {
223
+ padding: $unnnic-space-0 $unnnic-space-3 $unnnic-space-2;
224
+ }
225
+ }
226
+
227
+ &__buttons {
228
+ font-family: $unnnic-font-family-secondary;
229
+ font-weight: $unnnic-font-weight-bold;
230
+ font-size: $unnnic-font-size-body-gt;
231
+ line-height: $unnnic-font-size-body-gt + $unnnic-line-height-medium;
232
+
233
+ &__button {
234
+ margin: 0;
235
+ display: flex;
236
+ align-items: center;
237
+ justify-content: center;
238
+ gap: $unnnic-space-2;
239
+ padding: $unnnic-space-3;
240
+ border-top: 1px solid $unnnic-color-neutral-light;
241
+
242
+ &__text {
243
+ color: $unnnic-color-aux-blue-500;
244
+ margin: $unnnic-space-0;
245
+ }
246
+ }
247
+ }
248
+ }
249
+ </style>
@@ -0,0 +1,51 @@
1
+ <template>
2
+ <UnnnicModalDialog
3
+ :model-value="modelValue"
4
+ @update:modelValue="$event === false && $emit('close')"
5
+ :title="defaultTranslations.title[props.locale]"
6
+ :show-close-icon="true"
7
+ class="unnnic-template-preview-modal"
8
+ >
9
+ <UnnnicTemplatePreview :template="template" />
10
+ </UnnnicModalDialog>
11
+ </template>
12
+
13
+ <script lang="ts" setup>
14
+ import UnnnicTemplatePreview from "./TemplatePreview.vue";
15
+ import UnnnicModalDialog from "../ModalDialog/ModalDialog.vue";
16
+
17
+ import type { Template } from "./types";
18
+
19
+ const defaultTranslations = {
20
+ title: {
21
+ "pt-br": "Visualizar modelo",
22
+ en: "Template preview",
23
+ es: "Vista previa de plantilla",
24
+ },
25
+ };
26
+
27
+ interface Props {
28
+ locale?: string;
29
+ template: Template;
30
+ modelValue: boolean;
31
+ }
32
+
33
+ const props = withDefaults(defineProps<Props>(), {
34
+ locale: "en",
35
+ });
36
+
37
+ defineEmits<{
38
+ close: void;
39
+ }>();
40
+ </script>
41
+
42
+ <style lang="scss" scoped>
43
+ @use "@/assets/scss/unnnic" as *;
44
+
45
+ :deep(.unnnic-modal-dialog__container__content) {
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ background-color: $unnnic-color-neutral-lightest;
50
+ }
51
+ </style>
@@ -0,0 +1,16 @@
1
+ export interface Template {
2
+ header: {
3
+ type: "TEXT" | "MEDIA";
4
+ mediaType?: "IMAGE" | "VIDEO" | "DOCUMENT";
5
+ text?: string | null;
6
+ src?: string | null;
7
+ };
8
+ body?: string;
9
+ footer?: string;
10
+ buttons?: Array<{
11
+ type: "QUICK_REPLY" | "PHONE_NUMBER";
12
+ text: string;
13
+ countryCode?: string;
14
+ phoneNumber?: string;
15
+ }>;
16
+ }
@@ -88,6 +88,9 @@ import ModalDialog from "./ModalDialog/ModalDialog.vue";
88
88
  import Tour from "./Tour/Tour.vue";
89
89
  import Navigator from "./Navigator/index.vue";
90
90
  import SelectTime from "./SelectTime/index.vue";
91
+ import TemplatePreview from "./TemplatePreview/TemplatePreview.vue";
92
+ import TemplatePreviewModal from "./TemplatePreview/TemplatePreviewModal.vue";
93
+ import DataTable from './DataTable/index.vue';
91
94
 
92
95
  type VueComponent = Component;
93
96
 
@@ -186,6 +189,9 @@ export const components: ComponentsMap = {
186
189
  unnnicTour: Tour,
187
190
  unnnicNavigator: Navigator,
188
191
  unnnicSelectTime: SelectTime,
192
+ unnnicTemplatePreview: TemplatePreview,
193
+ unnnicTemplatePreviewModal: TemplatePreviewModal,
194
+ unnnicDataTable: DataTable,
189
195
  };
190
196
 
191
197
  export const unnnicFontSize = fontSize;
@@ -279,3 +285,6 @@ export const unnnicTableNext = TableNext;
279
285
  export const unnnicTour = Tour;
280
286
  export const unnnicNavigator = Navigator;
281
287
  export const unnnicSelectTime = SelectTime as VueComponent;
288
+ export const unnnicTemplatePreview = TemplatePreview as VueComponent;
289
+ export const unnnicTemplatePreviewModal = TemplatePreviewModal as VueComponent;
290
+ export const unnnicDataTable = DataTable;
@@ -0,0 +1,332 @@
1
+ import UnnnicDataTable from '../components/DataTable/index.vue';
2
+ import { action } from '@storybook/addon-actions';
3
+
4
+ export default {
5
+ title: 'Data Display/DataTable',
6
+ component: UnnnicDataTable,
7
+ tags: ['autodocs'],
8
+ args: {
9
+ page: 1,
10
+ },
11
+ argTypes: {
12
+ headers: {
13
+ description:
14
+ 'Array of header items defining the structure of the table header.',
15
+ control: 'object',
16
+ },
17
+ items: {
18
+ description: 'Array of row items defining the content of the table rows.',
19
+ control: 'object',
20
+ },
21
+ size: {
22
+ description:
23
+ 'The size of the table. Options are `sm` for small and `md` for medium.',
24
+ control: { type: 'select' },
25
+ options: ['sm', 'md'],
26
+ },
27
+ page: {
28
+ description: 'The current page number for pagination.',
29
+ control: 'number',
30
+ },
31
+ pageTotal: {
32
+ description: 'The total number of pages available for pagination.',
33
+ control: 'number',
34
+ },
35
+ pageInterval: {
36
+ description: 'The number of items displayed per page.',
37
+ control: 'number',
38
+ },
39
+ isLoading: {
40
+ description: 'Indicates whether the table data is loading.',
41
+ control: 'boolean',
42
+ },
43
+ hideHeaders: {
44
+ description: 'Determines if the table headers should be hidden.',
45
+ control: 'boolean',
46
+ },
47
+ height: {
48
+ description: 'The height of the table.',
49
+ control: 'text',
50
+ },
51
+ maxHeight: {
52
+ description: 'The maximum height of the table.',
53
+ control: 'text',
54
+ },
55
+ clickable: {
56
+ description: 'Indicates whether the table rows should be clickable.',
57
+ control: 'boolean',
58
+ },
59
+ fixedHeaders: {
60
+ description:
61
+ 'Indicates whether the table headers should be fixed in scroll.',
62
+ control: 'boolean',
63
+ },
64
+ hidePagination: {
65
+ description: 'Indicates whether the pagination should be hidden.',
66
+ control: 'boolean',
67
+ },
68
+ locale: {
69
+ description: 'The locale for the table translations.',
70
+ control: { type: 'select' },
71
+ options: ['en', 'pt-br', 'es'],
72
+ },
73
+ },
74
+ render: (args) => ({
75
+ components: {
76
+ UnnnicDataTable,
77
+ },
78
+ setup() {
79
+ const sort = ({ order, header }) => {
80
+ action('update:sort')({ order, header });
81
+ if (order === 'asc')
82
+ args.items = args.items.sort((a, b) => a.id - b.id);
83
+ if (order === 'desc')
84
+ args.items = args.items.sort((a, b) => b.id - a.id);
85
+ };
86
+ const updatePage = (page) => {
87
+ action('update:page')(page);
88
+ args.page = page;
89
+ };
90
+ const itemClick = (item) => {
91
+ action('itemClick')(item);
92
+ };
93
+
94
+ return { args, sort, updatePage, itemClick };
95
+ },
96
+ template: `
97
+ <UnnnicDataTable
98
+ v-bind="args"
99
+ :headers="args.headers"
100
+ :items="args.items"
101
+ :pageTotal="125"
102
+ :pageInterval="5"
103
+ @update:sort="sort"
104
+ @update:page="updatePage"
105
+ @itemClick="itemClick"
106
+ >
107
+ </UnnnicDataTable>
108
+ `,
109
+ }),
110
+ };
111
+
112
+ const headers = [
113
+ {
114
+ title: 'ID',
115
+ itemKey: 'id',
116
+ isSortable: true,
117
+ },
118
+ {
119
+ title: 'Name',
120
+ itemKey: 'name',
121
+ },
122
+ {
123
+ title: 'Age',
124
+ itemKey: 'age',
125
+ },
126
+ {
127
+ title: 'Country',
128
+ itemKey: 'country',
129
+ },
130
+ ];
131
+
132
+ const items = [
133
+ {
134
+ id: '1',
135
+ name: 'Eduardo',
136
+ age: 27,
137
+ country: 'Brazil',
138
+ },
139
+ {
140
+ id: '2',
141
+ name: 'Marcus',
142
+ age: 27,
143
+ country: 'Brazil',
144
+ },
145
+ {
146
+ id: '3',
147
+ name: 'Paulo',
148
+ age: 29,
149
+ country: 'Brazil',
150
+ },
151
+ {
152
+ id: '4',
153
+ name: 'Cristian',
154
+ age: 27,
155
+ country: 'Brazil',
156
+ },
157
+ {
158
+ id: '5',
159
+ name: 'Aldemylla',
160
+ age: 27,
161
+ country: 'Brazil',
162
+ },
163
+ ];
164
+
165
+ export const Default = {
166
+ args: {
167
+ headers,
168
+ items,
169
+ },
170
+ };
171
+
172
+ export const Clickable = {
173
+ args: {
174
+ headers,
175
+ items,
176
+ clickable: true,
177
+ },
178
+ };
179
+
180
+ export const WithHeightLimit = {
181
+ args: {
182
+ headers,
183
+ items,
184
+ height: '165px',
185
+ },
186
+ };
187
+
188
+ export const FixedHeaders = {
189
+ args: {
190
+ headers,
191
+ items,
192
+ fixedHeaders: true,
193
+ height: '165px',
194
+ },
195
+ };
196
+
197
+ export const Medium = {
198
+ args: {
199
+ headers,
200
+ items,
201
+ size: 'md',
202
+ },
203
+ };
204
+
205
+ export const Small = {
206
+ args: {
207
+ headers,
208
+ items,
209
+ size: 'sm',
210
+ },
211
+ };
212
+
213
+ export const HideHeaders = {
214
+ args: {
215
+ headers,
216
+ items,
217
+ hideHeaders: true,
218
+ },
219
+ };
220
+
221
+ export const SlotHeader = {
222
+ args: { headers, items },
223
+ render: (args) => ({
224
+ components: {
225
+ UnnnicDataTable,
226
+ },
227
+ setup() {
228
+ const sort = ({ order, header }) => {
229
+ action('update:sort')({ order, header });
230
+ if (order === 'asc')
231
+ args.items = args.items.sort((a, b) => a.id - b.id);
232
+ if (order === 'desc')
233
+ args.items = args.items.sort((a, b) => b.id - a.id);
234
+ };
235
+ const updatePage = (page) => {
236
+ action('update:page')(page);
237
+ args.page = page;
238
+ };
239
+ const itemClick = (item) => {
240
+ action('itemClick')(item);
241
+ };
242
+
243
+ return { args, sort, updatePage, itemClick };
244
+ },
245
+ template: `
246
+ <UnnnicDataTable
247
+ v-bind="args"
248
+ :headers="args.headers"
249
+ :items="args.items"
250
+ :pageTotal="125"
251
+ :pageInterval="5"
252
+ @update:sort="sort"
253
+ @update:page="updatePage"
254
+ @itemClick="itemClick"
255
+ >
256
+ <template #header-name="{ header }">
257
+ <button>
258
+ {{ header.title }}
259
+ </button>
260
+ </template>
261
+ </UnnnicDataTable>
262
+ `,
263
+ }),
264
+ };
265
+
266
+ export const SlotItem = {
267
+ args: { headers, items },
268
+ render: (args) => ({
269
+ components: {
270
+ UnnnicDataTable,
271
+ },
272
+ setup() {
273
+ const sort = ({ order, header }) => {
274
+ action('update:sort')({ order, header });
275
+ if (order === 'asc')
276
+ args.items = args.items.sort((a, b) => a.id - b.id);
277
+ if (order === 'desc')
278
+ args.items = args.items.sort((a, b) => b.id - a.id);
279
+ };
280
+ const updatePage = (page) => {
281
+ action('update:page')(page);
282
+ args.page = page;
283
+ };
284
+ const itemClick = (item) => {
285
+ action('itemClick')(item);
286
+ };
287
+
288
+ return { args, sort, updatePage, itemClick };
289
+ },
290
+ template: `
291
+ <UnnnicDataTable
292
+ v-bind="args"
293
+ :headers="args.headers"
294
+ :items="args.items"
295
+ :pageTotal="125"
296
+ :pageInterval="5"
297
+ @update:sort="sort"
298
+ @update:page="updatePage"
299
+ @itemClick="itemClick"
300
+ >
301
+ <template #body-id="{ item }">
302
+ <button>
303
+ {{ item.id }}
304
+ </button>
305
+ </template>
306
+ </UnnnicDataTable>
307
+ `,
308
+ }),
309
+ };
310
+
311
+ export const HidePagination = {
312
+ args: {
313
+ headers,
314
+ items,
315
+ hidePagination: true,
316
+ },
317
+ };
318
+
319
+ export const WithoutResults = {
320
+ args: {
321
+ headers,
322
+ items: [],
323
+ },
324
+ };
325
+
326
+ export const Loading = {
327
+ args: {
328
+ headers,
329
+ items,
330
+ isLoading: true,
331
+ },
332
+ };