@blokkli/editor 1.1.0 → 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.
Files changed (39) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +12 -8
  3. package/dist/runtime/components/Blocks/FromLibrary/index.vue +2 -8
  4. package/dist/runtime/components/BlokkliItem.vue +1 -0
  5. package/dist/runtime/components/Edit/Actions/index.vue +5 -0
  6. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +2 -2
  7. package/dist/runtime/components/Edit/BlockProxy/index.vue +40 -9
  8. package/dist/runtime/components/Edit/DragInteractions/index.vue +16 -7
  9. package/dist/runtime/components/Edit/DraggableList.vue +3 -3
  10. package/dist/runtime/components/Edit/Features/Artboard/Overview/index.vue +7 -5
  11. package/dist/runtime/components/Edit/Features/Artboard/index.vue +7 -1
  12. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +29 -4
  13. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +27 -9
  14. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +7 -1
  15. package/dist/runtime/components/Edit/Features/CommandPalette/index.vue +1 -1
  16. package/dist/runtime/components/Edit/Features/Delete/index.vue +46 -2
  17. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +2 -2
  18. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +14 -6
  19. package/dist/runtime/components/Edit/Features/Duplicate/index.vue +33 -15
  20. package/dist/runtime/components/Edit/Features/History/List/index.vue +149 -0
  21. package/dist/runtime/components/Edit/Features/History/index.vue +7 -134
  22. package/dist/runtime/components/Edit/Features/Library/index.vue +1 -1
  23. package/dist/runtime/components/Edit/Features/Structure/index.vue +1 -0
  24. package/dist/runtime/components/Edit/ScrollBoundary/index.vue +17 -2
  25. package/dist/runtime/composables/defineBlokkli.js +10 -3
  26. package/dist/runtime/composables/defineBlokkliFragment.js +6 -3
  27. package/dist/runtime/css/output.css +1 -1
  28. package/dist/runtime/helpers/domProvider.d.ts +9 -5
  29. package/dist/runtime/helpers/domProvider.js +33 -34
  30. package/dist/runtime/helpers/index.d.ts +2 -1
  31. package/dist/runtime/helpers/index.js +9 -0
  32. package/dist/runtime/helpers/keyboardProvider.d.ts +1 -0
  33. package/dist/runtime/helpers/keyboardProvider.js +13 -2
  34. package/dist/runtime/helpers/selectionProvider.d.ts +1 -1
  35. package/dist/runtime/helpers/selectionProvider.js +6 -0
  36. package/dist/runtime/helpers/stateProvider.d.ts +1 -0
  37. package/dist/runtime/helpers/stateProvider.js +9 -1
  38. package/dist/runtime/types/index.d.ts +6 -0
  39. 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
- <div class="bk bk-history bk-control">
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 { RelativeTime, Icon } from '#blokkli/components'
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 canSetStatus = !!adapter.setMutationItemStatus
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
- async function setHistoryIndex(index: number) {
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
- const redo = () =>
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) => {
@@ -50,7 +50,7 @@
50
50
  </Teleport>
51
51
 
52
52
  <Teleport to="body">
53
- <transition name="bk-slide-up" :duration="200">
53
+ <transition appear name="bk-slide-in" :duration="200">
54
54
  <LibraryDialog
55
55
  v-if="placedAction && adapter.getLibraryItems"
56
56
  :field="placedAction.field"
@@ -15,6 +15,7 @@
15
15
  v-if="isLoaded"
16
16
  id="bk-structure"
17
17
  class="bk bk-structure bk-control"
18
+ dragging
18
19
  >
19
20
  <List
20
21
  :entity-bundle="context.entityBundle"
@@ -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
- if (selection.isDragging.value) {
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(INJECT_FRAGMENT_CONTEXT);
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
  });