@sbc-connect/nuxt-base 0.0.0-test-ld-20260520212549

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 (179) hide show
  1. package/.env.example +11 -0
  2. package/CHANGELOG.md +338 -0
  3. package/LICENSE +28 -0
  4. package/README.md +55 -0
  5. package/app/app.config.ts +441 -0
  6. package/app/app.vue +18 -0
  7. package/app/assets/css/connect-base-layout.css +13 -0
  8. package/app/assets/css/connect-base-tw.css +303 -0
  9. package/app/components/Connect/Address/Display.vue +84 -0
  10. package/app/components/Connect/BCGovLogo.vue +42 -0
  11. package/app/components/Connect/Breadcrumb.vue +68 -0
  12. package/app/components/Connect/ButtonControl/Buttons.vue +28 -0
  13. package/app/components/Connect/ButtonControl/Index.vue +66 -0
  14. package/app/components/Connect/ButtonControl/Wrapper.vue +18 -0
  15. package/app/components/Connect/Contact/Display.vue +65 -0
  16. package/app/components/Connect/FloatingLabel.vue +67 -0
  17. package/app/components/Connect/Footer.vue +99 -0
  18. package/app/components/Connect/Header/LogoHomeLink.vue +20 -0
  19. package/app/components/Connect/Header/WhatsNew.vue +36 -0
  20. package/app/components/Connect/Header/Wrapper.vue +14 -0
  21. package/app/components/Connect/Header/index.vue +17 -0
  22. package/app/components/Connect/I18n/Helper.vue +40 -0
  23. package/app/components/Connect/Input.vue +69 -0
  24. package/app/components/Connect/InputDate.vue +104 -0
  25. package/app/components/Connect/Layout/Index.vue +25 -0
  26. package/app/components/Connect/Layout/Sidebar.vue +38 -0
  27. package/app/components/Connect/LocaleSelect.vue +37 -0
  28. package/app/components/Connect/Modal/Error.vue +76 -0
  29. package/app/components/Connect/Modal/index.vue +51 -0
  30. package/app/components/Connect/PageSection.vue +57 -0
  31. package/app/components/Connect/Select.vue +28 -0
  32. package/app/components/Connect/Slideover/WhatsNew.vue +61 -0
  33. package/app/components/Connect/Spinner.vue +91 -0
  34. package/app/components/Connect/SystemBanner.vue +53 -0
  35. package/app/components/Connect/Textarea.vue +27 -0
  36. package/app/components/Connect/Tombstone/Item.vue +51 -0
  37. package/app/components/Connect/Tombstone/index.vue +123 -0
  38. package/app/components/Connect/Transition/Collapse.vue +39 -0
  39. package/app/components/Connect/Transition/Fade.vue +31 -0
  40. package/app/components/HelloWorld/Index.vue +14 -0
  41. package/app/composables/useConnectButtonControl.ts +146 -0
  42. package/app/composables/useConnectLaunchDarkly.ts +173 -0
  43. package/app/composables/useConnectModal.ts +13 -0
  44. package/app/composables/useConnectTombstone.ts +25 -0
  45. package/app/coverage/app/app.config.ts.html +1408 -0
  46. package/app/coverage/app/app.vue.html +139 -0
  47. package/app/coverage/app/components/Connect/Address/Display.vue.html +337 -0
  48. package/app/coverage/app/components/Connect/Address/index.html +116 -0
  49. package/app/coverage/app/components/Connect/BCGovLogo.vue.html +211 -0
  50. package/app/coverage/app/components/Connect/Breadcrumb.vue.html +289 -0
  51. package/app/coverage/app/components/Connect/ButtonControl/Buttons.vue.html +166 -0
  52. package/app/coverage/app/components/Connect/ButtonControl/Index.vue.html +283 -0
  53. package/app/coverage/app/components/Connect/ButtonControl/Wrapper.vue.html +139 -0
  54. package/app/coverage/app/components/Connect/ButtonControl/index.html +146 -0
  55. package/app/coverage/app/components/Connect/Contact/Display.vue.html +280 -0
  56. package/app/coverage/app/components/Connect/Contact/index.html +116 -0
  57. package/app/coverage/app/components/Connect/FloatingLabel.vue.html +286 -0
  58. package/app/coverage/app/components/Connect/Footer.vue.html +382 -0
  59. package/app/coverage/app/components/Connect/Header/LogoHomeLink.vue.html +145 -0
  60. package/app/coverage/app/components/Connect/Header/WhatsNew.vue.html +193 -0
  61. package/app/coverage/app/components/Connect/Header/Wrapper.vue.html +127 -0
  62. package/app/coverage/app/components/Connect/Header/index.html +161 -0
  63. package/app/coverage/app/components/Connect/Header/index.vue.html +136 -0
  64. package/app/coverage/app/components/Connect/I18n/Helper.vue.html +205 -0
  65. package/app/coverage/app/components/Connect/I18n/index.html +116 -0
  66. package/app/coverage/app/components/Connect/Input.vue.html +262 -0
  67. package/app/coverage/app/components/Connect/InputDate.vue.html +406 -0
  68. package/app/coverage/app/components/Connect/Layout/Index.vue.html +160 -0
  69. package/app/coverage/app/components/Connect/Layout/Sidebar.vue.html +199 -0
  70. package/app/coverage/app/components/Connect/Layout/index.html +131 -0
  71. package/app/coverage/app/components/Connect/LocaleSelect.vue.html +196 -0
  72. package/app/coverage/app/components/Connect/Modal/Error.vue.html +313 -0
  73. package/app/coverage/app/components/Connect/Modal/index.html +131 -0
  74. package/app/coverage/app/components/Connect/Modal/index.vue.html +238 -0
  75. package/app/coverage/app/components/Connect/PageSection.vue.html +256 -0
  76. package/app/coverage/app/components/Connect/Select.vue.html +169 -0
  77. package/app/coverage/app/components/Connect/Slideover/WhatsNew.vue.html +268 -0
  78. package/app/coverage/app/components/Connect/Slideover/index.html +116 -0
  79. package/app/coverage/app/components/Connect/Spinner.vue.html +358 -0
  80. package/app/coverage/app/components/Connect/SystemBanner.vue.html +244 -0
  81. package/app/coverage/app/components/Connect/Textarea.vue.html +160 -0
  82. package/app/coverage/app/components/Connect/Tombstone/Item.vue.html +238 -0
  83. package/app/coverage/app/components/Connect/Tombstone/index.html +131 -0
  84. package/app/coverage/app/components/Connect/Tombstone/index.vue.html +454 -0
  85. package/app/coverage/app/components/Connect/Transition/Collapse.vue.html +202 -0
  86. package/app/coverage/app/components/Connect/Transition/Fade.vue.html +178 -0
  87. package/app/coverage/app/components/Connect/Transition/index.html +131 -0
  88. package/app/coverage/app/components/Connect/index.html +281 -0
  89. package/app/coverage/app/components/HelloWorld/Index.vue.html +127 -0
  90. package/app/coverage/app/components/HelloWorld/index.html +116 -0
  91. package/app/coverage/app/composables/index.html +161 -0
  92. package/app/coverage/app/composables/useConnectButtonControl.ts.html +523 -0
  93. package/app/coverage/app/composables/useConnectLaunchDarkly.ts.html +595 -0
  94. package/app/coverage/app/composables/useConnectModal.ts.html +124 -0
  95. package/app/coverage/app/composables/useConnectTombstone.ts.html +160 -0
  96. package/app/coverage/app/error.vue.html +247 -0
  97. package/app/coverage/app/index.html +146 -0
  98. package/app/coverage/app/interfaces/connect-address.ts.html +121 -0
  99. package/app/coverage/app/interfaces/connect-breadcrumb.ts.html +100 -0
  100. package/app/coverage/app/interfaces/connect-button-control.ts.html +151 -0
  101. package/app/coverage/app/interfaces/connect-contact-item.ts.html +103 -0
  102. package/app/coverage/app/interfaces/connect-modal.ts.html +100 -0
  103. package/app/coverage/app/interfaces/connect-tombstone.ts.html +208 -0
  104. package/app/coverage/app/interfaces/connect-whatsnew.ts.html +127 -0
  105. package/app/coverage/app/interfaces/index.html +206 -0
  106. package/app/coverage/app/layouts/ConnectBase.vue.html +100 -0
  107. package/app/coverage/app/layouts/index.html +116 -0
  108. package/app/coverage/app/plugins/index.html +146 -0
  109. package/app/coverage/app/plugins/maska.client.ts.html +115 -0
  110. package/app/coverage/app/plugins/sanitize.client.ts.html +151 -0
  111. package/app/coverage/app/plugins/whats-new.client.ts.html +220 -0
  112. package/app/coverage/app/types/dates.ts.html +136 -0
  113. package/app/coverage/app/types/index.html +116 -0
  114. package/app/coverage/app/utils/appendUrlParam.ts.html +97 -0
  115. package/app/coverage/app/utils/getErrorMessage.ts.html +211 -0
  116. package/app/coverage/app/utils/getErrorStatus.ts.html +196 -0
  117. package/app/coverage/app/utils/index.html +191 -0
  118. package/app/coverage/app/utils/logFetchError.ts.html +193 -0
  119. package/app/coverage/app/utils/parseSpecialCharacters.ts.html +160 -0
  120. package/app/coverage/app/utils/setBreadcrumbs.ts.html +100 -0
  121. package/app/coverage/base.css +224 -0
  122. package/app/coverage/block-navigation.js +87 -0
  123. package/app/coverage/clover.xml +2094 -0
  124. package/app/coverage/coverage-final.json +58 -0
  125. package/app/coverage/favicon.png +0 -0
  126. package/app/coverage/index.html +386 -0
  127. package/app/coverage/prettify.css +1 -0
  128. package/app/coverage/prettify.js +2 -0
  129. package/app/coverage/sort-arrow-sprite.png +0 -0
  130. package/app/coverage/sorter.js +210 -0
  131. package/app/error.vue +54 -0
  132. package/app/interfaces/connect-address.ts +12 -0
  133. package/app/interfaces/connect-breadcrumb.ts +5 -0
  134. package/app/interfaces/connect-button-control.ts +23 -0
  135. package/app/interfaces/connect-contact-item.ts +6 -0
  136. package/app/interfaces/connect-modal.ts +5 -0
  137. package/app/interfaces/connect-tombstone.ts +41 -0
  138. package/app/interfaces/connect-whatsnew.ts +14 -0
  139. package/app/layouts/ConnectBase.vue +5 -0
  140. package/app/plugins/maska.client.ts +10 -0
  141. package/app/plugins/sanitize.client.ts +22 -0
  142. package/app/plugins/whats-new.client.ts +45 -0
  143. package/app/spa-loading-template.html +61 -0
  144. package/app/types/base-app-config.d.ts +15 -0
  145. package/app/types/base-directives.d.ts +7 -0
  146. package/app/types/base-page-meta.d.ts +8 -0
  147. package/app/types/dates.ts +17 -0
  148. package/app/utils/appendUrlParam.ts +4 -0
  149. package/app/utils/getErrorMessage.ts +42 -0
  150. package/app/utils/getErrorStatus.ts +37 -0
  151. package/app/utils/logFetchError.ts +36 -0
  152. package/app/utils/parseSpecialCharacters.ts +25 -0
  153. package/app/utils/setBreadcrumbs.ts +7 -0
  154. package/firebase.json +34 -0
  155. package/i18n/locales/en-CA.ts +70 -0
  156. package/i18n/locales/fr-CA.ts +96 -0
  157. package/nuxt.config.ts +147 -0
  158. package/package.json +49 -0
  159. package/public/BCGovLogo/gov_bc_logo_horiz_en.png +0 -0
  160. package/public/BCGovLogo/gov_bc_logo_horiz_fr.png +0 -0
  161. package/public/BCGovLogo/gov_bc_logo_vert_en.png +0 -0
  162. package/public/BCGovLogo/gov_bc_logo_vert_fr.png +0 -0
  163. package/public/favicon.ico +0 -0
  164. package/public/fonts/BCSans/BCSans-Bold.woff +0 -0
  165. package/public/fonts/BCSans/BCSans-Bold.woff2 +0 -0
  166. package/public/fonts/BCSans/BCSans-BoldItalic.woff +0 -0
  167. package/public/fonts/BCSans/BCSans-BoldItalic.woff2 +0 -0
  168. package/public/fonts/BCSans/BCSans-Italic.woff +0 -0
  169. package/public/fonts/BCSans/BCSans-Italic.woff2 +0 -0
  170. package/public/fonts/BCSans/BCSans-Regular.woff +0 -0
  171. package/public/fonts/BCSans/BCSans-Regular.woff2 +0 -0
  172. package/public/fonts/BCSans/LICENSE_OFL.txt +94 -0
  173. package/test-results/.last-run.json +7 -0
  174. package/test-results/error-page-404-Error-vue-D-1eb51-cted-visuals-with-404-error-Desktop-Chrome/error-context.md +135 -0
  175. package/test-results/error-page-404-Error-vue-D-1eb51-cted-visuals-with-404-error-Desktop-Chrome/test-failed-1.png +0 -0
  176. package/test-results/error-page-404-Error-vue-D-1eb51-cted-visuals-with-404-error-Desktop-Chrome/trace.zip +0 -0
  177. package/test-results/error-page-500-Error-vue-D-8c2cf-cted-visuals-with-500-error-Desktop-Chrome/error-context.md +135 -0
  178. package/test-results/error-page-500-Error-vue-D-8c2cf-cted-visuals-with-500-error-Desktop-Chrome/test-failed-1.png +0 -0
  179. package/test-results/error-page-500-Error-vue-D-8c2cf-cted-visuals-with-500-error-Desktop-Chrome/trace.zip +0 -0
