@blokkli/editor 1.1.1 → 1.1.2
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/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/components/Blocks/FromLibrary/index.vue +2 -8
- package/dist/runtime/components/BlokkliItem.vue +1 -0
- package/dist/runtime/components/Edit/Actions/index.vue +5 -0
- package/dist/runtime/components/Edit/AnimationCanvas/index.vue +2 -2
- package/dist/runtime/components/Edit/BlockProxy/index.vue +40 -9
- package/dist/runtime/components/Edit/DragInteractions/index.vue +16 -7
- package/dist/runtime/components/Edit/Features/Artboard/Overview/index.vue +7 -5
- package/dist/runtime/components/Edit/Features/Artboard/index.vue +7 -1
- package/dist/runtime/components/Edit/Features/Clipboard/index.vue +27 -9
- package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +7 -1
- package/dist/runtime/components/Edit/Features/CommandPalette/index.vue +1 -1
- package/dist/runtime/components/Edit/Features/Delete/index.vue +46 -2
- package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +2 -2
- package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +14 -6
- package/dist/runtime/components/Edit/Features/Duplicate/index.vue +33 -15
- package/dist/runtime/components/Edit/Features/History/List/index.vue +149 -0
- package/dist/runtime/components/Edit/Features/History/index.vue +7 -134
- package/dist/runtime/components/Edit/Features/Library/index.vue +1 -1
- package/dist/runtime/components/Edit/Features/Structure/index.vue +1 -0
- package/dist/runtime/components/Edit/ScrollBoundary/index.vue +17 -2
- package/dist/runtime/composables/defineBlokkli.js +10 -3
- package/dist/runtime/composables/defineBlokkliFragment.js +6 -3
- package/dist/runtime/css/output.css +1 -1
- package/dist/runtime/helpers/domProvider.d.ts +0 -2
- package/dist/runtime/helpers/domProvider.js +0 -22
- package/dist/runtime/helpers/index.d.ts +2 -1
- package/dist/runtime/helpers/index.js +9 -0
- package/dist/runtime/helpers/keyboardProvider.d.ts +1 -0
- package/dist/runtime/helpers/keyboardProvider.js +13 -2
- package/dist/runtime/helpers/selectionProvider.d.ts +1 -1
- package/dist/runtime/helpers/selectionProvider.js +6 -0
- package/dist/runtime/helpers/stateProvider.d.ts +1 -0
- package/dist/runtime/helpers/stateProvider.js +9 -1
- package/dist/runtime/types/index.d.ts +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="bk bk-history bk-control">
|
|
3
|
+
<ul v-if="mapped.length">
|
|
4
|
+
<li
|
|
5
|
+
v-for="item in mapped"
|
|
6
|
+
:key="item.index"
|
|
7
|
+
:class="{
|
|
8
|
+
'bk-is-not-active': item.index > currentMutationIndex,
|
|
9
|
+
'bk-is-active': item.index === currentMutationIndex,
|
|
10
|
+
'bk-is-disabled': !item.enabled,
|
|
11
|
+
'bk-is-applied': item.index < currentMutationIndex && item.enabled,
|
|
12
|
+
}"
|
|
13
|
+
>
|
|
14
|
+
<button
|
|
15
|
+
:disabled="!canEdit"
|
|
16
|
+
class="bk-history-item-button"
|
|
17
|
+
@click="setHistoryIndex(item.index)"
|
|
18
|
+
>
|
|
19
|
+
<div>
|
|
20
|
+
<div>
|
|
21
|
+
<strong>{{ item.mutation.plugin?.label }}</strong>
|
|
22
|
+
</div>
|
|
23
|
+
<RelativeTime
|
|
24
|
+
v-if="item.timestamp"
|
|
25
|
+
v-slot="{ formatted }"
|
|
26
|
+
:timestamp="item.timestamp"
|
|
27
|
+
>
|
|
28
|
+
<em>{{ formatted }}</em>
|
|
29
|
+
</RelativeTime>
|
|
30
|
+
</div>
|
|
31
|
+
</button>
|
|
32
|
+
<div v-if="canSetStatus" class="bk-history-item-actions">
|
|
33
|
+
<button
|
|
34
|
+
@click.prevent="setMutationItemStatus(item.index, !item.enabled)"
|
|
35
|
+
>
|
|
36
|
+
<Icon name="close" />
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
</li>
|
|
40
|
+
<li v-if="totalMutations > showAmount" class="bk-history-load-more">
|
|
41
|
+
<button class="bk-history-item-button" @click="showAmount += 100">
|
|
42
|
+
<strong
|
|
43
|
+
>{{
|
|
44
|
+
$t('historyShowMore', 'Show @count more').replace(
|
|
45
|
+
'@count',
|
|
46
|
+
Math.min(totalMutations - showAmount, 100).toString(),
|
|
47
|
+
)
|
|
48
|
+
}}
|
|
49
|
+
</strong>
|
|
50
|
+
</button>
|
|
51
|
+
</li>
|
|
52
|
+
<li
|
|
53
|
+
class="bk-is-last"
|
|
54
|
+
:class="[
|
|
55
|
+
currentMutationIndex === -1 ? 'bk-is-active' : 'bk-is-applied',
|
|
56
|
+
{ 'bk-has-shadow': !scrolledToEnd },
|
|
57
|
+
]"
|
|
58
|
+
>
|
|
59
|
+
<button class="bk-history-item-button" @click="setHistoryIndex(-1)">
|
|
60
|
+
<div>
|
|
61
|
+
<strong>{{
|
|
62
|
+
$t('historyCurrentRevision', 'Current revision')
|
|
63
|
+
}}</strong>
|
|
64
|
+
</div>
|
|
65
|
+
<!-- @TODO: Pass in the timestamp of the entity's latest revision. -->
|
|
66
|
+
<!-- <RelativeTime -->
|
|
67
|
+
<!-- v-if="item.timestamp" -->
|
|
68
|
+
<!-- :timestamp="item.timestamp" -->
|
|
69
|
+
<!-- v-slot="{ formatted }" -->
|
|
70
|
+
<!-- > -->
|
|
71
|
+
<!-- <div>{{ formatted }}</div> -->
|
|
72
|
+
<!-- </RelativeTime> -->
|
|
73
|
+
</button>
|
|
74
|
+
</li>
|
|
75
|
+
</ul>
|
|
76
|
+
<div v-else class="bk-history-empty-message">
|
|
77
|
+
{{ $t('historyEmpty', 'There are now changes yet.') }}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
81
|
+
|
|
82
|
+
<script setup lang="ts">
|
|
83
|
+
import { ref, computed, useBlokkli, watch } from '#imports'
|
|
84
|
+
import { RelativeTime, Icon } from '#blokkli/components'
|
|
85
|
+
import type { MutationItem } from '#blokkli/types'
|
|
86
|
+
|
|
87
|
+
defineProps<{
|
|
88
|
+
scrolledToEnd: boolean
|
|
89
|
+
}>()
|
|
90
|
+
|
|
91
|
+
const { state, $t, adapter } = useBlokkli()
|
|
92
|
+
|
|
93
|
+
const { mutations, currentMutationIndex, canEdit, mutateWithLoadingState } =
|
|
94
|
+
state
|
|
95
|
+
|
|
96
|
+
const canSetStatus = !!adapter.setMutationItemStatus
|
|
97
|
+
|
|
98
|
+
const showAmount = ref(50)
|
|
99
|
+
const totalMutations = computed(() => mutations.value.length)
|
|
100
|
+
|
|
101
|
+
watch(totalMutations, (newTotal, previousTotal) => {
|
|
102
|
+
if (newTotal !== previousTotal) {
|
|
103
|
+
showAmount.value = 50
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
type HistoryItem = {
|
|
108
|
+
index: number
|
|
109
|
+
mutation: MutationItem
|
|
110
|
+
timestamp: number
|
|
111
|
+
enabled: boolean
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const mapped = computed<HistoryItem[]>(() =>
|
|
115
|
+
mutations.value
|
|
116
|
+
.map((mutation, index) => {
|
|
117
|
+
return {
|
|
118
|
+
index,
|
|
119
|
+
mutation,
|
|
120
|
+
timestamp: mutation.timestamp ? Number.parseInt(mutation.timestamp) : 0,
|
|
121
|
+
enabled: mutation.enabled !== false,
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
.sort((a, b) => {
|
|
125
|
+
return b.timestamp - a.timestamp
|
|
126
|
+
})
|
|
127
|
+
.filter((v, _i, arr) => {
|
|
128
|
+
return v.index >= arr.length - showAmount.value
|
|
129
|
+
}),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
async function setHistoryIndex(index: number) {
|
|
133
|
+
if (!adapter.setHistoryIndex) {
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
if (index !== currentMutationIndex.value) {
|
|
137
|
+
await mutateWithLoadingState(() => adapter.setHistoryIndex!(index))
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function setMutationItemStatus(index: number, status: boolean) {
|
|
142
|
+
if (!adapter.setMutationItemStatus) {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
await mutateWithLoadingState(() =>
|
|
146
|
+
adapter.setMutationItemStatus!(index, status),
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
</script>
|
|
@@ -12,84 +12,7 @@
|
|
|
12
12
|
icon="history"
|
|
13
13
|
weight="-100"
|
|
14
14
|
>
|
|
15
|
-
<
|
|
16
|
-
<ul v-if="mapped.length">
|
|
17
|
-
<li
|
|
18
|
-
v-for="item in mapped"
|
|
19
|
-
:key="item.index"
|
|
20
|
-
:class="{
|
|
21
|
-
'bk-is-not-active': item.index > currentMutationIndex,
|
|
22
|
-
'bk-is-active': item.index === currentMutationIndex,
|
|
23
|
-
'bk-is-disabled': !item.enabled,
|
|
24
|
-
'bk-is-applied': item.index < currentMutationIndex && item.enabled,
|
|
25
|
-
}"
|
|
26
|
-
>
|
|
27
|
-
<button
|
|
28
|
-
:disabled="!canEdit"
|
|
29
|
-
class="bk-history-item-button"
|
|
30
|
-
@click="setHistoryIndex(item.index)"
|
|
31
|
-
>
|
|
32
|
-
<div>
|
|
33
|
-
<div>
|
|
34
|
-
<strong>{{ item.mutation.plugin?.label }}</strong>
|
|
35
|
-
</div>
|
|
36
|
-
<RelativeTime
|
|
37
|
-
v-if="item.timestamp"
|
|
38
|
-
v-slot="{ formatted }"
|
|
39
|
-
:timestamp="item.timestamp"
|
|
40
|
-
>
|
|
41
|
-
<em>{{ formatted }}</em>
|
|
42
|
-
</RelativeTime>
|
|
43
|
-
</div>
|
|
44
|
-
</button>
|
|
45
|
-
<div v-if="canSetStatus" class="bk-history-item-actions">
|
|
46
|
-
<button
|
|
47
|
-
@click.prevent="setMutationItemStatus(item.index, !item.enabled)"
|
|
48
|
-
>
|
|
49
|
-
<Icon name="close" />
|
|
50
|
-
</button>
|
|
51
|
-
</div>
|
|
52
|
-
</li>
|
|
53
|
-
<li v-if="totalMutations > showAmount" class="bk-history-load-more">
|
|
54
|
-
<button class="bk-history-item-button" @click="showAmount += 100">
|
|
55
|
-
<strong
|
|
56
|
-
>{{
|
|
57
|
-
$t('historyShowMore', 'Show @count more').replace(
|
|
58
|
-
'@count',
|
|
59
|
-
Math.min(totalMutations - showAmount, 100).toString(),
|
|
60
|
-
)
|
|
61
|
-
}}
|
|
62
|
-
</strong>
|
|
63
|
-
</button>
|
|
64
|
-
</li>
|
|
65
|
-
<li
|
|
66
|
-
class="bk-is-last"
|
|
67
|
-
:class="[
|
|
68
|
-
currentMutationIndex === -1 ? 'bk-is-active' : 'bk-is-applied',
|
|
69
|
-
{ 'bk-has-shadow': !scrolledToEnd },
|
|
70
|
-
]"
|
|
71
|
-
>
|
|
72
|
-
<button class="bk-history-item-button" @click="setHistoryIndex(-1)">
|
|
73
|
-
<div>
|
|
74
|
-
<strong>{{
|
|
75
|
-
$t('historyCurrentRevision', 'Current revision')
|
|
76
|
-
}}</strong>
|
|
77
|
-
</div>
|
|
78
|
-
<!-- @TODO: Pass in the timestamp of the entity's latest revision. -->
|
|
79
|
-
<!-- <RelativeTime -->
|
|
80
|
-
<!-- v-if="item.timestamp" -->
|
|
81
|
-
<!-- :timestamp="item.timestamp" -->
|
|
82
|
-
<!-- v-slot="{ formatted }" -->
|
|
83
|
-
<!-- > -->
|
|
84
|
-
<!-- <div>{{ formatted }}</div> -->
|
|
85
|
-
<!-- </RelativeTime> -->
|
|
86
|
-
</button>
|
|
87
|
-
</li>
|
|
88
|
-
</ul>
|
|
89
|
-
<div v-else class="bk-history-empty-message">
|
|
90
|
-
{{ $t('historyEmpty', 'There are now changes yet.') }}
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
15
|
+
<HistoryList :scrolled-to-end="scrolledToEnd" />
|
|
93
16
|
</PluginSidebar>
|
|
94
17
|
|
|
95
18
|
<PluginToolbarButton
|
|
@@ -120,7 +43,6 @@
|
|
|
120
43
|
|
|
121
44
|
<script lang="ts" setup>
|
|
122
45
|
import {
|
|
123
|
-
ref,
|
|
124
46
|
computed,
|
|
125
47
|
useBlokkli,
|
|
126
48
|
watch,
|
|
@@ -129,8 +51,7 @@ import {
|
|
|
129
51
|
onBeforeUnmount,
|
|
130
52
|
} from '#imports'
|
|
131
53
|
import { PluginSidebar, PluginToolbarButton } from '#blokkli/plugins'
|
|
132
|
-
import
|
|
133
|
-
import type { MutationItem } from '#blokkli/types'
|
|
54
|
+
import HistoryList from './List/index.vue'
|
|
134
55
|
|
|
135
56
|
const { adapter, settings } = defineBlokkliFeature({
|
|
136
57
|
id: 'history',
|
|
@@ -152,72 +73,24 @@ const { adapter, settings } = defineBlokkliFeature({
|
|
|
152
73
|
|
|
153
74
|
const { state, $t, ui } = useBlokkli()
|
|
154
75
|
|
|
155
|
-
const
|
|
76
|
+
const { mutations, currentMutationIndex, mutateWithLoadingState } = state
|
|
156
77
|
|
|
157
|
-
const { mutations, currentMutationIndex, canEdit, mutateWithLoadingState } =
|
|
158
|
-
state
|
|
159
|
-
|
|
160
|
-
const showAmount = ref(50)
|
|
161
78
|
const useMouseForHistory = computed(() => settings.value.useMouseButtons)
|
|
162
79
|
const canUndo = computed(() => currentMutationIndex.value >= 0)
|
|
163
80
|
const canRedo = computed(
|
|
164
81
|
() => currentMutationIndex.value < mutations.value.length - 1,
|
|
165
82
|
)
|
|
166
|
-
const totalMutations = computed(() => mutations.value.length)
|
|
167
|
-
|
|
168
|
-
watch(totalMutations, (newTotal, previousTotal) => {
|
|
169
|
-
if (newTotal !== previousTotal) {
|
|
170
|
-
showAmount.value = 50
|
|
171
|
-
}
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
type HistoryItem = {
|
|
175
|
-
index: number
|
|
176
|
-
mutation: MutationItem
|
|
177
|
-
timestamp: number
|
|
178
|
-
enabled: boolean
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const mapped = computed<HistoryItem[]>(() =>
|
|
182
|
-
mutations.value
|
|
183
|
-
.map((mutation, index) => {
|
|
184
|
-
return {
|
|
185
|
-
index,
|
|
186
|
-
mutation,
|
|
187
|
-
timestamp: mutation.timestamp ? Number.parseInt(mutation.timestamp) : 0,
|
|
188
|
-
enabled: mutation.enabled !== false,
|
|
189
|
-
}
|
|
190
|
-
})
|
|
191
|
-
.sort((a, b) => {
|
|
192
|
-
return b.timestamp - a.timestamp
|
|
193
|
-
})
|
|
194
|
-
.filter((v, _i, arr) => {
|
|
195
|
-
return v.index >= arr.length - showAmount.value
|
|
196
|
-
}),
|
|
197
|
-
)
|
|
198
83
|
|
|
199
|
-
|
|
200
|
-
if (index !== currentMutationIndex.value) {
|
|
201
|
-
await mutateWithLoadingState(() => adapter.setHistoryIndex(index))
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const undo = () =>
|
|
84
|
+
function undo() {
|
|
206
85
|
mutateWithLoadingState(() =>
|
|
207
86
|
adapter.setHistoryIndex(currentMutationIndex.value - 1),
|
|
208
87
|
)
|
|
209
|
-
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function redo() {
|
|
210
91
|
mutateWithLoadingState(() =>
|
|
211
92
|
adapter.setHistoryIndex(currentMutationIndex.value + 1),
|
|
212
93
|
)
|
|
213
|
-
|
|
214
|
-
async function setMutationItemStatus(index: number, status: boolean) {
|
|
215
|
-
if (!adapter.setMutationItemStatus) {
|
|
216
|
-
return
|
|
217
|
-
}
|
|
218
|
-
await mutateWithLoadingState(() =>
|
|
219
|
-
adapter.setMutationItemStatus!(index, status),
|
|
220
|
-
)
|
|
221
94
|
}
|
|
222
95
|
|
|
223
96
|
const onMouseUp = (e: MouseEvent) => {
|
|
@@ -5,12 +5,28 @@
|
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script setup lang="ts">
|
|
8
|
+
/**
|
|
9
|
+
* Provides a boundary for wheel events to make the slot scrollable.
|
|
10
|
+
*
|
|
11
|
+
* During a drag operation the wheel event is propagated so that the artboard
|
|
12
|
+
* always becomes scrollable.
|
|
13
|
+
*/
|
|
8
14
|
import { useBlokkli } from '#imports'
|
|
9
15
|
|
|
10
16
|
const { selection } = useBlokkli()
|
|
11
17
|
|
|
18
|
+
const props = defineProps<{
|
|
19
|
+
/**
|
|
20
|
+
* Allow scrolling during dragging.
|
|
21
|
+
*/
|
|
22
|
+
dragging?: boolean
|
|
23
|
+
}>()
|
|
24
|
+
|
|
12
25
|
function onWheel(e: WheelEvent) {
|
|
13
|
-
|
|
26
|
+
// Unless allowed via prop, during dragging the only thing that should be
|
|
27
|
+
// scrollable is the artboard.
|
|
28
|
+
if (selection.isDragging.value && !props.dragging) {
|
|
29
|
+
e.preventDefault()
|
|
14
30
|
return
|
|
15
31
|
}
|
|
16
32
|
|
|
@@ -18,7 +34,6 @@ function onWheel(e: WheelEvent) {
|
|
|
18
34
|
return
|
|
19
35
|
}
|
|
20
36
|
|
|
21
|
-
// e.preventDefault()
|
|
22
37
|
e.stopImmediatePropagation()
|
|
23
38
|
}
|
|
24
39
|
</script>
|
|
@@ -26,12 +26,18 @@ export function defineBlokkli(config) {
|
|
|
26
26
|
computed(() => "default")
|
|
27
27
|
);
|
|
28
28
|
const siblings = inject(
|
|
29
|
-
INJECT_FIELD_LIST_BLOCKS
|
|
29
|
+
INJECT_FIELD_LIST_BLOCKS,
|
|
30
|
+
computed(function() {
|
|
31
|
+
return [];
|
|
32
|
+
})
|
|
30
33
|
);
|
|
31
34
|
const rootBlocks = inject(
|
|
32
|
-
INJECT_PROVIDER_BLOCKS
|
|
35
|
+
INJECT_PROVIDER_BLOCKS,
|
|
36
|
+
computed(function() {
|
|
37
|
+
return [];
|
|
38
|
+
})
|
|
33
39
|
);
|
|
34
|
-
const item = inject(INJECT_BLOCK_ITEM);
|
|
40
|
+
const item = inject(INJECT_BLOCK_ITEM, null);
|
|
35
41
|
const uuid = item?.value.uuid || "";
|
|
36
42
|
const index = item?.value.index !== void 0 ? item.value.index : computed(() => 0);
|
|
37
43
|
const fromLibraryOptions = inject(
|
|
@@ -103,6 +109,7 @@ export function defineBlokkli(config) {
|
|
|
103
109
|
return {
|
|
104
110
|
uuid,
|
|
105
111
|
index,
|
|
112
|
+
// Must be cast because type of options is inferred automatically.
|
|
106
113
|
options,
|
|
107
114
|
isEditing,
|
|
108
115
|
parentType,
|
|
@@ -12,7 +12,10 @@ import {
|
|
|
12
12
|
} from "#imports";
|
|
13
13
|
import { globalOptionsDefaults } from "#blokkli/default-global-options";
|
|
14
14
|
export function defineBlokkliFragment(config) {
|
|
15
|
-
const ctx = inject(
|
|
15
|
+
const ctx = inject(
|
|
16
|
+
INJECT_FRAGMENT_CONTEXT,
|
|
17
|
+
null
|
|
18
|
+
);
|
|
16
19
|
const editContext = inject(INJECT_EDIT_CONTEXT, null);
|
|
17
20
|
const optionKeys = [
|
|
18
21
|
...Object.keys(config.options || {}),
|
|
@@ -34,7 +37,7 @@ export function defineBlokkliFragment(config) {
|
|
|
34
37
|
return result;
|
|
35
38
|
});
|
|
36
39
|
onMounted(() => {
|
|
37
|
-
if (editContext && editContext.dom) {
|
|
40
|
+
if (editContext && editContext.dom && ctx) {
|
|
38
41
|
const instance = getCurrentInstance();
|
|
39
42
|
editContext.dom.registerBlock(
|
|
40
43
|
ctx.uuid,
|
|
@@ -46,7 +49,7 @@ export function defineBlokkliFragment(config) {
|
|
|
46
49
|
}
|
|
47
50
|
});
|
|
48
51
|
onBeforeUnmount(() => {
|
|
49
|
-
if (editContext && ctx.uuid && editContext.dom) {
|
|
52
|
+
if (editContext && ctx && ctx.uuid && editContext.dom) {
|
|
50
53
|
editContext.dom.unregisterBlock(ctx.uuid);
|
|
51
54
|
}
|
|
52
55
|
});
|