@ditojs/admin 2.8.1 → 2.9.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.
@@ -1,5 +1,8 @@
1
1
  <template lang="pug">
2
- aside.dito-sidebar.dito-scroll-parent
2
+ aside.dito-sidebar.dito-scroll-parent(
3
+ v-resize="onResizeSidebar"
4
+ :class="classes"
5
+ )
3
6
  nav.dito-header
4
7
  slot
5
8
  .dito-sidebar__teleport.dito-scroll
@@ -9,7 +12,31 @@ aside.dito-sidebar.dito-scroll-parent
9
12
  import DitoComponent from '../DitoComponent.js'
10
13
 
11
14
  // @vue/component
12
- export default DitoComponent.component('DitoSidebar', {})
15
+ export default DitoComponent.component('DitoSidebar', {
16
+ data() {
17
+ return {
18
+ sidebarWidth: 0
19
+ }
20
+ },
21
+
22
+ computed: {
23
+ classes() {
24
+ const prefix = 'dito-sidebar'
25
+ // NOTE: Keep synced with $sidebar-max-width in SCSS:
26
+ const sidebarWidth = 360
27
+ return {
28
+ [`${prefix}--width-99`]: this.sidebarWidth < sidebarWidth,
29
+ [`${prefix}--width-60`]: this.sidebarWidth <= sidebarWidth * 0.6
30
+ }
31
+ }
32
+ },
33
+
34
+ methods: {
35
+ onResizeSidebar({ contentRect: { width } }) {
36
+ this.sidebarWidth = width
37
+ }
38
+ }
39
+ })
13
40
  </script>
14
41
 
15
42
  <style lang="scss">
@@ -19,7 +46,5 @@ export default DitoComponent.component('DitoSidebar', {})
19
46
  flex: 0 1 $sidebar-max-width;
20
47
  max-width: $sidebar-max-width;
21
48
  min-width: $sidebar-min-width;
22
- // For the `@container` rule in `.dito-container` to work:
23
- container-type: inline-size;
24
49
  }
25
50
  </style>
@@ -2,7 +2,7 @@
2
2
  .dito-tree-item(
3
3
  :id="dataPath"
4
4
  :class=`{
5
- 'dito-dragging': dragging,
5
+ 'dito-dragging': isDragging,
6
6
  'dito-active': active
7
7
  }`
8
8
  :style="level > 0 && { '--level': level }"
@@ -76,7 +76,7 @@
76
76
  v-if="childrenSchema"
77
77
  v-show="opened"
78
78
  :modelValue="updateOrder(childrenSchema, childrenList)"
79
- :options="getSortableOptions(true)"
79
+ :options="getDraggableOptions(true)"
80
80
  :draggable="childrenDraggable"
81
81
  @update:modelValue="value => (childrenList = value)"
82
82
  )