@@ -0,0 +1,51 @@
1
+ <script setup lang="ts">
2
+ const isSmallScreen = useMediaQuery('(max-width: 640px)')
3
+
4
+ defineProps<{
5
+ title: string
6
+ description: string
7
+ dismissible: boolean
8
+ buttons?: ConnectModalButton[]
9
+ }>()
10
+ defineEmits<{ close: [] }>()
11
+ </script>
12
+
13
+ <template>
14
+ <UModal
15
+ overlay
16
+ :title
17
+ :description
18
+ :dismissible
19
+ >
20
+ <template #content>
21
+ <div class="p-10 flex flex-col gap-6">
22
+ <div class="flex flex-col gap-6 text-left">
23
+ <h2 class="text-2xl">
24
+ {{ title }}
25
+ </h2>
26
+ <p class="-mt-2">
27
+ {{ description }}
28
+ </p>
29
+ </div>
30
+ <div v-if="buttons && buttons.length" class="flex flex-wrap items-center justify-center gap-4">
31
+ <template
32
+ v-for="button in buttons"
33
+ :key="button.label"
34
+ >
35
+ <UButton
36
+ v-if="button.shouldClose"
37
+ v-bind="button"
38
+ :block="isSmallScreen"
39
+ @click="$emit('close')"
40
+ />
41
+ <UButton
42
+ v-else
43
+ v-bind="button"
44
+ :block="isSmallScreen"
45
+ />
46
+ </template>
47
+ </div>
48
+ </div>
49
+ </template>
50
+ </UModal>
51
+ </template>
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import type { ButtonProps } from '#ui/types'
3
+
4
+ defineProps<{
5
+ heading?: {
6
+ label?: string
7
+ labelClass?: string
8
+ level?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
9
+ icon?: string
10
+ iconClass?: string
11
+ ui?: string
12
+ }
13
+ uiBody?: string
14
+ actions?: ButtonProps[]
15
+ }>()
16
+ </script>
17
+
18
+ <template>
19
+ <UCard
20
+ as="section"
21
+ class="w-full"
22
+ variant="outline"
23
+ :ui="{
24
+ header: heading?.ui ?? 'bg-shade-secondary px-4 py-4 sm:px-4 rounded-t-md',
25
+ body: uiBody ?? 'p-0 sm:p-0',
26
+ footer: 'p-0 sm:p-0',
27
+ }"
28
+ >
29
+ <template v-if="heading?.label || $slots.header" #header>
30
+ <slot name="header">
31
+ <div class="flex items-center justify-between gap-2.5">
32
+ <component :is="heading?.level || 'h2'">
33
+ <div class="flex items-center gap-2.5">
34
+ <UIcon
35
+ v-if="heading?.icon"
36
+ :name="heading.icon"
37
+ :class="heading?.iconClass || 'size-6 shrink-0 text-primary'"
38
+ />
39
+ <span :class="heading?.labelClass || 'font-semibold text-neutral-highlighted text-base'">
40
+ {{ heading?.label }}
41
+ </span>
42
+ </div>
43
+ </component>
44
+
45
+ <div class="flex items-center gap-2.5">
46
+ <UButton
47
+ v-for="(action, i) in actions"
48
+ :key="i"
49
+ v-bind="action"
50
+ />
51
+ </div>
52
+ </div>
53
+ </slot>
54
+ </template>
55
+ <slot />
56
+ </UCard>
57
+ </template>
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ const props = defineProps<{
3
+ id: string
4
+ label: string
5
+ }>()
6
+
7
+ defineEmits<{
8
+ change: []
9
+ }>()
10
+
11
+ const labelId = props.id + '-label'
12
+ </script>
13
+
14
+ <template>
15
+ <ConnectFloatingLabel
16
+ :id="labelId"
17
+ :label
18
+ variant="select"
19
+ >
20
+ <USelect
21
+ :id
22
+ :data-testid="id"
23
+ :aria-labelledby="labelId"
24
+ v-bind="$attrs"
25
+ @change="$emit('change')"
26
+ />
27
+ </ConnectFloatingLabel>
28
+ </template>
@@ -0,0 +1,61 @@
1
+ <script setup lang="ts">
2
+ const { $sanitize } = useNuxtApp()
3
+
4
+ defineProps<{
5
+ items: ConnectWhatsNewItem[]
6
+ }>()
7
+ </script>
8
+
9
+ <template>
10
+ <USlideover
11
+ :title="$t('connect.label.whatsNewSlideover')"
12
+ :description="$t('connect.text.whatsNewSlideoverDescription')"
13
+ :overlay="false"
14
+ :close="{
15
+ color: 'neutral',
16
+ variant: 'ghost',
17
+ class: 'cursor-pointer hover:bg-shade/50 focus-visible:bg-transparent focus-visible:ring-2 rounded-full',
18
+ }"
19
+ :ui="{
20
+ header: 'bg-brand-inverted',
21
+ title: 'text-brand',
22
+ body: 'flex-1 overflow-y-auto p-0 sm:p-0',
23
+ description: 'sr-only',
24
+ }"
25
+ >
26
+ <template #body>
27
+ <div class="overflow-y-auto text-neutral">
28
+ <div class="flex-1">
29
+ <ol v-if="items.length">
30
+ <li
31
+ v-for="item, i in items"
32
+ :key="i"
33
+ class="flex flex-col border-b border-gray-500 p-4 last:border-0"
34
+ >
35
+ <h3 class="text-lg font-bold">
36
+ {{ item.title }}
37
+ </h3>
38
+ <time class="text-sm">{{ item.date }}</time>
39
+ <!-- eslint-disable vue/no-v-html -->
40
+ <div
41
+ class="pt-3 vhtml"
42
+ v-html="$sanitize(item.description)"
43
+ />
44
+ </li>
45
+ </ol>
46
+ <div v-else class="flex justify-center py-10">
47
+ <span>{{ $t('connect.text.whatsNewSlideoverEmpty') }}</span>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ </template>
52
+ </USlideover>
53
+ </template>
54
+
55
+ <!-- must style globally for vhtml style to work -->
56
+ <style>
57
+ .vhtml a {
58
+ color: var(--ui-mark);
59
+ text-decoration: underline;
60
+ }
61
+ </style>
@@ -0,0 +1,91 @@
1
+ <script setup lang="ts">
2
+ const {
3
+ fullscreen = false,
4
+ size = 75
5
+ } = defineProps<{
6
+ fullscreen?: boolean
7
+ size?: number
8
+ }>()
9
+
10
+ const spinnerStyle = computed(() => ({
11
+ '--spinner-size': `${size}px`,
12
+ '--spinner-margin': `${size / -2}px`
13
+ }))
14
+ </script>
15
+
16
+ <template>
17
+ <!-- eslint-disable tailwindcss/no-custom-classname -->
18
+ <Teleport v-if="fullscreen" to="body">
19
+ <div class="fixed inset-0 z-[999] h-screen w-screen bg-gray-100 opacity-50" />
20
+ <svg
21
+ class="spinner fixed"
22
+ viewBox="0 0 50 50"
23
+ :style="spinnerStyle"
24
+ >
25
+ <circle
26
+ class="path"
27
+ cx="25"
28
+ cy="25"
29
+ r="20"
30
+ fill="none"
31
+ stroke-width="5"
32
+ />
33
+ </svg>
34
+ </Teleport>
35
+ <svg
36
+ v-else
37
+ class="spinner absolute"
38
+ viewBox="0 0 50 50"
39
+ :style="spinnerStyle"
40
+ >
41
+ <circle
42
+ class="path"
43
+ cx="25"
44
+ cy="25"
45
+ r="20"
46
+ fill="none"
47
+ stroke-width="5"
48
+ />
49
+ </svg>
50
+ </template>
51
+
52
+ <style scoped>
53
+ .spinner {
54
+ animation: rotate 1.5s linear infinite;
55
+ z-index: 10000;
56
+ top: 50%;
57
+ left: 50%;
58
+ margin-top: var(--spinner-margin, -37.5px);
59
+ margin-left: var(--spinner-margin, -37.5px);
60
+ width: var(--spinner-size, 75px);
61
+ height: var(--spinner-size, 75px);
62
+ transform-origin: 50% 50%;
63
+ }
64
+
65
+ .spinner .path {
66
+ stroke: #1669bb;
67
+ stroke-linecap: round;
68
+ animation: dash 1.25s ease-in-out infinite;
69
+ }
70
+
71
+ @keyframes rotate {
72
+ 100% {
73
+ transform: rotate(360deg);
74
+ }
75
+ }
76
+
77
+ @keyframes dash {
78
+ 0% {
79
+ stroke-dasharray: 1, 150;
80
+ stroke-dashoffset: 0;
81
+ }
82
+ 50% {
83
+ stroke-dasharray: 90, 150;
84
+ stroke-dashoffset: -35;
85
+ }
86
+ 100% {
87
+ stroke-dasharray: 90, 150;
88
+ stroke-dashoffset: -124;
89
+ }
90
+ }
91
+ </style>
@@ -0,0 +1,53 @@
1
+ <script setup lang="ts">
2
+ const ld = useConnectLaunchDarkly()
3
+ const { $sanitize } = useNuxtApp()
4
+
5
+ const {
6
+ dismissible = false,
7
+ icon = 'i-mdi-information'
8
+ } = defineProps<{
9
+ dismissible?: boolean
10
+ icon?: string
11
+ }>()
12
+
13
+ const close = ref(false)
14
+ const message = ref('')
15
+ onMounted(async () => {
16
+ message.value = $sanitize(await ld.getStoredFlag('banner-text', '', 'await'))
17
+ })
18
+ </script>
19
+
20
+ <template>
21
+ <div id="connect-system-banner" class="bg-brand-inverted px-2 sm:px-4">
22
+ <UAlert
23
+ v-show="!!message && !close"
24
+ class="py-0"
25
+ :description="message"
26
+ :close="dismissible"
27
+ close-icon="i-mdi-close"
28
+ :ui="{
29
+ root: 'rounded-none bg-brand-inverted px-0 sm:px-0 app-inner-container',
30
+ wrapper: 'bg-brand-inverted',
31
+ close: 'mt-2 text-neutral-highlighted',
32
+ }"
33
+ @update:open="close = true"
34
+ >
35
+ <!-- dismissible ? { class: 'pr-2 text-neutral-highlighted' } : null -->
36
+ <template #description>
37
+ <div class="flex gap-2 items-center py-2">
38
+ <UIcon class="size-7 shrink-0 text-neutral-highlighted self-start" :name="icon" />
39
+ <!-- eslint-disable vue/no-v-html tailwindcss/no-custom-classname -->
40
+ <p class="vhtml text-neutral-highlighted" v-html="message" />
41
+ </div>
42
+ </template>
43
+ </UAlert>
44
+ </div>
45
+ </template>
46
+
47
+ <!-- must style globally for vhtml style to work -->
48
+ <style>
49
+ .vhtml > a {
50
+ color: var(--ui-neutral-highlighted);
51
+ text-decoration: underline;
52
+ }
53
+ </style>
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import type { TextareaProps } from '@nuxt/ui'
3
+
4
+ const model = defineModel<Exclude<TextareaProps['modelValue'], null>>({ required: true })
5
+
6
+ defineProps<{
7
+ id: string
8
+ label: string
9
+ }>()
10
+ </script>
11
+
12
+ <template>
13
+ <UTextarea
14
+ :id
15
+ v-model.trim="model"
16
+ :data-testid="id"
17
+ placeholder="&nbsp;"
18
+ class="w-full grow"
19
+ >
20
+ <label
21
+ class="floating-label-textarea bg-shade w-[96%] flex-1 pt-1 -mt-1"
22
+ :for="id"
23
+ >
24
+ {{ label }}
25
+ </label>
26
+ </UTextarea>
27
+ </template>
@@ -0,0 +1,51 @@
1
+ <script setup lang="ts">
2
+ import type { IconProps, BadgeProps, LinkProps } from '@nuxt/ui'
3
+ import type { VNode } from 'vue'
4
+
5
+ interface ConnectTombstoneLink extends LinkProps {
6
+ label?: string
7
+ }
8
+
9
+ // cant use imported interface here as it causes vue compiler to break when extended
10
+ // must also update connect-tombstone interface if changing these props
11
+ defineProps<{
12
+ text?: string
13
+ itemClass?: string
14
+ icon?: IconProps
15
+ badge?: BadgeProps
16
+ link?: ConnectTombstoneLink
17
+ vNode?: VNode
18
+ }>()
19
+ </script>
20
+
21
+ <template>
22
+ <div class="flex space-x-1">
23
+ <UIcon
24
+ v-if="icon"
25
+ v-bind="icon"
26
+ :class="itemClass || 'mt-1 text-primary'"
27
+ />
28
+ <UBadge
29
+ v-if="badge"
30
+ v-bind="badge"
31
+ :class="itemClass || 'px-3'"
32
+ />
33
+ <ULink
34
+ v-else-if="link"
35
+ v-bind="link"
36
+ :class="itemClass || 'mt-[2px] text-sm text-primary underline'"
37
+ >
38
+ {{ link.label }}
39
+ </ULink>
40
+ <component
41
+ :is="vNode"
42
+ v-else-if="vNode"
43
+ />
44
+ <p
45
+ v-else-if="text"
46
+ :class="itemClass || 'mt-[2px] text-sm'"
47
+ >
48
+ {{ text }}
49
+ </p>
50
+ </div>
51
+ </template>
@@ -0,0 +1,123 @@
1
+ <script setup lang="ts">
2
+ import type { ButtonProps } from '@nuxt/ui'
3
+
4
+ const props = defineProps<{ stateKey?: string }>()
5
+
6
+ const { tombstone } = useConnectTombstone(props.stateKey)
7
+
8
+ async function handleButtonAction(button: ButtonProps, event: MouseEvent) {
9
+ button.loading = true
10
+ if (button.onClick) {
11
+ if (Array.isArray(button.onClick)) {
12
+ await Promise.all(button.onClick.map(fn => fn(event)))
13
+ } else if (button.onClick) {
14
+ await button.onClick(event)
15
+ }
16
+ }
17
+ button.loading = false
18
+ }
19
+ </script>
20
+
21
+ <template>
22
+ <div class="bg-white py-8 px-2 sm:px-4" data-testid="connect-tombstone-wrapper">
23
+ <div class="app-inner-container">
24
+ <div
25
+ v-if="tombstone.loading"
26
+ class="flex flex-col gap-2 *:space-y-2 sm:flex-row"
27
+ >
28
+ <slot name="loading">
29
+ <div class="grow">
30
+ <USkeleton class="h-9 w-[400px] rounded" />
31
+ <USkeleton class="h-5 w-[250px] rounded" />
32
+ <USkeleton class="h-5 w-[200px] rounded" />
33
+ <USkeleton class="h-5 w-[150px] rounded" />
34
+ </div>
35
+ <div>
36
+ <USkeleton class="h-5 w-[300px] rounded" />
37
+ <USkeleton class="h-5 w-[300px] rounded" />
38
+ <USkeleton class="h-5 w-[300px] rounded" />
39
+ <USkeleton class="h-5 w-[300px] rounded" />
40
+ </div>
41
+ </slot>
42
+ </div>
43
+ <div
44
+ v-else
45
+ class="flex flex-col gap-2 sm:flex-row"
46
+ >
47
+ <div class="grow space-y-4">
48
+ <div>
49
+ <slot name="title">
50
+ <component
51
+ :is="tombstone.title.as"
52
+ class="text-[1.375rem] font-bold text-neutral-highlighted"
53
+ >
54
+ {{ tombstone.title.text }}
55
+ </component>
56
+ </slot>
57
+ <slot name="subtitles">
58
+ <div
59
+ v-if="tombstone.subtitles.length"
60
+ class="flex divide-x divide-gray-500"
61
+ >
62
+ <ConnectTombstoneItem
63
+ v-for="subtitle, i in tombstone.subtitles"
64
+ :key="'subtitle-' + i"
65
+ v-bind="subtitle"
66
+ class="px-2"
67
+ :class="i === 0 ? 'pl-0' : ''"
68
+ />
69
+ </div>
70
+ </slot>
71
+ </div>
72
+ <div class="space-y-1">
73
+ <slot name="details">
74
+ <div class="flex space-x-2">
75
+ <div
76
+ v-for="detail, i in tombstone.details"
77
+ :key="'detail-' + i"
78
+ >
79
+ <ConnectTombstoneItem v-bind="detail" />
80
+ </div>
81
+ </div>
82
+ </slot>
83
+ <slot name="buttons">
84
+ <div
85
+ v-if="tombstone.bottomButtons.length"
86
+ class="flex flex-wrap gap-2"
87
+ >
88
+ <template v-for="btn in tombstone.bottomButtons" :key="btn.button?.label || btn.vNode?.key">
89
+ <component :is="btn.vNode" v-if="btn.vNode" />
90
+ <UButton
91
+ v-else-if="btn.button"
92
+ v-bind="{
93
+ ...btn.button,
94
+ onClick(event) {
95
+ handleButtonAction(btn.button!, event)
96
+ },
97
+ }"
98
+ />
99
+ </template>
100
+ </div>
101
+ </slot>
102
+ </div>
103
+ </div>
104
+ <slot name="sideDetails">
105
+ <dl class="space-y-1 text-sm">
106
+ <div
107
+ v-for="detail in tombstone.sideDetails"
108
+ :key="detail.label"
109
+ class="flex flex-row flex-wrap gap-2"
110
+ >
111
+ <dt class="font-bold text-neutral-highlighted">
112
+ {{ detail.label }}:
113
+ </dt>
114
+ <dd>
115
+ {{ detail.value }}
116
+ </dd>
117
+ </div>
118
+ </dl>
119
+ </slot>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </template>
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <Transition name="collapse">
3
+ <slot />
4
+ </Transition>
5
+ </template>
6
+
7
+ <style>
8
+ .collapse-enter-active,
9
+ .collapse-leave-active {
10
+ transition: max-height 0.3s ease-in-out, opacity 0.3s ease-in-out;
11
+ }
12
+ .collapse-enter-from,
13
+ .collapse-leave-to {
14
+ max-height: 0;
15
+ opacity: 0;
16
+ }
17
+ .collapse-enter-to,
18
+ .collapse-leave-from {
19
+ max-height: 1000px;
20
+ opacity: 1;
21
+ }
22
+
23
+ @media (prefers-reduced-motion) {
24
+ .collapse-enter-active,
25
+ .collapse-leave-active {
26
+ transition: max-height 0s ease-out, opacity 0s ease-out;
27
+ }
28
+ .collapse-enter-from,
29
+ .collapse-leave-to {
30
+ max-height: 0;
31
+ opacity: 0;
32
+ }
33
+ .collapse-enter-to,
34
+ .collapse-leave-from {
35
+ max-height: 1000px;
36
+ opacity: 1;
37
+ }
38
+ }
39
+ </style>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <Transition name="fade">
3
+ <slot />
4
+ </Transition>
5
+ </template>
6
+
7
+ <style>
8
+ .fade-enter-active {
9
+ transition: opacity 0.3s ease-in-out;
10
+ }
11
+ .fade-leave-active {
12
+ transition: opacity 0s ease-in-out;
13
+ }
14
+ .fade-enter-from,
15
+ .fade-leave-to {
16
+ opacity: 0;
17
+ }
18
+
19
+ @media (prefers-reduced-motion) {
20
+ .fade-enter-active {
21
+ transition: opacity 0s ease-in-out;
22
+ }
23
+ .fade-leave-active {
24
+ transition: opacity 0s ease-in-out;
25
+ }
26
+ .fade-enter-from,
27
+ .fade-leave-to {
28
+ opacity: 0;
29
+ }
30
+ }
31
+ </style>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ const { myLayer } = useAppConfig()
3
+ </script>
4
+
5
+ <template>
6
+ <div class="bg-primary">
7
+ Should have bg-primary
8
+ <h1>Hello World!</h1>
9
+ <pre>{{ myLayer }}</pre>
10
+ <p class="text-gray-900">
11
+ Hello World text base should be gray-900 test
12
+ </p>
13
+ </div>
14
+ </template>