@ditojs/admin 2.8.2 → 2.9.1
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/dist/dito-admin.es.js +1917 -1849
- package/dist/dito-admin.umd.js +6 -6
- package/dist/style.css +1 -1
- package/package.json +5 -5
- package/src/appState.js +2 -0
- package/src/components/DitoClipboard.vue +37 -57
- package/src/components/DitoContainer.vue +5 -7
- package/src/components/DitoDialog.vue +3 -7
- package/src/components/DitoDraggable.vue +16 -13
- package/src/components/DitoLabel.vue +2 -1
- package/src/components/DitoPane.vue +23 -10
- package/src/components/DitoRoot.vue +32 -8
- package/src/components/DitoSchema.vue +9 -4
- package/src/components/DitoSidebar.vue +29 -4
- package/src/components/DitoUploadFile.vue +1 -1
- package/src/mixins/DitoMixin.js +4 -3
- package/src/types/DitoTypeCheckbox.vue +8 -7
- package/src/types/DitoTypeCheckboxes.vue +10 -9
- package/src/utils/agent.js +47 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Dito.js Admin is a schema based admin interface for Dito.js Server, featuring auto-generated views and forms and built with Vue.js",
|
|
6
6
|
"repository": "https://github.com/ditojs/dito/tree/master/packages/admin",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"not ie_mob > 0"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ditojs/ui": "^2.
|
|
37
|
-
"@ditojs/utils": "^2.
|
|
36
|
+
"@ditojs/ui": "^2.9.0",
|
|
37
|
+
"@ditojs/utils": "^2.9.0",
|
|
38
38
|
"@kyvg/vue3-notification": "^2.9.0",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
40
40
|
"@tiptap/core": "^2.0.3",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"vue-upload-component": "^3.1.8"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@ditojs/build": "^2.
|
|
77
|
+
"@ditojs/build": "^2.9.0",
|
|
78
78
|
"@vitejs/plugin-vue": "^4.2.1",
|
|
79
79
|
"@vue/compiler-sfc": "^3.2.47",
|
|
80
80
|
"pug": "^3.0.2",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"vite": "^4.3.5"
|
|
84
84
|
},
|
|
85
85
|
"types": "types",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "002f3c713f9d3b10e348d2e9fd07d3a5bea426e6",
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "vite build",
|
|
89
89
|
"watch": "yarn build --mode 'development' --watch",
|
package/src/appState.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { reactive } from 'vue'
|
|
2
|
+
import { parseUserAgent } from './utils/agent'
|
|
2
3
|
|
|
3
4
|
export default reactive({
|
|
4
5
|
title: '',
|
|
5
6
|
routeComponents: [],
|
|
6
7
|
user: null,
|
|
8
|
+
agent: parseUserAgent(navigator.userAgent || ''),
|
|
7
9
|
loadCache: {}, // See TypeMixin.load()
|
|
8
10
|
activeLabel: null,
|
|
9
11
|
clipboardData: null
|
|
@@ -20,15 +20,16 @@
|
|
|
20
20
|
<script>
|
|
21
21
|
import { isObject, clone, deindent } from '@ditojs/utils'
|
|
22
22
|
import DitoComponent from '../DitoComponent.js'
|
|
23
|
-
import DitoContext from '../DitoContext.js'
|
|
24
23
|
import DomMixin from '../mixins/DomMixin.js'
|
|
24
|
+
import DitoContext from '../DitoContext.js'
|
|
25
25
|
|
|
26
26
|
// @vue/component
|
|
27
27
|
export default DitoComponent.component('DitoClipboard', {
|
|
28
28
|
mixins: [DomMixin],
|
|
29
29
|
|
|
30
30
|
props: {
|
|
31
|
-
clipboard: { type: [Boolean, Object],
|
|
31
|
+
clipboard: { type: [Boolean, Object], required: true },
|
|
32
|
+
schema: { type: Object, required: true },
|
|
32
33
|
dataPath: { type: String, required: true },
|
|
33
34
|
data: { type: [Object, Array], default: null }
|
|
34
35
|
},
|
|
@@ -36,8 +37,7 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
36
37
|
data() {
|
|
37
38
|
return {
|
|
38
39
|
copyEnabled: false,
|
|
39
|
-
pasteEnabled: false
|
|
40
|
-
fixClipboard: true
|
|
40
|
+
pasteEnabled: false
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
|
|
@@ -50,12 +50,7 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
50
50
|
const { copy } = this.clipboardOptions
|
|
51
51
|
return copy
|
|
52
52
|
? clipboardData =>
|
|
53
|
-
copy.call(
|
|
54
|
-
this,
|
|
55
|
-
new DitoContext(this, {
|
|
56
|
-
clipboardData
|
|
57
|
-
})
|
|
58
|
-
)
|
|
53
|
+
copy.call(this, new DitoContext(this, { clipboardData }))
|
|
59
54
|
: clipboardData => clone(clipboardData)
|
|
60
55
|
},
|
|
61
56
|
|
|
@@ -63,38 +58,27 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
63
58
|
const { paste } = this.clipboardOptions
|
|
64
59
|
return paste
|
|
65
60
|
? clipboardData =>
|
|
66
|
-
paste.call(
|
|
67
|
-
this,
|
|
68
|
-
new DitoContext(this, {
|
|
69
|
-
clipboardData
|
|
70
|
-
})
|
|
71
|
-
)
|
|
61
|
+
paste.call(this, new DitoContext(this, { clipboardData }))
|
|
72
62
|
: clipboardData => clipboardData
|
|
73
63
|
}
|
|
74
64
|
},
|
|
75
65
|
|
|
76
66
|
watch: {
|
|
77
|
-
'
|
|
67
|
+
'parentComponent.hasData': {
|
|
68
|
+
// Check right away also in case there's already data (e.g. create form).
|
|
69
|
+
immediate: true,
|
|
70
|
+
handler(hasData) {
|
|
71
|
+
this.copyEnabled = hasData
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
'appState.clipboardData': 'updatePaste'
|
|
78
75
|
},
|
|
79
76
|
|
|
80
77
|
mounted() {
|
|
81
78
|
// Check clipboard content whenever something gets copied or the window gets
|
|
82
79
|
// (re)activated, as those are the moments when the clipboard can change:
|
|
83
|
-
this.domOn(document, {
|
|
84
|
-
|
|
85
|
-
})
|
|
86
|
-
this.domOn(window, {
|
|
87
|
-
focus: this.checkClipboard
|
|
88
|
-
})
|
|
89
|
-
this.$watch('data', {
|
|
90
|
-
// Check right away also in case there's already data (e.g. create form).
|
|
91
|
-
immediate: true,
|
|
92
|
-
handler: (to, from) => {
|
|
93
|
-
if (to !== from) {
|
|
94
|
-
this.checkClipboard()
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
})
|
|
80
|
+
this.domOn(document, { copy: this.updatePaste })
|
|
81
|
+
this.domOn(window, { focus: this.updatePaste })
|
|
98
82
|
},
|
|
99
83
|
|
|
100
84
|
methods: {
|
|
@@ -103,12 +87,6 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
103
87
|
let { clipboardData } = this.appState
|
|
104
88
|
try {
|
|
105
89
|
const json = await navigator.clipboard?.readText?.()
|
|
106
|
-
if (this.fixClipboard && json) {
|
|
107
|
-
// This appears to be needed on Safari to prevent a strange "Paste"
|
|
108
|
-
// button from appearing when the clipboard is accessed (why?!).
|
|
109
|
-
await navigator.clipboard?.writeText?.(json)
|
|
110
|
-
this.fixClipboard = false
|
|
111
|
-
}
|
|
112
90
|
if (json) {
|
|
113
91
|
clipboardData = JSON.parse(json)
|
|
114
92
|
}
|
|
@@ -124,27 +102,34 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
124
102
|
}
|
|
125
103
|
}
|
|
126
104
|
const { $schema, ...data } = clipboardData || {}
|
|
127
|
-
return $schema === this.
|
|
105
|
+
return $schema === this.schema.name ? data : null
|
|
128
106
|
},
|
|
129
107
|
|
|
130
|
-
async
|
|
131
|
-
this.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
108
|
+
async updatePaste() {
|
|
109
|
+
this.pasteEnabled = !!this.appState.clipboardData
|
|
110
|
+
if (!this.pasteEnabled && this.appState.agent.chrome) {
|
|
111
|
+
// See if the clipboard content is valid JSON data that is compatible
|
|
112
|
+
// with the current target schema, and only then activate the pasting:
|
|
113
|
+
const data = await this.getClipboardData(false) // Don't report
|
|
114
|
+
this.pasteEnabled = !!data
|
|
115
|
+
}
|
|
135
116
|
},
|
|
136
117
|
|
|
137
118
|
async onCopy() {
|
|
138
|
-
let data = this.
|
|
119
|
+
let data = this.parentComponent.clipboardData
|
|
139
120
|
try {
|
|
140
|
-
|
|
121
|
+
if (data) {
|
|
122
|
+
data = {
|
|
123
|
+
$schema: this.schema.name,
|
|
124
|
+
...this.copyData(data)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
141
127
|
// Keep an internal clipboard as fallback.
|
|
142
128
|
this.appState.clipboardData = data
|
|
129
|
+
this.pasteEnabled = true
|
|
143
130
|
try {
|
|
144
131
|
const json = JSON.stringify(data, null, 2)
|
|
145
132
|
await navigator.clipboard?.writeText?.(json)
|
|
146
|
-
// See if we can activate the paste button, depending on browsers:
|
|
147
|
-
await this.checkClipboard()
|
|
148
133
|
} catch (err) {
|
|
149
134
|
console.error(err, err.name, err.message)
|
|
150
135
|
}
|
|
@@ -155,15 +140,10 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
155
140
|
},
|
|
156
141
|
|
|
157
142
|
async onPaste() {
|
|
158
|
-
let data = await this.getClipboardData(true) //
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
this.schemaComponent.setData(data)
|
|
163
|
-
}
|
|
164
|
-
} catch (error) {
|
|
165
|
-
console.error(error)
|
|
166
|
-
alert(error.message)
|
|
143
|
+
let data = await this.getClipboardData(true) // Report
|
|
144
|
+
data = data && this.pasteData(data)
|
|
145
|
+
if (data) {
|
|
146
|
+
this.parentComponent.clipboardData = data
|
|
167
147
|
}
|
|
168
148
|
}
|
|
169
149
|
}
|
|
@@ -255,26 +255,24 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
255
255
|
// percentages in flex-basis to work.
|
|
256
256
|
padding: $form-spacing-half;
|
|
257
257
|
|
|
258
|
-
.dito-
|
|
259
|
-
|
|
258
|
+
.dito-pane > & {
|
|
259
|
+
.dito-page--width-80 & {
|
|
260
260
|
flex-grow: 1;
|
|
261
261
|
flex-basis: var(--basis-mobile, var(--basis));
|
|
262
262
|
// DEBUG: background: yellow;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
|
|
265
|
+
.dito-page--width-60 & {
|
|
266
266
|
flex-basis: calc(2 * var(--basis));
|
|
267
267
|
// DEBUG: background: orange;
|
|
268
268
|
}
|
|
269
|
-
}
|
|
270
269
|
|
|
271
|
-
|
|
272
|
-
@container (width < #{$sidebar-max-width}) {
|
|
270
|
+
.dito-sidebar--width-99 & {
|
|
273
271
|
flex-grow: 1;
|
|
274
272
|
// DEBUG: background: yellow;
|
|
275
273
|
}
|
|
276
274
|
|
|
277
|
-
|
|
275
|
+
.dito-sidebar--width-60 & {
|
|
278
276
|
flex-basis: calc(2 * var(--basis));
|
|
279
277
|
// DEBUG: background: orange;
|
|
280
278
|
}
|
|
@@ -31,13 +31,14 @@
|
|
|
31
31
|
|
|
32
32
|
<script>
|
|
33
33
|
import { clone } from '@ditojs/utils'
|
|
34
|
-
import { addEvents } from '@ditojs/ui/src'
|
|
35
34
|
import DitoComponent from '../DitoComponent.js'
|
|
35
|
+
import DomMixin from '../mixins/DomMixin.js'
|
|
36
36
|
import { getButtonSchemas } from '../utils/schema.js'
|
|
37
37
|
import { UseFocusTrap } from '@vueuse/integrations/useFocusTrap/component'
|
|
38
38
|
|
|
39
39
|
// @vue/component
|
|
40
40
|
export default DitoComponent.component('DitoDialog', {
|
|
41
|
+
mixins: [DomMixin],
|
|
41
42
|
components: { UseFocusTrap },
|
|
42
43
|
emits: ['remove'],
|
|
43
44
|
|
|
@@ -70,7 +71,6 @@ export default DitoComponent.component('DitoDialog', {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
return {
|
|
73
|
-
windowEvents: null,
|
|
74
74
|
dialogData
|
|
75
75
|
}
|
|
76
76
|
},
|
|
@@ -125,7 +125,7 @@ export default DitoComponent.component('DitoDialog', {
|
|
|
125
125
|
},
|
|
126
126
|
|
|
127
127
|
mounted() {
|
|
128
|
-
this.
|
|
128
|
+
this.domOn(window, {
|
|
129
129
|
keyup: event => {
|
|
130
130
|
if ((this.hasCancel || !this.hasButtons) && event.keyCode === 27) {
|
|
131
131
|
this.cancel()
|
|
@@ -134,10 +134,6 @@ export default DitoComponent.component('DitoDialog', {
|
|
|
134
134
|
})
|
|
135
135
|
},
|
|
136
136
|
|
|
137
|
-
unmounted() {
|
|
138
|
-
this.windowEvents.remove()
|
|
139
|
-
},
|
|
140
|
-
|
|
141
137
|
methods: {
|
|
142
138
|
remove() {
|
|
143
139
|
this.$emit('remove')
|
|
@@ -16,12 +16,13 @@ component(
|
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
18
|
<script>
|
|
19
|
-
import { addEvents } from '@ditojs/ui'
|
|
20
19
|
import DitoComponent from '../DitoComponent'
|
|
20
|
+
import DomMixin from '../mixins/DomMixin.js'
|
|
21
21
|
import { UseSortable } from '@vueuse/integrations/useSortable/component'
|
|
22
22
|
|
|
23
23
|
// @vue/component
|
|
24
24
|
export default DitoComponent.component('DitoDraggable', {
|
|
25
|
+
mixins: [DomMixin],
|
|
25
26
|
components: { UseSortable },
|
|
26
27
|
emits: ['update:modelValue'],
|
|
27
28
|
|
|
@@ -53,8 +54,8 @@ export default DitoComponent.component('DitoDraggable', {
|
|
|
53
54
|
|
|
54
55
|
methods: {
|
|
55
56
|
onStart(event) {
|
|
56
|
-
this.isDragging = true
|
|
57
57
|
this.options.onStart?.(event)
|
|
58
|
+
this.isDragging = true
|
|
58
59
|
this.mouseEvents?.remove()
|
|
59
60
|
},
|
|
60
61
|
|
|
@@ -62,7 +63,7 @@ export default DitoComponent.component('DitoDraggable', {
|
|
|
62
63
|
this.options.onEnd?.(event)
|
|
63
64
|
// Keep `isDragging` true until the next mouse interaction so that
|
|
64
65
|
// confused hover states are cleared before removing the hover catcher.
|
|
65
|
-
this.mouseEvents =
|
|
66
|
+
this.mouseEvents = this.domOn(document, {
|
|
66
67
|
mousedown: this.onMouse,
|
|
67
68
|
mousemove: this.onMouse,
|
|
68
69
|
mouseleave: this.onMouse
|
|
@@ -71,7 +72,7 @@ export default DitoComponent.component('DitoDraggable', {
|
|
|
71
72
|
|
|
72
73
|
onMouse() {
|
|
73
74
|
this.isDragging = false
|
|
74
|
-
this.mouseEvents
|
|
75
|
+
this.mouseEvents?.remove()
|
|
75
76
|
this.mouseEvents = null
|
|
76
77
|
}
|
|
77
78
|
}
|
|
@@ -83,16 +84,18 @@ export default DitoComponent.component('DitoDraggable', {
|
|
|
83
84
|
|
|
84
85
|
.dito-draggable {
|
|
85
86
|
// Overlay a hover catcher while we're dragging to prevent hover states from
|
|
86
|
-
// getting stuck / confused.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
// getting stuck / confused. Safari struggles with this, so disable it there.
|
|
88
|
+
@include browser-query(('chrome', 'firefox')) {
|
|
89
|
+
&:has(&__chosen),
|
|
90
|
+
&--dragging {
|
|
91
|
+
> * {
|
|
92
|
+
position: relative;
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
> :first-child::after {
|
|
95
|
+
content: '';
|
|
96
|
+
position: absolute;
|
|
97
|
+
inset: 0;
|
|
98
|
+
}
|
|
96
99
|
}
|
|
97
100
|
}
|
|
98
101
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<template lang="pug">
|
|
3
3
|
.dito-pane(
|
|
4
4
|
v-if="isPopulated && componentSchemas.length > 0"
|
|
5
|
+
v-resize="onResizePane"
|
|
5
6
|
:class=`{
|
|
6
7
|
'dito-pane--single': isSingleComponent
|
|
7
8
|
}`
|
|
@@ -22,8 +23,9 @@
|
|
|
22
23
|
)
|
|
23
24
|
DitoContainer(
|
|
24
25
|
v-if="shouldRenderSchema(schema)"
|
|
26
|
+
ref="containers"
|
|
25
27
|
:key="nestedDataPath"
|
|
26
|
-
|
|
28
|
+
:data-index="index"
|
|
27
29
|
:schema="schema"
|
|
28
30
|
:dataPath="dataPath"
|
|
29
31
|
:data="data"
|
|
@@ -196,15 +198,26 @@ export default DitoComponent.component('DitoPane', {
|
|
|
196
198
|
}
|
|
197
199
|
},
|
|
198
200
|
|
|
199
|
-
|
|
200
|
-
this
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
201
|
+
onResizePane() {
|
|
202
|
+
this.$nextTick(() => {
|
|
203
|
+
for (const container of this.$refs.containers) {
|
|
204
|
+
const node = container.$el
|
|
205
|
+
const index = +node.dataset.index
|
|
206
|
+
const bounds = node.getBoundingClientRect()
|
|
207
|
+
const style = getComputedStyle(node)
|
|
208
|
+
const padding = parseFloat(style.padding)
|
|
209
|
+
const fontSize = parseFloat(style.fontSize)
|
|
210
|
+
const height = bounds.height - 2 * padding
|
|
211
|
+
this.positions[index] =
|
|
212
|
+
height <= 0
|
|
213
|
+
? null
|
|
214
|
+
: {
|
|
215
|
+
top: bounds.y,
|
|
216
|
+
height: height / fontSize,
|
|
217
|
+
node
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
})
|
|
208
221
|
},
|
|
209
222
|
|
|
210
223
|
isInLabeledRow(index) {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
.dito-root
|
|
2
|
+
.dito-root(
|
|
3
|
+
:data-agent-browser="appState.agent.browser"
|
|
4
|
+
:data-agent-platform="appState.agent.platform"
|
|
5
|
+
:data-agent-version="appState.agent.versionNumber"
|
|
6
|
+
)
|
|
3
7
|
VueNotifications.dito-notifications(
|
|
4
8
|
ref="notifications"
|
|
5
9
|
position="top right"
|
|
@@ -21,7 +25,10 @@
|
|
|
21
25
|
@remove="removeDialog(key)"
|
|
22
26
|
)
|
|
23
27
|
DitoNavigation
|
|
24
|
-
main.dito-page.dito-scroll-parent(
|
|
28
|
+
main.dito-page.dito-scroll-parent(
|
|
29
|
+
v-resize="onResizePage"
|
|
30
|
+
:class="pageClasses"
|
|
31
|
+
)
|
|
25
32
|
DitoHeader(
|
|
26
33
|
:spinner="options.spinner"
|
|
27
34
|
:isLoading="isLoading"
|
|
@@ -43,10 +50,10 @@
|
|
|
43
50
|
import { delegate as tippyDelegate } from 'tippy.js'
|
|
44
51
|
import { asArray, mapConcurrently, stripTags } from '@ditojs/utils'
|
|
45
52
|
import DitoComponent from '../DitoComponent.js'
|
|
53
|
+
import DomMixin from '../mixins/DomMixin.js'
|
|
46
54
|
import DitoUser from '../DitoUser.js'
|
|
47
55
|
import DitoView from '../components/DitoView.vue'
|
|
48
56
|
import DitoDialog from './DitoDialog.vue'
|
|
49
|
-
import DomMixin from '../mixins/DomMixin.js'
|
|
50
57
|
import {
|
|
51
58
|
processView,
|
|
52
59
|
resolveViews,
|
|
@@ -74,8 +81,9 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
74
81
|
resolvedViews: {},
|
|
75
82
|
removeRoutes: null,
|
|
76
83
|
dialogs: {},
|
|
77
|
-
|
|
84
|
+
pageWidth: 0,
|
|
78
85
|
loadingCount: 0,
|
|
86
|
+
allowLogin: false,
|
|
79
87
|
isDraggingFiles: false
|
|
80
88
|
}
|
|
81
89
|
},
|
|
@@ -87,6 +95,19 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
87
95
|
|
|
88
96
|
isLoading() {
|
|
89
97
|
return this.loadingCount > 0
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
pageClasses() {
|
|
101
|
+
const prefix = 'dito-page'
|
|
102
|
+
// NOTE: Keep synced with $content-width in SCSS:
|
|
103
|
+
const contentWidth = 900
|
|
104
|
+
return [
|
|
105
|
+
this.appState.pageClass,
|
|
106
|
+
{
|
|
107
|
+
[`${prefix}--width-80`]: this.pageWidth <= contentWidth * 0.8,
|
|
108
|
+
[`${prefix}--width-60`]: this.pageWidth <= contentWidth * 0.6
|
|
109
|
+
}
|
|
110
|
+
]
|
|
90
111
|
}
|
|
91
112
|
},
|
|
92
113
|
|
|
@@ -103,7 +124,7 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
103
124
|
tippyDelegate(this.$el, {
|
|
104
125
|
target: '.dito-info',
|
|
105
126
|
theme: 'info',
|
|
106
|
-
appendTo: '
|
|
127
|
+
appendTo: node => node.closest('.dito-pane'),
|
|
107
128
|
animation: 'shift-away-subtle',
|
|
108
129
|
interactive: true,
|
|
109
130
|
delay: 250,
|
|
@@ -438,6 +459,10 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
438
459
|
...routes.flat()
|
|
439
460
|
])
|
|
440
461
|
this.$router.replace(fullPath)
|
|
462
|
+
},
|
|
463
|
+
|
|
464
|
+
onResizePage({ contentRect: { width } }) {
|
|
465
|
+
this.pageWidth = width
|
|
441
466
|
}
|
|
442
467
|
}
|
|
443
468
|
})
|
|
@@ -475,10 +500,9 @@ function addRoutes(router, routes) {
|
|
|
475
500
|
|
|
476
501
|
flex: 0 1 var(--max-page-width);
|
|
477
502
|
background: $content-color-background;
|
|
503
|
+
min-width: 0%;
|
|
478
504
|
max-width: var(--max-page-width);
|
|
479
505
|
overflow: visible; // For .dito-header full-width background.
|
|
480
|
-
// For the `@container` rule in `.dito-container` to work:
|
|
481
|
-
container-type: inline-size;
|
|
482
506
|
|
|
483
507
|
&--wide {
|
|
484
508
|
--max-content-width: #{$content-width-wide};
|
|
@@ -505,9 +529,9 @@ function addRoutes(router, routes) {
|
|
|
505
529
|
position: fixed;
|
|
506
530
|
top: 0;
|
|
507
531
|
left: 0;
|
|
508
|
-
z-index: $z-index-drag-overlay;
|
|
509
532
|
width: 100%;
|
|
510
533
|
height: 100%;
|
|
534
|
+
z-index: $z-index-drag-overlay;
|
|
511
535
|
background: rgba(0, 0, 0, 0.25);
|
|
512
536
|
pointer-events: none;
|
|
513
537
|
backdrop-filter: blur(8px);
|
|
@@ -39,7 +39,9 @@ slot(name="before")
|
|
|
39
39
|
:tabs="tabs"
|
|
40
40
|
)
|
|
41
41
|
DitoClipboard(
|
|
42
|
+
v-if="clipboard"
|
|
42
43
|
:clipboard="clipboard"
|
|
44
|
+
:schema="schema"
|
|
43
45
|
:dataPath="dataPath"
|
|
44
46
|
:data="data"
|
|
45
47
|
)
|
|
@@ -236,10 +238,13 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
236
238
|
return this.processData({ target: 'server', schemaOnly: true })
|
|
237
239
|
},
|
|
238
240
|
|
|
239
|
-
clipboardData
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
clipboardData: {
|
|
242
|
+
get() {
|
|
243
|
+
return this.processData({ target: 'clipboard', schemaOnly: true })
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
set(data) {
|
|
247
|
+
this.setData(data)
|
|
243
248
|
}
|
|
244
249
|
},
|
|
245
250
|
|
|
@@ -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>
|
|
@@ -51,7 +51,7 @@ export default DitoComponent.component('DitoUploadFile', {
|
|
|
51
51
|
'file.upload.file': {
|
|
52
52
|
immediate: true,
|
|
53
53
|
handler(file) {
|
|
54
|
-
if (
|
|
54
|
+
if (this.thumbnail && file?.type.startsWith('image/')) {
|
|
55
55
|
const reader = new FileReader()
|
|
56
56
|
reader.onload = () => {
|
|
57
57
|
this.uploadUrl = reader.result
|
package/src/mixins/DitoMixin.js
CHANGED
|
@@ -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:
|
|
45
|
-
$dataComponent:
|
|
45
|
+
$parentComponent: self,
|
|
46
|
+
$dataComponent: self
|
|
46
47
|
}
|
|
47
48
|
: {
|
|
48
|
-
$parentComponent:
|
|
49
|
+
$parentComponent: self
|
|
49
50
|
}
|
|
50
51
|
},
|
|
51
52
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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>
|