@afeefa/vue-app 0.0.109 → 0.0.111

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- 0.0.109
1
+ 0.0.111
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
1
  # @afeefa/vue-app
2
2
 
3
3
  Force push :-);
4
+
5
+ ## Documentation
6
+
7
+ * [Components / AModal](docs/components/amodal.md)
@@ -0,0 +1,19 @@
1
+ # AModal
2
+
3
+ It's a Modal capsule for vuetifys Modals. Whats the magic about it?
4
+
5
+ The Modal is by default relatively positioned near its activator.
6
+
7
+ ## Properties
8
+
9
+ * show
10
+ * icon
11
+ * title
12
+ * beforeClose
13
+ * anchorPosition
14
+ * screenCentered
15
+
16
+
17
+ ### screenCentered
18
+
19
+ if set to true the Modal is positioned in the middle of the Viewport, like in vuetify's default beavior.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afeefa/vue-app",
3
- "version": "0.0.109",
3
+ "version": "0.0.111",
4
4
  "description": "",
5
5
  "author": "Afeefa Kollektiv <kollektiv@afeefa.de>",
6
6
  "license": "MIT",
@@ -10,6 +10,7 @@ export class ApiAction extends ApiResourcesApiAction {
10
10
  _dispatchGlobalSaveEvents = false
11
11
  _minDuration = 100
12
12
  _startTime = 0
13
+ _showError = true
13
14
 
14
15
  id (id) {
15
16
  this.param('id', id)
@@ -21,6 +22,11 @@ export class ApiAction extends ApiResourcesApiAction {
21
22
  return this
22
23
  }
23
24
 
25
+ hideError () {
26
+ this._showError = false
27
+ return this
28
+ }
29
+
24
30
  dispatchGlobalLoadingEvents (dispatch = true) {
25
31
  this._dispatchGlobalLoadingEvents = dispatch
26
32
  return this
@@ -27,10 +27,12 @@ export class DeleteAction extends ApiAction {
27
27
  }
28
28
 
29
29
  processError (result) {
30
- eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
31
- headline: 'Die Daten konnten nicht gelöscht werden.',
32
- message: result.message,
33
- detail: result.detail
34
- }))
30
+ if (this._showError) {
31
+ eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
32
+ headline: 'Die Daten konnten nicht gelöscht werden.',
33
+ message: result.message,
34
+ detail: result.detail
35
+ }))
36
+ }
35
37
  }
36
38
  }
@@ -9,10 +9,12 @@ export class GetAction extends ApiAction {
9
9
  }
10
10
 
11
11
  processError (result) {
12
- eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
13
- headline: 'Die Daten konntent nicht geladen werden.',
14
- message: result.message,
15
- detail: result.detail
16
- }))
12
+ if (this._showError) {
13
+ eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
14
+ headline: 'Die Daten konntent nicht geladen werden.',
15
+ message: result.message,
16
+ detail: result.detail
17
+ }))
18
+ }
17
19
  }
18
20
  }
@@ -17,10 +17,12 @@ export class SaveAction extends ApiAction {
17
17
  }
18
18
 
19
19
  processError (result) {
20
- eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
21
- headline: 'Die Daten konnten nicht gespeichert werden.',
22
- message: result.message,
23
- detail: result.detail
24
- }))
20
+ if (this._showError) {
21
+ eventBus.dispatch(new AlertEvent(AlertEvent.ERROR, {
22
+ headline: 'Die Daten konnten nicht gespeichert werden.',
23
+ message: result.message,
24
+ detail: result.detail
25
+ }))
26
+ }
25
27
  }
26
28
  }
@@ -11,7 +11,7 @@
11
11
  no-filter
12
12
 
13
13
  :rules="validationRules"
14
- v-bind="$attrs"
14
+ v-bind="{...$attrs, dense, outlined}"
15
15
  v-on="$listeners"
16
16
  />
17
17
  </template>
@@ -23,7 +23,7 @@ import { Model } from '@afeefa/api-resources-client'
23
23
  import { debounce } from '@a-vue/utils/debounce'
24
24
 
25
25
  @Component({
26
- props: ['items', 'validator', 'defaultValue', 'selectedItemText', 'debounce']
26
+ props: ['items', 'validator', 'defaultValue', 'selectedItemText', 'debounce', {dense: true, outlined: true}]
27
27
  })
