@mindful-web/marko-web-identity-x 1.0.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.
Files changed (138) hide show
  1. package/.eslintignore +1 -0
  2. package/LICENSE +21 -0
  3. package/README.md +200 -0
  4. package/api/fragment-types.json +1 -0
  5. package/api/fragments/active-user.js +108 -0
  6. package/api/mutations/add-external-user-id.js +24 -0
  7. package/api/mutations/create-app-user.js +11 -0
  8. package/api/mutations/delete-app-user-for-current-application.js +7 -0
  9. package/api/mutations/impersonate-app-user.js +12 -0
  10. package/api/mutations/logout-app-user.js +11 -0
  11. package/api/mutations/send-change-email-link.js +7 -0
  12. package/api/mutations/send-login-link.js +7 -0
  13. package/api/mutations/set-custom-attributes.js +15 -0
  14. package/api/queries/check-content-access.js +19 -0
  15. package/api/queries/get-active-context.js +45 -0
  16. package/api/queries/load-user-by-external-id.js +14 -0
  17. package/api/queries/load-user-by-id.js +11 -0
  18. package/api/queries/load-user.js +11 -0
  19. package/browser/.eslintrc.js +11 -0
  20. package/browser/access.vue +377 -0
  21. package/browser/authenticate.vue +278 -0
  22. package/browser/change-email-confirm.vue +120 -0
  23. package/browser/change-email-init.vue +179 -0
  24. package/browser/comments/create.vue +107 -0
  25. package/browser/comments/post.vue +151 -0
  26. package/browser/comments/stream.vue +319 -0
  27. package/browser/custom-column.vue +314 -0
  28. package/browser/dayjs.js +6 -0
  29. package/browser/download-related.vue +120 -0
  30. package/browser/download.vue +380 -0
  31. package/browser/errors/authentication.js +7 -0
  32. package/browser/errors/feature.js +7 -0
  33. package/browser/errors/form.js +7 -0
  34. package/browser/errors/logout.js +7 -0
  35. package/browser/form/address-block.vue +131 -0
  36. package/browser/form/common/checkbox-group.vue +140 -0
  37. package/browser/form/common/form-group.vue +24 -0
  38. package/browser/form/common/form-label.vue +17 -0
  39. package/browser/form/consent.vue +121 -0
  40. package/browser/form/fields/address-extra.vue +68 -0
  41. package/browser/form/fields/city.vue +68 -0
  42. package/browser/form/fields/comment-body.vue +63 -0
  43. package/browser/form/fields/country.vue +94 -0
  44. package/browser/form/fields/custom-boolean.vue +58 -0
  45. package/browser/form/fields/custom-select-group.vue +25 -0
  46. package/browser/form/fields/custom-select-multiple.vue +97 -0
  47. package/browser/form/fields/custom-select-write-in-inline.vue +39 -0
  48. package/browser/form/fields/custom-select-write-in.vue +66 -0
  49. package/browser/form/fields/custom-select.vue +191 -0
  50. package/browser/form/fields/custom-text.vue +62 -0
  51. package/browser/form/fields/display-name.vue +64 -0
  52. package/browser/form/fields/email.vue +62 -0
  53. package/browser/form/fields/family-name.vue +68 -0
  54. package/browser/form/fields/given-name.vue +68 -0
  55. package/browser/form/fields/organization-title.vue +68 -0
  56. package/browser/form/fields/organization.vue +68 -0
  57. package/browser/form/fields/phone-number.vue +68 -0
  58. package/browser/form/fields/postal-code.vue +68 -0
  59. package/browser/form/fields/receive-email.vue +58 -0
  60. package/browser/form/fields/region.vue +106 -0
  61. package/browser/form/fields/regional-policy.vue +59 -0
  62. package/browser/form/fields/street.vue +68 -0
  63. package/browser/graphql/create-client.js +65 -0
  64. package/browser/graphql/parse.js +1 -0
  65. package/browser/graphql/queries/download-related-content.js +38 -0
  66. package/browser/index.js +110 -0
  67. package/browser/login-fields.vue +214 -0
  68. package/browser/login.vue +331 -0
  69. package/browser/logout.vue +68 -0
  70. package/browser/mixins/global-auto-signup-event-emitter.js +18 -0
  71. package/browser/mixins/global-event-emitter.js +28 -0
  72. package/browser/profile.vue +688 -0
  73. package/browser/service.js +32 -0
  74. package/browser/utils/clean-path.js +1 -0
  75. package/browser/utils/cookies-enabled.js +10 -0
  76. package/browser/utils/get-as-array.js +6 -0
  77. package/browser/utils/get-referring-page.js +7 -0
  78. package/browser/utils/get.js +8 -0
  79. package/browser/utils/post.js +10 -0
  80. package/browser/utils/redirect.js +7 -0
  81. package/browser/utils/region-country-codes.js +1 -0
  82. package/components/access.marko +24 -0
  83. package/components/access.marko.js +61 -0
  84. package/components/comment-stream.marko +31 -0
  85. package/components/comment-stream.marko.js +71 -0
  86. package/components/context.marko +15 -0
  87. package/components/context.marko.js +52 -0
  88. package/components/form-access.marko +60 -0
  89. package/components/form-access.marko.js +111 -0
  90. package/components/form-authenticate.marko +32 -0
  91. package/components/form-authenticate.marko.js +73 -0
  92. package/components/form-change-email.marko +27 -0
  93. package/components/form-change-email.marko.js +68 -0
  94. package/components/form-login.marko +32 -0
  95. package/components/form-login.marko.js +72 -0
  96. package/components/form-logout.marko +7 -0
  97. package/components/form-logout.marko.js +36 -0
  98. package/components/form-profile.marko +38 -0
  99. package/components/form-profile.marko.js +78 -0
  100. package/components/form-register.marko +2 -0
  101. package/components/form-register.marko.js +32 -0
  102. package/components/identify.marko +17 -0
  103. package/components/identify.marko.js +59 -0
  104. package/components/marko.json +90 -0
  105. package/components/non-auth-identify.marko +15 -0
  106. package/components/non-auth-identify.marko.js +53 -0
  107. package/config.js +161 -0
  108. package/hooks.js +20 -0
  109. package/index.js +30 -0
  110. package/marko.json +6 -0
  111. package/middleware/content-access-state.js +31 -0
  112. package/middleware/content-download-state.js +27 -0
  113. package/middleware.js +32 -0
  114. package/package.json +40 -0
  115. package/routes/access.js +29 -0
  116. package/routes/authenticate.js +58 -0
  117. package/routes/change-email-confirm.js +60 -0
  118. package/routes/change-email-init.js +16 -0
  119. package/routes/comment-count.js +19 -0
  120. package/routes/comments.js +43 -0
  121. package/routes/countries.js +19 -0
  122. package/routes/create-comment.js +25 -0
  123. package/routes/download.js +29 -0
  124. package/routes/flag-comment.js +21 -0
  125. package/routes/index.js +40 -0
  126. package/routes/login-fields.js +35 -0
  127. package/routes/login.js +95 -0
  128. package/routes/logout.js +19 -0
  129. package/routes/profile.js +183 -0
  130. package/routes/regions.js +22 -0
  131. package/service.js +483 -0
  132. package/utils/call-hooks-for.js +28 -0
  133. package/utils/context-cookie.js +30 -0
  134. package/utils/create-client.js +48 -0
  135. package/utils/create-identity-builder.js +33 -0
  136. package/utils/get-as-array.js +6 -0
  137. package/utils/json-error-handler.js +41 -0
  138. package/utils/token-cookie.js +30 -0
