@sbc-connect/nuxt-base 0.1.23 → 0.1.25
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.
- package/CHANGELOG.md +16 -0
- package/app/app.config.ts +72 -10
- package/app/components/Connect/ButtonControl/Buttons.vue +27 -0
- package/app/components/Connect/ButtonControl/Index.vue +66 -0
- package/app/components/Connect/ButtonControl/Wrapper.vue +18 -0
- package/app/components/Connect/FloatingLabel.vue +67 -0
- package/app/components/Connect/Layout/Index.vue +2 -0
- package/app/components/Connect/Select.vue +28 -0
- package/app/components/Connect/Textarea.vue +1 -1
- package/app/composables/useConnectButtonControl.ts +146 -0
- package/app/composables/useConnectTombstone.ts +4 -1
- package/app/interfaces/connect-button-control.ts +22 -0
- package/modules/base-assets/runtime/assets/connect-base-tw.css +0 -11
- package/nuxt.config.ts +3 -4
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @sbc-connect/nuxt-base
|
|
2
2
|
|
|
3
|
+
## 0.1.25
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#84](https://github.com/bcgov/connect-nuxt/pull/84) [`f37700a`](https://github.com/bcgov/connect-nuxt/commit/f37700ab568335df724a5e9472a5e0b4198704b5) Thanks [@deetz99](https://github.com/deetz99)! - Add generic Select component with floating label. Update textarea v-model type.
|
|
8
|
+
|
|
9
|
+
- [#85](https://github.com/bcgov/connect-nuxt/pull/85) [`6b0f70a`](https://github.com/bcgov/connect-nuxt/commit/6b0f70ab895a26c0b049dce84b130d6a04fd911e) Thanks [@kialj876](https://github.com/kialj876)! - Common layout updates, default state key for tombstone, fee store - waive fees, add prioirty, expose cached fees
|
|
10
|
+
|
|
11
|
+
- [#82](https://github.com/bcgov/connect-nuxt/pull/82) [`ba04c84`](https://github.com/bcgov/connect-nuxt/commit/ba04c8424353b32af0811534d9c3edd31e15d39e) Thanks [@deetz99](https://github.com/deetz99)! - feat: Create floating label wrapper component.
|
|
12
|
+
|
|
13
|
+
## 0.1.24
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#80](https://github.com/bcgov/connect-nuxt/pull/80) [`0615542`](https://github.com/bcgov/connect-nuxt/commit/06155422d0a8d61ee862bb3483330610b4a9434d) Thanks [@deetz99](https://github.com/deetz99)! - feat: Move button control to base and handle loading state internally
|
|
18
|
+
|
|
3
19
|
## 0.1.23
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/app/app.config.ts
CHANGED
|
@@ -63,9 +63,6 @@ export default defineAppConfig({
|
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
65
|
button: {
|
|
66
|
-
slots: {
|
|
67
|
-
base: 'cursor-pointer'
|
|
68
|
-
},
|
|
69
66
|
compoundVariants: [
|
|
70
67
|
{
|
|
71
68
|
color: 'primary',
|
|
@@ -280,7 +277,7 @@ export default defineAppConfig({
|
|
|
280
277
|
input: {
|
|
281
278
|
variants: {
|
|
282
279
|
size: {
|
|
283
|
-
|
|
280
|
+
bcGov: {
|
|
284
281
|
base: 'px-2.5 pb-2 pt-6 text-base gap-1.5',
|
|
285
282
|
leading: 'ps-2.5',
|
|
286
283
|
trailing: 'pe-2.5',
|
|
@@ -294,7 +291,34 @@ export default defineAppConfig({
|
|
|
294
291
|
}
|
|
295
292
|
},
|
|
296
293
|
defaultVariants: {
|
|
297
|
-
size: '
|
|
294
|
+
size: 'bcGov',
|
|
295
|
+
color: 'primary',
|
|
296
|
+
variant: 'bcGov'
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
inputMenu: {
|
|
300
|
+
slots: {
|
|
301
|
+
group: 'p-0',
|
|
302
|
+
item: 'py-3 px-4 data-highlighted:not-data-disabled:text-primary data-highlighted:not-data-disabled:before:bg-shade my-0.75 before:rounded-none',
|
|
303
|
+
trailingIcon: 'delay-50 group-data-[state=open]:rotate-180 transition-transform duration-200 text-(--ui-text) group-focus-visible:text-primary group-data-[state=open]:text-primary group-has-[[aria-invalid=true]]:text-error!'
|
|
304
|
+
},
|
|
305
|
+
variants: {
|
|
306
|
+
size: {
|
|
307
|
+
bcGov: {
|
|
308
|
+
base: 'px-2.5 pb-2 pt-6 text-base gap-1.5',
|
|
309
|
+
leading: 'ps-2.5',
|
|
310
|
+
trailing: 'pe-2.5',
|
|
311
|
+
leadingIcon: 'size-5',
|
|
312
|
+
leadingAvatarSize: '2xs',
|
|
313
|
+
trailingIcon: 'size-5'
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
variant: {
|
|
317
|
+
bcGov: 'ring-0 ring-transparent peer rounded-t-sm rounded-b-none bg-shade shadow-input focus:ring-0 focus:outline-none focus:shadow-input-focus text-neutral-highlighted aria-invalid:shadow-input-error aria-invalid:focus:shadow-input-error aria-invalid:ring-0'
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
defaultVariants: {
|
|
321
|
+
size: 'bcGov',
|
|
298
322
|
color: 'primary',
|
|
299
323
|
variant: 'bcGov'
|
|
300
324
|
}
|
|
@@ -303,17 +327,55 @@ export default defineAppConfig({
|
|
|
303
327
|
base: 'bg-gray-200'
|
|
304
328
|
},
|
|
305
329
|
select: {
|
|
330
|
+
slots: {
|
|
331
|
+
base: 'ring-0',
|
|
332
|
+
content: 'rounded-sm',
|
|
333
|
+
group: 'px-0 py-2',
|
|
334
|
+
trailingIcon: 'delay-50 group-data-[state=open]:rotate-180 transition-transform duration-200 text-(--ui-text) group-focus-visible:text-primary group-data-[state=open]:text-primary group-has-[[aria-invalid=true]]:text-error!',
|
|
335
|
+
item: 'my-0.75 text-neutral-highlighted before:rounded-none data-highlighted:not-data-disabled:text-primary data-highlighted:not-data-disabled:before:bg-shade data-[state=checked]:text-primary data-[state=checked]:bg-blue-50',
|
|
336
|
+
itemLeadingIcon: 'group-data-[state=checked]:text-primary group-data-highlighted:not-data-disabled:text-primary text-neutral-highlighted',
|
|
337
|
+
itemTrailingIcon: 'hidden'
|
|
338
|
+
},
|
|
339
|
+
variants: {
|
|
340
|
+
size: {
|
|
341
|
+
bcGov: {
|
|
342
|
+
base: 'px-2.5 pb-2 pt-6 text-base gap-1.5',
|
|
343
|
+
leading: 'ps-2.5',
|
|
344
|
+
trailing: 'pe-2.5',
|
|
345
|
+
leadingIcon: 'size-5',
|
|
346
|
+
leadingAvatarSize: '2xs',
|
|
347
|
+
trailingIcon: 'size-5',
|
|
348
|
+
label: 'p-1.5 text-xs gap-1.5',
|
|
349
|
+
item: 'py-3 px-4 text-sm gap-3',
|
|
350
|
+
itemLeadingIcon: 'size-5',
|
|
351
|
+
itemLeadingAvatarSize: '2xs',
|
|
352
|
+
itemLeadingChip: 'size-5',
|
|
353
|
+
itemLeadingChipSize: 'md',
|
|
354
|
+
itemTrailingIcon: 'size-5'
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
variant: {
|
|
358
|
+
bcGov: 'peer ring-0! rounded-t-sm rounded-b-none bg-shade focus:ring-0 focus:outline-none shadow-input shadow-input focus-visible:shadow-input-focus data-[state=open]:shadow-input-focus text-neutral-highlighted aria-[invalid=true]:shadow-input-error! delay-50'
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
defaultVariants: {
|
|
362
|
+
size: 'bcGov',
|
|
363
|
+
color: 'primary',
|
|
364
|
+
variant: 'bcGov'
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
selectMenu: {
|
|
306
368
|
slots: {
|
|
307
369
|
content: 'rounded-sm',
|
|
308
370
|
group: 'px-0 py-2',
|
|
309
|
-
trailingIcon: 'group-data-[state=open]:rotate-180 transition-transform duration-200 text-(--ui-text) group-data-[state=open]:text-primary group-
|
|
371
|
+
trailingIcon: 'delay-50 group-data-[state=open]:rotate-180 transition-transform duration-200 text-(--ui-text) group-focus-visible:text-primary group-data-[state=open]:text-primary group-has-[[aria-invalid=true]]:text-error!',
|
|
310
372
|
item: 'my-0.75 text-neutral-highlighted before:rounded-none data-highlighted:not-data-disabled:text-primary data-highlighted:not-data-disabled:before:bg-shade data-[state=checked]:text-primary data-[state=checked]:bg-blue-50',
|
|
311
373
|
itemLeadingIcon: 'group-data-[state=checked]:text-primary group-data-highlighted:not-data-disabled:text-primary text-neutral-highlighted'
|
|
312
374
|
},
|
|
313
375
|
variants: {
|
|
314
376
|
size: {
|
|
315
377
|
bcGov: {
|
|
316
|
-
base: 'px-
|
|
378
|
+
base: 'px-2.5 pb-2 pt-6 text-base gap-1.5',
|
|
317
379
|
leading: 'ps-2.5',
|
|
318
380
|
trailing: 'pe-2.5',
|
|
319
381
|
leadingIcon: 'size-5',
|
|
@@ -329,7 +391,7 @@ export default defineAppConfig({
|
|
|
329
391
|
}
|
|
330
392
|
},
|
|
331
393
|
variant: {
|
|
332
|
-
bcGov: 'peer rounded-t-sm rounded-b-none bg-shade focus:ring-0 focus:outline-none shadow-input data-[state=open]:shadow-input-focus
|
|
394
|
+
bcGov: 'peer ring-0! rounded-t-sm rounded-b-none bg-shade focus:ring-0 focus:outline-none shadow-input shadow-input focus-visible:shadow-input-focus data-[state=open]:shadow-input-focus text-neutral-highlighted aria-[invalid=true]:shadow-input-error! delay-50'
|
|
333
395
|
}
|
|
334
396
|
},
|
|
335
397
|
defaultVariants: {
|
|
@@ -341,7 +403,7 @@ export default defineAppConfig({
|
|
|
341
403
|
textarea: {
|
|
342
404
|
variants: {
|
|
343
405
|
size: {
|
|
344
|
-
|
|
406
|
+
bcGov: {
|
|
345
407
|
base: 'px-2.5 pb-1.5 pt-5 text-base gap-1.5 resize-none',
|
|
346
408
|
leading: 'ps-2.5',
|
|
347
409
|
trailing: 'pe-2.5',
|
|
@@ -355,7 +417,7 @@ export default defineAppConfig({
|
|
|
355
417
|
}
|
|
356
418
|
},
|
|
357
419
|
defaultVariants: {
|
|
358
|
-
size: '
|
|
420
|
+
size: 'bcGov',
|
|
359
421
|
color: 'primary',
|
|
360
422
|
variant: 'bcGov'
|
|
361
423
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{ buttons: ConnectButton[], position: 'left' | 'right' }>()
|
|
3
|
+
|
|
4
|
+
// remove alertText and removeAlertSpacing from being added to button html attrs
|
|
5
|
+
const removeButtonAttrs = (button: ConnectButton) => {
|
|
6
|
+
const newButton = { ...button }
|
|
7
|
+
delete newButton['alertText']
|
|
8
|
+
delete newButton['removeAlertSpacing']
|
|
9
|
+
return newButton
|
|
10
|
+
}
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<div
|
|
15
|
+
v-for="(button, i) in buttons"
|
|
16
|
+
:key="`${position}-button-${i}`"
|
|
17
|
+
data-testid="button-wrapper"
|
|
18
|
+
>
|
|
19
|
+
<UButton
|
|
20
|
+
class="max-w-fit px-7 py-3 mb-1"
|
|
21
|
+
v-bind="removeButtonAttrs(button)"
|
|
22
|
+
/>
|
|
23
|
+
<p :class="['text-center', !button.removeAlertSpacing ? 'h-[1.25rem]' : '']">
|
|
24
|
+
<span v-if="button.alertText" class="text-error">{{ button.alertText }}</span>
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const {
|
|
3
|
+
stateKey = 'default-button-control'
|
|
4
|
+
} = defineProps<{
|
|
5
|
+
stateKey?: string
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const { buttonControl: meta } = useConnectButtonControl(stateKey)
|
|
9
|
+
const buttonControl = computed(() => meta.value)
|
|
10
|
+
const leftGroup = computed(() => buttonControl.value?.leftGroup || [])
|
|
11
|
+
const rightGroup = computed(() => buttonControl.value?.rightGroup || [])
|
|
12
|
+
const leftAlertText = computed(() => buttonControl.value?.leftGroup.alertText || undefined)
|
|
13
|
+
const rightAlertText = computed(() => buttonControl.value?.rightGroup.alertText || undefined)
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<template>
|
|
17
|
+
<div
|
|
18
|
+
class="@container"
|
|
19
|
+
data-testid="connect-button-control"
|
|
20
|
+
>
|
|
21
|
+
<div class="grid grid-cols-1 gap-4 @3xl:grid-cols-2">
|
|
22
|
+
<div>
|
|
23
|
+
<div
|
|
24
|
+
class="flex justify-center @3xl:justify-start"
|
|
25
|
+
data-testid="left-buttons"
|
|
26
|
+
>
|
|
27
|
+
<div
|
|
28
|
+
class="relative flex flex-col flex-wrap gap-4 justify-center"
|
|
29
|
+
:class="leftGroup.stacked ? '' : 'flex-row'"
|
|
30
|
+
>
|
|
31
|
+
<div
|
|
32
|
+
v-if="leftAlertText"
|
|
33
|
+
class="absolute flex flex-wrap justify-start bottom-1/3 right-[-13rem] w-[12rem]"
|
|
34
|
+
>
|
|
35
|
+
<p class="text-error" role="alert">
|
|
36
|
+
{{ leftAlertText }}
|
|
37
|
+
</p>
|
|
38
|
+
</div>
|
|
39
|
+
<ConnectButtonControlButtons :buttons="leftGroup.buttons" position="left" />
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<div>
|
|
44
|
+
<div
|
|
45
|
+
class="flex justify-center @3xl:justify-end"
|
|
46
|
+
data-testid="right-buttons"
|
|
47
|
+
>
|
|
48
|
+
<div
|
|
49
|
+
class="relative flex flex-col flex-wrap gap-4 justify-center"
|
|
50
|
+
:class="rightGroup.stacked ? '' : 'flex-row'"
|
|
51
|
+
>
|
|
52
|
+
<div
|
|
53
|
+
v-if="rightAlertText"
|
|
54
|
+
class="absolute flex flex-wrap justify-end bottom-1/3 left-[-13rem] w-[12rem]"
|
|
55
|
+
>
|
|
56
|
+
<p class="text-error" role="alert">
|
|
57
|
+
{{ rightAlertText }}
|
|
58
|
+
</p>
|
|
59
|
+
</div>
|
|
60
|
+
<ConnectButtonControlButtons :buttons="rightGroup.buttons" position="right" />
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const {
|
|
3
|
+
stateKey = 'default-button-control'
|
|
4
|
+
} = defineProps<{
|
|
5
|
+
stateKey?: string
|
|
6
|
+
}>()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<div
|
|
11
|
+
class="bg-shade-inverted pb-6 pt-10"
|
|
12
|
+
data-testid="connect-button-control-wrapper"
|
|
13
|
+
>
|
|
14
|
+
<div class="app-inner-container app-body">
|
|
15
|
+
<ConnectButtonControl :state-key="stateKey" />
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
type VariantOption = 'input' | 'textarea' | 'select' | 'selectmenu'
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
variant = 'input'
|
|
6
|
+
} = defineProps<{
|
|
7
|
+
label: string
|
|
8
|
+
variant?: VariantOption
|
|
9
|
+
id: string
|
|
10
|
+
}>()
|
|
11
|
+
|
|
12
|
+
const variantClass: Record<VariantOption, string[]> = {
|
|
13
|
+
input: [
|
|
14
|
+
'-translate-y-1/2 top-1/2 group-focus-within:top-3 delay-50',
|
|
15
|
+
'group-has-[div>input:not(:placeholder-shown)]:top-3',
|
|
16
|
+
'group-has-[div>input:not(:placeholder-shown)]:text-xs',
|
|
17
|
+
'group-has-[div>input[aria-invalid=true]]:text-error'
|
|
18
|
+
],
|
|
19
|
+
textarea: [
|
|
20
|
+
'top-1 group-focus-within:top-1 delay-50',
|
|
21
|
+
'group-has-[div>textarea:not(:placeholder-shown)]:top-1',
|
|
22
|
+
'group-has-[div>textarea:not(:placeholder-shown)]:text-xs',
|
|
23
|
+
'group-has-[div>textarea[aria-invalid=true]]:text-error'
|
|
24
|
+
],
|
|
25
|
+
select: [
|
|
26
|
+
'delay-100',
|
|
27
|
+
'-translate-y-1/2 top-1/2 group-focus-within:top-3',
|
|
28
|
+
'group-has-[button[aria-invalid=true]]:text-error',
|
|
29
|
+
'group-has-[button[data-state=open]]:top-3',
|
|
30
|
+
'group-has-[button[data-state=open]]:text-xs',
|
|
31
|
+
'group-has-[button:not([data-placeholder])]:top-3',
|
|
32
|
+
'group-has-[button:not([data-placeholder])]:text-xs',
|
|
33
|
+
'group-has-[button[data-state=open]:not([aria-invalid=true])]:text-primary'
|
|
34
|
+
],
|
|
35
|
+
selectmenu: [
|
|
36
|
+
'delay-100',
|
|
37
|
+
'-translate-y-1/2 top-1/2 group-focus-within:top-3',
|
|
38
|
+
'group-has-[button[aria-invalid=true]]:text-error',
|
|
39
|
+
'group-has-[button[data-state=open]]:top-3',
|
|
40
|
+
'group-has-[button[data-state=open]]:text-xs',
|
|
41
|
+
'group-has-[button[data-placeholder=false]]:top-3',
|
|
42
|
+
'group-has-[button[data-placeholder=false]]:text-xs',
|
|
43
|
+
'group-has-[button[data-state=open]:not([aria-invalid=true])]:text-primary'
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<div class="relative group">
|
|
50
|
+
<span
|
|
51
|
+
:id
|
|
52
|
+
:class="[
|
|
53
|
+
variantClass[variant],
|
|
54
|
+
'line-clamp-1 px-2.5',
|
|
55
|
+
'absolute z-10 group-focus-within:text-primary',
|
|
56
|
+
'pointer-events-none text-neutral transition-all',
|
|
57
|
+
'motion-reduce:transition-none duration-200',
|
|
58
|
+
'group-focus-within:text-xs',
|
|
59
|
+
'group-focus-within:text-primary',
|
|
60
|
+
'w-fit',
|
|
61
|
+
]"
|
|
62
|
+
>
|
|
63
|
+
{{ label }}
|
|
64
|
+
</span>
|
|
65
|
+
<slot />
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
<slot name="breadcrumb">
|
|
10
10
|
<ConnectBreadcrumb />
|
|
11
11
|
</slot>
|
|
12
|
+
<slot name="bottomHeaders" />
|
|
12
13
|
<main class="app-body px-2 sm:px-4">
|
|
13
14
|
<slot name="body">
|
|
14
15
|
<div class="app-inner-container grow flex flex-col overflow-hidden">
|
|
@@ -16,6 +17,7 @@
|
|
|
16
17
|
</div>
|
|
17
18
|
</slot>
|
|
18
19
|
</main>
|
|
20
|
+
<slot name="topFooters" />
|
|
19
21
|
<slot name="footer">
|
|
20
22
|
<ConnectFooter />
|
|
21
23
|
</slot>
|
|
@@ -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,146 @@
|
|
|
1
|
+
const defaultOptions: ConnectButtonControlOptions = {
|
|
2
|
+
handleLoading: true,
|
|
3
|
+
clearAlertTextOnClick: true
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export const useConnectButtonControl = (
|
|
7
|
+
stateKey: string = 'default-button-control',
|
|
8
|
+
opts: Partial<ConnectButtonControlOptions> = {}
|
|
9
|
+
) => {
|
|
10
|
+
const options = {
|
|
11
|
+
...defaultOptions,
|
|
12
|
+
...opts
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const buttonControl = useState<ConnectButtonControl>(stateKey, () => ({
|
|
16
|
+
leftGroup: { buttons: [] },
|
|
17
|
+
rightGroup: { buttons: [] }
|
|
18
|
+
}))
|
|
19
|
+
|
|
20
|
+
const forEachButton = (update: (button: ConnectButton, group: 'left' | 'right', index: number) => void) => {
|
|
21
|
+
buttonControl.value.leftGroup?.buttons?.forEach((btn, index) => update(btn, 'left', index))
|
|
22
|
+
buttonControl.value.rightGroup?.buttons?.forEach((btn, index) => update(btn, 'right', index))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const forEachGroup = (update: (group: ConnectButtonGroup) => void) => {
|
|
26
|
+
if (buttonControl.value.leftGroup) {
|
|
27
|
+
update(buttonControl.value.leftGroup)
|
|
28
|
+
}
|
|
29
|
+
if (buttonControl.value.rightGroup) {
|
|
30
|
+
update(buttonControl.value.rightGroup)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function setAlertText(text?: string, group?: 'left' | 'right', index?: number) {
|
|
35
|
+
forEachGroup(group => group.alertText = undefined)
|
|
36
|
+
forEachButton(btn => btn.alertText = undefined)
|
|
37
|
+
|
|
38
|
+
if (text && group !== undefined) {
|
|
39
|
+
await nextTick()
|
|
40
|
+
|
|
41
|
+
const buttonGroup = group === 'left' ? buttonControl.value.leftGroup : buttonControl.value.rightGroup
|
|
42
|
+
|
|
43
|
+
if (index !== undefined) {
|
|
44
|
+
const button = buttonGroup.buttons[index]
|
|
45
|
+
if (button) {
|
|
46
|
+
button.alertText = text
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
buttonGroup.alertText = text
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const handleClick = (
|
|
55
|
+
originalClick: ConnectButton['onClick'],
|
|
56
|
+
group: 'left' | 'right',
|
|
57
|
+
index: number
|
|
58
|
+
) => {
|
|
59
|
+
if (!originalClick || typeof originalClick !== 'function') {
|
|
60
|
+
return undefined
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return async () => {
|
|
64
|
+
try {
|
|
65
|
+
if (options.clearAlertTextOnClick) {
|
|
66
|
+
await setAlertText(undefined)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (options.handleLoading) {
|
|
70
|
+
const clickedButton = buttonControl.value[group === 'left' ? 'leftGroup' : 'rightGroup']?.buttons[index]
|
|
71
|
+
if (!clickedButton) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
clickedButton.loading = true
|
|
76
|
+
forEachButton((button, btnGroup, btnIndex) => {
|
|
77
|
+
if (btnGroup !== group || btnIndex !== index) {
|
|
78
|
+
button.disabled = true
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
await (originalClick as () => Promise<void> | void)()
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (import.meta.env.DEV) {
|
|
86
|
+
console.error(`Error on button click. group: ${group} index: ${index} error: ${error}`)
|
|
87
|
+
}
|
|
88
|
+
} finally {
|
|
89
|
+
if (options.handleLoading) {
|
|
90
|
+
forEachButton((button) => {
|
|
91
|
+
button.loading = false
|
|
92
|
+
button.disabled = false
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function setButtonControl(config: ConnectButtonControl) {
|
|
100
|
+
const updateGroup = (config: { buttons: ConnectButton[] }, group: 'left' | 'right') => {
|
|
101
|
+
if (!config || !config.buttons.length) {
|
|
102
|
+
return { ...config, buttons: [] }
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...config,
|
|
106
|
+
buttons: config.buttons.map((button, index) => ({
|
|
107
|
+
...button,
|
|
108
|
+
onClick: handleClick(button.onClick, group, index)
|
|
109
|
+
}))
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
buttonControl.value = {
|
|
114
|
+
leftGroup: updateGroup(config.leftGroup, 'left'),
|
|
115
|
+
rightGroup: updateGroup(config.rightGroup, 'right')
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function handleButtonLoading(
|
|
120
|
+
loading: boolean,
|
|
121
|
+
group?: 'left' | 'right',
|
|
122
|
+
index?: number
|
|
123
|
+
) {
|
|
124
|
+
if (!loading) {
|
|
125
|
+
forEachButton((button) => {
|
|
126
|
+
button.loading = false
|
|
127
|
+
button.disabled = false
|
|
128
|
+
})
|
|
129
|
+
} else if (group !== undefined && index !== undefined) {
|
|
130
|
+
forEachButton((button, btnGroup, btnIndex) => {
|
|
131
|
+
if (btnGroup === group && btnIndex === index) {
|
|
132
|
+
button.loading = true
|
|
133
|
+
} else {
|
|
134
|
+
button.disabled = true
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
setButtonControl,
|
|
142
|
+
setAlertText,
|
|
143
|
+
handleButtonLoading,
|
|
144
|
+
buttonControl
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export const useConnectTombstone = (
|
|
1
|
+
export const useConnectTombstone = (
|
|
2
|
+
stateKey: string = 'default-tombstone',
|
|
3
|
+
initialState?: Partial<ConnectTombstoneState>
|
|
4
|
+
) => {
|
|
2
5
|
function createInitialState(): ConnectTombstoneState {
|
|
3
6
|
const baseState: ConnectTombstoneState = {
|
|
4
7
|
loading: false,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ButtonProps } from '@nuxt/ui'
|
|
2
|
+
|
|
3
|
+
export interface ConnectButton extends ButtonProps {
|
|
4
|
+
alertText?: string
|
|
5
|
+
removeAlertSpacing?: boolean
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ConnectButtonGroup {
|
|
9
|
+
alertText?: string
|
|
10
|
+
buttons: ConnectButton[]
|
|
11
|
+
stacked?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ConnectButtonControl {
|
|
15
|
+
leftGroup: ConnectButtonGroup
|
|
16
|
+
rightGroup: ConnectButtonGroup
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ConnectButtonControlOptions {
|
|
20
|
+
handleLoading: boolean
|
|
21
|
+
clearAlertTextOnClick: boolean
|
|
22
|
+
}
|
|
@@ -276,14 +276,3 @@ body {
|
|
|
276
276
|
@apply pointer-events-none absolute left-0 top-1 text-neutral text-xs font-medium px-2.5 transition-all duration-200 peer-focus:top-1 peer-focus:text-xs peer-placeholder-shown:text-sm peer-placeholder-shown:top-2.5 peer-focus:translate-none peer-focus:text-primary peer-aria-invalid:text-error;
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
|
-
|
|
280
|
-
/* TODO: maybe delete this */
|
|
281
|
-
/* Extra Utilities */
|
|
282
|
-
/* This should be working out-of-the-box from Nuxt UI but isnt for some reason */
|
|
283
|
-
/* https://ui.nuxt.com/getting-started/theme#neutral */
|
|
284
|
-
/* .text-highlighted {
|
|
285
|
-
color: var(--color-gray-900);
|
|
286
|
-
@variant dark {
|
|
287
|
-
color: var(--color-gray-900);
|
|
288
|
-
}
|
|
289
|
-
} */
|
package/nuxt.config.ts
CHANGED
|
@@ -120,10 +120,9 @@ export default defineNuxtConfig({
|
|
|
120
120
|
}
|
|
121
121
|
},
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// },
|
|
123
|
+
typescript: {
|
|
124
|
+
includeWorkspace: true // allow auto imports in tests
|
|
125
|
+
},
|
|
127
126
|
|
|
128
127
|
runtimeConfig: {
|
|
129
128
|
public: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sbc-connect/nuxt-base",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.25",
|
|
5
5
|
"repository": "github:bcgov/connect-nuxt",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"typescript": "5.9.3",
|
|
26
26
|
"vue-tsc": "3.1.2",
|
|
27
27
|
"@sbc-connect/eslint-config": "0.0.8",
|
|
28
|
-
"@sbc-connect/
|
|
29
|
-
"@sbc-connect/
|
|
28
|
+
"@sbc-connect/vitest-config": "0.0.6",
|
|
29
|
+
"@sbc-connect/playwright-config": "0.0.8"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"preinstall": "npx only-allow pnpm",
|