@ramathibodi/nuxt-commons 0.0.9 → 0.1.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 (32) hide show
  1. package/README.md +6 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +14 -9
  4. package/dist/runtime/components/ExportCSV.vue +4 -4
  5. package/dist/runtime/components/FileBtn.vue +10 -4
  6. package/dist/runtime/components/ImportCSV.vue +7 -4
  7. package/dist/runtime/components/SplitterPanel.vue +12 -22
  8. package/dist/runtime/components/document/TemplateBuilder.vue +217 -0
  9. package/dist/runtime/components/form/Dialog.vue +138 -0
  10. package/dist/runtime/components/form/Hidden.vue +32 -0
  11. package/dist/runtime/components/form/Pad.vue +18 -6
  12. package/dist/runtime/components/form/Table.vue +264 -0
  13. package/dist/runtime/components/master/Autocomplete.vue +159 -0
  14. package/dist/runtime/composables/api.d.ts +9 -0
  15. package/dist/runtime/composables/api.mjs +64 -0
  16. package/dist/runtime/composables/document/template.d.ts +2 -0
  17. package/dist/runtime/composables/document/template.mjs +104 -0
  18. package/dist/runtime/composables/graphql.d.ts +17 -0
  19. package/dist/runtime/composables/graphql.mjs +61 -0
  20. package/dist/runtime/composables/menu.d.ts +19 -0
  21. package/dist/runtime/composables/menu.mjs +60 -0
  22. package/dist/runtime/composables/utils/fuzzy.d.ts +2 -0
  23. package/dist/runtime/composables/utils/fuzzy.mjs +19 -0
  24. package/dist/runtime/composables/utils/validation.d.ts +2 -2
  25. package/dist/runtime/composables/utils/validation.mjs +2 -2
  26. package/dist/runtime/labs/form/TextFieldMask.vue +5 -5
  27. package/dist/runtime/plugins/permission.d.ts +2 -0
  28. package/dist/runtime/plugins/permission.mjs +23 -0
  29. package/dist/runtime/types/menu.d.ts +15 -0
  30. package/package.json +6 -3
  31. /package/dist/runtime/components/{Pdf → pdf}/Print.vue +0 -0
  32. /package/dist/runtime/components/{Pdf → pdf}/View.vue +0 -0
