barbican-reset 3.36.0 → 3.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/BrAlert.vue +2 -2
- package/components/BrButton.vue +11 -3
- package/components/BrCard.vue +1 -1
- package/components/BrCardTearoff.vue +1 -1
- package/components/BrCollapse/Button.vue +1 -1
- package/components/BrConfirmDone.vue +6 -6
- package/components/BrConfirmEmail.vue +6 -6
- package/components/BrDetails.vue +5 -1
- package/components/BrFormCheckbox.vue +3 -3
- package/components/BrFormCheckboxGroup.vue +1 -1
- package/components/BrFormDate.vue +1 -1
- package/components/BrFormEdit.vue +2 -2
- package/components/BrFormEmail.vue +1 -1
- package/components/BrFormInput.vue +18 -1
- package/components/BrFormPassword.vue +2 -2
- package/components/BrFormRadio.vue +3 -3
- package/components/BrFormRadioGroup.vue +2 -2
- package/components/BrFormRow.vue +2 -2
- package/components/BrFormSelect.vue +3 -57
- package/components/BrFormSelectItem.vue +1 -7
- package/components/BrFormTel.vue +1 -1
- package/components/BrFormTextarea.vue +1 -1
- package/components/BrFormToggle.vue +6 -9
- package/components/BrFormUpdate.vue +1 -1
- package/components/BrFormVisible.vue +3 -3
- package/components/BrLink.vue +20 -5
- package/components/BrLoader.vue +1 -1
- package/components/BrOverlay.vue +57 -23
- package/components/BrQrCode.vue +21 -0
- package/icons/{city_of_london_lockup.vue → CityOfLondonLockup.vue} +5 -12
- package/icons/Dropdown.vue +6 -0
- package/icons/Renew.vue +5 -0
- package/icons/dots.vue +50 -0
- package/icons/index.js +18 -18
- package/index.js +52 -102
- package/package.json +8 -14
- package/scss/_atomic.scss +1 -1
- package/scss/_br-button.scss +13 -19
- package/scss/_br-form-select.scss +52 -0
- package/scss/_br-form-toggle.scss +27 -24
- package/scss/_br-overlay.scss +29 -4
- package/scss/_br-qr-code.scss +3 -0
- package/scss/_br-table-row.scss +1 -1
- package/scss/_input.scss +1 -1
- package/scss/_variables.scss +176 -22
- package/scss/card/_membership-new.scss +10 -23
- package/scss/index.scss +2 -1
- package/scss/mixins/_br-alert.scss +1 -1
- package/scss/mixins/_br-card.scss +1 -1
- package/scss/mixins/_br-form-radio.scss +1 -1
- package/scss/mixins/_content.scss +1 -1
- package/scss/mixins/_focus.scss +1 -1
- package/scss/mixins/_font-size.scss +3 -3
- package/scss/mixins/buttons/_custom.scss +12 -85
- package/scss/mixins/buttons/_outline.scss +8 -12
- package/scss/mixins/buttons/_setup.scss +3 -7
- package/scss/mixins/buttons/custom/_edit-input.scss +22 -0
- package/scss/mixins/buttons/custom/_exit-overlay-bg.scss +12 -0
- package/scss/mixins/buttons/custom/_exit-overlay.scss +3 -19
- package/scss/mixins/buttons/custom/_exit.scss +11 -0
- package/scss/mixins/buttons/custom/_invisible.scss +2 -2
- package/scss/mixins/buttons/custom/_link.scss +19 -0
- package/scss/mixins/buttons/custom/_manage-order.scss +4 -4
- package/scss/mixins/buttons/custom/_outline-secondary.scss +1 -5
- package/scss/mixins/buttons/custom/_renew-membership.scss +3 -3
- package/scss/mixins/buttons/custom/_select-form.scss +15 -5
- package/scss/mixins/buttons/custom/_voucher-amount.scss +18 -0
- package/scss/mixins/card/_membership.scss +10 -49
- package/scss/mixins/card/_qrcode.scss +60 -3
- package/scss/mixins/input/_checkbox.scss +1 -1
- package/scss/mixins/input/_generic.scss +1 -1
- package/scss/mixins/input/_select.scss +1 -1
- package/scss/mixins/input/_text.scss +1 -1
- package/scss/mixins/table/_details.scss +1 -1
- package/scss/mixins/table/_etickets.scss +1 -1
- package/scss/mixins/table/_gifts.scss +1 -1
- package/scss/mixins/table/_orders.scss +1 -1
- package/scss/mixins/table/_preferences.scss +1 -1
- package/scss/mixins/table/_tickets.scss +1 -1
- package/scss/reset.scss +4 -0
- package/utils/datetimes.js +162 -0
- package/utils/numbers.js +23 -0
- package/utils.js +6 -0
- package/components/BrAnchor.vue +0 -34
- package/components/BrButton/dot_typing.vue +0 -60
- package/components/BrButton/remove_ticket.vue +0 -46
- package/icons/account/index.js +0 -20
- package/icons/confirm/index.js +0 -4
- package/icons/password/index.js +0 -4
- package/icons/qr_code.vue +0 -5
- package/icons/stream/airplay.vue +0 -15
- package/icons/stream/cast.vue +0 -13
- package/icons/stream/chat.vue +0 -15
- package/icons/stream/cog.vue +0 -13
- package/icons/stream/index.js +0 -15
- package/icons/stream/live.vue +0 -12
- package/icons/stream/volume.vue +0 -13
- package/icons/wheelchair.vue +0 -18
- package/logos/arts-council-england.svg +0 -1
- package/logos/barbican.svg +0 -1
- package/logos/city-of-london.svg +0 -1
- package/logos/lso.svg +0 -1
- package/scripts/helpers.js +0 -6
- package/scss/_br-form-select-link.scss +0 -15
- /package/{scripts/animations → animations}/confirm.js +0 -0
- /package/icons/{account/contact.vue → AccountContact.vue} +0 -0
- /package/icons/{account/edit.vue → AccountEdit.vue} +0 -0
- /package/icons/{account/membership.vue → AccountMembership.vue} +0 -0
- /package/icons/{account/orders.vue → AccountOrders.vue} +0 -0
- /package/icons/{account/payment.vue → AccountPayment.vue} +0 -0
- /package/icons/{person.vue → AccountPerson.vue} +0 -0
- /package/icons/{account/personal.vue → AccountPersonal.vue} +0 -0
- /package/icons/{account/ticket.vue → AccountTicket.vue} +0 -0
- /package/icons/{back_arrow.vue → BackArrow.vue} +0 -0
- /package/icons/{city_of_london.vue → CityOfLondon.vue} +0 -0
- /package/icons/{information.vue → Info.vue} +0 -0
- /package/{scripts/helpers → utils}/compareArrays.js +0 -0
- /package/{scripts/helpers → utils}/constrainTabbing.js +0 -0
- /package/{scripts/helpers → utils}/formatKebabCase.js +0 -0
- /package/{scripts/helpers → utils}/logObject.js +0 -0
package/components/BrAlert.vue
CHANGED
package/components/BrButton.vue
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
aria-live="polite"
|
|
8
8
|
ref="button">
|
|
9
9
|
<template v-if="state == 'default'">
|
|
10
|
-
<slot name="default"
|
|
10
|
+
<slot name="default" />
|
|
11
11
|
</template>
|
|
12
12
|
<template v-else-if="state == 'loading'">
|
|
13
13
|
<template v-if="$slots.loading">
|
|
14
14
|
<slot name="loading">loading</slot>
|
|
15
15
|
</template>
|
|
16
|
-
<
|
|
16
|
+
<dots-animation v-else />
|
|
17
17
|
</template>
|
|
18
18
|
<template v-else-if="state == 'loaded'">
|
|
19
19
|
<slot name="loaded">loaded</slot>
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
<script setup>
|
|
28
28
|
import { computed, useTemplateRef } from 'vue'
|
|
29
|
-
import
|
|
29
|
+
import DotsAnimation from '../icons/Dots.vue'
|
|
30
30
|
|
|
31
31
|
const emits = defineEmits(['click'])
|
|
32
32
|
|
|
@@ -43,6 +43,10 @@ const generateClassnames = computed(() => {
|
|
|
43
43
|
classnames.push('btn-slim')
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
if (!props.noReact) {
|
|
47
|
+
classnames.push('btn-react')
|
|
48
|
+
}
|
|
49
|
+
|
|
46
50
|
return classnames
|
|
47
51
|
})
|
|
48
52
|
|
|
@@ -69,6 +73,10 @@ const props = defineProps({
|
|
|
69
73
|
type: Boolean,
|
|
70
74
|
default: false,
|
|
71
75
|
},
|
|
76
|
+
noReact: {
|
|
77
|
+
type: Boolean,
|
|
78
|
+
default: false,
|
|
79
|
+
},
|
|
72
80
|
})
|
|
73
81
|
|
|
74
82
|
defineExpose({
|
package/components/BrCard.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<br-card class="confirm-done">
|
|
3
|
-
<done-icon />
|
|
3
|
+
<br-done-icon />
|
|
4
4
|
<br-card-title class="title">Done</br-card-title>
|
|
5
5
|
<br-card-text v-if="$slots.default" class="margin-top-1">
|
|
6
6
|
<slot />
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
<script setup>
|
|
12
12
|
import { onMounted } from 'vue'
|
|
13
|
-
import { animateDone } from '
|
|
13
|
+
import { animateDone } from '../animations/confirm'
|
|
14
14
|
|
|
15
|
-
import BrCard from '
|
|
16
|
-
import BrCardTitle from '
|
|
17
|
-
import BrCardText from '
|
|
18
|
-
import
|
|
15
|
+
import BrCard from './BrCard.vue'
|
|
16
|
+
import BrCardTitle from './BrCardTitle.vue'
|
|
17
|
+
import BrCardText from './BrCardText.vue'
|
|
18
|
+
import BrDoneIcon from '../icons/Confirm/Done.vue'
|
|
19
19
|
|
|
20
20
|
onMounted(() => animateDone())
|
|
21
21
|
</script>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<br-card class="confirm-email">
|
|
3
|
-
<email-icon />
|
|
3
|
+
<br-email-icon />
|
|
4
4
|
<br-card-title v-if="$slots.title" class="title">
|
|
5
5
|
<slot name="title" />
|
|
6
6
|
</br-card-title>
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
|
|
13
13
|
<script setup>
|
|
14
14
|
import { onMounted } from 'vue'
|
|
15
|
-
import { animateEmail } from '
|
|
15
|
+
import { animateEmail } from '../animations/confirm'
|
|
16
16
|
|
|
17
|
-
import BrCard from '
|
|
18
|
-
import BrCardTitle from '
|
|
19
|
-
import BrCardText from '
|
|
20
|
-
import
|
|
17
|
+
import BrCard from './BrCard.vue'
|
|
18
|
+
import BrCardTitle from './BrCardTitle.vue'
|
|
19
|
+
import BrCardText from './BrCardText.vue'
|
|
20
|
+
import BrEmailIcon from '../icons/Confirm/Email.vue'
|
|
21
21
|
|
|
22
22
|
onMounted(() => animateEmail())
|
|
23
23
|
</script>
|
package/components/BrDetails.vue
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="br-details">
|
|
3
|
-
<br-button
|
|
3
|
+
<br-button
|
|
4
|
+
:data-test="'toggle-' + label"
|
|
5
|
+
variant="summary"
|
|
6
|
+
@click="update"
|
|
7
|
+
no-react>
|
|
4
8
|
<div class="wrap-title">
|
|
5
9
|
<slot name="title">Title goes here</slot>
|
|
6
10
|
</div>
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
|
|
29
29
|
<script setup>
|
|
30
30
|
import { computed, useAttrs } from 'vue'
|
|
31
|
-
import formatKebabCase from '
|
|
32
|
-
import BrFormLabel from '
|
|
33
|
-
import BrFormInput from '
|
|
31
|
+
import formatKebabCase from '../utils/formatKebabCase'
|
|
32
|
+
import BrFormLabel from './BrFormLabel.vue'
|
|
33
|
+
import BrFormInput from './BrFormInput.vue'
|
|
34
34
|
|
|
35
35
|
/** All fallthrough attributes from the parent. */
|
|
36
36
|
const attrs = useAttrs()
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
14
|
<script>
|
|
15
|
-
import BrButton from '
|
|
16
|
-
import EditIcon from '
|
|
15
|
+
import BrButton from './BrButton.vue'
|
|
16
|
+
import EditIcon from '../icons/AccountEdit.vue'
|
|
17
17
|
|
|
18
18
|
export default {
|
|
19
19
|
props: {
|
|
@@ -6,12 +6,13 @@
|
|
|
6
6
|
:type="generateType"
|
|
7
7
|
v-model="model"
|
|
8
8
|
v-bind="$attrs"
|
|
9
|
+
:style="generateStyles"
|
|
9
10
|
:id="id" />
|
|
10
11
|
</template>
|
|
11
12
|
|
|
12
13
|
<script setup>
|
|
13
14
|
import { computed } from 'vue'
|
|
14
|
-
import formatKebabCase from '
|
|
15
|
+
import formatKebabCase from '../utils/formatKebabCase'
|
|
15
16
|
|
|
16
17
|
const model = defineModel()
|
|
17
18
|
|
|
@@ -20,6 +21,7 @@ const props = defineProps({
|
|
|
20
21
|
type: String,
|
|
21
22
|
dataTest: String,
|
|
22
23
|
autocomplete: String,
|
|
24
|
+
inputCustomColors: Object,
|
|
23
25
|
})
|
|
24
26
|
|
|
25
27
|
defineOptions({
|
|
@@ -56,6 +58,21 @@ const generateDataTest = computed(() => {
|
|
|
56
58
|
return result && formatKebabCase(result)
|
|
57
59
|
})
|
|
58
60
|
|
|
61
|
+
const generateStyles = computed(function () {
|
|
62
|
+
const colors = props.inputCustomColors
|
|
63
|
+
|
|
64
|
+
if (!colors) return
|
|
65
|
+
|
|
66
|
+
return Object.fromEntries(
|
|
67
|
+
[
|
|
68
|
+
['--background-color-toggle-unchecked', colors.default],
|
|
69
|
+
['--background-color-toggle-checked', colors.checked],
|
|
70
|
+
['--background-color-toggle-before-unchecked', colors.defaultCircle],
|
|
71
|
+
['--background-color-toggle-before-checked', colors.checkedCircle],
|
|
72
|
+
].filter(([, value]) => value),
|
|
73
|
+
)
|
|
74
|
+
})
|
|
75
|
+
|
|
59
76
|
// @description Returns a string for the "type" attribute
|
|
60
77
|
// @returns {string} result - string based on preceeding conditions
|
|
61
78
|
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
<script setup>
|
|
14
14
|
import { ref, computed } from 'vue'
|
|
15
|
-
import BrFormInput from '
|
|
16
|
-
import BrFormVisible from '
|
|
15
|
+
import BrFormInput from './BrFormInput.vue'
|
|
16
|
+
import BrFormVisible from './BrFormVisible.vue'
|
|
17
17
|
|
|
18
18
|
const props = defineProps({
|
|
19
19
|
toggle: Boolean,
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
|
|
21
21
|
<script setup>
|
|
22
22
|
import { computed } from 'vue'
|
|
23
|
-
import formatKebabCase from '
|
|
23
|
+
import formatKebabCase from '../utils/formatKebabCase'
|
|
24
24
|
|
|
25
|
-
import BrFormLabel from '
|
|
26
|
-
import BrFormInput from '
|
|
25
|
+
import BrFormLabel from './BrFormLabel.vue'
|
|
26
|
+
import BrFormInput from './BrFormInput.vue'
|
|
27
27
|
|
|
28
28
|
const generateClassnames = computed(() => {
|
|
29
29
|
let classnames = ['br-form-radio']
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
</template>
|
|
18
18
|
|
|
19
19
|
<script setup>
|
|
20
|
-
import BrFormRadio from '
|
|
21
|
-
import BrWrap from '
|
|
20
|
+
import BrFormRadio from './BrFormRadio.vue'
|
|
21
|
+
import BrWrap from './BrWrap.vue'
|
|
22
22
|
|
|
23
23
|
const model = defineModel()
|
|
24
24
|
|
package/components/BrFormRow.vue
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
<script setup>
|
|
18
18
|
import { computed } from 'vue'
|
|
19
|
-
import formatKebabCase from '
|
|
20
|
-
import BrFormLabel from '
|
|
19
|
+
import formatKebabCase from '../utils/formatKebabCase'
|
|
20
|
+
import BrFormLabel from './BrFormLabel.vue'
|
|
21
21
|
|
|
22
22
|
const props = defineProps({
|
|
23
23
|
label: String,
|
|
@@ -9,16 +9,8 @@
|
|
|
9
9
|
aria-expanded="false"
|
|
10
10
|
data-title="title"
|
|
11
11
|
role="combobox">
|
|
12
|
+
<br-dropdown-icon />
|
|
12
13
|
<span class="br-select-form-button--title">{{ placeholder }}</span>
|
|
13
|
-
<svg
|
|
14
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
15
|
-
class="br-select-form-icon"
|
|
16
|
-
width="12"
|
|
17
|
-
height="6"
|
|
18
|
-
version="1.1"
|
|
19
|
-
viewBox="0 0 12 6">
|
|
20
|
-
<path d="M6,5.48L1.04.52h9.92l-4.96,4.96Z" />
|
|
21
|
-
</svg>
|
|
22
14
|
</button>
|
|
23
15
|
<ul class="br-select-form-list" role="listbox">
|
|
24
16
|
<slot />
|
|
@@ -27,7 +19,8 @@
|
|
|
27
19
|
</template>
|
|
28
20
|
|
|
29
21
|
<script setup>
|
|
30
|
-
import
|
|
22
|
+
import BrDropdownIcon from '../icons/Dropdown.vue'
|
|
23
|
+
import constrainTabbing from '../utils/constrainTabbing'
|
|
31
24
|
|
|
32
25
|
let listenConstrainTabbing = null
|
|
33
26
|
|
|
@@ -117,52 +110,5 @@ defineProps({
|
|
|
117
110
|
type: String,
|
|
118
111
|
default: 'Add to wallet',
|
|
119
112
|
},
|
|
120
|
-
// options: {
|
|
121
|
-
// type: Array,
|
|
122
|
-
// default: [
|
|
123
|
-
// {
|
|
124
|
-
// link: {
|
|
125
|
-
// href: 'https://apple.com',
|
|
126
|
-
// target: '_blank',
|
|
127
|
-
// title: 'apple',
|
|
128
|
-
// },
|
|
129
|
-
// },
|
|
130
|
-
// {
|
|
131
|
-
// link: {
|
|
132
|
-
// href: 'https://google.com',
|
|
133
|
-
// target: '_blank',
|
|
134
|
-
// title: 'google',
|
|
135
|
-
// },
|
|
136
|
-
// },
|
|
137
|
-
// ],
|
|
138
|
-
// },
|
|
139
113
|
})
|
|
140
114
|
</script>
|
|
141
|
-
|
|
142
|
-
<style scoped>
|
|
143
|
-
.br-select-form {
|
|
144
|
-
position: relative;
|
|
145
|
-
width: 200px;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.br-select-form-button[aria-expanded='false'] + .br-select-form-list {
|
|
149
|
-
visibility: hidden;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
.br-select-form-list {
|
|
153
|
-
border-bottom: 1px solid currentColor;
|
|
154
|
-
border-right: 1px solid currentColor;
|
|
155
|
-
border-left: 1px solid currentColor;
|
|
156
|
-
border-bottom-right-radius: 0.5rem;
|
|
157
|
-
border-bottom-left-radius: 0.5rem;
|
|
158
|
-
background-color: white;
|
|
159
|
-
position: absolute;
|
|
160
|
-
margin-bottom: 0;
|
|
161
|
-
list-style: none;
|
|
162
|
-
overflow: hidden;
|
|
163
|
-
padding-left: 0;
|
|
164
|
-
margin-top: 0;
|
|
165
|
-
width: 100%;
|
|
166
|
-
z-index: 2;
|
|
167
|
-
}
|
|
168
|
-
</style>
|
package/components/BrFormTel.vue
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="generateClasses">
|
|
3
|
-
<
|
|
4
|
-
<span>
|
|
5
|
-
<slot />
|
|
6
|
-
</span>
|
|
7
|
-
<BrFormInput v-bind="$attrs" type="checkbox" />
|
|
8
|
-
</BrFormLabel>
|
|
3
|
+
<BrFormInput v-bind="$attrs" type="checkbox" />
|
|
9
4
|
</div>
|
|
10
5
|
</template>
|
|
11
6
|
|
|
12
7
|
<script setup>
|
|
13
8
|
import { computed } from 'vue'
|
|
14
|
-
import
|
|
15
|
-
import BrFormInput from '#components/BrFormInput.vue'
|
|
9
|
+
import BrFormInput from './BrFormInput.vue'
|
|
16
10
|
|
|
17
11
|
defineOptions({
|
|
18
12
|
inheritAttrs: false,
|
|
@@ -20,6 +14,7 @@ defineOptions({
|
|
|
20
14
|
|
|
21
15
|
const props = defineProps({
|
|
22
16
|
drawer: Boolean,
|
|
17
|
+
inputCustomClass: String,
|
|
23
18
|
})
|
|
24
19
|
|
|
25
20
|
const generateClasses = computed(() => {
|
|
@@ -27,7 +22,9 @@ const generateClasses = computed(() => {
|
|
|
27
22
|
|
|
28
23
|
if (props.drawer) result.push('drawer')
|
|
29
24
|
|
|
30
|
-
if (
|
|
25
|
+
if (props.inputCustomClass) result.push(props.inputCustomClass)
|
|
26
|
+
|
|
27
|
+
if (!props.drawer && !props.inputCustomClass) result.push('default')
|
|
31
28
|
|
|
32
29
|
return result
|
|
33
30
|
})
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
</template>
|
|
14
14
|
|
|
15
15
|
<script setup>
|
|
16
|
-
import BrButton from '
|
|
17
|
-
import HidePasswordIcon from '
|
|
18
|
-
import ShowPasswordIcon from '
|
|
16
|
+
import BrButton from './BrButton.vue'
|
|
17
|
+
import HidePasswordIcon from '../icons/Password/Hide.vue'
|
|
18
|
+
import ShowPasswordIcon from '../icons/Password/Show.vue'
|
|
19
19
|
|
|
20
20
|
const props = defineProps({
|
|
21
21
|
visible: Boolean,
|
package/components/BrLink.vue
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<a
|
|
3
|
-
|
|
2
|
+
<a
|
|
3
|
+
v-if="isExternal"
|
|
4
|
+
:href="to"
|
|
5
|
+
:class="generateClassnames"
|
|
6
|
+
@click="animateDots">
|
|
7
|
+
<slot v-if="!showDots" />
|
|
8
|
+
<dots-animation v-else />
|
|
4
9
|
</a>
|
|
5
|
-
<router-link v-else :to="to" :class="generateClassnames">
|
|
6
|
-
<slot />
|
|
10
|
+
<router-link v-else :to="to" :class="generateClassnames" @click="animateDots">
|
|
11
|
+
<slot v-if="!showDots" />
|
|
12
|
+
<dots-animation v-else />
|
|
7
13
|
</router-link>
|
|
8
14
|
</template>
|
|
9
15
|
|
|
10
16
|
<script setup>
|
|
11
17
|
// https://vueschool.io/lessons/extending-router-link-for-external-urls
|
|
12
18
|
|
|
13
|
-
import
|
|
19
|
+
import DotsAnimation from '../icons/Dots.vue'
|
|
20
|
+
|
|
21
|
+
import { computed, ref } from 'vue'
|
|
22
|
+
|
|
23
|
+
const showDots = ref(false)
|
|
24
|
+
|
|
25
|
+
const animateDots = () => (showDots.value = props.animate)
|
|
14
26
|
|
|
15
27
|
const isExternal = computed(() => typeof props.to == 'string')
|
|
16
28
|
|
|
@@ -44,5 +56,8 @@ const props = defineProps({
|
|
|
44
56
|
active: {
|
|
45
57
|
type: Boolean,
|
|
46
58
|
},
|
|
59
|
+
animate: {
|
|
60
|
+
type: Boolean,
|
|
61
|
+
},
|
|
47
62
|
})
|
|
48
63
|
</script>
|
package/components/BrLoader.vue
CHANGED
package/components/BrOverlay.vue
CHANGED
|
@@ -1,40 +1,74 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<div class="br-overlay-
|
|
4
|
-
<
|
|
2
|
+
<Transition name="fade">
|
|
3
|
+
<div v-if="show" class="br-overlay-wrap">
|
|
4
|
+
<div class="br-overlay-content">
|
|
5
|
+
<slot />
|
|
6
|
+
</div>
|
|
7
|
+
<div class="br-overlay-background">
|
|
8
|
+
<div class="wrap-overlay-exit-button">
|
|
9
|
+
<br-button variant="exit-overlay" @click="emit('closeOverlay')">
|
|
10
|
+
<close-icon class="close-icon" />
|
|
11
|
+
</br-button>
|
|
12
|
+
</div>
|
|
13
|
+
<br-button variant="exit-overlay-bg" @click="emit('closeOverlay')" />
|
|
14
|
+
</div>
|
|
5
15
|
</div>
|
|
6
|
-
|
|
7
|
-
<close-icon class="close-icon" />
|
|
8
|
-
</br-button>
|
|
9
|
-
</div>
|
|
16
|
+
</Transition>
|
|
10
17
|
</template>
|
|
11
18
|
|
|
12
19
|
<script setup>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
/**
|
|
21
|
+
* @component BrOverlay
|
|
22
|
+
* @description Modal overlay with a fade transition, focus trap, and Escape-to-close.
|
|
23
|
+
*
|
|
24
|
+
* @prop {Boolean} show - Controls overlay visibility via v-if.
|
|
25
|
+
* @emits closeOverlay - Fired when the user clicks the close button, the background, or presses Escape.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* <BrOverlay :show="isOpen" @closeOverlay="isOpen = false">
|
|
29
|
+
* <p>Content here</p>
|
|
30
|
+
* </BrOverlay>
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { onUnmounted, watch, nextTick, Transition } from 'vue'
|
|
34
|
+
|
|
35
|
+
const props = defineProps({
|
|
36
|
+
/** Controls overlay visibility. */
|
|
37
|
+
show: Boolean
|
|
38
|
+
})
|
|
39
|
+
import constrainTabbing from '../utils/constrainTabbing'
|
|
40
|
+
import BrButton from './BrButton.vue'
|
|
41
|
+
import CloseIcon from '../icons/Close.vue'
|
|
17
42
|
|
|
18
43
|
const emit = defineEmits(['closeOverlay'])
|
|
19
44
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
constrainTabbing($overlay)
|
|
23
|
-
}
|
|
45
|
+
/** @type {{ stop: () => void } | null} */
|
|
46
|
+
let tabTrap = null
|
|
24
47
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
48
|
+
// Set up / tear down the focus trap whenever the overlay opens or closes.
|
|
49
|
+
// nextTick ensures the v-if element is in the DOM before querying it.
|
|
50
|
+
watch(() => props.show, async (val) => {
|
|
51
|
+
if (val) {
|
|
52
|
+
await nextTick()
|
|
53
|
+
const $overlay = document.querySelector('.br-overlay-wrap')
|
|
54
|
+
if ($overlay) tabTrap = constrainTabbing($overlay)
|
|
55
|
+
} else {
|
|
56
|
+
tabTrap?.stop()
|
|
57
|
+
tabTrap = null
|
|
28
58
|
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {KeyboardEvent} event
|
|
63
|
+
*/
|
|
64
|
+
function listenForKeys({ key }) {
|
|
65
|
+
if (key == 'Escape') emit('closeOverlay')
|
|
29
66
|
}
|
|
30
67
|
|
|
31
|
-
|
|
32
|
-
document.addEventListener('keydown', listenForKeys)
|
|
33
|
-
document.addEventListener('keydown', constrainOverlayPadding)
|
|
34
|
-
})
|
|
68
|
+
document.addEventListener('keydown', listenForKeys)
|
|
35
69
|
|
|
36
70
|
onUnmounted(() => {
|
|
37
71
|
document.removeEventListener('keydown', listenForKeys)
|
|
38
|
-
|
|
72
|
+
tabTrap?.stop()
|
|
39
73
|
})
|
|
40
74
|
</script>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="br-qr-code" v-html="qrCode" />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup>
|
|
6
|
+
import { ref, watchEffect } from 'vue'
|
|
7
|
+
import * as qrcode from 'qrcode'
|
|
8
|
+
|
|
9
|
+
const props = defineProps({
|
|
10
|
+
code: {
|
|
11
|
+
type: String,
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const qrCode = ref('')
|
|
17
|
+
|
|
18
|
+
watchEffect(async () => {
|
|
19
|
+
qrCode.value = await qrcode.toString(props.code, { type: 'svg', margin: 0 })
|
|
20
|
+
})
|
|
21
|
+
</script>
|