create-nuxt-base 0.1.23 → 0.2.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 (74) hide show
  1. package/.eslintignore +14 -0
  2. package/.eslintrc +3 -0
  3. package/.github/workflows/release.yml +1 -1
  4. package/.prettierignore +5 -0
  5. package/.prettierrc +6 -0
  6. package/.vscode/settings.json +10 -10
  7. package/CHANGELOG.md +22 -33
  8. package/README.md +1 -0
  9. package/index.js +30 -29
  10. package/nuxt-base-template/.env.example +8 -0
  11. package/nuxt-base-template/.eslintrc +1 -1
  12. package/nuxt-base-template/.vscode/settings.json +6 -16
  13. package/nuxt-base-template/e2e/init.spec.ts +18 -0
  14. package/nuxt-base-template/nuxt.config.ts +27 -12
  15. package/nuxt-base-template/package-lock.json +6050 -4606
  16. package/nuxt-base-template/package.json +47 -29
  17. package/nuxt-base-template/playwright.config.ts +77 -0
  18. package/nuxt-base-template/src/app.vue +4 -4
  19. package/nuxt-base-template/src/assets/css/tailwind.css +42 -33
  20. package/nuxt-base-template/src/components/SocialMediaBubble.vue +1 -1
  21. package/nuxt-base-template/src/components/base/BaseAccordion.vue +16 -13
  22. package/nuxt-base-template/src/components/base/BaseButton.vue +10 -13
  23. package/nuxt-base-template/src/components/base/BaseContainer.vue +1 -1
  24. package/nuxt-base-template/src/components/base/BaseContextMenuContainer.vue +61 -0
  25. package/nuxt-base-template/src/components/base/BaseInfinityList.vue +1 -1
  26. package/nuxt-base-template/src/components/base/BaseProgressbar.vue +28 -30
  27. package/nuxt-base-template/src/components/base/BaseToggle.vue +17 -10
  28. package/nuxt-base-template/src/components/form/FormInput.vue +34 -0
  29. package/nuxt-base-template/src/components/form/FormPassword.vue +47 -0
  30. package/nuxt-base-template/src/components/form/FormSelect.vue +40 -0
  31. package/nuxt-base-template/src/components/form/FormSubmit.vue +18 -0
  32. package/nuxt-base-template/src/components/form/FormTextarea.vue +36 -0
  33. package/nuxt-base-template/src/components/form/FormToggle.vue +27 -0
  34. package/nuxt-base-template/src/components/modal/Modal.vue +48 -0
  35. package/nuxt-base-template/src/components/modal/ModalConfirm.vue +38 -0
  36. package/nuxt-base-template/src/components/{base/BaseModalContainer.vue → modal/ModalContainer.vue} +1 -1
  37. package/nuxt-base-template/src/components/modal/ModalInfo.vue +22 -0
  38. package/nuxt-base-template/src/components/{ModalShare.vue → modal/ModalShare.vue} +7 -11
  39. package/nuxt-base-template/src/components/{base/BaseNotification.vue → notification/Notification.vue} +8 -7
  40. package/nuxt-base-template/src/components/{base/BaseNotificationContainer.vue → notification/NotificationContainer.vue} +11 -5
  41. package/nuxt-base-template/src/components/pwa/pwa-install-banner.vue +224 -0
  42. package/nuxt-base-template/src/components/transition/TransitionFade.vue +10 -7
  43. package/nuxt-base-template/src/components/transition/TransitionFadeScale.vue +10 -7
  44. package/nuxt-base-template/src/composables/use-auth-fetch.ts +22 -8
  45. package/nuxt-base-template/src/composables/use-context-menu.ts +19 -0
  46. package/nuxt-base-template/src/composables/use-file.ts +1 -2
  47. package/nuxt-base-template/src/composables/use-modal.ts +1 -1
  48. package/nuxt-base-template/src/composables/use-notification.ts +2 -2
  49. package/nuxt-base-template/src/composables/use-share.ts +3 -3
  50. package/nuxt-base-template/src/error.vue +10 -14
  51. package/nuxt-base-template/src/layouts/default.vue +13 -0
  52. package/nuxt-base-template/src/middleware/auth.global.ts +2 -2
  53. package/nuxt-base-template/src/pages/index.vue +31 -6
  54. package/nuxt-base-template/src/plugins/auth.server.ts +72 -0
  55. package/nuxt-base-template/src/plugins/form.plugin.ts +21 -0
  56. package/nuxt-base-template/src/plugins/pwa.plugin.ts +110 -0
  57. package/nuxt-base-template/src/tests/init.test.ts +1 -1
  58. package/nuxt-base-template/tailwind.config.js +33 -23
  59. package/nuxt-base-template/vitest.config.js +3 -3
  60. package/package.json +3 -1
  61. package/nuxt-base-template/formkit-theme.js +0 -137
  62. package/nuxt-base-template/formkit.config.js +0 -33
  63. package/nuxt-base-template/src/components/hello-world.vue +0 -10
  64. package/nuxt-base-template/src/composables/use-form-helper.ts +0 -100
  65. package/nuxt-base-template/src/composables/use-helper.ts +0 -52
  66. package/nuxt-base-template/src/forms/inputs/InputCheckbox.vue +0 -29
  67. package/nuxt-base-template/src/forms/inputs/InputFreeTags.vue +0 -98
  68. package/nuxt-base-template/src/forms/inputs/InputImage.vue +0 -65
  69. package/nuxt-base-template/src/forms/inputs/InputTags.vue +0 -112
  70. package/nuxt-base-template/src/forms/inputs/InputToggle.vue +0 -18
  71. package/nuxt-base-template/src/forms/plugins/asterisk-plugin.ts +0 -29
  72. package/nuxt-base-template/src/forms/plugins/scroll-error-plugin.ts +0 -36
  73. package/nuxt-base-template/src/forms/plugins/value-changes-plugin.ts +0 -13
  74. package/nuxt-base-template/src/plugins/4.auth.server.ts +0 -70