28
28
  export default class AAutocomplete extends Vue {
29
29
  isLoading = false
@@ -12,7 +12,7 @@
12
12
  :value="formattedDate"
13
13
  :label="label"
14
14
  :style="cwm_widthStyle"
15
- v-bind="{...$attrs, ...attrs}"
15
+ v-bind="{...$attrs, ...attrs, dense, outlined}"
16
16
  :rules="validationRules"
17
17
  :error-messages="errorMessages"
18
18
  :readonly="type === 'month'"
@@ -41,7 +41,7 @@ import { formatDate } from '@a-vue/utils/format-date'
41
41
  import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
42
42
 
43
43
  @Component({
44
- props: ['value', 'validator', 'type']
44
+ props: ['value', 'validator', 'type', {dense: true, outlined: true}]
45
45
  })
46
46
  export default class ADatePicker extends Mixins(ComponentWidthMixin) {
47
47
  value_ = null
@@ -153,6 +153,7 @@ export default class ADatePicker extends Mixins(ComponentWidthMixin) {
153
153
  <style lang="scss" scoped>
154
154
  :deep(.v-select__slot) {
155
155
  cursor: pointer;
156
+
156
157
  input {
157
158
  cursor: pointer;
158
159
  }
@@ -1,5 +1,8 @@
1
1
  <template>
2
- <div :class="['a-grid', colsClass, gapClass, evenClass, breakMobileClass]">
2
+ <div
3
+ :style="{display: displayStyle}"
4
+ :class="['a-grid', colsClass, gapClass, evenClass, breakMobileClass]"
5
+ >
3
6
  <slot />
4
7
  </div>
5
8
  </template>
@@ -10,7 +13,7 @@ import { Component, Mixins } from '@a-vue'
10
13
  import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
11
14
 
12
15
  @Component({
13
- props: ['gap', 'hGap', 'vGap', 'cols', {even: false}, 'breakMobile']
16
+ props: ['gap', 'hGap', 'vGap', 'cols', {inline: false, even: false}, 'breakMobile']
14
17
  })
15
18
  export default class AGrid extends Mixins(ComponentWidthMixin) {
16
19
  get breakMobileClass () {
@@ -19,6 +22,10 @@ export default class AGrid extends Mixins(ComponentWidthMixin) {
19
22
  }
20
23
  }
21
24
 
25
+ get displayStyle () {
26
+ return this.inline ? 'inline-grid' : 'grid'
27
+ }
28
+
22
29
  get colsClass () {
23
30
  const cols = this.cols || 2
24
31
  return 'cols-' + cols
@@ -53,11 +60,10 @@ export default class AGrid extends Mixins(ComponentWidthMixin) {
53
60
 
54
61
  <style scoped lang="scss">
55
62
  .a-grid {
56
- display: grid;
57
-
58
63
  @for $i from 1 through 8 {
59
64
  &.cols-#{$i} {
60
65
  grid-template-columns: repeat(#{$i}, auto);
66
+
61
67
  &.even {
62
68
  grid-template-columns: repeat(#{$i}, 1fr);
63
69
  }
@@ -67,6 +73,7 @@ export default class AGrid extends Mixins(ComponentWidthMixin) {
67
73
  &.breakMobile {
68
74
  @media (max-width: 900px), (orientation : portrait) {
69
75
  grid-template-columns: 1fr;
76
+
70
77
  &.even {
71
78
  grid-template-columns: 1fr;
72
79
  }
@@ -14,7 +14,7 @@
14
14
  <template #activator="{ on }">
15
15
  <div
16
16
  style="width: max-content;"
17
- :class="[activatorClass, triggerClass]"
17
+ :class="activatorClass"
18
18
  v-on="on"
19
19
  >
20
20
  <slot name="activator" />
@@ -56,7 +56,7 @@ import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
56
56
  import { CancelOnEscMixin } from '@a-vue/services/escape/CancelOnEscMixin'
57
57
 
58
58
  @Component({
59
- props: ['show', 'icon', 'title', 'beforeClose', 'triggerClass', 'anchorPosition']
59
+ props: ['show', 'icon', 'title', 'beforeClose', 'anchorPosition', 'screenCentered']
60
60
  })
61
61
  export default class ADialog extends Mixins(UsesPositionServiceMixin, ComponentWidthMixin, CancelOnEscMixin) {
62
62
  modalId = randomCssClass(10)
@@ -121,7 +121,9 @@ export default class ADialog extends Mixins(UsesPositionServiceMixin, ComponentW
121
121
  @Watch('modal')
122
122
  modalChanged () {
123
123
  if (this.modal) {
124
- this.setPosition()
124
+ if (!this.screenCentered) {
125
+ this.setPosition()
126
+ }
125
127
  } else {
126
128
  this.removeTransientAnchor()
127
129
  }
@@ -204,13 +206,12 @@ export default class ADialog extends Mixins(UsesPositionServiceMixin, ComponentW
204
206
 
205
207
  :deep(.v-dialog) {
206
208
  position: absolute;
207
- top: 0;
208
- left: 0;
209
209
  margin: 0;
210
210
 
211
211
  transition: none;
212
212
 
213
213
  &.v-fade-transition {
214
+
214
215
  &-enter-active, &-leave, &-leave-to {
215
216
  transition: opacity .3s ease;
216
217
  }
@@ -5,7 +5,7 @@
5
5
  :items="items_"
6
6
  :valueComparator="compareValues"
7
7
  :style="cwm_widthStyle"
8
- v-bind="$attrs"
8
+ v-bind="{...$attrs, dense, outlined}"
9
9
  v-on="$listeners"
10
10
  />
11
11
  </template>
@@ -17,7 +17,7 @@ import { Model } from '@afeefa/api-resources-client'
17
17
  import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
18
18
 
19
19
  @Component({
20
- props: ['validator', 'defaultValue', 'items']
20
+ props: ['validator', 'defaultValue', 'items', {dense: true, outlined: true}]
21
21
  })
22
22
  export default class ASelect extends Mixins(ComponentWidthMixin) {
23
23
  items_ = []
@@ -96,3 +96,10 @@ export default class ASelect extends Mixins(ComponentWidthMixin) {
96
96
  }
97
97
  }
98
98
  </script>
99
+
100
+
101
+ <style lang="scss" scoped>
102
+ .v-text-field :deep(.v-input__icon--clear) { // always show clear icon, https://github.com/vuetifyjs/vuetify/pull/15876
103
+ opacity: 1;
104
+ }
105
+ </style>
@@ -3,7 +3,7 @@
3
3
  ref="input"
4
4
  :rules="validationRules"
5
5
  :counter="counter"
6
- v-bind="$attrs"
6
+ v-bind="{...$attrs, dense, outlined}"
7
7
  v-on="$listeners"
8
8
  />
9
9
  </template>
@@ -13,7 +13,7 @@
13
13
  import { Component, Vue } from '@a-vue'
14
14
 
15
15
  @Component({
16
- props: ['validator']
16
+ props: ['validator', {dense: true, outlined: true}]
17
17
  })
18
18
  export default class ATextArea extends Vue {
19
19
  mounted () {
@@ -1,45 +1,142 @@
1
1
  <template>
2
2
  <v-text-field
3
3
  ref="input"
4
- :type="type"
5
- :autocomplete="autocomplete"
6
- :rules="validationRules"
4
+ v-model="internalValue"
7
5
  :counter="counter"
8
6
  :style="cwm_widthStyle"
9
- v-bind="$attrs"
10
- v-on="$listeners"
11
- @click:append="showPassword = !showPassword"
7
+ :error-messages="errorMessages"
8
+ v-bind="attrs"
9
+ @input="inputChanged"
10
+ @keyup.esc="clear"
11
+ @click:clear="clear"
12
+ v-on="listeners"
12
13
  />
13
14
  </template>
14
15
 
15
16
 
16
17
  <script>
17
- import { Component, Watch, Mixins } from '@a-vue'
18
+ import { Component, Watch, Mixins, Inject } from '@a-vue'
18
19
  import { debounce } from '@a-vue/utils/debounce'
19
20
  import { ComponentWidthMixin } from './mixins/ComponentWidthMixin'
20
21
 
21
22
  @Component({
22
- props: ['debounce', 'validator', {focus: false, password: false, number: false}]
23
+ props: ['value', 'debounce', 'validator', 'rules', {dense: true, outlined: true, focus: false, number: false}]
23
24
  })
24
25
  export default class ATextField extends Mixins(ComponentWidthMixin) {
25
26
  $hasOptions = ['counter']
26
27
 
27
- showPassword = false
28
+ @Inject({ from: 'form', default: null }) form
29
+
30
+ internalValue = null
31
+ errorMessages = []
32
+ debounceInputFunction = null
28
33
 
29
34
  created () {
30
- if (this.debounce) {
31
- this.$listeners.input = debounce(value => {
32
- this.$emit('input', value)
33
- }, this.debounce, value => value)
34
- }
35
+ this.form && this.form.register(this)
36
+
37
+ this.setInternalValue(this.value)
35
38
  }
36
39
 
37
40
  mounted () {
38
41
  this.setFocus()
39
42
 
40
- if (this.validator) {
41
- this.$refs.input.validate(true)
43
+ this.$emit('input:internal', this.internalValue)
44
+ this.validate()
45
+ }
46
+
47
+ setInternalValue (value) {
48
+ if (typeof value === 'number') {
49
+ value = value.toString()
42
50
  }
51
+ this.internalValue = value || ''
52
+ }
53
+
54
+ @Watch('value')
55
+ valueChanged () {
56
+ this.setInternalValue(this.value)
57
+ }
58
+
59
+ get listeners () {
60
+ // remove input from nested listening
61
+ // let clients listend to only THIS component
62
+ const listeners = {...this.$listeners}
63
+ delete listeners.input
64
+ return listeners
65
+ }
66
+
67
+ get attrs () {
68
+ // remove 'rules' from being passed to v-text-field
69
+ const attrs = {...this.$attrs}
70
+ delete attrs.rules
71
+
72
+ attrs.dense = this.dense
73
+ attrs.outlined = this.outlined
74
+ return attrs
75
+ }
76
+
77
+ clear () {
78
+ if (this.$attrs.clearable || this.escClearable) {
79
+ this.setInternalValue('')
80
+ this.validate()
81
+ this.$emit('input', this.emptyValue)
82
+ }
83
+ }
84
+
85
+ inputChanged () {
86
+ this.$emit('input:internal', this.internalValue)
87
+
88
+ const valid = this.validate()
89
+ if (!valid) {
90
+ return
91
+ }
92
+
93
+ const value = this.stringToNumber(this.internalValue)
94
+
95
+ if (this.debounce) {
96
+ if (!this.debounceInputFunction) {
97
+ this.debounceInputFunction = debounce(value => {
98
+ this.$emit('input', value)
99
+ }, this.debounce, value => value) // fire immediately if !value (click clearable-x)
100
+ }
101
+ this.debounceInputFunction(value)
102
+ } else {
103
+ this.$emit('input', value)
104
+ }
105
+ }
106
+
107
+ stringToNumber (value) {
108
+ if (this.treatAsNumericValue) {
109
+ if (!value) {
110
+ value = null
111
+ } else {
112
+ value = this.internalValue.match(/^\d*(.\d+)?$/) ? parseFloat(this.internalValue) : NaN
113
+ }
114
+ }
115
+ return value
116
+ }
117
+
118
+ get type () {
119
+ return this.$attrs.type || 'text'
120
+ }
121
+
122
+ get treatAsNumericValue () {
123
+ return this.type === 'number' || this.number
124
+ }
125
+
126
+ validate () {
127
+ const rules = this.validationRules
128
+ let errorMessage = null
129
+ for (const rule of rules) {
130
+ const value = this.stringToNumber(this.internalValue)
131
+ const result = rule(value)
132
+ if (result !== true) {
133
+ errorMessage = result
134
+ break
135
+ }
136
+ }
137
+
138
+ this.errorMessages = [errorMessage].filter(e => e)
139
+ return !this.errorMessages.length
43
140
  }
44
141
 
45
142
  @Watch('focus')
@@ -58,49 +155,42 @@ export default class ATextField extends Mixins(ComponentWidthMixin) {
58
155
  }
59
156
  }
60
157
 
61
- get type () {
62
- if (this.password && !this.showPassword) {
63
- return 'password'
64
- }
65
- return 'text'
66
- }
67
-
68
- get appendIcon () {
69
- if (this.password) {
70
- return this.showPassword ? '$eyeIcon' : '$eyeOffIcon'
71
- }
72
- return null
73
- }
74
-
75
- get autocomplete () {
76
- if (this.password) {
77
- return 'new-password'
78
- }
79
- return null
80
- }
81
-
82
158
  get validationRules () {
159
+ if (this.$attrs.rules) {
160
+ return this.$attrs.rules
161
+ }
83
162
  const label = this.$attrs.label
84
163
  return (this.validator && this.validator.getRules(label)) || []
85
164
  }
86
165
 
87
166
  get counter () {
88
167
  if (!this.$has.counter) {
89
- return false
168
+ return null
90
169
  }
91
170
 
92
171
  if (!this.validator) {
93
- return false
172
+ return null
94
173
  }
95
174
 
96
- return (!this.number && this.validator.getParams().max) || false
175
+ return this.validator.getMaxValueLength()
176
+ }
177
+
178
+ get emptyValue () {
179
+ if (this.validator) {
180
+ return this.validator.getEmptyValue()
181
+ }
182
+ return null
97
183
  }
98
184
  }
99
185
  </script>
100
186
 
101
187
 
102
188
  <style lang="scss" scoped>
103
- .v-input:not(.v-input--is-focused) :deep(.v-counter) {
189
+ .v-input:not(.v-input--is-focused) :deep(.v-counter) { // hide counter when not focused
104
190
  display: none;
105
191
  }
192
+
193
+ .v-text-field :deep(.v-input__icon--clear) { // always show clear icon, https://github.com/vuetifyjs/vuetify/pull/15876
194
+ opacity: 1;
195
+ }
106
196
  </style>
@@ -1,12 +1,10 @@
1
1
  <template>
2
2
  <a-text-field
3
- :value="internalValue"
3
+ v-model="model[name]"
4
4
  :label="label || name"
5
5
  :validator="validator"
6
6
  v-bind="$attrs"
7
7
  v-on="$listeners"
8
- @input="textFieldValueChanged"
9
- @blur="onBlur"
10
8
  />
11
9
  </template>
12
10
 
@@ -14,71 +12,7 @@
14
12
  import { Component, Mixins } from '@a-vue'
15
13
  import { FormFieldMixin } from '../FormFieldMixin'
16
14
 
17
- @Component({
18
- props: [{emptyNull: false}]
19
- })
15
+ @Component
20
16
  export default class FormFieldText extends Mixins(FormFieldMixin) {
21
- internalValue = ''
22
-
23
- created () {
24
- this.setInternalValue(this.model[this.name])
25
- this.$watch(() => this.model[this.name], value => {
26
- this.setInternalValue(value)
27
- })
28
- }
29
-
30
- onBlur () {
31
- this.setInternalValue(this.model[this.name], true)
32
- }
33
-
34
- textFieldValueChanged (value) {
35
- this.internalValue = value
36
-
37
- // cast to number
38
- if (this.isNumber) {
39
- value = Number(value)
40
- if (isNaN(value)) {
41
- return // do not set anything to the model
42
- }
43
- }
44
-
45
- // set model value to null if empty
46
- if (this.emptyNull) {
47
- if (this.isNumber) {
48
- if (value === 0) {
49
- value = null
50
- }
51
- } else {
52
- if (!value) {
53
- value = null
54
- }
55
- }
56
- }
57
-
58
- this.model[this.name] = value
59
- this.$emit('input', value)
60
- }
61
-
62
- setInternalValue (value, reset = false) {
63
- if (this.isNumber) {
64
- // reset text field if value is null but keep leading 0 (allows for copy and paste)
65
- if (value === null) {
66
- if (!reset && this.internalValue === '0') {
67
- value = '0'
68
- } else {
69
- value = ''
70
- }
71
- }
72
- } else { // null string should be ''
73
- if (!value) {
74
- value = ''
75
- }
76
- }
77
- this.internalValue = value
78
- }
79
-
80
- get isNumber () {
81
- return this.$attrs.number === ''
82
- }
83
17
  }
84
18
  </script>
@@ -15,7 +15,6 @@ import NestedEditForm from './form/NestedEditForm'
15
15
  import ListFilterPage from './list/filters/ListFilterPage'
16
16
  import ListFilterSearch from './list/filters/ListFilterSearch'
17
17
  import ListFilterSelect from './list/filters/ListFilterSelect'
18
- import ListFilterRow from './list/ListFilterRow'
19
18
 
20
19
  Vue.component('EditForm', EditForm)
21
20
  Vue.component('NestedEditForm', NestedEditForm)
@@ -31,5 +30,4 @@ Vue.component('FormFieldSelect', FormFieldSelect)
31
30
  Vue.component('FormFieldSelect2', FormFieldSelect2)
32
31
  Vue.component('ListFilterPage', ListFilterPage)
33
32
  Vue.component('ListFilterSearch', ListFilterSearch)
34
- Vue.component('ListFilterRow', ListFilterRow)
35
33
  Vue.component('ListFilterSelect', ListFilterSelect)
@@ -1,7 +1,5 @@
1
1
  <template>
2
- <a-row
3
- gap="8"
4
- >
2
+ <a-row gap="8">
5
3
  <a-pagination
6
4
  v-if="count && numPages > 1"
7
5
  v-model="filter.value"
@@ -20,6 +18,7 @@
20
18
  :items="pageSizeFilter.options"
21
19
  :defaultValue="pageSizeFilter.defaultValue"
22
20
  :clearable="!pageSizeFilter.hasDefaultValueSet()"
21
+ hide-details
23
22
  />
24
23
  </a-row>
25
24
  </template>
@@ -54,7 +53,7 @@ export default class ListFilterPage extends Mixins(ListFilterMixin) {
54
53
 
55
54
  <style lang="scss" scoped>
56
55
  .v-select {
57
- max-width: 100px;
56
+ max-width: 150px;
58
57
  }
59
58
 
60
59
  .pageNumber {
@@ -6,6 +6,7 @@
6
6
  :debounce="500"
7
7
  v-bind="$attrs"
8
8
  clearable
9
+ hide-details
9
10
  @keyup.esc="clearValue"
10
11
  />
11
12
  </template>
@@ -7,6 +7,7 @@
7
7
  itemValue="itemValue"
8
8
  :clearable="filter.value !== filter.defaultValue"
9
9
  :defaultValue="filter.defaultValue"
10
+ hide-details
10
11
  v-bind="$attrs"
11
12
  />
12
13
  </template>
package/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import './styles/vue-app.scss'
2
2
 
3
- export { Mixins, Vue, Watch } from 'vue-property-decorator'
3
+ export { Mixins, Vue, Watch, Inject, Provide } from 'vue-property-decorator'
4
4
  export { Component } from '@a-vue/components/vue/Component'
@@ -70,5 +70,5 @@ export async function bootstrap ({ apis, models, routing, authService, getTransl
70
70
  splash
71
71
  }
72
72
  })
73
- }, 500)
73
+ }, 300)
74
74
  }
@@ -76,7 +76,7 @@
76
76
  </template>
77
77
 
78
78
  <template #filters>
79
- <list-filter-row>
79
+ <a-row gap="4">
80
80
  <list-filter-search
81
81
  :focus="true"
82
82
  maxWidth="100%"
@@ -87,7 +87,7 @@
87
87
  :has="{page_size: false, page_number: true}"
88
88
  :totalVisible="0"
89
89
  />
90
- </list-filter-row>
90
+ </a-row>
91
91
  </template>
92
92
 
93
93
  <template #row="{ model, on }">
@@ -1,26 +0,0 @@
1
- <template>
2
- <a-row
3
- :gap="gap || 4"
4
- class="mb-0"
5
- >
6
- <slot />
7
- </a-row>
8
- </template>
9
-
10
-
11
- <script>
12
- import { Component, Vue } from '@a-vue'
13
-
14
- @Component({
15
- props: ['gap']
16
- })
17
- export default class ListFilterRow extends Vue {
18
- }
19
- </script>
20
-
21
-
22
- <style scoped lang="scss">
23
- :deep(.v-text-field__details) {
24
- display: none;
25
- }
26
- </style>