@caipira/tamandua 0.0.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 (295) hide show
  1. package/.editorconfig +12 -0
  2. package/.prettierrc +5 -0
  3. package/.storybook/main.ts +25 -0
  4. package/.storybook/preview-body.html +3 -0
  5. package/.storybook/preview.ts +24 -0
  6. package/App.vue +1 -0
  7. package/Dockerfile +21 -0
  8. package/LICENSE +674 -0
  9. package/README.md +11 -0
  10. package/assets/icons/account.svg +1 -0
  11. package/assets/icons/alert-octagon-outline.svg +1 -0
  12. package/assets/icons/alert-octagon.svg +1 -0
  13. package/assets/icons/archive-outline.svg +1 -0
  14. package/assets/icons/archive.svg +1 -0
  15. package/assets/icons/arrow-left.svg +1 -0
  16. package/assets/icons/arrow-right.svg +1 -0
  17. package/assets/icons/bank-outline.svg +1 -0
  18. package/assets/icons/bank.svg +1 -0
  19. package/assets/icons/camera.svg +1 -0
  20. package/assets/icons/cards-outline.svg +1 -0
  21. package/assets/icons/cards-variant.svg +1 -0
  22. package/assets/icons/cart-outline.svg +1 -0
  23. package/assets/icons/chart-box-outline.svg +1 -0
  24. package/assets/icons/chart-box.svg +1 -0
  25. package/assets/icons/check-circle-outline.svg +1 -0
  26. package/assets/icons/check-circle.svg +1 -0
  27. package/assets/icons/check.svg +1 -0
  28. package/assets/icons/checkbox-dark.svg +1 -0
  29. package/assets/icons/checkbox-indeterminate-dark.svg +1 -0
  30. package/assets/icons/checkbox-indeterminate.svg +1 -0
  31. package/assets/icons/checkbox.svg +1 -0
  32. package/assets/icons/chevron-down.svg +1 -0
  33. package/assets/icons/chevron-left.svg +1 -0
  34. package/assets/icons/chevron-right.svg +1 -0
  35. package/assets/icons/chevron-up.svg +1 -0
  36. package/assets/icons/circle.svg +1 -0
  37. package/assets/icons/clock.svg +1 -0
  38. package/assets/icons/close-circle-outline.svg +1 -0
  39. package/assets/icons/close-circle.svg +1 -0
  40. package/assets/icons/close.svg +1 -0
  41. package/assets/icons/cog.svg +1 -0
  42. package/assets/icons/color-fill.svg +1 -0
  43. package/assets/icons/copy.svg +1 -0
  44. package/assets/icons/credit-card-plus.svg +1 -0
  45. package/assets/icons/credit-card.svg +1 -0
  46. package/assets/icons/currency.svg +1 -0
  47. package/assets/icons/database.svg +1 -0
  48. package/assets/icons/dots-grid.svg +1 -0
  49. package/assets/icons/dots-vertical.svg +1 -0
  50. package/assets/icons/email-open-outline.svg +1 -0
  51. package/assets/icons/email-outline.svg +1 -0
  52. package/assets/icons/eye-off.svg +1 -0
  53. package/assets/icons/eye.svg +1 -0
  54. package/assets/icons/file-document-plus-outline.svg +1 -0
  55. package/assets/icons/filmstrip.svg +1 -0
  56. package/assets/icons/filter.svg +1 -0
  57. package/assets/icons/fullscreen-exit.svg +1 -0
  58. package/assets/icons/fullscreen.svg +1 -0
  59. package/assets/icons/group.svg +1 -0
  60. package/assets/icons/image-album-outline.svg +1 -0
  61. package/assets/icons/image-album.svg +1 -0
  62. package/assets/icons/image-outline.svg +1 -0
  63. package/assets/icons/image.svg +1 -0
  64. package/assets/icons/info-outline.svg +1 -0
  65. package/assets/icons/key-chain.svg +1 -0
  66. package/assets/icons/key-variant.svg +1 -0
  67. package/assets/icons/key.svg +1 -0
  68. package/assets/icons/listbox-outline.svg +1 -0
  69. package/assets/icons/loading.svg +1 -0
  70. package/assets/icons/lock-outline.svg +1 -0
  71. package/assets/icons/lock.svg +1 -0
  72. package/assets/icons/logout.svg +1 -0
  73. package/assets/icons/menu-down.svg +1 -0
  74. package/assets/icons/menu-left.svg +1 -0
  75. package/assets/icons/menu-right.svg +1 -0
  76. package/assets/icons/menu.svg +1 -0
  77. package/assets/icons/minus-circle-outline.svg +1 -0
  78. package/assets/icons/minus-circle.svg +1 -0
  79. package/assets/icons/minus.svg +1 -0
  80. package/assets/icons/moon.svg +1 -0
  81. package/assets/icons/open-in-new.svg +1 -0
  82. package/assets/icons/pencil.svg +1 -0
  83. package/assets/icons/people.svg +1 -0
  84. package/assets/icons/piggy-bank-outline.svg +1 -0
  85. package/assets/icons/plus-circle-outline.svg +1 -0
  86. package/assets/icons/plus-circle.svg +1 -0
  87. package/assets/icons/plus.svg +1 -0
  88. package/assets/icons/qrcode-scan.svg +1 -0
  89. package/assets/icons/radio-dark.svg +1 -0
  90. package/assets/icons/radio.svg +1 -0
  91. package/assets/icons/refresh.svg +1 -0
  92. package/assets/icons/save.svg +1 -0
  93. package/assets/icons/search.svg +1 -0
  94. package/assets/icons/spotlight.svg +1 -0
  95. package/assets/icons/store-outline.svg +1 -0
  96. package/assets/icons/sun.svg +1 -0
  97. package/assets/icons/swap-horizontal.svg +1 -0
  98. package/assets/icons/swap-left.svg +1 -0
  99. package/assets/icons/swap-right.svg +1 -0
  100. package/assets/icons/swap.svg +1 -0
  101. package/assets/icons/system-theme.svg +1 -0
  102. package/assets/icons/tag-outline.svg +1 -0
  103. package/assets/icons/trash-can-outline.svg +1 -0
  104. package/assets/icons/trash-can.svg +1 -0
  105. package/assets/icons/upload.svg +1 -0
  106. package/assets/icons/user-circle.svg +1 -0
  107. package/assets/icons/zip-box.svg +1 -0
  108. package/assets/images/fs/apk.svg +11 -0
  109. package/assets/images/fs/bmp.svg +7 -0
  110. package/assets/images/fs/css.svg +8 -0
  111. package/assets/images/fs/doc.svg +9 -0
  112. package/assets/images/fs/docx.svg +9 -0
  113. package/assets/images/fs/folder-adwaita.svg +8 -0
  114. package/assets/images/fs/folder-black.svg +8 -0
  115. package/assets/images/fs/folder-brown.svg +8 -0
  116. package/assets/images/fs/folder-grey.svg +8 -0
  117. package/assets/images/fs/folder-nordic.svg +8 -0
  118. package/assets/images/fs/folder-orange.svg +8 -0
  119. package/assets/images/fs/folder-palebrown.svg +8 -0
  120. package/assets/images/fs/folder-paleorange.svg +8 -0
  121. package/assets/images/fs/folder-teal.svg +8 -0
  122. package/assets/images/fs/folder-white.svg +8 -0
  123. package/assets/images/fs/folder-yellow.svg +8 -0
  124. package/assets/images/fs/gif.svg +7 -0
  125. package/assets/images/fs/go.svg +9 -0
  126. package/assets/images/fs/ics.svg +24 -0
  127. package/assets/images/fs/iso.svg +10 -0
  128. package/assets/images/fs/jpeg.svg +7 -0
  129. package/assets/images/fs/jpg.svg +7 -0
  130. package/assets/images/fs/js.svg +9 -0
  131. package/assets/images/fs/json.svg +9 -0
  132. package/assets/images/fs/lua.svg +9 -0
  133. package/assets/images/fs/m4v.svg +7 -0
  134. package/assets/images/fs/md.svg +10 -0
  135. package/assets/images/fs/mov.svg +7 -0
  136. package/assets/images/fs/mp3.svg +9 -0
  137. package/assets/images/fs/mp4.svg +7 -0
  138. package/assets/images/fs/pdf.svg +9 -0
  139. package/assets/images/fs/pgp.svg +8 -0
  140. package/assets/images/fs/php.svg +9 -0
  141. package/assets/images/fs/png.svg +7 -0
  142. package/assets/images/fs/ppt.svg +9 -0
  143. package/assets/images/fs/py.svg +9 -0
  144. package/assets/images/fs/rar.svg +20 -0
  145. package/assets/images/fs/rpm.svg +7 -0
  146. package/assets/images/fs/rs.svg +9 -0
  147. package/assets/images/fs/sh.svg +9 -0
  148. package/assets/images/fs/tar.svg +20 -0
  149. package/assets/images/fs/txt.svg +8 -0
  150. package/assets/images/fs/unknown.svg +8 -0
  151. package/assets/images/fs/xls.svg +9 -0
  152. package/assets/images/fs/xlsx.svg +9 -0
  153. package/assets/images/fs/xml.svg +8 -0
  154. package/assets/images/fs/yaml.svg +9 -0
  155. package/assets/images/fs/zip.svg +20 -0
  156. package/components/Avatar/Avatar.story.ts +55 -0
  157. package/components/Avatar/Avatar.vue +82 -0
  158. package/components/Avatar/index.ts +12 -0
  159. package/components/Backdrop/Backdrop.vue +27 -0
  160. package/components/Backdrop/index.ts +12 -0
  161. package/components/Button/Button.story.ts +74 -0
  162. package/components/Button/Button.vue +230 -0
  163. package/components/Button/index.ts +12 -0
  164. package/components/ButtonCopy/ButtonCopy.vue +61 -0
  165. package/components/ButtonCopy/index.ts +12 -0
  166. package/components/Drawer/Drawer.vue +102 -0
  167. package/components/Drawer/index.ts +12 -0
  168. package/components/Dropdown/Dropdown.vue +258 -0
  169. package/components/Dropdown/index.ts +12 -0
  170. package/components/EventListener/EventListener.vue +12 -0
  171. package/components/FileDrop/FileDrop.vue +116 -0
  172. package/components/FileDrop/index.ts +12 -0
  173. package/components/Form/Form.spec.ts +72 -0
  174. package/components/Form/Form.vue +134 -0
  175. package/components/Form/index.ts +12 -0
  176. package/components/FormItem/FormItem.vue +85 -0
  177. package/components/FormItem/index.ts +12 -0
  178. package/components/GraphyEmpty/GraphyEmpty.vue +16 -0
  179. package/components/GraphyEmpty/index.ts +12 -0
  180. package/components/GraphyLabel/GraphyLabel.vue +34 -0
  181. package/components/GraphyLabel/index.ts +12 -0
  182. package/components/GraphyPrice/GraphyPrice.story.ts +37 -0
  183. package/components/GraphyPrice/GraphyPrice.vue +65 -0
  184. package/components/GraphyPrice/index.ts +12 -0
  185. package/components/GraphySubtitle/GraphySubtitle.vue +22 -0
  186. package/components/GraphySubtitle/index.ts +12 -0
  187. package/components/GraphyTitle/GraphyTitle.vue +13 -0
  188. package/components/GraphyTitle/index.ts +12 -0
  189. package/components/Icon/Icon.vue +84 -0
  190. package/components/Icon/index.ts +12 -0
  191. package/components/IconButton/IconButton.vue +168 -0
  192. package/components/IconButton/index.ts +12 -0
  193. package/components/InputAvatar/InputAvatar.vue +63 -0
  194. package/components/InputAvatar/index.ts +12 -0
  195. package/components/InputCheckbox/InputCheckbox.vue +77 -0
  196. package/components/InputCheckbox/index.ts +12 -0
  197. package/components/InputColor/InputColor.vue +54 -0
  198. package/components/InputColor/index.ts +12 -0
  199. package/components/InputDate/InputDate.story.ts +15 -0
  200. package/components/InputDate/InputDate.vue +368 -0
  201. package/components/InputDate/index.ts +12 -0
  202. package/components/InputMultiplier/InputMultiplier.vue +144 -0
  203. package/components/InputMultiplier/index.ts +12 -0
  204. package/components/InputPassword/InputPassword.vue +168 -0
  205. package/components/InputPassword/index.ts +12 -0
  206. package/components/InputPhone/InputPhone.vue +125 -0
  207. package/components/InputPhone/index.ts +12 -0
  208. package/components/InputPrice/InputPrice.vue +96 -0
  209. package/components/InputPrice/index.ts +12 -0
  210. package/components/InputRadio/InputRadio.vue +41 -0
  211. package/components/InputRadio/InputRadioGroup.story.ts +24 -0
  212. package/components/InputRadio/InputRadioGroup.vue +48 -0
  213. package/components/InputRadio/index.ts +14 -0
  214. package/components/InputSelect/InputSelect.story.ts +87 -0
  215. package/components/InputSelect/InputSelect.vue +507 -0
  216. package/components/InputSelect/index.ts +12 -0
  217. package/components/InputSwitch/InputSwitch.story.ts +34 -0
  218. package/components/InputSwitch/InputSwitch.vue +82 -0
  219. package/components/InputSwitch/index.ts +12 -0
  220. package/components/InputText/InputText.vue +62 -0
  221. package/components/InputText/index.ts +12 -0
  222. package/components/InputTextarea/InputTextarea.vue +64 -0
  223. package/components/InputTextarea/index.ts +12 -0
  224. package/components/LineChart/LineChart.vue +14 -0
  225. package/components/LineChart/index.ts +12 -0
  226. package/components/Modal/Modal.vue +106 -0
  227. package/components/Modal/index.ts +12 -0
  228. package/components/ModalForm/ModalForm.vue +141 -0
  229. package/components/ModalForm/index.ts +12 -0
  230. package/components/Pagination/Pagination.story.ts +15 -0
  231. package/components/Pagination/Pagination.vue +138 -0
  232. package/components/Pagination/index.ts +12 -0
  233. package/components/PieChart/PieChart.vue +14 -0
  234. package/components/PieChart/index.ts +12 -0
  235. package/components/Popconfirm/Popconfirm.vue +80 -0
  236. package/components/Popconfirm/index.ts +12 -0
  237. package/components/Popover/Popover.vue +133 -0
  238. package/components/Popover/index.ts +12 -0
  239. package/components/ProgressCircle/ProgressCircle.story.ts +31 -0
  240. package/components/ProgressCircle/ProgressCircle.vue +82 -0
  241. package/components/ProgressCircle/index.ts +12 -0
  242. package/components/ProgressLine/ProgressLine.story.ts +27 -0
  243. package/components/ProgressLine/ProgressLine.vue +104 -0
  244. package/components/ProgressLine/index.ts +12 -0
  245. package/components/SensitiveInfo/SensitiveInfo.vue +18 -0
  246. package/components/SensitiveInfo/index.ts +12 -0
  247. package/components/Tab/Tab.vue +58 -0
  248. package/components/Tab/index.ts +12 -0
  249. package/components/Table/Table.story.ts +32 -0
  250. package/components/Table/Table.vue +318 -0
  251. package/components/Table/index.ts +12 -0
  252. package/components/Tag/Tag.vue +73 -0
  253. package/components/Tag/index.ts +12 -0
  254. package/components/Toast/Toast.vue +75 -0
  255. package/components/Toast/index.ts +12 -0
  256. package/components/index.ts +43 -0
  257. package/components/plugins.ts +89 -0
  258. package/composables/index.ts +2 -0
  259. package/composables/useBreakpoints.ts +30 -0
  260. package/composables/useRender.ts +29 -0
  261. package/entrypoint.sh +19 -0
  262. package/enums/app.ts +5 -0
  263. package/enums/form.ts +25 -0
  264. package/enums/ui.ts +160 -0
  265. package/env.d.ts +8 -0
  266. package/i18n.ts +20 -0
  267. package/index.css +383 -0
  268. package/index.html +22 -0
  269. package/index.ts +14 -0
  270. package/main.ts +31 -0
  271. package/package.json +70 -0
  272. package/plugins/register-component.ts +5 -0
  273. package/postcss.config.js +6 -0
  274. package/services/clipboard.ts +5 -0
  275. package/services/date.ts +27 -0
  276. package/services/form/crud.ts +109 -0
  277. package/services/form/form-data-transformers.ts +148 -0
  278. package/services/form/form-json-transformers.ts +91 -0
  279. package/services/form/form-transformer.ts +54 -0
  280. package/services/form/form-value-transformers.ts +35 -0
  281. package/services/form/form.test.ts +98 -0
  282. package/services/form/form.ts +80 -0
  283. package/services/password.ts +309 -0
  284. package/services/ui.ts +43 -0
  285. package/tailwind.config.js +16 -0
  286. package/tsconfig.json +23 -0
  287. package/types/address.ts +44 -0
  288. package/types/api.ts +28 -0
  289. package/types/common.ts +5 -0
  290. package/types/form.ts +144 -0
  291. package/types/index.ts +5 -0
  292. package/types/ui.ts +55 -0
  293. package/types/website.ts +16 -0
  294. package/vite.config.mts +38 -0
  295. package/vitest.setup.ts +21 -0