@@ -1,11 +1,14 @@
1
1
  <script setup lang="ts">
2
- const props = withDefaults(defineProps<{
3
- startDuration?: number | `${number}`;
4
- leaveDuration?: number | `${number}`;
5
- }>(), {
6
- startDuration: 100,
7
- leaveDuration: 100,
8
- });
2
+ const props = withDefaults(
3
+ defineProps<{
4
+ startDuration?: number | `${number}`;
5
+ leaveDuration?: number | `${number}`;
6
+ }>(),
7
+ {
8
+ startDuration: 100,
9
+ leaveDuration: 100,
10
+ }
11
+ );
9
12
  </script>
10
13
 
11
14
  <template>
@@ -1,19 +1,33 @@
1
1
  import type { ExtractedRouteMethod, NitroFetchOptions, NitroFetchRequest, TypedInternalResponse } from 'nitropack';
2
2
 
3
- export function useAuthFetch<DefaultT = unknown, DefaultR extends NitroFetchRequest = NitroFetchRequest, T = DefaultT, R extends NitroFetchRequest = DefaultR, O extends NitroFetchOptions<R> = NitroFetchOptions<R>>(request: R, opts?: O): Promise<TypedInternalResponse<R, T, ExtractedRouteMethod<R, O>>> {
3
+ export function useAuthFetch<
4
+ DefaultT = unknown,
5
+ DefaultR extends NitroFetchRequest = NitroFetchRequest,
6
+ T = DefaultT,
7
+ R extends NitroFetchRequest = DefaultR,
8
+ O extends NitroFetchOptions<R> = NitroFetchOptions<R>
9
+ >(request: R, opts?: O): Promise<TypedInternalResponse<R, T, ExtractedRouteMethod<R, O>>> {
4
10
  const { requestNewToken } = useAuth();
11
+ const { accessTokenState } = useAuthState();
5
12
  const config = useRuntimeConfig();
6
13
 
7
14
  // @ts-expect-error - because of nice types from ofetch <3
8
15
  return $fetch(request, {
9
16
  ...opts,
10
17
  baseURL: config.public.apiUrl,
11
- retry: 3,
12
- async onRequest({ request, options }) {
13
- const { token } = await requestNewToken();
14
- options.headers = {
15
- 'Authorization': 'Bearer ' + token,
16
- };
18
+ async onRequest(data: any) {
19
+ if (accessTokenState.value) {
20
+ data.options.headers = {
21
+ ...data.options.headers,
22
+ Authorization: `Bearer ${accessTokenState.value}`,
23
+ };
24
+ }
25
+ },
26
+ onResponseError: async () => {
27
+ await requestNewToken();
17
28
  },
29
+ retry: 3,
30
+ retryDelay: 500,
31
+ retryStatusCodes: [401],
18
32
  });
19
- }
33
+ }
@@ -0,0 +1,19 @@
1
+ const contextMenuState = <T>() => useState<any | null>(() => null);
2
+
3
+ export function useContextMenu<T = object>() {
4
+ const menu = contextMenuState<T>();
5
+
6
+ const open = (config: { items: any[] }) => {
7
+ menu.value = Object.assign(config, { show: true });
8
+ };
9
+
10
+ const close = () => {
11
+ menu.value = null;
12
+ };
13
+
14
+ return {
15
+ activeMenu: menu,
16
+ close,
17
+ open,
18
+ };
19
+ }
@@ -1,5 +1,4 @@
1
1
  import { useFetch } from '@vueuse/core';
2
- import { useHelper } from '~/composables/use-helper';
3
2
 
4
3
  export function useFile() {
5
4
  const { isValidMongoID } = useHelper();
@@ -18,4 +17,4 @@ export function useFile() {
18
17
  }
19
18
 
20
19
  return { getFileInfo };
21
- }
20
+ }
@@ -81,4 +81,4 @@ export function useModal<T = object>() {
81
81
  open,
82
82
  close,
83
83
  };