@@ -51,7 +51,7 @@ export default DitoComponent.component('DitoUploadFile', {
51
51
  'file.upload.file': {
52
52
  immediate: true,
53
53
  handler(file) {
54
- if (file && this.thumbnail) {
54
+ if (this.thumbnail && file?.type.startsWith('image/')) {
55
55
  const reader = new FileReader()
56
56
  reader.onload = () => {
57
57
  this.uploadUrl = reader.result
@@ -39,13 +39,14 @@ export default {
39
39
  ],
40
40
 
41
41
  provide() {
42
+ const self = () => this
42
43
  return this.providesData
43
44
  ? {
44
- $parentComponent: () => this,
45
- $dataComponent: () => this
45
+ $parentComponent: self,
46
+ $dataComponent: self
46
47
  }
47
48
  : {
48
- $parentComponent: () => this
49
+ $parentComponent: self
49
50
  }
50
51
  },
51
52
 
@@ -2,19 +2,20 @@
2
2
  export default {
3
3
  data() {
4
4
  return {
5
- dragging: false
5
+ isDragging: false
6
6
  }
7
7
  },
8
8
 
9
9
  methods: {
10
- getSortableOptions(forceFallback = false) {
10
+ getDraggableOptions(forceFallback = false) {
11
+ const prefix = 'dito-draggable'
11
12
  return {
12
13
  animation: 150,
13
14
  handle: '.dito-button-drag',
14
- dragClass: 'dito-sortable-active',
15
- chosenClass: 'dito-sortable-chosen',
16
- ghostClass: 'dito-sortable-ghost',
17
- fallbackClass: 'dito-sortable-fallback',
15
+ dragClass: `${prefix}__drag`,
16
+ chosenClass: `${prefix}__chosen`,
17
+ ghostClass: `${prefix}__ghost`,
18
+ fallbackClass: `${prefix}__fallback`,
18
19
  forceFallback,
19
20
  onStart: this.onStartDrag,
20
21
  onEnd: this.onEndDrag
@@ -22,11 +23,11 @@ export default {
22
23
  },
23
24
 
24
25
  onStartDrag() {
25
- this.dragging = true
26
+ this.isDragging = true
26
27
  },
27
28
 
28
29
  onEndDrag({ oldIndex, newIndex }) {
29
- this.dragging = false
30
+ this.isDragging = false
30
31
  if (oldIndex !== newIndex) {
31
32
  this.onChange()
32
33
  }
@@ -13,7 +13,7 @@
13
13
  }
14
14
 
15
15
  .dito-layout-horizontal {
16
- > *:not(:first-child) {
16
+ > :not(:first-child) {
17
17
  padding-left: $form-spacing;
18
18
  }
19
19
  }
@@ -4,7 +4,6 @@
4
4
  @import '_pulldown';
5
5
  @import '_layout';
6
6
  @import '_scroll';
7
- @import '_sortable';
8
7
  @import '_table';
9
8
  @import '_info';
10
9
  @import '_tippy';
@@ -1,11 +1,12 @@
1
1
  <template lang="pug">
2
- input.dito-checkbox(
3
- :id="dataPath"
4
- ref="element"
5
- v-model="value"
6
- type="checkbox"
7
- v-bind="attributes"
8
- )
2
+ .dito-checkbox
3
+ input(
4
+ :id="dataPath"
5
+ ref="element"
6
+ v-model="value"
7
+ type="checkbox"
8
+ v-bind="attributes"
9
+ )
9
10
  </template>
10
11
 
11
12
  <script>
@@ -7,14 +7,15 @@ ul.dito-checkboxes(
7
7
  v-for="option in options"
8
8
  )
9
9
  label
10
- input.dito-checkbox(
11
- ref="element"
12
- v-model="selectedOptions"
13
- type="checkbox"
14
- :value="getValueForOption(option)"
15
- v-bind="attributes"
16
- )
17
- | {{ getLabelForOption(option) }}
10
+ .dito-checkbox
11
+ input(
12
+ ref="element"
13
+ v-model="selectedOptions"
14
+ type="checkbox"
15
+ :value="getValueForOption(option)"
16
+ v-bind="attributes"
17
+ )
18
+ span {{ getLabelForOption(option) }}
18
19
  </template>
19
20
 
20
21
  <script>
@@ -51,7 +52,7 @@ export default DitoTypeComponent.register('checkboxes', {
51
52
  @extend %input-borderless;
52
53
  }
53
54
 
54
- .dito-checkbox {
55
+ input {
55
56
  margin-right: $form-spacing;
56
57
  }
57
58
  }
@@ -39,7 +39,7 @@
39
39
  DitoDraggable(
40
40
  tag="tbody"
41
41
  :modelValue="updateOrder(sourceSchema, listData, paginationRange)"
42
- :options="getSortableOptions()"
42
+ :options="getDraggableOptions()"
43
43
  :draggable="draggable"
44
44
  @update:modelValue="value => (listData = value)"
45
45
  )
@@ -1,15 +1,14 @@
1
1
  <template lang="pug">
2
- .dito-multiselect(
3
- :class=`{
4
- 'dito-multiselect-single': !multiple,
5
- 'dito-multiselect-multiple': multiple
6
- }`
7
- )
2
+ .dito-multiselect
8
3
  .dito-multiselect__inner
9
4
  VueMultiselect(
10
5
  ref="element"
11
6
  v-model="selectedOptions"
12
- :class="{ 'multiselect--show-highlight': showHighlight }"
7
+ :class=`{
8
+ 'multiselect--multiple': multiple,
9
+ 'multiselect--loading': isLoading,
10
+ 'multiselect--highlight': showHighlight
11
+ }`
13
12
  :showLabels="false"
14
13
  :placeholder="placeholder"
15
14
  tagPlaceholder="Press enter to add new tag"
@@ -241,16 +240,6 @@ $tag-line-height: 1em;
241
240
  position: relative;
242
241
  }
243
242
 
244
- // TODO: BEM
245
- &.dito-multiselect-single {
246
- --input-width: 100%;
247
- }
248
-
249
- // TODO: BEM
250
- &.dito-multiselect-multiple {
251
- --input-width: auto;
252
- }
253
-
254
243
  .dito-edit-buttons {
255
244
  margin-left: $form-spacing-half;
256
245
  }
@@ -258,10 +247,16 @@ $tag-line-height: 1em;
258
247
  .multiselect {
259
248
  $self: last-selector(&);
260
249
 
250
+ --input-width: 100%;
251
+
261
252
  font-size: inherit;
262
253
  min-height: inherit;
263
254
  color: $color-black;
264
255
 
256
+ &--multiple {
257
+ --input-width: auto;
258
+ }
259
+
265
260
  &__tags {
266
261
  display: flex;
267
262
  font-size: inherit;
@@ -373,11 +368,11 @@ $tag-line-height: 1em;
373
368
  }
374
369
 
375
370
  // Only show the highlight once the pulldown has received mouse or
376
- // keyboard interaction, in which case `&--show-highlight` will be set,
371
+ // keyboard interaction, in which case `&--highlight` will be set,
377
372
  // which is controlled by `pointerDirty` in vue-multiselect.
378
373
  // Until then, clear the highlight style, but only if it isn't also
379
374
  // disabled or selected, in which case we want to keep the style.
380
- @at-root #{$self}:not(#{$self}--show-highlight)
375
+ @at-root #{$self}:not(#{$self}--highlight)
381
376
  #{$option}:not(#{$option}--disabled):not(#{$option}--selected) {
382
377
  color: $color-text;
383
378
  background: transparent;
@@ -391,7 +386,7 @@ $tag-line-height: 1em;
391
386
  color: $color-white;
392
387
  }
393
388
 
394
- @at-root #{$self}#{$self}--show-highlight #{last-selector(&)} {
389
+ @at-root #{$self}#{$self}--highlight #{last-selector(&)} {
395
390
  color: $color-text-inverted;
396
391
  background: $color-active;
397
392
  }
@@ -402,7 +397,7 @@ $tag-line-height: 1em;
402
397
  color: $color-text;
403
398
  background: $color-highlight;
404
399
 
405
- @at-root #{$self}#{$self}--show-highlight &#{$option}--highlight {
400
+ @at-root #{$self}#{$self}--highlight &#{$option}--highlight {
406
401
  color: $color-text-inverted;
407
402
  }
408
403
  }
@@ -490,6 +485,16 @@ $tag-line-height: 1em;
490
485
  }
491
486
  }
492
487
  }
488
+
489
+ &--loading {
490
+ #{$self}__tags {
491
+ border-radius: $border-radius;
492
+ }
493
+
494
+ #{$self}__content-wrapper {
495
+ display: none;
496
+ }
497
+ }
493
498
  }
494
499
  }
495
500
  </style>
@@ -35,7 +35,7 @@
35
35
  DitoDraggable(
36
36
  v-model="files"
37
37
  tag="tbody"
38
- :options="getSortableOptions()"
38
+ :options="getDraggableOptions()"
39
39
  :draggable="draggable"
40
40
  )
41
41
  template(
@@ -0,0 +1,47 @@
1
+ // This user-agent parser was lifted from Paper.js:
2
+ // https://github.com/paperjs/paper.js/blob/cc15696750035ab00e00c64c7c95daa2c85efe01/src/core/PaperScope.js#L75-L107
3
+
4
+ export function parseUserAgent(userAgent = '') {
5
+ const agent = {}
6
+ // Use replace() to get all matches, and deal with Chrome/Webkit overlap:
7
+ const ua = userAgent.toLowerCase()
8
+ const [os] =
9
+ /(iphone|ipad|linux; android|darwin|win|mac|linux|freebsd|sunos)/.exec(
10
+ ua
11
+ ) || []
12
+ const platform = (
13
+ {
14
+ 'darwin': 'mac',
15
+ 'iphone': 'ios',
16
+ 'ipad': 'ios',
17
+ 'linux; android': 'android'
18
+ }[os] ||
19
+ os
20
+ )
21
+ if (platform) {
22
+ agent.platform = platform
23
+ agent[platform] = true
24
+ }
25
+ ua.replace(
26
+ /(opera|chrome|safari|webkit|firefox|msie|trident)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv:v?([.\d]+))?/g,
27
+ (match, browser, v1, v2, rv) => {
28
+ // Do not set additional browsers once chrome is detected.
29
+ if (!agent.chrome) {
30
+ const version = rv || v2 || v1
31
+ if (!agent.version || browser !== 'safari') {
32
+ // Use the version we get for webkit for Safari, which is actually
33
+ // The Safari version, e.g. 16.0
34
+ agent.version = version
35
+ agent.versionNumber = parseFloat(version)
36
+ }
37
+ agent.browser = browser
38
+ agent[browser] = true
39
+ }
40
+ }
41
+ )
42
+ if (agent.chrome) {
43
+ // Can't have it both ways, Chrome.
44
+ delete agent.webkit
45
+ }
46
+ return agent
47
+ }
@@ -485,11 +485,11 @@ export function getFormSchemas(schema, context, modifyForm) {
485
485
 
486
486
  let { form, forms } = schema
487
487
  if (!form && !forms) {
488
- const { components, tabs, compact, clipboard } = schema
488
+ const { name, compact, clipboard, tabs, components } = schema
489
489
  if (components || tabs) {
490
- // Convert inlined components to forms, also supporting `tabs`, `compact`
491
- // and `clipboard` settings.
492
- form = { components, tabs, compact, clipboard }
490
+ // Convert inlined forms to stand-alone forms, supporting `name`,
491
+ // `compact`, `clipboard`, `tabs` and `components` settings.
492
+ form = { type: 'form', name, compact, clipboard, tabs, components }
493
493
  } else {
494
494
  // No `forms`, `form` or `components`, return and empty `forms` object.
495
495
  return {}
@@ -702,10 +702,11 @@ function cloneItem(sourceSchema, item, options) {
702
702
 
703
703
  export function processData(schema, sourceSchema, data, dataPath, {
704
704
  component,
705
+ rootData,
705
706
  schemaOnly, // whether to only include data covered by the schema, or all data
706
707
  target
707
708
  } = {}) {
708
- const options = { component, schemaOnly, target, rootData: data }
709
+ const options = { component, rootData, schemaOnly, target }
709
710
  const processedData = cloneItem(sourceSchema, data, options)
710
711
  const graph = new SchemaGraph()
711
712
 
@@ -837,15 +838,15 @@ export function processSchemaData(
837
838
  const componentDataPath = getDataPath(dataPath, name)
838
839
 
839
840
  const processItem = (item, index = null) => {
840
- const dataPath =
841
+ const itemDataPath =
841
842
  index !== null
842
843
  ? getDataPath(componentDataPath, index)
843
844
  : componentDataPath
844
845
  const context = new DitoContext(options.component, {
845
846
  schema: componentSchema,
846
- data,
847
+ data: item,
847
848
  value: item,
848
- dataPath,
849
+ dataPath: itemDataPath,
849
850
  index,
850
851
  rootData: options.rootData
851
852
  })
@@ -862,7 +863,7 @@ export function processSchemaData(
862
863
  return processSchemaData(
863
864
  form,
864
865
  item,
865
- dataPath,
866
+ itemDataPath,
866
867
  processedItem,
867
868
  processBefore,
868
869
  processAfter,
@@ -882,6 +883,7 @@ export function processSchemaData(
882
883
  componentDataPath,
883
884
  processedData
884
885
  )
886
+
885
887
  let value = processedData ? processedData[name] : data[name]
886
888
  if (value != null && hasFormSchema(componentSchema)) {
887
889
  // Recursively process data on nested form items.
@@ -897,6 +899,7 @@ export function processSchemaData(
897
899
  processedData[name] = value
898
900
  }
899
901
  }
902
+
900
903
  processAfter?.(
901
904
  componentSchema,
902
905
  data,
@@ -1,13 +0,0 @@
1
- .dito-sortable-fallback {
2
- filter: drop-shadow(0 2px 4px $color-shadow);
3
-
4
- // Nested <td> need to also switch to `display: block` style during dragging
5
- &,
6
- td {
7
- display: flex;
8
-
9
- > * {
10
- flex: 1;
11
- }
12
- }
13
- }