@dargmuesli/nuxt-vio 2.0.1 → 3.0.0-beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. package/app.config.ts +78 -34
  2. package/components/{VioApp.vue → vio/_/VioApp.vue} +31 -8
  3. package/components/{VioError.vue → vio/_/VioError.vue} +1 -1
  4. package/components/vio/button/VioButtonColored.vue +52 -0
  5. package/components/vio/card/VioCard.vue +19 -0
  6. package/components/vio/card/state/VioCardState.vue +20 -0
  7. package/components/vio/card/state/VioCardStateAlert.vue +14 -0
  8. package/components/vio/form/VioForm.vue +84 -0
  9. package/components/vio/form/VioFormCheckbox.vue +27 -0
  10. package/components/vio/form/input/VioFormInput.vue +192 -0
  11. package/components/vio/form/input/VioFormInputIconWrapper.vue +7 -0
  12. package/components/vio/form/input/VioFormInputUrl.vue +54 -0
  13. package/components/vio/form/input/state/VioFormInputState.vue +5 -0
  14. package/components/vio/form/input/state/VioFormInputStateError.vue +32 -0
  15. package/components/vio/form/input/state/VioFormInputStateInfo.vue +32 -0
  16. package/components/vio/icon/IconArrowRight.vue +31 -0
  17. package/components/vio/icon/IconCalendar.vue +31 -0
  18. package/components/vio/icon/IconChatOutline.vue +27 -0
  19. package/components/vio/icon/IconChatSolid.vue +26 -0
  20. package/components/vio/icon/IconCheckCircle.vue +29 -0
  21. package/components/vio/icon/IconContainer.vue +15 -0
  22. package/components/vio/icon/IconDownload.vue +31 -0
  23. package/components/vio/icon/IconExclamationCircle.vue +29 -0
  24. package/components/vio/icon/IconHome.vue +31 -0
  25. package/components/vio/icon/IconHourglass.vue +32 -0
  26. package/components/vio/icon/IconLightbulb.vue +27 -0
  27. package/components/vio/icon/IconLogo.vue +17 -0
  28. package/components/vio/icon/IconMixcloud.vue +23 -0
  29. package/components/vio/icon/IconMusic.vue +27 -0
  30. package/components/vio/icon/IconPlay.vue +25 -0
  31. package/components/vio/icon/IconShare.vue +27 -0
  32. package/components/{VioLayout.vue → vio/layout/VioLayout.vue} +1 -1
  33. package/components/vio/layout/VioLayoutBreadcrumbs.vue +83 -0
  34. package/components/vio/layout/VioLayoutFooter.vue +40 -0
  35. package/components/vio/layout/VioLayoutFooterCategory.vue +17 -0
  36. package/components/vio/layout/VioLayoutHeader.vue +98 -0
  37. package/components/vio/layout/VioLayoutSpanList.vue +20 -0
  38. package/components/vio/loader/indicator/VioLoaderIndicator.vue +14 -0
  39. package/components/vio/loader/indicator/VioLoaderIndicatorPing.vue +12 -0
  40. package/components/vio/loader/indicator/VioLoaderIndicatorSpinner.vue +24 -0
  41. package/components/{VioLegalNotice.vue → vio/page/VioPageLegalNotice.vue} +1 -1
  42. package/components/{VioPrivacyPolicy.vue → vio/page/VioPagePrivacyPolicy.vue} +1 -1
  43. package/composables/useAppLayout.ts +2 -2
  44. package/composables/useDateTime.ts +17 -0
  45. package/composables/useFavicons.ts +2 -2
  46. package/composables/useFireError.ts +17 -0
  47. package/composables/useGetServiceHref.ts +47 -0
  48. package/composables/useHeadDefault.ts +34 -0
  49. package/composables/useStrapiFetch.ts +10 -0
  50. package/error.vue +5 -2
  51. package/locales/de.json +7 -1
  52. package/locales/en.json +7 -1
  53. package/nuxt.config.ts +38 -2
  54. package/package.json +23 -10
  55. package/pages/legal-notice.vue +1 -1
  56. package/pages/privacy-policy.vue +1 -1
  57. package/plugins/dayjs.ts +34 -0
  58. package/plugins/i18n.ts +5 -0
  59. package/plugins/marked.ts +9 -0
  60. package/server/middleware/headers.ts +41 -10
  61. package/tailwind.config.ts +129 -8
  62. package/utils/constants.ts +9 -1
  63. package/utils/form.ts +19 -0
  64. package/utils/networking.ts +82 -0
  65. package/utils/text.ts +20 -0
  66. /package/components/{VioLink.vue → vio/_/VioLink.vue} +0 -0
  67. /package/components/{VioButton.vue → vio/button/VioButton.vue} +0 -0
  68. /package/components/{VioHr.vue → vio/layout/VioLayoutHr.vue} +0 -0
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="flex items-center gap-1">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <VioFormInputState
3
+ v-if="
4
+ (!formInput && !validationProperty) ||
5
+ (formInput &&
6
+ formInput[isValidationLive ? '$invalid' : '$error'] &&
7
+ !formInput.$pending &&
8
+ validationProperty &&
9
+ validationProperty in formInput &&
10
+ formInput[validationProperty].$invalid)
11
+ "
12
+ class="text-red-600"
13
+ >
14
+ <IconExclamationCircle v-if="formInput && validationProperty" />
15
+ <slot />
16
+ </VioFormInputState>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import type { BaseValidation } from '@vuelidate/core'
21
+
22
+ export interface Props {
23
+ formInput?: BaseValidation
24
+ isValidationLive?: boolean
25
+ validationProperty?: string
26
+ }
27
+ withDefaults(defineProps<Props>(), {
28
+ formInput: undefined,
29
+ isValidationLive: false,
30
+ validationProperty: undefined,
31
+ })
32
+ </script>
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <VioFormInputState
3
+ v-if="
4
+ (!formInput && !validationProperty) ||
5
+ (formInput &&
6
+ formInput[isValidationLive ? '$invalid' : '$error'] &&
7
+ !formInput.$pending &&
8
+ validationProperty &&
9
+ validationProperty in formInput &&
10
+ formInput[validationProperty].$invalid)
11
+ "
12
+ class="text-gray-500 dark:text-gray-400"
13
+ >
14
+ <IconInformationCircle />
15
+ <slot />
16
+ </VioFormInputState>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import type { BaseValidation } from '@vuelidate/core'
21
+
22
+ export interface Props {
23
+ formInput?: BaseValidation
24
+ isValidationLive?: boolean
25
+ validationProperty?: string
26
+ }
27
+ withDefaults(defineProps<Props>(), {
28
+ formInput: undefined,
29
+ isValidationLive: false,
30
+ validationProperty: undefined,
31
+ })
32
+ </script>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <IconContainer
3
+ fill="none"
4
+ viewBox="0 0 24 24"
5
+ stroke="currentColor"
6
+ stroke-width="2"
7
+ :title="title || t('title')"
8
+ >
9
+ <path
10
+ stroke-linecap="round"
11
+ stroke-linejoin="round"
12
+ d="M14 5l7 7m0 0l-7 7m7-7H3"
13
+ />
14
+ </IconContainer>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ export interface Props {
19
+ title?: string // eslint-disable-line vue/require-default-prop
20
+ }
21
+ withDefaults(defineProps<Props>(), {})
22
+
23
+ const { t } = useI18n()
24
+ </script>
25
+
26
+ <i18n lang="yaml">
27
+ de:
28
+ title: Vor
29
+ en:
30
+ title: Forward
31
+ </i18n>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <IconContainer
3
+ fill="none"
4
+ viewBox="0 0 24 24"
5
+ stroke="currentColor"
6
+ :title="title || t('title')"
7
+ >
8
+ <path
9
+ stroke-linecap="round"
10
+ stroke-linejoin="round"
11
+ stroke-width="2"
12
+ d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
13
+ />
14
+ </IconContainer>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ export interface Props {
19
+ title?: string // eslint-disable-line vue/require-default-prop
20
+ }
21
+ withDefaults(defineProps<Props>(), {})
22
+
23
+ const { t } = useI18n()
24
+ </script>
25
+
26
+ <i18n lang="yaml">
27
+ de:
28
+ title: Kalender
29
+ en:
30
+ title: Calendar
31
+ </i18n>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ :class="classes"
5
+ fill="none"
6
+ viewBox="0 0 24 24"
7
+ stroke="currentColor"
8
+ stroke-width="2"
9
+ >
10
+ <path
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"
14
+ />
15
+ </svg>
16
+ </template>
17
+
18
+ <script lang="ts">
19
+ export default defineComponent({
20
+ props: {
21
+ classes: {
22
+ default: 'h-5 md:h-6 w-5 md:w-6',
23
+ type: String,
24
+ },
25
+ },
26
+ })
27
+ </script>
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ :class="classes"
5
+ viewBox="0 0 20 20"
6
+ fill="currentColor"
7
+ >
8
+ <path
9
+ d="M2 5a2 2 0 012-2h7a2 2 0 012 2v4a2 2 0 01-2 2H9l-3 3v-3H4a2 2 0 01-2-2V5z"
10
+ />
11
+ <path
12
+ d="M15 7v2a4 4 0 01-4 4H9.828l-1.766 1.767c.28.149.599.233.938.233h2l3 3v-3h2a2 2 0 002-2V9a2 2 0 00-2-2h-1z"
13
+ />
14
+ </svg>
15
+ </template>
16
+
17
+ <script lang="ts">
18
+ export default defineComponent({
19
+ props: {
20
+ classes: {
21
+ default: 'h-5 md:h-6 w-5 md:w-6',
22
+ type: String,
23
+ },
24
+ },
25
+ })
26
+ </script>
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <IconContainer
3
+ viewBox="0 0 20 20"
4
+ fill="currentColor"
5
+ :title="title || t('title')"
6
+ >
7
+ <path
8
+ fill-rule="evenodd"
9
+ d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
10
+ clip-rule="evenodd"
11
+ />
12
+ </IconContainer>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ export interface Props {
17
+ title?: string // eslint-disable-line vue/require-default-prop
18
+ }
19
+ withDefaults(defineProps<Props>(), {})
20
+
21
+ const { t } = useI18n()
22
+ </script>
23
+
24
+ <i18n lang="yaml">
25
+ de:
26
+ title: Akzeptieren
27
+ en:
28
+ title: Accept
29
+ </i18n>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" :class="classes" :title="title">
3
+ <slot />
4
+ </svg>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ export interface Props {
9
+ classes?: string
10
+ title: string
11
+ }
12
+ withDefaults(defineProps<Props>(), {
13
+ classes: 'h-5 md:h-6 w-5 md:w-6 shrink-0',
14
+ })
15
+ </script>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <IconContainer
3
+ fill="none"
4
+ viewBox="0 0 24 24"
5
+ stroke="currentColor"
6
+ :title="title || t('title')"
7
+ >
8
+ <path
9
+ stroke-linecap="round"
10
+ stroke-linejoin="round"
11
+ stroke-width="2"
12
+ d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
13
+ />
14
+ </IconContainer>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ export interface Props {
19
+ title?: string // eslint-disable-line vue/require-default-prop
20
+ }
21
+ withDefaults(defineProps<Props>(), {})
22
+
23
+ const { t } = useI18n()
24
+ </script>
25
+
26
+ <i18n lang="yaml">
27
+ de:
28
+ title: Herunterladen
29
+ en:
30
+ title: Download
31
+ </i18n>
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <IconContainer
3
+ viewBox="0 0 20 20"
4
+ fill="currentColor"
5
+ :title="title || t('title')"
6
+ >
7
+ <path
8
+ fill-rule="evenodd"
9
+ d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
10
+ clip-rule="evenodd"
11
+ />
12
+ </IconContainer>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ export interface Props {
17
+ title?: string // eslint-disable-line vue/require-default-prop
18
+ }
19
+ withDefaults(defineProps<Props>(), {})
20
+
21
+ const { t } = useI18n()
22
+ </script>
23
+
24
+ <i18n lang="yaml">
25
+ de:
26
+ title: Fehlerhaft
27
+ en:
28
+ title: Erroneous
29
+ </i18n>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <IconContainer
3
+ fill="none"
4
+ viewBox="0 0 24 24"
5
+ stroke="currentColor"
6
+ :title="title || t('title')"
7
+ >
8
+ <path
9
+ stroke-linecap="round"
10
+ stroke-linejoin="round"
11
+ stroke-width="2"
12
+ d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
13
+ />
14
+ </IconContainer>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ export interface Props {
19
+ title?: string // eslint-disable-line vue/require-default-prop
20
+ }
21
+ withDefaults(defineProps<Props>(), {})
22
+
23
+ const { t } = useI18n()
24
+ </script>
25
+
26
+ <i18n lang="yaml">
27
+ de:
28
+ title: Homepage
29
+ en:
30
+ title: Homepage
31
+ </i18n>
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <IconContainer
3
+ aria-hidden="true"
4
+ focusable="false"
5
+ data-prefix="fas"
6
+ data-icon="hourglass"
7
+ role="img"
8
+ viewBox="0 0 384 512"
9
+ :title="title || t('title')"
10
+ >
11
+ <path
12
+ fill="currentColor"
13
+ d="M352 0C369.7 0 384 14.33 384 32C384 49.67 369.7 64 352 64V74.98C352 117.4 335.1 158.1 305.1 188.1L237.3 256L305.1 323.9C335.1 353.9 352 394.6 352 437V448C369.7 448 384 462.3 384 480C384 497.7 369.7 512 352 512H32C14.33 512 0 497.7 0 480C0 462.3 14.33 448 32 448V437C32 394.6 48.86 353.9 78.86 323.9L146.7 256L78.86 188.1C48.86 158.1 32 117.4 32 74.98V64C14.33 64 0 49.67 0 32C0 14.33 14.33 0 32 0H352zM111.1 128H272C282.4 112.4 288 93.98 288 74.98V64H96V74.98C96 93.98 101.6 112.4 111.1 128zM111.1 384H272C268.5 378.7 264.5 373.7 259.9 369.1L192 301.3L124.1 369.1C119.5 373.7 115.5 378.7 111.1 384V384z"
14
+ />
15
+ </IconContainer>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ export interface Props {
20
+ title?: string // eslint-disable-line vue/require-default-prop
21
+ }
22
+ withDefaults(defineProps<Props>(), {})
23
+
24
+ const { t } = useI18n()
25
+ </script>
26
+
27
+ <i18n lang="yaml">
28
+ de:
29
+ title: Dauer
30
+ en:
31
+ title: Duration
32
+ </i18n>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ :class="classes"
5
+ fill="none"
6
+ viewBox="0 0 24 24"
7
+ stroke="currentColor"
8
+ stroke-width="2"
9
+ >
10
+ <path
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"
14
+ />
15
+ </svg>
16
+ </template>
17
+
18
+ <script lang="ts">
19
+ export default defineComponent({
20
+ props: {
21
+ classes: {
22
+ default: 'h-5 md:h-6 w-5 md:w-6',
23
+ type: String,
24
+ },
25
+ },
26
+ })
27
+ </script>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width="1064pt"
5
+ height="1064pt"
6
+ version="1.1"
7
+ viewBox="0 0 1064 1064"
8
+ >
9
+ <g id="#9a9a9aff">
10
+ <path
11
+ fill="#ecc94b"
12
+ d="M 802.62 185.62 C 806.76 181.54 810.71 177.26 815.06 173.41 C 828.57 186.40 841.60 199.89 854.94 213.06 C 866.81 225.07 878.95 236.83 890.68 248.99 C 858.25 281.90 825.33 314.33 792.78 347.13 C 801.85 360.72 810.67 374.54 817.81 389.27 C 849.17 451.62 859.14 524.40 845.66 592.88 C 835.73 644.31 812.88 693.19 779.77 733.77 C 748.01 772.91 706.76 804.28 660.61 824.52 C 601.85 850.47 535.17 858.08 472.10 845.87 C 399.83 832.28 332.81 792.71 286.03 735.97 C 261.50 706.51 242.51 672.51 229.95 636.31 C 214.56 591.74 209.12 543.75 214.40 496.88 C 219.97 445.89 238.13 396.34 266.77 353.78 C 297.11 308.55 339.24 271.29 387.93 246.85 C 436.80 222.00 492.22 210.23 546.98 212.87 C 592.26 214.95 637.06 226.87 677.39 247.55 C 691.14 254.44 704.16 262.67 716.88 271.28 C 745.53 242.80 774.02 214.15 802.62 185.62 M 668.11 321.11 C 659.08 330.37 649.57 339.17 640.85 348.72 C 671.30 366.97 697.16 392.75 715.33 423.27 C 726.58 412.55 737.35 401.34 748.40 390.41 C 762.78 375.92 777.38 361.65 791.64 347.04 C 771.18 318.23 745.87 292.82 717.00 272.43 C 700.48 288.43 684.45 304.92 668.11 321.11 M 436.34 342.35 C 401.95 359.59 372.51 386.48 352.08 419.07 C 331.27 452.09 319.83 490.96 319.57 530.00 C 319.10 567.70 329.06 605.44 347.89 638.09 C 365.96 669.51 392.23 696.14 423.39 714.64 C 456.33 734.24 494.65 744.78 533.00 744.45 C 574.05 744.36 615.02 731.94 649.19 709.17 C 676.80 690.95 700.05 666.14 716.43 637.39 C 736.74 602.03 746.42 560.71 744.11 520.01 C 742.05 486.63 732.53 453.44 715.15 424.78 C 673.22 466.47 631.56 508.43 589.65 550.14 C 586.42 547.81 583.82 544.77 581.00 542.00 C 559.16 520.17 537.32 498.33 515.49 476.50 C 514.40 475.63 513.59 474.12 515.09 473.18 C 556.44 431.67 598.01 390.37 639.32 348.82 C 615.75 334.67 589.17 325.65 561.99 321.72 C 519.31 315.51 474.81 322.86 436.34 342.35 Z"
13
+ opacity="1"
14
+ />
15
+ </g>
16
+ </svg>
17
+ </template>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 640 512"
5
+ :class="classes"
6
+ >
7
+ <!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
8
+ <path
9
+ d="M424.43 219.729C416.124 134.727 344.135 68 256.919 68c-72.266 0-136.224 46.516-159.205 114.074-54.545 8.029-96.63 54.822-96.63 111.582 0 62.298 50.668 112.966 113.243 112.966h289.614c52.329 0 94.969-42.362 94.969-94.693 0-45.131-32.118-83.063-74.48-92.2zm-20.489 144.53H114.327c-39.04 0-70.881-31.564-70.881-70.604s31.841-70.604 70.881-70.604c18.827 0 36.548 7.475 49.838 20.766 19.963 19.963 50.133-10.227 30.18-30.18-14.675-14.398-32.672-24.365-52.053-29.349 19.935-44.3 64.79-73.926 114.628-73.926 69.496 0 125.979 56.483 125.979 125.702 0 13.568-2.215 26.857-6.369 39.594-8.943 27.517 32.133 38.939 40.147 13.29 2.769-8.306 4.984-16.889 6.369-25.472 19.381 7.476 33.502 26.303 33.502 48.453 0 28.795-23.535 52.33-52.607 52.33zm235.069-52.33c0 44.024-12.737 86.386-37.102 122.657-4.153 6.092-10.798 9.414-17.72 9.414-16.317 0-27.127-18.826-17.443-32.949 19.381-29.349 29.903-63.682 29.903-99.122s-10.521-69.773-29.903-98.845c-15.655-22.831 19.361-47.24 35.163-23.534 24.366 35.993 37.102 78.356 37.102 122.379zm-70.88 0c0 31.565-9.137 62.021-26.857 88.325-4.153 6.091-10.798 9.136-17.72 9.136-17.201 0-27.022-18.979-17.443-32.948 13.013-19.104 19.658-41.255 19.658-64.513 0-22.981-6.645-45.408-19.658-64.512-15.761-22.986 19.008-47.095 35.163-23.535 17.719 26.026 26.857 56.483 26.857 88.047z"
10
+ />
11
+ </svg>
12
+ </template>
13
+
14
+ <script lang="ts">
15
+ export default defineComponent({
16
+ props: {
17
+ classes: {
18
+ default: 'h-5 md:h-6 w-5 md:w-6',
19
+ type: String,
20
+ },
21
+ },
22
+ })
23
+ </script>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ :class="classes"
5
+ fill="none"
6
+ viewBox="0 0 24 24"
7
+ stroke="currentColor"
8
+ stroke-width="2"
9
+ >
10
+ <path
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3"
14
+ />
15
+ </svg>
16
+ </template>
17
+
18
+ <script lang="ts">
19
+ export default defineComponent({
20
+ props: {
21
+ classes: {
22
+ default: 'h-5 md:h-6 w-5 md:w-6',
23
+ type: String,
24
+ },
25
+ },
26
+ })
27
+ </script>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ :class="classes"
5
+ viewBox="0 0 20 20"
6
+ fill="currentColor"
7
+ >
8
+ <path
9
+ fill-rule="evenodd"
10
+ d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z"
11
+ clip-rule="evenodd"
12
+ />
13
+ </svg>
14
+ </template>
15
+
16
+ <script lang="ts">
17
+ export default defineComponent({
18
+ props: {
19
+ classes: {
20
+ default: 'h-5 md:h-6 w-5 md:w-6',
21
+ type: String,
22
+ },
23
+ },
24
+ })
25
+ </script>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ :class="classes"
5
+ fill="none"
6
+ viewBox="0 0 24 24"
7
+ stroke="currentColor"
8
+ stroke-width="2"
9
+ >
10
+ <path
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"
14
+ />
15
+ </svg>
16
+ </template>
17
+
18
+ <script lang="ts">
19
+ export default defineComponent({
20
+ props: {
21
+ classes: {
22
+ default: 'h-5 md:h-6 w-5 md:w-6',
23
+ type: String,
24
+ },
25
+ },
26
+ })
27
+ </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="p-4 md:px-8">
2
+ <div class="container mx-auto p-4 md:px-8">
3
3
  <main>