84
- }
84
+ }
@@ -18,7 +18,7 @@ export function useNotification() {
18
18
  };
19
19
 
20
20
  const remove = (uuid: string) => {
21
- notifications.value = notifications.value.filter(n => n.uuid !== uuid);
21
+ notifications.value = notifications.value.filter((n) => n.uuid !== uuid);
22
22
  };
23
23
 
24
24
  return {
@@ -26,4 +26,4 @@ export function useNotification() {
26
26
  remove,
27
27
  notifications,
28
28
  };
29
- }
29
+ }
@@ -1,5 +1,5 @@
1
- import { ModalShare } from '#components';
2
1
  import { useModal } from '~/composables/use-modal';
2
+ import ModalShare from '~/components/ModalShare.vue';
3
3
 
4
4
  export function useShare() {
5
5
  const route = useRoute();
@@ -12,11 +12,11 @@ export function useShare() {
12
12
  text: text ?? window.location.origin,
13
13
  });
14
14
  } else {
15
- useModal().open({ component: ModalShare, size: 'md', data: { link: url ?? window.location.origin } });
15
+ useModal().open({ component: ModalShare, size: 'md', data: { link: url ?? window.location.origin, name: window.name } });
16
16
  }
17
17
  }
18
18
 
19
19
  return {
20
20
  share,
21
21
  };
22
- }
22
+ }
@@ -7,7 +7,8 @@ console.error(props.error);
7
7
  const debugWord = ref<string>('');
8
8
  const { current } = useMagicKeys();
9
9
 