@@ -0,0 +1,19 @@
1
+ import { type InjectionKey, type ComputedRef, type Ref } from 'vue';
2
+ import { type RouteRecordNormalized, type RouteRecordRaw } from 'vue-router';
3
+ export interface MenuItem {
4
+ title: string;
5
+ icon: string;
6
+ role: string;
7
+ link: any;
8
+ menuItems: Array<MenuItem>;
9
+ active: boolean;
10
+ name: string;
11
+ }
12
+ export interface MenuProvide {
13
+ menuAll: Ref<MenuItem[]>;
14
+ menuByRoute: ComputedRef<MenuItem[]>;
15
+ }
16
+ export declare const MenuKey: InjectionKey<MenuProvide>;
17
+ export declare function routeToMenuItem(route: RouteRecordRaw | RouteRecordNormalized): MenuItem | undefined;
18
+ export declare function createMenu(): void;
19
+ export declare function useMenu(): MenuProvide | null;
@@ -0,0 +1,60 @@
1
+ import { inject, provide, ref, computed } from "vue";
2
+ import { useRoute, useRouter } from "vue-router";
3
+ import { isUndefined } from "lodash-es";
4
+ export const MenuKey = Symbol.for("ramacare:menu");
5
+ export function routeToMenuItem(route) {
6
+ let menuItem = void 0;
7
+ if (!isUndefined(route.meta) && !isUndefined(route.meta?.menuItem)) {
8
+ const menuMeta = route.meta?.menuItem;
9
+ menuItem = {
10
+ title: menuMeta.title,
11
+ icon: menuMeta.icon,
12
+ role: menuMeta.role,
13
+ name: route.name,
14
+ menuItems: [],
15
+ link: {
16
+ name: route.name
17
+ },
18
+ active: true
19
+ };
20
+ if (route.children) {
21
+ const menuItems = new Array();
22
+ for (const children of route.children) {
23
+ const childMenuItem = routeToMenuItem(children);
24
+ if (childMenuItem)
25
+ menuItems.push(childMenuItem);
26
+ menuItem.menuItems = menuItems;
27
+ }
28
+ }
29
+ }
30
+ return menuItem;
31
+ }
32
+ export function createMenu() {
33
+ const menuAll = ref([]);
34
+ const routes = useRouter().getRoutes();
35
+ for (const route of routes) {
36
+ const paths = route.path.split("/");
37
+ if (paths.length == 2) {
38
+ if (route.path != "/login" && route.path != "/") {
39
+ const menuItem = routeToMenuItem(route);
40
+ if (menuItem)
41
+ menuAll.value.push(menuItem);
42
+ }
43
+ }
44
+ }
45
+ provide(MenuKey, {
46
+ menuByRoute: computed(() => {
47
+ const route = useRoute();
48
+ for (const menuItem of menuAll.value) {
49
+ if (menuItem.name == route.path.split("/")[1]) {
50
+ return menuItem.menuItems;
51
+ }
52
+ }
53
+ return [];
54
+ }),
55
+ menuAll
56
+ });
57
+ }
58
+ export function useMenu() {
59
+ return inject(MenuKey, null);
60
+ }
@@ -0,0 +1,2 @@
1
+ import type { MaybeRefOrGetter } from 'vue';
2
+ export declare function useFuzzy(searchTerm: MaybeRefOrGetter<string>, items: MaybeRefOrGetter<any[]>, fieldName: MaybeRefOrGetter<string[]>, options?: MaybeRefOrGetter<Record<string, any>>): import("vue").ComputedRef<import("fuse.js").default.FuseResult<any>[]>;
@@ -0,0 +1,19 @@
1
+ import { useFuse } from "@vueuse/integrations/useFuse";
2
+ import { computed, toValue } from "vue";
3
+ export function useFuzzy(searchTerm, items, fieldName, options) {
4
+ const useFuzeOptions = computed(() => {
5
+ const optionsValue = toValue(options);
6
+ const fieldNameValue = toValue(fieldName);
7
+ return {
8
+ fuseOptions: {
9
+ keys: fieldNameValue,
10
+ isCaseSensitive: optionsValue?.isCaseSensitive ?? false,
11
+ threshold: optionsValue?.threshold ?? 0.5
12
+ },
13
+ resultLimit: optionsValue?.resultLimit ?? 20,
14
+ matchAllWhenSearchEmpty: optionsValue?.matchAllWhenSearchEmpty ?? false
15
+ };
16
+ });
17
+ const { results } = useFuse(searchTerm, items, useFuzeOptions);
18
+ return results;
19
+ }
@@ -12,7 +12,7 @@ export declare function useRules(): {
12
12
  lengthLess: (length: number, customError?: string) => (value: any) => string | true;
13
13
  telephone: (customError?: string) => (value: any) => string | true;
14
14
  email: (customError?: string) => (value: any) => string | true;
15
- regex: (regex: string, customError?: string) => (value: any) => string | true;
15
+ regex: (regex: RegExp | string, customError?: string) => (value: any) => string | true;
16
16
  idcard: (customError?: string) => (value: any) => string | true;
17
17
  rules: import("vue").Ref<{
18
18
  require: (customError?: string) => (value: any) => string | true;
@@ -28,7 +28,7 @@ export declare function useRules(): {
28
28
  lengthLess: (length: number, customError?: string) => (value: any) => string | true;
29
29
  telephone: (customError?: string) => (value: any) => string | true;
30
30
  email: (customError?: string) => (value: any) => string | true;
31
- regex: (regex: string, customError?: string) => (value: any) => string | true;
31
+ regex: (regex: RegExp | string, customError?: string) => (value: any) => string | true;
32
32
  idcard: (customError?: string) => (value: any) => string | true;
33
33
  }>;
34
34
  };
@@ -13,8 +13,8 @@ export function useRules() {
13
13
  const length = (length2, customError = `Length must be ${length2}`) => (value) => condition(!value || value.length == length2, customError);
14
14
  const lengthGreater = (length2, customError = `Length must be greater than ${length2}`) => (value) => condition(!value || value.length >= length2, customError);
15
15
  const lengthLess = (length2, customError = `Length must be less than ${length2}`) => (value) => condition(!value || value.length <= length2, customError);
16
- const telephone = (customError = "Invalid telephone number") => (value) => condition(!value || /^(?:\s*(?:0[23457][0-9]{7}|0[689][0-9]{8})(?:#[0-9]{1,5})?\s*(?:\([^()]+\))?\s*(?:,(?=.+))?)*$/.test(value), customError);
17
- const email = (customError = "Invalid email address") => (value) => condition(!value || /^([a-zA-Z0-9_\-.]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,5})$/.test(value), customError);
16
+ const telephone = (customError = "Invalid telephone number") => (value) => condition(!value || /^(?:\s*(?:0[2-57]\d{7}|0[689]\d{8})(?:#\d{1,5})?\s*(?:\([^()]+\)\s*)?(?:,(?=.+))?)*$/.test(value), customError);
17
+ const email = (customError = "Invalid email address") => (value) => condition(!value || /^([\w\-.]+)@([\w\-.]+)\.([a-z]{2,5})$/i.test(value), customError);
18
18
  const regex = (regex2, customError = "Invalid format") => (value) => condition(!value || new RegExp(regex2).test(value), customError);
19
19
  const idcard = (customError = "Invalid idcard") => (value) => condition(/^\d{13}$/.test(value) && (11 - [...value].slice(0, 12).reduce((sum, n, i) => sum + +n * (13 - i), 0) % 11) % 10 === +value[12], customError);
20
20
  const rules = ref({
@@ -13,7 +13,7 @@ const emit = defineEmits<{
13
13
  }>()
14
14
 
15
15
  const computedMaskOption = computed<MaskOptions>(() => {
16
- if (props.type == 'eReceipt') return { mask: '##-##-N', tokens: { N: { pattern: /[0-9]/, multiple: true } } }
16
+ if (props.type == 'eReceipt') return { mask: '##-##-N', tokens: { N: { pattern: /\d/, multiple: true } } }
17
17
  if (props.type == 'telephone') return { mask: '###-###-####' }
18
18
  return {}
19
19
  })
@@ -30,13 +30,13 @@ function onMaska(event: CustomEvent<MaskaDetail>) {
30
30
  @maska="onMaska"
31
31
  >
32
32
  <template
33
- v-for="(_, slot, index) in ($slots as {})"
33
+ v-for="(_, name, index) in ($slots as {})"
34
34
  :key="index"
35
- #[slot]="scope"
35
+ #[name]="slotData"
36
36
  >
37
37
  <slot
38
- :name="slot"
39
- v-bind="{ scope }"
38
+ :name="name"
39
+ v-bind="(slotData as object)"
40
40
  />
41
41
  </template>
42
42
  </v-text-field>
@@ -0,0 +1,2 @@
1
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -0,0 +1,23 @@
1
+ import { defineNuxtPlugin } from "nuxt/app";
2
+ import { useAuthentication } from "#imports";
3
+ export default defineNuxtPlugin(async (nuxtApp) => {
4
+ function permission(permissionId) {
5
+ if (!permissionId || useAuthentication()?.hasPermission(permissionId) === void 0)
6
+ return true;
7
+ return useAuthentication()?.hasPermission(permissionId);
8
+ }
9
+ nuxtApp.vueApp.config.globalProperties.$permission = permission;
10
+ nuxtApp.vueApp.directive("permission", (el, binding, vnode) => {
11
+ if (!permission(binding.value)) {
12
+ if (vnode) {
13
+ if (vnode.um?.length) {
14
+ vnode.um.forEach((um) => {
15
+ um();
16
+ });
17
+ }
18
+ if (el.parentElement)
19
+ el.parentElement.removeChild(el);
20
+ }
21
+ }
22
+ });
23
+ });
@@ -0,0 +1,15 @@
1
+ declare module '#app' {
2
+ interface PageMeta {
3
+ menuItem?: MenuMeta
4
+ }
5
+ }
6
+
7
+ declare global {
8
+ interface MenuMeta {
9
+ title: string
10
+ icon: string
11
+ role: string
12
+ }
13
+ }
14
+
15
+ export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ramathibodi/nuxt-commons",
3
- "version": "0.0.9",
3
+ "version": "0.1.0",
4
4
  "description": "Ramathibodi Nuxt modules for common components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,8 +19,8 @@
19
19
  "import": "./dist/runtime/utils/*.mjs",
20
20
  "require": "./dist/runtime/utils/*.cjs"
21
21
  },
22
- "./lab/*" : "./dist/runtime/labs/*.vue",
23
- "./lab/*/*" : "./dist/runtime/labs/*/*.vue"
22
+ "./lab/*": "./dist/runtime/labs/*.vue",
23
+ "./lab/*/*": "./dist/runtime/labs/*/*.vue"
24
24
  },
25
25
  "main": "./dist/module.cjs",
26
26
  "types": "./dist/types.d.ts",
@@ -52,9 +52,11 @@
52
52
  "@nuxtjs/apollo": "5.0.0-alpha.14",
53
53
  "@vue/apollo-composable": "^4.0.2",
54
54
  "@vuepic/vue-datepicker": "^7.4.1",
55
+ "@vueuse/integrations": "^10.10.0",
55
56
  "@zxing/browser": "^0.1.4",
56
57
  "cropperjs": "^1.6.2",
57
58
  "currency.js": "^2.0.4",
59
+ "fuse.js": "^6.6.2",
58
60
  "gql-query-builder": "^3.8.0",
59
61
  "lodash": "^4.17.21",
60
62
  "luxon": "^3.4.4",
@@ -82,6 +84,7 @@
82
84
  "eslint": "^9.1.1",
83
85
  "nuxt": "^3.11.2",
84
86
  "nuxt-lodash": "^2.5.3",
87
+ "prettier": "3.3.2",
85
88
  "sass": "^1.75.0",
86
89
  "typescript": "^5.4.5",
87
90
  "vitest": "^1.5.1",
File without changes
File without changes