@@ -0,0 +1,140 @@
1
+ <template>
2
+ <div class="checkbox-group">
3
+ <div
4
+ v-for="option in options"
5
+ :key="option.id"
6
+ class="custom-control custom-checkbox"
7
+ >
8
+ <input
9
+ :id="createId(option.id)"
10
+ v-model="checked"
11
+ :required="isRequired"
12
+ :value="option.id"
13
+ type="checkbox"
14
+ class="custom-control-input"
15
+ >
16
+ <label
17
+ :for="createId(option.id)"
18
+ class="custom-control-label w-100"
19
+ :class="{ 'has-write-in': showWriteIn(option.id) }"
20
+ >
21
+ <custom-select-write-in-inline
22
+ v-if="showWriteIn(option.id)"
23
+ :answer="writeInAnswer"
24
+ :placeholder="writeInLabel"
25
+ @change="$emit('change', $event)"
26
+ />
27
+ <span v-else>
28
+ {{ option.label }}
29
+ </span>
30
+ </label>
31
+ </div>
32
+ </div>
33
+ </template>
34
+
35
+ <script>
36
+ import CustomSelectWriteInInline from '../fields/custom-select-write-in-inline.vue';
37
+
38
+ export default {
39
+ components: {
40
+ CustomSelectWriteInInline,
41
+ },
42
+ props: {
43
+ /**
44
+ * The wrapping field group identifier.
45
+ */
46
+ groupId: {
47
+ type: String,
48
+ required: true,
49
+ },
50
+
51
+ /**
52
+ * Whether the checkbox group is required.
53
+ */
54
+ required: {
55
+ type: Boolean,
56
+ default: false,
57
+ },
58
+
59
+ /**
60
+ * An array of option objects:
61
+ * [
62
+ * { id: 'some-id', label: 'Some label' },
63
+ * ]
64
+ */
65
+ options: {
66
+ type: Array,
67
+ default: () => [],
68
+ },
69
+
70
+ /**
71
+ * An array of selected option IDs.
72
+ * ['some-id']
73
+ */
74
+ selected: {
75
+ type: Array,
76
+ default: () => [],
77
+ },
78
+
79
+ canWriteIn: {
80
+ type: Boolean,
81
+ default: false,
82
+ },
83
+ writeInLabel: {
84
+ type: String,
85
+ default: 'Other',
86
+ },
87
+ writeInAnswer: {
88
+ type: Object,
89
+ default: () => ({}),
90
+ },
91
+ },
92
+
93
+ computed: {
94
+ /**
95
+ * This is used internally as the `v-model` for the checkboxes.
96
+ * The value is then watched to emit the change event.
97
+ */
98
+ checked: {
99
+ get() {
100
+ return [...this.selected];
101
+ },
102
+ set(value) {
103
+ this.$emit('change', value);
104
+ },
105
+ },
106
+ /**
107
+ * Determines if the checkboxes are required from a
108
+ * validation perspective. Because HTML5 doesn't support
109
+ * checkbox groups out-of-the-box, this will make all the boxes
110
+ * required when none are checked, but optional when at least one
111
+ * is checked.
112
+ *
113
+ * This only applies when the overall group `required` prop is set to true.
114
+ */
115
+ isRequired() {
116
+ if (!this.required) return false;
117
+ if (this.selected.length) return false;
118
+ return true;
119
+ },
120
+ },
121
+
122
+ methods: {
123
+ createId(optionId) {
124
+ return `checkbox-${this.groupId}-${optionId}`;
125
+ },
126
+ showWriteIn(optionId) {
127
+ return this.canWriteIn && this.writeInAnswer.id === optionId;
128
+ },
129
+ },
130
+ };
131
+ </script>
132
+
133
+ <style>
134
+ .custom-control-label.has-write-in::before {
135
+ top: calc(0.125rem + 3px);
136
+ }
137
+ .custom-control-label.has-write-in::after {
138
+ top: calc(0.125rem + 3px);
139
+ }
140
+ </style>
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <div :class="classNames">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ props: {
10
+ className: {
11
+ type: String,
12
+ default: '',
13
+ },
14
+ },
15
+ computed: {
16
+ classNames() {
17
+ const classNames = ['form-group'];
18
+ const { className } = this;
19
+ if (className) classNames.push(className);
20
+ return classNames;
21
+ },
22
+ },
23
+ };
24
+ </script>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <label>
3
+ <slot />
4
+ <strong v-if="required" class="text-danger">*</strong>
5
+ </label>
6
+ </template>
7
+
8
+ <script>
9
+ export default {
10
+ props: {
11
+ required: {
12
+ type: Boolean,
13
+ default: false,
14
+ },
15
+ },
16
+ };
17
+ </script>
@@ -0,0 +1,121 @@
1
+ <template>
2
+ <div>
3
+ <div v-if="emailConsentRequest" class="row mt-3">
4
+ <div class="col-12">
5
+ <receive-email
6
+ v-model="user.receiveEmail"
7
+ :email-consent-request="emailConsentRequest"
8
+ />
9
+ </div>
10
+ </div>
11
+ <div v-if="regionalPolicyFields.length" class="row mt-3">
12
+ <div class="col-12">
13
+ <regional-policy
14
+ v-for="policy in regionalPolicyFields"
15
+ :id="policy.id"
16
+ :key="policy.id"
17
+ :message="policy.message"
18
+ :required="policy.required"
19
+ :value="getRegionalPolicyAnswerValue(policy.id)"
20
+ @input="setPolicyAnswer(policy.id, $event)"
21
+ />
22
+ </div>
23
+ </div>
24
+ <small
25
+ v-if="consentPolicy"
26
+ class="text-muted mb-3 d-inline-block"
27
+ v-html="consentPolicy"
28
+ />
29
+ </div>
30
+ </template>
31
+ <script>
32
+ import ReceiveEmail from './fields/receive-email.vue';
33
+ import RegionalPolicy from './fields/regional-policy.vue';
34
+
35
+ export default {
36
+ components: {
37
+ ReceiveEmail,
38
+ RegionalPolicy,
39
+ },
40
+ props: {
41
+ user: {
42
+ type: Object,
43
+ default: () => ({}),
44
+ },
45
+ consentPolicy: {
46
+ type: String,
47
+ default: null,
48
+ },
49
+ consentPolicyEnabled: {
50
+ type: Boolean,
51
+ default: false,
52
+ },
53
+ emailConsentRequest: {
54
+ type: String,
55
+ default: null,
56
+ },
57
+ emailConsentRequestEnabled: {
58
+ type: Boolean,
59
+ default: false,
60
+ },
61
+ regionalConsentPolicies: {
62
+ type: Array,
63
+ default: () => [],
64
+ },
65
+ countryCode: {
66
+ type: String,
67
+ default: null,
68
+ },
69
+ },
70
+
71
+ /**
72
+ *
73
+ */
74
+ computed: {
75
+ /**
76
+ *
77
+ */
78
+ regionalPolicyFields() {
79
+ const { regionalConsentPolicies, countryCode } = this;
80
+ if (!regionalConsentPolicies.length || !countryCode) return [];
81
+ return regionalConsentPolicies.filter((policy) => {
82
+ const countryCodes = policy.countries.map((country) => country.id);
83
+ return countryCodes.includes(countryCode);
84
+ });
85
+ },
86
+ },
87
+
88
+ /**
89
+ *
90
+ */
91
+ methods: {
92
+ /**
93
+ *
94
+ */
95
+ getRegionalPolicyAnswer(policyId) {
96
+ return this.user.regionalConsentAnswers.find((a) => a.id === policyId);
97
+ },
98
+
99
+ /**
100
+ *
101
+ */
102
+ getRegionalPolicyAnswerValue(policyId) {
103
+ const answer = this.getRegionalPolicyAnswer(policyId);
104
+ if (answer) return answer.given;
105
+ return false;
106
+ },
107
+
108
+ /**
109
+ *
110
+ */
111
+ setPolicyAnswer(policyId, given) {
112
+ const answer = this.getRegionalPolicyAnswer(policyId);
113
+ if (answer) {
114
+ answer.given = given;
115
+ } else {
116
+ this.user.regionalConsentAnswers.push({ id: policyId, given });
117
+ }
118
+ },
119
+ },
120
+ };
121
+ </script>
@@ -0,0 +1,68 @@
1
+ <template>
2
+ <form-group :class-name="className">
3
+ <form-label :for="id" :required="required">
4
+ {{ label }}
5
+ </form-label>
6
+ <input
7
+ :id="id"
8
+ v-model="addressExtra"
9
+ class="form-control"
10
+ type="text"
11
+ :required="required"
12
+ :disabled="disabled"
13
+ :placeholder="placeholder"
14
+ autocomplete="address-extra"
15
+ >
16
+ </form-group>
17
+ </template>
18
+
19
+ <script>
20
+ import FormGroup from '../common/form-group.vue';
21
+ import FormLabel from '../common/form-label.vue';
22
+
23
+ export default {
24
+ components: {
25
+ FormGroup,
26
+ FormLabel,
27
+ },
28
+ props: {
29
+ disabled: {
30
+ type: Boolean,
31
+ default: false,
32
+ },
33
+ required: {
34
+ type: Boolean,
35
+ default: false,
36
+ },
37
+ label: {
38
+ type: String,
39
+ default: 'Extra (Apt, Suite, etc.)',
40
+ },
41
+ placeholder: {
42
+ type: String,
43
+ default: '',
44
+ },
45
+ value: {
46
+ type: String,
47
+ default: '',
48
+ },
49
+ className: {
50
+ type: String,
51
+ default: 'col-md-4',
52
+ },
53
+ },
54
+ data: () => ({
55
+ id: 'sign-on-address-extra',
56
+ }),
57
+ computed: {
58
+ addressExtra: {
59
+ get() {
60
+ return this.value || '';
61
+ },
62
+ set(addressExtra) {
63
+ this.$emit('input', addressExtra || null);
64
+ },
65
+ },
66
+ },
67
+ };
68
+ </script>
@@ -0,0 +1,68 @@
1
+ <template>
2
+ <form-group :class-name="className">
3
+ <form-label :for="id" :required="required">
4
+ {{ label }}
5
+ </form-label>
6
+ <input
7
+ :id="id"
8
+ v-model="city"
9
+ class="form-control"
10
+ type="text"
11
+ :required="required"
12
+ :disabled="disabled"
13
+ :placeholder="placeholder"
14
+ autocomplete="city"
15
+ >
16
+ </form-group>
17
+ </template>
18
+
19
+ <script>
20
+ import FormGroup from '../common/form-group.vue';
21
+ import FormLabel from '../common/form-label.vue';
22
+
23
+ export default {
24
+ components: {
25
+ FormGroup,
26
+ FormLabel,
27
+ },
28
+ props: {
29
+ disabled: {
30
+ type: Boolean,
31
+ default: false,
32
+ },
33
+ required: {
34
+ type: Boolean,
35
+ default: false,
36
+ },
37
+ label: {
38
+ type: String,
39
+ default: 'City',
40
+ },
41
+ placeholder: {
42
+ type: String,
43
+ default: '',
44
+ },
45
+ value: {
46
+ type: String,
47
+ default: '',
48
+ },
49
+ className: {
50
+ type: String,
51
+ default: 'col-md-6',
52
+ },
53
+ },
54
+ data: () => ({
55
+ id: 'sign-on-city',
56
+ }),
57
+ computed: {
58
+ city: {
59
+ get() {
60
+ return this.value || '';
61
+ },
62
+ set(city) {
63
+ this.$emit('input', city || null);
64
+ },
65
+ },
66
+ },
67
+ };
68
+ </script>
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <form-group>
3
+ <form-label :for="id" :required="required">
4
+ {{ label }}
5
+ </form-label>
6
+ <textarea
7
+ :id="id"
8
+ v-model="body"
9
+ class="form-control"
10
+ rows="3"
11
+ :required="required"
12
+ :disabled="disabled"
13
+ :placeholder="placeholder"
14
+ />
15
+ </form-group>
16
+ </template>
17
+
18
+ <script>
19
+ import FormGroup from '../common/form-group.vue';
20
+ import FormLabel from '../common/form-label.vue';
21
+
22
+ export default {
23
+ components: {
24
+ FormGroup,
25
+ FormLabel,
26
+ },
27
+ props: {
28
+ disabled: {
29
+ type: Boolean,
30
+ default: false,
31
+ },
32
+ required: {
33
+ type: Boolean,
34
+ default: true,
35
+ },
36
+ label: {
37
+ type: String,
38
+ default: 'Your Comment',
39
+ },
40
+ placeholder: {
41
+ type: String,
42
+ default: '',
43
+ },
44
+ value: {
45
+ type: String,
46
+ default: '',
47
+ },
48
+ },
49
+ data: () => ({
50
+ id: 'comment-body',
51
+ }),
52
+ computed: {
53
+ body: {
54
+ get() {
55
+ return this.value || '';
56
+ },
57
+ set(body) {
58
+ this.$emit('input', body || null);
59
+ },
60
+ },
61
+ },
62
+ };
63
+ </script>
@@ -0,0 +1,94 @@
1
+ <template>
2
+ <form-group :class-name="className">
3
+ <form-label :for="id" :required="required">
4
+ {{ label }}
5
+ </form-label>
6
+ <select
7
+ :id="id"
8
+ v-model="countryCode"
9
+ :readonly="isLoading"
10
+ :disabled="disabled"
11
+ :required="required"
12
+ class="custom-select"
13
+ autocomplete="country"
14
+ >
15
+ <option disabled value="">
16
+ Select country...
17
+ </option>
18
+ <option v-for="country in countries" :key="country.id" :value="country.id">
19
+ {{ country.name }} {{ country.flag }}
20
+ </option>
21
+ </select>
22
+ <p v-if="error">
23
+ Unable to load countries: {{ error.message }}
24
+ </p>
25
+ </form-group>
26
+ </template>
27
+
28
+ <script>
29
+ import FormGroup from '../common/form-group.vue';
30
+ import FormLabel from '../common/form-label.vue';
31
+ import get from '../../utils/get';
32
+
33
+ export default {
34
+ components: {
35
+ FormGroup,
36
+ FormLabel,
37
+ },
38
+ props: {
39
+ disabled: {
40
+ type: Boolean,
41
+ default: false,
42
+ },
43
+ required: {
44
+ type: Boolean,
45
+ default: false,
46
+ },
47
+ label: {
48
+ type: String,
49
+ default: 'Country',
50
+ },
51
+ value: {
52
+ type: String,
53
+ default: '',
54
+ },
55
+ className: {
56
+ type: String,
57
+ default: '',
58
+ },
59
+ },
60
+ data: () => ({
61
+ id: 'sign-on-country',
62
+ isLoading: false,
63
+ error: null,
64
+ countries: [],
65
+ }),
66
+ computed: {
67
+ countryCode: {
68
+ get() {
69
+ return this.value || '';
70
+ },
71
+ set(countryCode) {
72
+ this.$emit('input', countryCode || null);
73
+ },
74
+ },
75
+ },
76
+ created() {
77
+ this.load();
78
+ },
79
+ methods: {
80
+ async load() {
81
+ this.error = null;
82
+ this.isLoading = true;
83
+ try {
84
+ const res = await get('/countries');
85
+ this.countries = await res.json();
86
+ } catch (e) {
87
+ this.error = e;
88
+ } finally {
89
+ this.isLoading = false;
90
+ }
91
+ },
92
+ },
93
+ };
94
+ </script>
@@ -0,0 +1,58 @@
1
+ <template>
2
+ <form-group>
3
+ <div class="custom-control custom-checkbox">
4
+ <input
5
+ :id="`custom-boolean-${id}`"
6
+ v-model="given"
7
+ :disabled="disabled"
8
+ :required="required"
9
+ type="checkbox"
10
+ class="custom-control-input"
11
+ >
12
+ <form-label class="custom-control-label" :for="`custom-boolean-${id}`" :required="required">
13
+ <span v-html="message" />
14
+ </form-label>
15
+ </div>
16
+ </form-group>
17
+ </template>
18
+
19
+ <script>
20
+ import FormGroup from '../common/form-group.vue';
21
+ import FormLabel from '../common/form-label.vue';
22
+
23
+ export default {
24
+ components: { FormGroup, FormLabel },
25
+ props: {
26
+ id: {
27
+ type: String,
28
+ required: true,
29
+ },
30
+ disabled: {
31
+ type: Boolean,
32
+ default: false,
33
+ },
34
+ value: {
35
+ type: Boolean,
36
+ default: false,
37
+ },
38
+ required: {
39
+ type: Boolean,
40
+ default: false,
41
+ },
42
+ message: {
43
+ type: String,
44
+ required: true,
45
+ },
46
+ },
47
+ computed: {
48
+ given: {
49
+ get() {
50
+ return Boolean(this.value);
51
+ },
52
+ set(given) {
53
+ this.$emit('input', Boolean(given));
54
+ },
55
+ },
56
+ },
57
+ };
58
+ </script>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <fieldset class="csmulti-group">
3
+ <legend class="csmulti-legend">
4
+ {{ label }}
5
+ </legend>
6
+ <div class="pl-3 pb-2">
7
+ <slot />
8
+ </div>
9
+ </fieldset>
10
+ </template>
11
+
12
+ <script>
13
+ export default {
14
+ props: {
15
+ disabled: {
16
+ type: Boolean,
17
+ default: false,
18
+ },
19
+ label: {
20
+ type: String,
21
+ default: '',
22
+ },
23
+ },
24
+ };
25
+ </script>