@ditojs/admin 0.265.0 → 0.269.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 (39) hide show
  1. package/LICENSE +1 -1
  2. package/dist/dito-admin.common.js +1193 -968
  3. package/dist/dito-admin.common.js.map +1 -1
  4. package/dist/dito-admin.umd.js +1193 -968
  5. package/dist/dito-admin.umd.js.map +1 -1
  6. package/dist/dito-admin.umd.min.js +3 -3
  7. package/dist/dito-admin.umd.min.js.map +1 -1
  8. package/package.json +13 -13
  9. package/src/DitoAdmin.js +3 -2
  10. package/src/components/DitoAccount.vue +4 -3
  11. package/src/components/DitoButtons.vue +4 -6
  12. package/src/components/DitoClipboard.vue +20 -9
  13. package/src/components/{DitoComponentContainer.vue → DitoContainer.vue} +4 -8
  14. package/src/components/DitoForm.vue +30 -16
  15. package/src/components/DitoLabel.vue +2 -2
  16. package/src/components/{DitoComponents.vue → DitoPane.vue} +18 -28
  17. package/src/components/DitoPanel.vue +10 -5
  18. package/src/components/DitoPanels.vue +4 -2
  19. package/src/components/DitoSchema.vue +59 -51
  20. package/src/components/DitoSchemaInlined.vue +1 -1
  21. package/src/components/index.js +5 -6
  22. package/src/mixins/DitoMixin.js +13 -4
  23. package/src/mixins/ResourceMixin.js +6 -1
  24. package/src/mixins/RouteMixin.js +1 -1
  25. package/src/mixins/SchemaParentMixin.js +6 -0
  26. package/src/mixins/SourceMixin.js +63 -33
  27. package/src/mixins/TypeMixin.js +32 -17
  28. package/src/mixins/ValidatorMixin.js +0 -4
  29. package/src/styles/_button.sass +1 -1
  30. package/src/types/TypeButton.vue +12 -11
  31. package/src/types/TypeCode.vue +1 -1
  32. package/src/types/TypeMarkup.vue +1 -1
  33. package/src/types/TypeMultiselect.vue +11 -10
  34. package/src/types/TypeSection.vue +1 -1
  35. package/src/types/TypeTreeList.vue +1 -3
  36. package/src/types/TypeUpload.vue +1 -1
  37. package/src/utils/accessor.js +2 -0
  38. package/src/utils/schema.js +17 -7
  39. package/src/components/DitoButtonContainer.vue +0 -22
@@ -29,7 +29,7 @@
29
29
  :dataPath="dataPath"
30
30
  :data="data"
31
31
  )