@@ -0,0 +1,138 @@
1
+ <script lang="ts" setup>
2
+ import { Pagination } from "@/types/ui";
3
+ import { SelectOption } from "@/types/form";
4
+
5
+ import { computed, watch } from "vue";
6
+
7
+ defineOptions({ name: "TPagination" });
8
+
9
+ const props = withDefaults(
10
+ defineProps<{
11
+ disabled?: boolean;
12
+ pagination?: Pagination;
13
+ pageLengths?: Array<number>;
14
+ showDescription: boolean;
15
+ }>(),
16
+ {
17
+ disabled: false,
18
+ pagination: () => ({}) as Pagination,
19
+ pageLengths: () => [12, 18, 24, 30, 36, 42],
20
+ showDescription: false,
21
+ },
22
+ );
23
+
24
+ const emit = defineEmits<{
25
+ (e: "updated", val: Pagination): void;
26
+ }>();
27
+
28
+ const isFirstPage = computed<boolean>(() => {
29
+ return props.pagination.page === 1;
30
+ });
31
+
32
+ const isLastPage = computed<boolean>(() => {
33
+ return (
34
+ props.pagination.totalItems - props.pagination?.skip <=
35
+ props.pagination.perPage
36
+ );
37
+ });
38
+
39
+ const pageLengthsOptions = computed<SelectOption[]>(() => {
40
+ return props.pageLengths.map((l: number) => ({
41
+ label: `${l} / page`,
42
+ value: l,
43
+ }));
44
+ });
45
+
46
+ const description = computed<string>(() => {
47
+ const from = props.pagination.skip + 1;
48
+ const to = props.pagination.skip + props.pagination.items;
49
+ const total = props.pagination.totalItems;
50
+
51
+ return `Showing ${from} to ${to} of ${total} entries`;
52
+ });
53
+
54
+ const recalculate = (page: number = props.pagination.page) => {
55
+ const skip = page > 1 ? (page - 1) * props.pagination.perPage : 0;
56
+ const items = props.pagination.totalItems - skip;
57
+
58
+ Object.assign(props.pagination, {
59
+ ...props.pagination,
60
+ skip,
61
+ page,
62
+ items:
63
+ items > props.pagination.perPage ? props.pagination.perPage : items,
64
+ });
65
+
66
+ emit("updated", props.pagination);
67
+ };
68
+
69
+ const onPreviousPage = () => {
70
+ recalculate(props.pagination.page - 1);
71
+ };
72
+
73
+ const onNextPage = () => {
74
+ recalculate(props.pagination.page + 1);
75
+ };
76
+
77
+ const onPageSizeChange = (length: number) => {
78
+ Object.assign(props.pagination, {
79
+ ...props.pagination,
80
+ perPage: length,
81
+ page: 1,
82
+ });
83
+
84
+ emit("updated", props.pagination);
85
+ };
86
+
87
+ watch(
88
+ () => props.pagination,
89
+ () => {
90
+ if (props.pagination.totalItems > 0 && props.pagination.items === 0) {
91
+ recalculate();
92
+ }
93
+ },
94
+ { deep: true, immediate: true },
95
+ );
96
+ </script>
97
+
98
+ <template>
99
+ <div class="flex items-center justify-end w-full flex-wrap">
100
+ <div
101
+ v-if="showDescription"
102
+ class="mr-3 grow md:block hidden"
103
+ >
104
+ {{ description }}
105
+ </div>
106
+ <div class="h-9 flex">
107
+ <t-button
108
+ size="sm"
109
+ variant="primary"
110
+ :disable-style="true"
111
+ class="h-9 px-2 input-roundness rounded-r-none input-border border-r"
112
+ icon="chevron-left"
113
+ :class="{ 'opacity-50 cursor-not-allowed': isFirstPage }"
114
+ :disabled="isFirstPage"
115
+ @click="onPreviousPage"
116
+ />
117
+ <t-button
118
+ size="sm"
119
+ variant="primary"
120
+ :disable-style="true"
121
+ class="h-9 px-2 rounded-none"
122
+ icon="chevron-right"
123
+ :class="{ 'opacity-50 cursor-not-allowed': isLastPage }"
124
+ :disabled="isLastPage"
125
+ @click="onNextPage"
126
+ />
127
+ <t-input-select
128
+ v-model="pagination.perPage"
129
+ :disabled="disabled"
130
+ :options="pageLengthsOptions"
131
+ :disable-style="true"
132
+ dropdown-placement="top"
133
+ class="h-9 border input-border border-l-0 input-roundness rounded-l-none"
134
+ @update:modelValue="onPageSizeChange"
135
+ />
136
+ </div>
137
+ </div>
138
+ </template>
@@ -0,0 +1,12 @@
1
+ import type { App, Plugin } from "vue";
2
+ import registerComponent from "@/plugins/register-component";
3
+
4
+ import Pagination from "./Pagination.vue";
5
+
6
+ export default {
7
+ install(app: App) {
8
+ registerComponent(app, Pagination);
9
+ },
10
+ } as Plugin;
11
+
12
+ export { Pagination };
@@ -0,0 +1,14 @@
1
+ <script lang="ts" setup>
2
+ import { Pie } from "vue-chartjs";
3
+
4
+ defineOptions({ name: "TPieChart" });
5
+
6
+ const props = defineProps<{
7
+ data: any;
8
+ options: any;
9
+ }>();
10
+ </script>
11
+
12
+ <template>
13
+ <Pie v-bind="props" />
14
+ </template>
@@ -0,0 +1,12 @@
1
+ import type { App, Plugin } from "vue";
2
+ import registerComponent from "@/plugins/register-component";
3
+
4
+ import PieChart from "./PieChart.vue";
5
+
6
+ export default {
7
+ install(app: App) {
8
+ registerComponent(app, PieChart);
9
+ },
10
+ } as Plugin;
11
+
12
+ export { PieChart };
@@ -0,0 +1,80 @@
1
+ <script lang="ts" setup>
2
+ import { VNodeRef, ref } from "vue";
3
+ import { ElementPosition } from "@/enums/ui";
4
+
5
+ defineOptions({ name: "TPopconfirm" });
6
+
7
+ const props = withDefaults(
8
+ defineProps<{
9
+ title?: string;
10
+ placement?: `${ElementPosition}`;
11
+ }>(),
12
+ {
13
+ title: "",
14
+ placement: ElementPosition.BOTTOM,
15
+ },
16
+ );
17
+
18
+ const emit = defineEmits<{
19
+ (e: "confirm"): void;
20
+ }>();
21
+
22
+ const popoverRef = ref();
23
+
24
+ const setPopoverRef = (popover: VNodeRef | undefined) => {
25
+ popoverRef.value = popover;
26
+
27
+ return popover;
28
+ };
29
+
30
+ const cancel = () => {
31
+ popoverRef.value.visible = false;
32
+ };
33
+
34
+ const onClick = () => {
35
+ popoverRef.value.visible = true;
36
+ };
37
+ </script>
38
+
39
+ <template>
40
+ <t-popover
41
+ :placement="props.placement"
42
+ slot-wrapper-classes="rounded border border-gray-500"
43
+ :disable-style="true"
44
+ :ref="setPopoverRef"
45
+ >
46
+ <slot :onClick="onClick" />
47
+ <template v-slot:content>
48
+ <div
49
+ class="mx-2 my-3 select-none"
50
+ @click="(e) => e.stopPropagation()"
51
+ >
52
+ <p class="text-sm mb-6 flex">
53
+ <t-icon
54
+ icon="info-outline"
55
+ class="text-yellow-700 mr-2"
56
+ size="sm"
57
+ />
58
+ <span>
59
+ {{ props.title }}
60
+ </span>
61
+ </p>
62
+ <div class="flex justify-end">
63
+ <t-button
64
+ variant="warning"
65
+ label="Cancel"
66
+ size="sm"
67
+ class="mr-2"
68
+ @click="cancel"
69
+ />
70
+ <t-button
71
+ variant="primary"
72
+ label="Confirm"
73
+ size="sm"
74
+ @click="emit('confirm')"
75
+ />
76
+ </div>
77
+ </div>
78
+ </template>
79
+ </t-popover>
80
+ </template>
@@ -0,0 +1,12 @@
1
+ import type { App, Plugin } from "vue";
2
+ import registerComponent from "@/plugins/register-component";
3
+
4
+ import Popconfirm from "./Popconfirm.vue";
5
+
6
+ export default {
7
+ install(app: App) {
8
+ registerComponent(app, Popconfirm);
9
+ },
10
+ } as Plugin;
11
+
12
+ export { Popconfirm };
@@ -0,0 +1,133 @@
1
+ <script lang="ts" setup>
2
+ import { ElementPosition, ElementTrigger } from "@/enums/ui";
3
+
4
+ import uiService from "@/services/ui";
5
+ import { createPopper } from "@popperjs/core";
6
+ import { ref, computed, onMounted, onBeforeMount, onBeforeUnmount } from "vue";
7
+
8
+ import EventListener from "@/components/EventListener/EventListener.vue";
9
+
10
+ defineOptions({ name: "TPopover" });
11
+
12
+ const props = withDefaults(
13
+ defineProps<{
14
+ trigger?: `${ElementTrigger}`;
15
+ disabled?: boolean;
16
+ isVisible?: boolean | null;
17
+ placement?: `${ElementPosition}`;
18
+ disableStyle?: boolean;
19
+ slotWrapperClasses?: string;
20
+ }>(),
21
+ {
22
+ trigger: ElementTrigger.CLICK,
23
+ disabled: false,
24
+ isVisible: null,
25
+ placement: ElementPosition.BOTTOM,
26
+ disableStyle: false,
27
+ slotWrapperClasses: "",
28
+ },
29
+ );
30
+
31
+ const visible = ref<boolean>(false);
32
+ const popoverRef = ref<HTMLElement>();
33
+ const wrapperRef = ref<HTMLElement>();
34
+
35
+ const classes = computed<string>(() => {
36
+ return props.slotWrapperClasses;
37
+ });
38
+
39
+ const onTogglePopover = (isVisible: boolean = !visible.value) => {
40
+ visible.value = isVisible;
41
+ };
42
+
43
+ const onGlobalClick = (event: any) => {
44
+ if (
45
+ wrapperRef.value &&
46
+ uiService.wasClickOutsideOfContainer(event, wrapperRef.value)
47
+ ) {
48
+ visible.value = false;
49
+
50
+ return false;
51
+ }
52
+
53
+ return true;
54
+ };
55
+
56
+ onBeforeMount(() => {
57
+ document.addEventListener("click", onGlobalClick);
58
+ });
59
+
60
+ /**
61
+ * Get the first element inside the default slot that has the aria-describedby=tooltip
62
+ */
63
+ onMounted(() => {
64
+ if (!wrapperRef.value || !popoverRef.value) {
65
+ return;
66
+ }
67
+
68
+ let parent: HTMLElement | undefined = undefined;
69
+
70
+ for (const node of wrapperRef.value.childNodes.values()) {
71
+ if (
72
+ "hasAttribute" in node &&
73
+ (node as Element).hasAttribute("aria-describedby") &&
74
+ (node as Element).getAttribute("aria-describedby") === "tooltip"
75
+ ) {
76
+ parent = node as HTMLElement;
77
+
78
+ break;
79
+ }
80
+ }
81
+
82
+ if (!parent) {
83
+ console.error(
84
+ '[caipira-cloud-ui]: Popover activator not found (aria-describedby="tooltip")',
85
+ );
86
+
87
+ return;
88
+ }
89
+
90
+ createPopper(parent, popoverRef.value, {
91
+ placement: props.placement,
92
+ strategy: "fixed",
93
+ });
94
+ });
95
+
96
+ onBeforeUnmount(() => {
97
+ document.removeEventListener("click", onGlobalClick);
98
+ });
99
+
100
+ defineExpose({ visible });
101
+ </script>
102
+
103
+ <template>
104
+ <div
105
+ ref="wrapperRef"
106
+ class="inline"
107
+ >
108
+ <event-listener
109
+ v-if="$slots.default"
110
+ @popover-click="onTogglePopover"
111
+ >
112
+ <slot />
113
+ </event-listener>
114
+ <div
115
+ v-if="!props.disabled"
116
+ ref="popoverRef"
117
+ role="tooltip"
118
+ class="shadow bg-caipira-primary border-color z-10"
119
+ :class="{
120
+ hidden:
121
+ (props.isVisible !== null && props.isVisible === false) ||
122
+ (props.isVisible === null && visible === false),
123
+ 'rounded-lg': !props.disableStyle,
124
+ [classes]: true,
125
+ }"
126
+ >
127
+ <slot
128
+ name="content"
129
+ v-bind="{ onTogglePopover }"
130
+ />
131
+ </div>
132
+ </div>
133
+ </template>
@@ -0,0 +1,12 @@
1
+ import type { App, Plugin } from "vue";
2
+ import registerComponent from "@/plugins/register-component";
3
+
4
+ import Popover from "./Popover.vue";
5
+
6
+ export default {
7
+ install(app: App) {
8
+ registerComponent(app, Popover);
9
+ },
10
+ } as Plugin;
11
+
12
+ export { Popover };
@@ -0,0 +1,31 @@
1
+ const story = {
2
+ title: "Progress/Circle",
3
+ };
4
+
5
+ const Template = (args: any) => ({
6
+ setup() {
7
+ return { args };
8
+ },
9
+ template: `
10
+ <t-progress-circle
11
+ :value="value"
12
+ :width="width"
13
+ :strokeWidth="strokeWidth"
14
+ :strokeColor="strokeColor"
15
+ :backgroundColor="backgroundColor"
16
+ >
17
+ <span class="text-2xl">{{ value }}%</span>
18
+ </t-progress-circle>
19
+ `,
20
+ });
21
+
22
+ const defaultArgs: any = {
23
+ value: 75,
24
+ width: 100,
25
+ strokeWidth: 13,
26
+ };
27
+
28
+ const Default: any = Template.bind({});
29
+ Default.args = { ...defaultArgs };
30
+
31
+ export { story as default, Default };
@@ -0,0 +1,82 @@
1
+ <script lang="ts" setup>
2
+ import { computed } from "vue";
3
+
4
+ defineOptions({ name: "TProgressCircle" });
5
+
6
+ const props = withDefaults(
7
+ defineProps<{
8
+ value?: number;
9
+ width?: number;
10
+ strokeWidth?: number;
11
+ strokeColor?: string;
12
+ backgroundColor?: string;
13
+ }>(),
14
+ {
15
+ value: 0,
16
+ width: 90,
17
+ strokeWidth: 1,
18
+ strokeColor: "var(--caipira-blue)",
19
+ backgroundColor: "var(--caipira-tertiary)",
20
+ },
21
+ );
22
+
23
+ const radius = 90;
24
+
25
+ const dashOffset = computed(() => {
26
+ const c = Math.PI * (radius * 2);
27
+ let value = props.value;
28
+
29
+ if (props.value < 0) {
30
+ value = 0;
31
+ }
32
+
33
+ if (props.value > 100) {
34
+ value = 100;
35
+ }
36
+
37
+ return ((100 - value) / 100) * c;
38
+ });
39
+ </script>
40
+
41
+ <style scoped>
42
+ svg circle {
43
+ transition: stroke-dashoffset 1s linear;
44
+ }
45
+ </style>
46
+
47
+ <template>
48
+ <div class="relative w-min">
49
+ <svg
50
+ viewBox="0 0 200 200"
51
+ :width="props.width"
52
+ :heigh="props.width"
53
+ >
54
+ <circle
55
+ cy="100"
56
+ cx="100"
57
+ fill="transparent"
58
+ stroke-dasharray="565.48"
59
+ :r="radius"
60
+ :stroke-width="props.strokeWidth"
61
+ :stroke="props.backgroundColor"
62
+ stroke-dashoffset="0"
63
+ />
64
+ <circle
65
+ cy="100"
66
+ cx="100"
67
+ fill="transparent"
68
+ stroke-dasharray="565.48"
69
+ :r="radius"
70
+ :stroke-width="props.strokeWidth"
71
+ :stroke="props.strokeColor"
72
+ :stroke-dashoffset="dashOffset"
73
+ />
74
+ </svg>
75
+ <div
76
+ v-if="$slots.default"
77
+ class="absolute transform -translate-x-1/2 -translate-y-1/2 top-2/4 left-2/4"
78
+ >
79
+ <slot />
80
+ </div>
81
+ </div>
82
+ </template>
@@ -0,0 +1,12 @@
1
+ import type { App, Plugin } from "vue";
2
+ import registerComponent from "@/plugins/register-component";
3
+
4
+ import ProgressCircle from "./ProgressCircle.vue";
5
+
6
+ export default {
7
+ install(app: App) {
8
+ registerComponent(app, ProgressCircle);
9
+ },
10
+ } as Plugin;
11
+
12
+ export { ProgressCircle };
@@ -0,0 +1,27 @@
1
+ const story = {
2
+ title: "Progress/Line",
3
+ };
4
+
5
+ const Template = (args: any) => ({
6
+ setup() {
7
+ return { args };
8
+ },
9
+ template: `
10
+ <div class="w-96">
11
+ <c-progress-line
12
+ :value="value"
13
+ :height="height"
14
+ />
15
+ </div>
16
+ `,
17
+ });
18
+
19
+ const defaultArgs: any = {
20
+ value: 25,
21
+ height: 5,
22
+ };
23
+
24
+ const Default: any = Template.bind({});
25
+ Default.args = { ...defaultArgs };
26
+
27
+ export { story as default, Default };
@@ -0,0 +1,104 @@
1
+ <script lang="ts" setup>
2
+ import { computed, ref, watch } from "vue";
3
+
4
+ defineOptions({ name: "TProgressLine" });
5
+
6
+ const props = withDefaults(
7
+ defineProps<{
8
+ value?: number;
9
+ height?: number;
10
+ borderRadius?: number;
11
+ showPercentage?: boolean;
12
+
13
+ // CSS classes
14
+ svgClass?: string;
15
+ labelClass?: string;
16
+
17
+ // Colors
18
+ overColor?: string;
19
+ progressColor?: string;
20
+ finishedColor?: string;
21
+ backgroundColor?: string;
22
+ }>(),
23
+ {
24
+ value: 0,
25
+ height: 10,
26
+ borderRadius: 2,
27
+ showPercentage: true,
28
+
29
+ // Colors
30
+ overColor: "#f38ba8",
31
+ progressColor: "#89b4fa",
32
+ finishedColor: "#a6e3a1",
33
+ backgroundColor: "var(--caipira-tertiary)",
34
+ },
35
+ );
36
+
37
+ const percentage = ref<number>(0);
38
+
39
+ watch(
40
+ () => props.value,
41
+ (value: number) => {
42
+ if (value) {
43
+ percentage.value = Math.round(value);
44
+ }
45
+ },
46
+ { immediate: true },
47
+ );
48
+
49
+ const fillColor = computed<string>(() => {
50
+ if (percentage.value === 100) {
51
+ return props.finishedColor;
52
+ } else if (percentage.value > 100) {
53
+ return props.overColor;
54
+ }
55
+
56
+ return props.progressColor;
57
+ });
58
+ </script>
59
+
60
+ <template>
61
+ <div class="flex items-center">
62
+ <svg
63
+ width="100%"
64
+ :height="props.height"
65
+ class="inline-block flex-grow"
66
+ :class="props.svgClass"
67
+ >
68
+ <rect
69
+ width="100%"
70
+ height="100%"
71
+ :rx="props.borderRadius"
72
+ :fill="props.backgroundColor"
73
+ />
74
+ <rect
75
+ height="100%"
76
+ :width="`${props.value}%`"
77
+ :rx="props.borderRadius"
78
+ :fill="fillColor"
79
+ />
80
+ </svg>
81
+ <div
82
+ v-if="props.showPercentage"
83
+ class="flex-none ml-2"
84
+ :class="labelClass"
85
+ >
86
+ <slot
87
+ v-if="$slots.label"
88
+ name="label"
89
+ />
90
+ <span
91
+ v-else
92
+ class="text-sm"
93
+ >
94
+ {{ percentage }}%
95
+ </span>
96
+ </div>
97
+ </div>
98
+ </template>
99
+
100
+ <style scoped>
101
+ svg rect {
102
+ transition: width 0.3s linear;
103
+ }
104
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { App, Plugin } from "vue";
2
+ import registerComponent from "@/plugins/register-component";
3
+
4
+ import ProgressLine from "./ProgressLine.vue";
5
+
6
+ export default {
7
+ install(app: App) {
8
+ registerComponent(app, ProgressLine);
9
+ },
10
+ } as Plugin;
11
+
12
+ export { ProgressLine };