10
- watch(() => current.values(),
10
+ watch(
11
+ () => current.values(),
11
12
  () => {
12
13
  if (current.values().next().value === 'escape') {
13
14
  debugWord.value = '';
@@ -21,7 +22,7 @@ watch(() => current.values(),
21
22
  if (current.values().next().value && !debugWord.value.includes(current.values().next().value)) {
22
23
  debugWord.value += current.values().next().value;
23
24
  }
24
- },
25
+ }
25
26
  );
26
27
 
27
28
  const handleError = () => clearError({ redirect: '/' });
@@ -31,23 +32,18 @@ const handleError = () => clearError({ redirect: '/' });
31
32
  <NuxtLayout>
32
33
  <div class="w-full min-h-screen flex flex-col justify-center items-center">
33
34
  <div class="w-full flex flex-col items-center mb-20">
34
- <h1 class="text-[12rem] font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-primary-600 to-primary-400">
35
- Oops!
36
- </h1>
35
+ <h1 class="text-[12rem] font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-primary-600 to-primary-400">Oops!</h1>
37
36
  <h2 v-if="error?.statusCode" class="text-3xl text-gray-600">
38
37
  {{ error?.statusCode }}
39
38
  </h2>
40
39
  </div>
41
40
 
42
41
  <pre v-if="debugWord === 'debug'" class="w-full max-w-3xl mb-5 mx-auto bg-black/80 text-white font-mono p-2 rounded-lg overflow-x-scroll">
43
- {{
44
- { error }
45
- }}
46
- </pre>
47
-
48
- <BaseButton color="primary" appearance="outline" @click="handleError">
49
- Zurück zur Startseite
50
- </BaseButton>
42
+ {{ { error } }}
43
+ </pre
44
+ >
45
+
46
+ <BaseButton color="primary" appearance="outline" @click="handleError"> Zurück zur Startseite </BaseButton>
51
47
  </div>
52
48
  </NuxtLayout>
53
- </template>
49
+ </template>
@@ -0,0 +1,13 @@
1
+ <script setup lang="ts">
2
+ import { useGlobalMutationLoading, useGlobalQueryLoading } from '@vue/apollo-composable';
3
+
4
+ const queryLoading = useGlobalQueryLoading();
5
+ const mutationLoading = useGlobalMutationLoading();
6
+ </script>
7
+
8
+ <template>
9
+ <div>
10
+ <NuxtLoadingIndicator :loading="queryLoading || mutationLoading" />
11
+ <slot></slot>
12
+ </div>
13
+ </template>
@@ -1,8 +1,8 @@
1
1
  export default defineNuxtRouteMiddleware((to, from) => {
2
- const { accessToken } = useAuthState();
2
+ const { accessTokenState } = useAuthState();
3
3
 
4
4
  if (to.fullPath.startsWith('/app')) {
5
- if (!accessToken?.value) {
5
+ if (!accessTokenState?.value) {
6
6
  return navigateTo('/auth/login');
7
7
  }
8
8
  }
@@ -1,10 +1,35 @@
1
+ <script setup lang="ts">
2
+ import FormTextarea from '~/components/form/FormTextarea.vue';
3
+
4
+ const isSubmitting = ref(false);
5
+ </script>
6
+
1
7
  <template>
2
8
  <div class="flex h-screen items-center justify-center flex-col">
3
- <h1
4
- class="font-extrabold text-transparent text-8xl bg-clip-text bg-gradient-to-r from-purple-400 to-pink-600"
5
- >
6
- Lenne Nuxt Starter
7
- </h1>
8
- <HelloWorld />
9
+ <h1 class="font-extrabold text-transparent text-8xl bg-clip-text bg-gradient-to-r from-purple-400 to-pink-600">Lenne Nuxt Starter</h1>
10
+
11
+ <h2 class="mt-5">DEMO</h2>
12
+ <FormInput name="email" type="email" label="E-Mail" placeholder="max.mustermann@test.de" />
13
+ <FormTextarea name="description" label="Description" placeholder="..." />
14
+ <FormPassword name="password" label="Password" placeholder="Password" />
15
+ <FormSelect
16
+ name="select"
17
+ label="Select"
18
+ placeholder="placeholder"
19
+ :options="[
20
+ { label: 'Option 1', value: 1 },
21
+ { label: 'Option 2', value: 2 },
22
+ { label: 'Option 3', value: 3 },
23
+ ]"
24
+ />
25
+ <FormToggle name="toggle" label="Toggle" />
26
+ <div class="flex items-center gap-3">
27
+ <FormSubmit label="Save" :is-submitting="isSubmitting" @click="isSubmitting = true" />
28
+ <BaseButton size="sm" :loading="isSubmitting" @click="isSubmitting = true">Submit</BaseButton>
29
+ <BaseButton size="lg" :loading="isSubmitting" @click="isSubmitting = true">Submit</BaseButton>
30
+ <BaseButton size="md" :loading="isSubmitting" appearance="outline" @click="isSubmitting = true">Submit</BaseButton>
31
+ <BaseButton size="md" :loading="isSubmitting" appearance="none" @click="isSubmitting = true">Submit</BaseButton>
32
+ <BaseButton size="md" color="danger" @click="isSubmitting = false">Reset</BaseButton>
33
+ </div>
9
34
  </div>
10
35
  </template>
@@ -0,0 +1,72 @@
1
+ import { callWithNuxt, defineNuxtPlugin, useNuxtApp, useRuntimeConfig } from 'nuxt/app';
2
+ import { ofetch } from 'ofetch';
3
+
4
+ export default defineNuxtPlugin({
5
+ enforce: 'post',
6
+ name: 'auth-server',
7
+ async setup() {
8
+ const _nuxt = useNuxtApp();
9
+ const config = await callWithNuxt(_nuxt, useRuntimeConfig);
10
+ const { accessTokenState, currentUserState, refreshTokenState } = await callWithNuxt(_nuxt, useAuthState);
11
+ const { clearSession, getDecodedAccessToken, isTokenExpired, setCurrentUser, setTokens } = await callWithNuxt(_nuxt, useAuth);
12
+ const payload = accessTokenState.value ? getDecodedAccessToken(accessTokenState.value) : null;
13
+
14
+ if (!accessTokenState.value || !refreshTokenState.value || currentUserState.value) {
15
+ return;
16
+ }
17
+
18
+ let token = accessTokenState.value;
19
+ if (isTokenExpired(accessTokenState.value)) {
20
+ const refreshTokenResult = await ofetch(config.public.host, {
21
+ body: JSON.stringify({
22
+ query: 'mutation refreshToken {refreshToken {token, refreshToken}}',
23
+ variables: {},
24
+ }),
25
+ headers: {
26
+ Authorization: `Bearer ${refreshTokenState.value}`,
27
+ },
28
+ method: 'POST',
29
+ }).catch((err) => {
30
+ console.error('2.auth.server.ts::refreshToken::catch', err.data);
31
+ clearSession();
32
+ navigateTo('/auth/login');
33
+ });
34
+
35
+ const data = refreshTokenResult?.data?.refreshToken;
36
+ if (data) {
37
+ setTokens(data.token, data.refreshToken);
38
+ token = data?.token;
39
+ } else {
40
+ clearSession();
41
+ await navigateTo('/auth/login');
42
+ }
43
+ }
44
+
45
+ if (token && payload?.id) {
46
+ const userResult = await ofetch(config.public.host, {
47
+ body: JSON.stringify({
48
+ query: 'query getUser($id: String!){' + 'getUser(id: $id){' + 'id ' + 'avatar ' + 'firstName ' + 'lastName ' + 'email ' + 'gender ' + 'roles ' + '}}',
49
+ variables: {
50
+ id: payload.id,
51
+ },
52
+ }),
53
+ headers: {
54
+ Authorization: `Bearer ${token}`,
55
+ },
56
+ method: 'POST',
57
+ }).catch((err) => {
58
+ console.error('2.auth.server.ts::getUser::catch', err);
59
+ });
60
+
61
+ if (userResult?.errors) {
62
+ clearSession();
63
+ navigateTo('/auth/login');
64
+ return;
65
+ }
66
+
67
+ if (userResult?.data) {
68
+ setCurrentUser(userResult?.data?.getUser);
69
+ }
70
+ }
71
+ },
72
+ });
@@ -0,0 +1,21 @@
1
+ import { setLocale } from 'yup';
2
+
3
+ export default defineNuxtPlugin(async (_nuxtApp) => {
4
+ setLocale({
5
+ // use constant translation keys for messages without values
6
+ mixed: {
7
+ required: 'Dieses Feld ist erforderlich.',
8
+ default: 'Dieses Feld ist ungültig.',
9
+ notType: 'Dieses Feld ist ungültig.',
10
+ },
11
+ string: {
12
+ email: 'Bitte geben Sie eine gültige E-Mail-Adresse ein.',
13
+ },
14
+ });
15
+
16
+ // Custom validation rules
17
+ // https://github.com/jquense/yup?tab=readme-ov-file#addmethodschematype-schema-name-string-method--schema-void
18
+ // addMethod(string, 'plz', () => {
19
+ // return
20
+ // });
21
+ });
@@ -0,0 +1,110 @@
1
+ export default defineNuxtPlugin(async (_nuxtApp) => {
2
+ const applicationServerKey = useRuntimeConfig().public.webPushKey as string;
3
+ const permissionState = ref<PermissionState>('prompt');
4
+ const subscription = ref<PushSubscription | null>(null);
5
+
6
+ if (process.client) {
7
+ const iosPWASplash = (await import('ios-pwa-splash')).default;
8
+ iosPWASplash('/notification.png', '#FFFFFF');
9
+ }
10
+
11
+ async function subscribe() {
12
+ const sw = await navigator.serviceWorker.ready;
13
+ const push = await sw.pushManager.subscribe({
14
+ applicationServerKey,
15
+ userVisibleOnly: true,
16
+ });
17
+ await refreshSubscription();
18
+ await refreshPermissionState();
19
+ const body = {
20
+ payload: push,
21
+ };
22
+ try {
23
+ await useAuthFetch('/web-push/subscribe', {
24
+ baseURL: process.env.API_URL,
25
+ body,
26
+ method: 'POST',
27
+ });
28
+ } catch (error) {}
29
+ }
30
+
31
+ async function refreshPermissionState() {
32
+ try {
33
+ const sw = await navigator.serviceWorker.ready;
34
+ permissionState.value = await sw.pushManager.permissionState({
35
+ applicationServerKey,
36
+ userVisibleOnly: true,
37
+ });
38
+ } catch (error) {
39
+ console.error(error);
40
+ }
41
+ }
42
+
43
+ async function refreshSubscription() {
44
+ try {
45
+ const sw = await navigator.serviceWorker.ready;
46
+ subscription.value = await sw.pushManager.getSubscription();
47
+ } catch (e) {
48
+ console.error(e);
49
+ }
50
+ }
51
+
52
+ async function unsubscribe() {
53
+ if (subscription.value) {
54
+ await subscription.value.unsubscribe();
55
+ const body = {
56
+ payload: subscription.value,
57
+ };
58
+ await refreshPermissionState();
59
+ try {
60
+ await useAuthFetch('/web-push/', {
61
+ baseURL: process.env.API_URL,
62
+ body,
63
+ method: 'DELETE',
64
+ });
65
+ } catch (error) {}
66
+ subscription.value = null;
67
+ }
68
+ }
69
+
70
+ const route = useRoute();
71
+ const pwa = ref(false);
72
+ const isPwa = computed(() => route.query.standalone === 'true' || pwa.value);
73
+
74
+ if (process.client) {
75
+ if (window && window.matchMedia && document && window.matchMedia('(display-mode: standalone)').matches) {
76
+ if (navigator && navigator.serviceWorker) {
77
+ await refreshSubscription();
78
+ await refreshPermissionState();
79
+ }
80
+ pwa.value = true;
81
+ document.body.classList.add('select-none', 'overscroll-y-none', 'no-scrollbar', 'bg-rm-gray-1');
82
+ } else {
83
+ pwa.value = false;
84
+ document.body.classList.remove('select-none', 'overscroll-y-none', 'no-scrollbar', 'bg-rm-gray-1');
85
+ }
86
+ }
87
+
88
+ useHead({
89
+ htmlAttrs: { class: isPwa.value ? 'pwa' : '' },
90
+ meta: [
91
+ {
92
+ content: 'width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no',
93
+ hid: 'viewport',
94
+ name: 'viewport',
95
+ },
96
+ ],
97
+ });
98
+
99
+ return {
100
+ provide: {
101
+ pwa: {
102
+ isPwa: () => isPwa.value,
103
+ permissionState,
104
+ subscribe,
105
+ subscription,
106
+ unsubscribe,
107
+ },
108
+ },
109
+ };
110
+ });
@@ -9,4 +9,4 @@ describe('Initialization', async () => {
9
9
  test('Init test', () => {
10
10
  // ... write tests here
11
11
  });
12
- });
12
+ });
@@ -3,11 +3,10 @@ const defaultTheme = require('tailwindcss/defaultTheme');
3
3
  const { iconsPlugin, getIconCollections } = require('@egoist/tailwindcss-icons');
4
4
  const typography = require('@tailwindcss/typography');
5
5
  const forms = require('@tailwindcss/forms');
6
- const formkit = require('@formkit/themes/tailwindcss');
6
+ const plugin = require('tailwindcss/plugin');
7
7
 
8
8
  module.exports = {
9
- darkMode: "class",
10
- content: ['./formkit-theme.js'],
9
+ darkMode: 'class',
11
10
  theme: {
12
11
  // fontFamily: {
13
12
  // montserrat: ['Montserrat'],
@@ -15,34 +14,45 @@ module.exports = {
15
14
  // serif: ['Work Sans', 'Montserrat', ...defaultTheme.fontFamily.serif],
16
15
  // },
17
16
  extend: {
18
- // colors: {
19
- // primary: {
20
- // DEFAULT: '#57B39A',
21
- // 50: '#f3faf7',
22
- // 100: '#d6f1e7',
23
- // 200: '#ade2d0',
24
- // 300: '#7cccb3',
25
- // 400: '#57b39a',
26
- // 500: '#37957d',
27
- // 600: '#2a7765',
28
- // 700: '#256052',
29
- // 800: '#224d45',
30
- // 900: '#20413a',
31
- // 950: '#0d2621',
32
- // },
33
- // }
17
+ colors: {
18
+ primary: {
19
+ DEFAULT: '#57B39A',
20
+ 50: '#f3faf7',
21
+ 100: '#d6f1e7',
22
+ 200: '#ade2d0',
23
+ 300: '#7cccb3',
24
+ 400: '#57b39a',
25
+ 500: '#37957d',
26
+ 600: '#2a7765',
27
+ 700: '#256052',
28
+ 800: '#224d45',
29
+ 900: '#20413a',
30
+ 950: '#0d2621',
31
+ },
32
+ background: '#FFFFFF',
33
+ foreground: '#000000',
34
+ border: 'hsl(0 0% 0% / 0.5)',
35
+ hover: 'hsl(0 0% 100% / 0.2)',
36
+ active: 'hsl(0 0% 100% / 0.2)',
37
+ },
34
38
  screens: {
35
- '3xl': '2400px'
36
- }
37
- }
39
+ '3xl': '2400px',
40
+ },
41
+ },
38
42
  },
39
43
  plugins: [
40
44
  typography,
41
- formkit,
42
45
  forms,
43
46
  iconsPlugin({
44
47
  // Select the icon collections you want to use
45
48
  collections: getIconCollections(['bi']),
46
49
  }),
50
+ plugin(({ addVariant, e }) => {
51
+ addVariant('pwa', ({ modifySelectors, separator }) => {
52
+ modifySelectors(({ className }) => {
53
+ return `.pwa .${e(`pwa${separator}${className}`)}`;
54
+ });
55
+ });
56
+ }),
47
57
  ],
48
58
  };
@@ -1,5 +1,5 @@
1
- import vue from '@vitejs/plugin-vue'
2
- import { defineConfig } from 'vite'
1
+ import vue from '@vitejs/plugin-vue';
2
+ import { defineConfig } from 'vite';
3
3
 
4
4
  export default defineConfig({
5
5
  plugins: [vue()],
@@ -7,4 +7,4 @@ export default defineConfig({
7
7
  globals: true,
8
8
  environment: 'jsdom',
9
9
  },
10
- })
10
+ });
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "create-nuxt-base",
3
- "version": "0.1.23",
3
+ "version": "0.2.1",
4
4
  "description": "Starter to generate a configured environment with VueJS, Nuxt, Tailwind, Eslint, @lenne.tech/nuxt-base, Unit Tests, Cypress etc.",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "create-nuxt-base": "./index.js"
8
8
  },
9
9
  "scripts": {
10
+ "prettier": "prettier \"*.{js,json,yml,md,html,ts}\" .",
11
+ "format": "npm run prettier -- --write",
10
12
  "release": "standard-version && git push --follow-tags origin main",
11
13
  "release:minor": "standard-version --release-as minor && git push --follow-tags origin main",
12
14
  "release:major": "standard-version --release-as major && git push --follow-tags origin main"