32
- dito-components.dito-components-tab(
32
+ dito-pane.dito-pane-tab(
33
33
  v-if="hasTabs"
34
34
  v-for="(schema, tab) in tabs"
35
35
  ref="tabs"
@@ -41,16 +41,15 @@
41
41
  :data="data"
42
42
  :meta="meta"
43
43
  :store="store"
44
- :single="!inlined && !hasMainComponents"
44
+ :single="!inlined && !hasMainPane"
45
45
  :disabled="disabled"
46
46
  :generateLabels="generateLabels"
47
47
  )
48
48
  transition-height(
49
49
  :enabled="inlined"
50
50
  )
51
- dito-components.dito-components-main(
52
- v-if="hasMainComponents"
53
- v-show="opened"
51
+ dito-pane.dito-pane-main(
52
+ v-if="hasMainPane && opened"
54
53
  ref="components"
55
54
  :schema="schema"
56
55
  :dataPath="dataPath"
@@ -70,9 +69,8 @@
70
69
  v-if="!hasLabel"
71
70
  name="edit-buttons"
72
71
  )
73
- template(ve-else)
72
+ template(v-else-if="isPopulated")
74
73
  dito-panels(
75
- v-if="isPopulated && panelSchemas.length > 0"
76
74
  :panels="panelSchemas"
77
75
  :data="data"
78
76
  :meta="meta"
@@ -104,7 +102,7 @@
104
102
  > .dito-panels
105
103
  padding: $content-padding $content-padding $content-padding 0
106
104
  // Display a ruler between tabbed components and towards the .dito-buttons
107
- .dito-components-tab + .dito-components-main
105
+ .dito-pane-tab + .dito-pane-main
108
106
  &::before
109
107
  // Use a pseudo element to display a ruler with proper margins
110
108
  display: block
@@ -204,8 +202,8 @@ export default DitoComponent.component('dito-schema', {
204
202
  ? data.call(this, this.context)
205
203
  : data
206
204
  ),
207
- containersRegistry: {},
208
205
  componentsRegistry: {},
206
+ panesRegistry: {},
209
207
  panelsRegistry: {}
210
208
  }
211
209
  },
@@ -225,8 +223,8 @@ export default DitoComponent.component('dito-schema', {
225
223
 
226
224
  panelSchemas() {
227
225
  const panels = getPanelSchemas(this.schema.panels, '')
228
- for (const container of Object.values(this.containersRegistry)) {
229
- panels.push(...container.panelSchemas)
226
+ for (const pane of this.panes) {
227
+ panels.push(...pane.panelSchemas)
230
228
  }
231
229
  return panels
232
230
  },
@@ -341,7 +339,7 @@ export default DitoComponent.component('dito-schema', {
341
339
  return !this.inlined && !!this.tabs
342
340
  },
343
341
 
344
- hasMainComponents() {
342
+ hasMainPane() {
345
343
  const { components } = this.schema
346
344
  return !!components && Object.keys(components).length > 0
347
345
  },
@@ -352,14 +350,26 @@ export default DitoComponent.component('dito-schema', {
352
350
  }
353
351
  }),
354
352
 
355
- containersByDataPath() {
356
- return this._listEntriesByDataPath(this.containersRegistry)
353
+ components() {
354
+ return Object.values(this.componentsRegistry)
355
+ },
356
+
357
+ panes() {
358
+ return Object.values(this.panesRegistry)
359
+ },
360
+
361
+ panels() {
362
+ return Object.values(this.panelsRegistry)
357
363
  },
358
364
 
359
365
  componentsByDataPath() {
360
366
  return this._listEntriesByDataPath(this.componentsRegistry)
361
367
  },
362
368
 
369
+ panesByDataPath() {
370
+ return this._listEntriesByDataPath(this.panesRegistry)
371
+ },
372
+
363
373
  panelsByDataPath() {
364
374
  return this._listEntriesByDataPath(this.panelsRegistry)
365
375
  }
@@ -370,7 +380,7 @@ export default DitoComponent.component('dito-schema', {
370
380
  this.setupSchemaFields()
371
381
  // Delegate change events through to parent schema:
372
382
  this.delegate('change', this.parentSchemaComponent)
373
- this.emitEvent('create')
383
+ this.emitEvent('initialize') // Not `'create'`, since that's for data.
374
384
  },
375
385
 
376
386
  beforeDestroy() {
@@ -422,17 +432,11 @@ export default DitoComponent.component('dito-schema', {
422
432
  },
423
433
 
424
434
  someComponent(callback) {
425
- return (
426
- this.isPopulated &&
427
- Object.values(this.componentsRegistry).some(callback)
428
- )
435
+ return this.isPopulated && this.components.some(callback)
429
436
  },
430
437
 
431
438
  everyComponent(callback) {
432
- return (
433
- this.isPopulated &&
434
- Object.values(this.componentsRegistry).every(callback)
435
- )
439
+ return this.isPopulated && this.components.every(callback)
436
440
  },
437
441
 
438
442
  onExpand(expand) {
@@ -440,11 +444,16 @@ export default DitoComponent.component('dito-schema', {
440
444
  // TODO: Actually expose this on DitoContext?
441
445
  context: { expand }
442
446
  })
443
- this.opened = expand
444
- },
445
-
446
- onLoad() {
447
- this.emitEvent('load')
447
+ // Prevent closing the schema with invalid data, since the in-component
448
+ // validation will not be executed once it's closed.
449
+
450
+ // TODO: Move validation out of components, to schema, just like
451
+ // processing, and use `showValidationErrors()` for the resulting errors,
452
+ // then remove this requirement, since we can validate closed forms and
453
+ // schemas then.
454
+ if (!this.opened || expand || this.validateAll()) {
455
+ this.opened = expand
456
+ }
448
457
  },
449
458
 
450
459
  onChange() {
@@ -452,13 +461,13 @@ export default DitoComponent.component('dito-schema', {
452
461
  },
453
462
 
454
463
  resetValidation() {
455
- for (const component of Object.values(this.componentsRegistry)) {
464
+ for (const component of this.components) {
456
465
  component.resetValidation()
457
466
  }
458
467
  },
459
468
 
460
469
  clearErrors() {
461
- for (const component of Object.values(this.componentsRegistry)) {
470
+ for (const component of this.components) {
462
471
  component.clearErrors()
463
472
  }
464
473
  },
@@ -512,7 +521,7 @@ export default DitoComponent.component('dito-schema', {
512
521
  return this.validateAll(match, false)
513
522
  },
514
523
 
515
- showValidationErrors(errors, focus) {
524
+ async showValidationErrors(errors, focus) {
516
525
  this.clearErrors()
517
526
  let first = true
518
527
  const unmatched = []
@@ -531,7 +540,7 @@ export default DitoComponent.component('dito-schema', {
531
540
  for (const component of components) {
532
541
  if (component.showValidationErrors(errs, first && focus)) {
533
542
  found = true
534
- break
543
+ first = false
535
544
  }
536
545
  }
537
546
  if (!found) {
@@ -542,22 +551,21 @@ export default DitoComponent.component('dito-schema', {
542
551
  while (dataPathParts.length > 0) {
543
552
  const components = this.getComponentsByDataPath(dataPathParts)
544
553
  for (const component of components) {
545
- if (component.navigateToComponent?.(
554
+ if (await component.navigateToComponent?.(
546
555
  fullDataPath,
547
- subComponent => {
548
- // Filter the errors to only contain those that belong to the
549
- // matched dataPath:
550
- const parentPath = normalizeDataPath(dataPathParts)
551
- const filteredErrors = Object.entries(errors).reduce(
552
- (filtered, [dataPath, errs]) => {
553
- if (normalizeDataPath(dataPath).startsWith(parentPath)) {
554
- filtered[dataPath] = errs
555
- }
556
- return filtered
557
- },
558
- {}
559
- )
560
- subComponent.showValidationErrors(filteredErrors, true)
556
+ subComponents => {
557
+ let found = false
558
+ for (const component of subComponents) {
559
+ const errs = errors[component.dataPath]
560
+ if (
561
+ errs &&
562
+ component.showValidationErrors(errs, first && focus)
563
+ ) {
564
+ found = true
565
+ first = false
566
+ }
567
+ }
568
+ return found
561
569
  }
562
570
  )) {
563
571
  // Found a nested form to display at least parts fo the errors.
@@ -652,16 +660,16 @@ export default DitoComponent.component('dito-schema', {
652
660
  this.$schemaParentComponent()?._registerSchemaComponent(this, add)
653
661
  },
654
662
 
655
- _registerContainer(container, add) {
656
- this._registerEntry(this.containersRegistry, container, add)
657
- },
658
-
659
663
  _registerComponent(component, add) {
660
664
  this._registerEntry(this.componentsRegistry, component, add)
661
665
  // Only register with the parent if schema shares data with it.
662
666
  this.parentSchemaComponent?._registerComponent(component, add)
663
667
  },
664
668
 
669
+ _registerPane(pane, add) {
670
+ this._registerEntry(this.panesRegistry, pane, add)
671
+ },
672
+
665
673
  _registerPanel(panel, add) {
666
674
  this._registerEntry(this.panelsRegistry, panel, add)
667
675
  },
@@ -45,7 +45,7 @@
45
45
  box-sizing: border-box
46
46
  // Because tables have a funny way of allowing too much width growth:
47
47
  max-width: $content-width
48
- & +.dito-components
48
+ & +.dito-pane
49
49
  // Needed for transition-height in DitoSchema:
50
50
  min-height: $form-spacing
51
51
  </style>
@@ -12,15 +12,14 @@ import './DitoElement'
12
12
  import './DitoLabel'
13
13
  import './DitoSchema'
14
14
  import './DitoSchemaInlined'
15
- import './DitoComponents'
15
+ import './DitoPane'
16
+ import './DitoContainer'
17
+ import './DitoTabs'
18
+ import './DitoPanel'
19
+ import './DitoPanels'
16
20
  import './DitoButtons'
17
21
  import './DitoEditButtons'
18
- import './DitoComponentContainer'
19
- import './DitoButtonContainer'
20
22
  import './DitoCreateButton'
21
- import './DitoPanel'
22
- import './DitoPanels'
23
- import './DitoTabs'
24
23
  import './DitoClipboard'
25
24
  import './DitoView'
26
25
  import './DitoForm'
@@ -25,7 +25,8 @@ export default {
25
25
  '$sourceComponent',
26
26
  '$resourceComponent',
27
27
  '$dialogComponent',
28
- '$panelComponent'
28
+ '$panelComponent',
29
+ '$tabComponent'
29
30
  ],
30
31
 
31
32
  provide() {
@@ -122,6 +123,10 @@ export default {
122
123
  return this.$panelComponent()
123
124
  },
124
125
 
126
+ tabComponent() {
127
+ return this.$tabComponent()
128
+ },
129
+
125
130
  parentSchemaComponent() {
126
131
  return this.schemaComponent?.$parent.schemaComponent
127
132
  },
@@ -153,7 +158,7 @@ export default {
153
158
  // We can't store this in `data`, as this is already the pure data from the
154
159
  // API server. That's what the `store` is for: Memory that's available as
155
160
  // long as the current editing path is still valid. For type components,
156
- // this memory is provided by the parent, see RouteMixin and DitoComponents.
161
+ // this memory is provided by the parent, see RouteMixin and DitoPane.
157
162
  getStore(key) {
158
163
  return this.store[key]
159
164
  },
@@ -472,7 +477,7 @@ export default {
472
477
 
473
478
  const addEvent = (key, event, callback) => {
474
479
  if (isFunction(callback)) {
475
- this.on(event, callback)
480
+ this.on(hyphenate(event), callback)
476
481
  } else {
477
482
  console.error(`Invalid event definition: ${key}: ${callback}`)
478
483
  }
@@ -488,7 +493,7 @@ export default {
488
493
  // doing things. Decide which one to remove.
489
494
  for (const [key, value] of Object.entries(this.schema)) {
490
495
  if (/^on[A-Z]/.test(key)) {
491
- addEvent(key, hyphenate(key.slice(2)), value)
496
+ addEvent(key, key.slice(2), value)
492
497
  }
493
498
  }
494
499
  },
@@ -518,6 +523,10 @@ export default {
518
523
  }
519
524
  return res
520
525
  }
526
+ },
527
+
528
+ emitSchemaEvent(event, params) {
529
+ return this.schemaComponent.emitEvent(event, params)
521
530
  }
522
531
  }
523
532
  }
@@ -210,6 +210,7 @@ export default {
210
210
  }
211
211
  } else {
212
212
  this.setData(response.data)
213
+ this.emitSchemaEvent('load')
213
214
  }
214
215
  })
215
216
  },
@@ -288,6 +289,8 @@ export default {
288
289
 
289
290
  async submitResource(button, resource, method, data, {
290
291
  setData = false,
292
+ onSuccess,
293
+ onError,
291
294
  notifySuccess = () => this.notify({
292
295
  type: 'success',
293
296
  title: 'Request Successful',
@@ -311,9 +314,10 @@ export default {
311
314
  // See if we're dealing with a Dito validation error:
312
315
  const errors = this.isValidationError(response) && data.errors
313
316
  if (errors) {
314
- this.showValidationErrors(errors, true)
317
+ await this.showValidationErrors(errors, true)
315
318
  } else {
316
319
  const error = isObject(data) ? data : err
320
+ onError?.(error)
317
321
  await this.emitButtonEvent(button, 'error', {
318
322
  notify: notifyError,
319
323
  error
@@ -326,6 +330,7 @@ export default {
326
330
  if (setData && data) {
327
331
  this.setData(data)
328
332
  }
333
+ onSuccess?.()
329
334
  await this.emitButtonEvent(button, 'success', {
330
335
  notify: notifySuccess
331
336
  })
@@ -24,7 +24,7 @@ export default {
24
24
  reload: false,
25
25
  // Each route-component defines a store that gets passed on to its
26
26
  // child components, so they can store values in them that live beyond
27
- // their life-cycle. See: DitoComponents, SourceMixin
27
+ // their life-cycle. See: DitoPane, SourceMixin
28
28
  store: {},
29
29
  loadCache: {} // See TypeMixin.load()
30
30
  }
@@ -12,6 +12,12 @@ export default {
12
12
  }
13
13
  },
14
14
 
15
+ computed: {
16
+ mainSchemaComponent() {
17
+ return this.schemaComponents[0]
18
+ }
19
+ },
20
+
15
21
  methods: {
16
22
  // This method is called by `DitoSchema.created()/destroyed()` on its
17
23
  // $parent, if the parent uses the `SchemaParentMixin`:
@@ -362,7 +362,6 @@ export default {
362
362
  // including the nested list data.
363
363
  this.viewComponent.setData(data)
364
364
  }
365
- this.schemaComponent.onLoad()
366
365
  },
367
366
 
368
367
  unwrapListData(data) {
@@ -445,54 +444,85 @@ export default {
445
444
  }
446
445
  },
447
446
 
448
- openSchemaComponent(index) {
447
+ getSchemaComponent(index) {
449
448
  const { schemaComponents } = this
450
449
  const { length } = schemaComponents
451
- const idx = ((index % length) + length) % length
452
- const schemaComponent = schemaComponents[idx]
450
+ return schemaComponents[((index % length) + length) % length]
451
+ },
452
+
453
+ openSchemaComponent(index) {
454
+ const schemaComponent = this.getSchemaComponent(index)
453
455
  if (schemaComponent) {
454
456
  schemaComponent.opened = true
455
457
  }
456
458
  },
457
459
 
458
- navigateToComponent(dataPath, onComplete) {
459
- const callOnComplete = () => {
460
- if (onComplete) {
460
+ async navigateToComponent(dataPath, onComplete) {
461
+ if (this.collapsible) {
462
+ const index = dataPath.startsWith(this.dataPath)
463
+ ? this.isListSource
464
+ ? parseDataPath(dataPath.slice(this.dataPath.length + 1))[0] ?? null
465
+ : 0
466
+ : null
467
+ if (index !== null && isNumber(+index)) {
468
+ const schemaComponent = this.getSchemaComponent(+index)
469
+ if (schemaComponent) {
470
+ const { opened } = schemaComponent
471
+ if (!opened) {
472
+ schemaComponent.opened = true
473
+ await this.$nextTick()
474
+ }
475
+ const components = schemaComponent.getComponentsByDataPath(dataPath)
476
+ if (components.length > 0 && (onComplete?.(components) ?? true)) {
477
+ return true
478
+ } else {
479
+ schemaComponent.opened = opened
480
+ }
481
+ }
482
+ }
483
+ }
484
+ return this.navigateToRouteComponent(dataPath, onComplete)
485
+ },
486
+
487
+ navigateToRouteComponent(dataPath, onComplete) {
488
+ return new Promise((resolve, reject) => {
489
+ const callOnComplete = () => {
461
490
  // Retrieve the last route component, which will be the component that
462
491
  // we just navigated to, and pass it on to `onComplete()`
463
492
  const { routeComponents } = this.appState
464
- onComplete(routeComponents[routeComponents.length - 1])
493
+ const routeComponent = routeComponents[routeComponents.length - 1]
494
+ resolve(onComplete?.([routeComponent]) ?? true)
465
495
  }
466
- }
467
496
 
468
- const dataPathParts = parseDataPath(dataPath)
469
- // See if we can find a route that can serve part of the given dataPath,
470
- // and take it from there:
471
- while (dataPathParts.length > 0) {
472
- const path = this.routeComponent.getChildPath(
473
- this.api.normalizePath(normalizeDataPath(dataPathParts))
474
- )
475
- // See if there actually is a route for this sub-component:
476
- const { matched } = this.$router.match(path)
477
- if (matched.length) {
478
- if (this.$route.path === path) {
497
+ const dataPathParts = parseDataPath(dataPath)
498
+ // See if we can find a route that can serve part of the given dataPath,
499
+ // and take it from there:
500
+ while (dataPathParts.length > 0) {
501
+ const path = this.routeComponent.getChildPath(
502
+ this.api.normalizePath(normalizeDataPath(dataPathParts))
503
+ )
504
+ // See if there actually is a route for this sub-component:
505
+ const { matched } = this.$router.match(path)
506
+ if (matched.length) {
507
+ if (this.$route.path === path) {
479
508
  // We're already there, so just call `onComplete()`:
480
- callOnComplete()
481
- } else {
509
+ callOnComplete()
510
+ } else {
482
511
  // Navigate to the component's path, then call `onComplete()`_:
483
- this.$router.push(
484
- { path },
485
- // Wait for the last route component to be mounted in the next
486
- // tick before calling `onComplete()`
487
- () => this.$nextTick(callOnComplete)
488
- )
512
+ this.$router.push(
513
+ { path },
514
+ // Wait for the last route component to be mounted in the next
515
+ // tick before calling `onComplete()`
516
+ () => this.$nextTick(callOnComplete),
517
+ reject
518
+ )
519
+ }
489
520
  }
490
- return true
521
+ // Keep removing the last part until we find a match.
522
+ dataPathParts.pop()
491
523
  }
492
- // Keep removing the last part until we find a match.
493
- dataPathParts.pop()
494
- }
495
- return false
524
+ resolve(false)
525
+ })
496
526
  }
497
527
  }, // end of `methods`
498
528
 
@@ -9,10 +9,6 @@ import { isString, asArray } from '@ditojs/utils'
9
9
  export default {
10
10
  mixins: [ValidationMixin],
11
11
 
12
- inject: [
13
- 'tabComponent'
14
- ],
15
-
16
12
  props: {
17
13
  schema: { type: Object, required: true },
18
14
  // NOTE: While `dataPath` points to the actual `value`, `data` represents
@@ -186,12 +182,16 @@ export default {
186
182
  },
187
183
 
188
184
  listeners() {
189
- return {
190
- focus: this.onFocus,
191
- blur: this.onBlur,
192
- input: this.onInput,
193
- change: this.onChange
185
+ const listeners = this.getListeners()
186
+ const { events = {} } = this.schema
187
+ if (events) {
188
+ // Register callbacks for all provides non-recognized events,
189
+ // assuming they are native events.
190
+ for (const event of Object.keys(events)) {
191
+ listeners[event] ||= () => this.emitEvent(event)
192
+ }
194
193
  }
194
+ return listeners
195
195
  },
196
196
 
197
197
  validations() {
@@ -240,28 +240,43 @@ export default {
240
240
  }
241
241
  },
242
242
 
243
+ // @overridable
244
+ getListeners() {
245
+ return {
246
+ focus: this.onFocus,
247
+ blur: this.onBlur,
248
+ input: this.onInput,
249
+ change: this.onChange
250
+ }
251
+ },
252
+
243
253
  // @overridable
244
254
  getValidations() {
245
255
  return null
246
256
  },
247
257
 
248
- focus() {
249
- // Also focus this component's schema and panel in case it's a tab.
250
- this.schemaComponent.focus()
251
- this.tabComponent?.focus()
252
- const [focus] = asArray(this.$refs.element)
253
- if (focus) {
258
+ // @overridable
259
+ focusElement() {
260
+ const [element] = asArray(this.$refs.element)
261
+ if (element) {
254
262
  this.$nextTick(() => {
255
- focus.focus()
263
+ element.focus()
256
264
  // If the element is disabled, `focus()` will likely not have the
257
265
  // desired effect. Use `scrollIntoView()` if available:
258
266
  if (this.disabled) {
259
- (focus.$el || focus).scrollIntoView?.()
267
+ (element.$el || element).scrollIntoView?.()
260
268
  }
261
269
  })
262
270
  }
263
271
  },
264
272
 
273
+ focus() {
274
+ // Also focus this component's schema and panel in case it's a tab.
275
+ this.schemaComponent.focus()
276
+ this.tabComponent?.focus()
277
+ this.focusElement()
278
+ },
279
+
265
280
  clear() {
266
281
  this.value = null
267
282
  this.onChange()
@@ -5,10 +5,6 @@ export default {
5
5
  mixins: [SchemaParentMixin],
6
6
 
7
7
  computed: {
8
- mainSchemaComponent() {
9
- return this.schemaComponents[0]
10
- },
11
-
12
8
  errors() {
13
9
  return this.schemaComponents.reduce(
14
10
  (result, { errors }) =>
@@ -62,7 +62,7 @@
62
62
  font-size: $menu-font-size
63
63
  flex-flow: row wrap
64
64
  justify-content: center
65
- .dito-button-container
65
+ .dito-container
66
66
  // Do not specify this on .dito-buttons directly as it would break borders
67
67
  margin-top: $content-padding
68
68
  .dito-button
@@ -39,7 +39,15 @@ export default TypeComponent.register([
39
39
  }
40
40
  }),
41
41
 
42
- listeners() {
42
+ closeForm: getSchemaAccessor('closeForm', {
43
+ type: Boolean,
44
+ default: false
45
+ })
46
+ },
47
+
48
+ methods: {
49
+ // @override
50
+ getListeners() {
43
51
  return {
44
52
  focus: this.onFocus,
45
53
  blur: this.onBlur,
@@ -47,13 +55,10 @@ export default TypeComponent.register([
47
55
  }
48
56
  },
49
57
 
50
- closeForm: getSchemaAccessor('closeForm', {
51
- type: Boolean,
52
- default: false
53
- })
54
- },
58
+ async submit(options) {
59
+ return this.resourceComponent?.submit(this, options)
60
+ },
55
61
 
56
- methods: {
57
62
  async onClick() {
58
63
  const res = await this.emitEvent('click', {
59
64
  parent: this.schemaComponent
@@ -65,10 +70,6 @@ export default TypeComponent.register([
65
70
  ) {
66
71
  await this.submit()
67
72
  }
68
- },
69
-
70
- async submit(options) {
71
- return this.resourceComponent?.submit(this, options)
72
73
  }
73
74
  }
74
75
  })
@@ -120,7 +120,7 @@ export default TypeComponent.register('code', {
120
120
  },
121
121
 
122
122
  methods: {
123
- focus() {
123
+ focusElement() {
124
124
  this.$el.querySelector('textarea')?.focus()
125
125
  }
126
126
  }