4
4
  <slot />
5
5
  </main>
@@ -0,0 +1,83 @@
1
+ <template>
2
+ <div class="mb-4 flex items-center gap-2 overflow-auto p-1">
3
+ <VioLink
4
+ :aria-label="t('home')"
5
+ data-testid="breadcrumb-prefix-/"
6
+ :is-colored="false"
7
+ :to="localePath('/')"
8
+ >
9
+ <IconHome classes="h-6 w-6" />
10
+ </VioLink>
11
+ <ul v-if="prefixes" class="flex items-center gap-2">
12
+ <li
13
+ v-for="prefix in prefixes"
14
+ :key="prefix.name"
15
+ class="flex items-center gap-2"
16
+ >
17
+ <span>{{ t('separator') }}</span>
18
+ <VioLink
19
+ class="whitespace-nowrap text-2xl"
20
+ :data-testid="`breadcrumb-prefix-${prefix.to}`"
21
+ :is-colored="false"
22
+ :to="prefix.to"
23
+ >
24
+ {{ prefix.name }}
25
+ </VioLink>
26
+ </li>
27
+ </ul>
28
+ <span>{{ t('separator') }}</span>
29
+ <VioLink :is-colored="false" to="?">
30
+ <span
31
+ class="whitespace-nowrap text-2xl font-bold"
32
+ data-testid="breadcrumb"
33
+ >
34
+ <slot />
35
+ </span>
36
+ </VioLink>
37
+ <ul v-if="suffixes" class="flex items-center gap-2">
38
+ <li
39
+ v-for="suffix in suffixes"
40
+ :key="suffix.name"
41
+ class="flex items-center gap-2"
42
+ >
43
+ <span>{{ t('separator') }}</span>
44
+ <VioLink
45
+ class="whitespace-nowrap text-2xl"
46
+ :data-testid="`breadcrumb-suffix-${suffix.to}`"
47
+ :is-colored="false"
48
+ :to="suffix.to"
49
+ >
50
+ {{ suffix.name }}
51
+ </VioLink>
52
+ </li>
53
+ </ul>
54
+ </div>
55
+ </template>
56
+
57
+ <script setup lang="ts">
58
+ export interface Breadcrumb {
59
+ name: string
60
+ to: string
61
+ }
62
+
63
+ export interface Props {
64
+ prefixes?: Array<Breadcrumb>
65
+ suffixes?: Array<Breadcrumb>
66
+ }
67
+ withDefaults(defineProps<Props>(), {
68
+ prefixes: undefined,
69
+ suffixes: undefined,
70
+ })
71
+
72
+ const localePath = useLocalePath()
73
+ const { t } = useI18n()
74
+ </script>
75
+
76
+ <i18n lang="yaml">
77
+ de:
78
+ home: Nach Hause
79
+ separator: /
80
+ en:
81
+ home: Head home
82
+ separator: /
83
+ </i18n>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <footer class="text-sm leading-6">
3
+ <div class="flex flex-col gap-8">
4
+ <div class="flex items-center">
5
+ <VioLayoutHr />
6
+ <IconLogo class="mx-12 h-12 w-12 brightness-0 opacity-60 invert" />
7
+ <VioLayoutHr />
8
+ </div>
9
+ <!-- Justifying evenly, instead of "between", centers a single element. -->
10
+ <div class="flex flex-wrap justify-evenly">
11
+ <slot />
12
+ </div>
13
+ <p class="text-center text-gray-500 dark:text-gray-400">
14
+ {{
15
+ t('copyright', {
16
+ name: 'Jonas Thelemann',
17
+ year,
18
+ })
19
+ }}
20
+ </p>
21
+ </div>
22
+ </footer>
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ const { t } = useI18n()
27
+ const config = useRuntimeConfig()
28
+
29
+ // computations
30
+ const year = computed(() =>
31
+ config.public.isTesting ? 1337 : new Date().getFullYear(),
32
+ )
33
+ </script>
34
+
35
+ <i18n lang="yaml">
36
+ de:
37
+ copyright: © {year} {name}. Alle Rechte vorbehalten.
38
+ en:
39
+ copyright: © {year} {name}. All rights reserved.
40
+ </i18n>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div
3
+ class="flex flex-1 flex-col items-start p-4 basis-1/2 md:flex-none md:basis-auto gap-2"
4
+ >
5
+ <span class="whitespace-nowrap text-lg font-medium leading-7">
6
+ {{ heading }}
7
+ </span>
8
+ <slot />
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ export interface Props {
14
+ heading: string
15
+ }
16
+ withDefaults(defineProps<Props>(), {})
17
+ </script>