@blokkli/editor 1.2.0 → 1.3.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.
Files changed (63) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +1678 -41
  3. package/dist/runtime/adapter/drupal/graphql/base.graphql +14 -3
  4. package/dist/runtime/adapter/drupal/graphql/comments.graphql +6 -1
  5. package/dist/runtime/adapter/drupal/graphql/transform.graphql +10 -2
  6. package/dist/runtime/adapter/drupal/graphqlMiddleware.js +26 -18
  7. package/dist/runtime/adapter/index.d.ts +6 -2
  8. package/dist/runtime/blokkliPlugins/Sidebar/index.vue +4 -1
  9. package/dist/runtime/components/BlokkliField.vue +8 -2
  10. package/dist/runtime/components/Edit/Actions/index.vue +27 -6
  11. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +1 -0
  12. package/dist/runtime/components/Edit/DragInteractions/index.vue +7 -0
  13. package/dist/runtime/components/Edit/EditProvider.vue +23 -5
  14. package/dist/runtime/components/Edit/Features/Artboard/index.vue +4 -0
  15. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +1 -0
  16. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +3 -1
  17. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +14 -2
  18. package/dist/runtime/components/Edit/Features/Debug/index.vue +26 -4
  19. package/dist/runtime/components/Edit/Features/Diff/DiffView/index.vue +236 -0
  20. package/dist/runtime/components/Edit/Features/Diff/index.vue +37 -0
  21. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +14 -4
  22. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +3 -0
  23. package/dist/runtime/components/Edit/Features/EditForm/Frame/index.vue +8 -1
  24. package/dist/runtime/components/Edit/Features/EditableField/index.vue +11 -5
  25. package/dist/runtime/components/Edit/Features/EntityTitle/index.vue +1 -0
  26. package/dist/runtime/components/Edit/Features/History/index.vue +3 -1
  27. package/dist/runtime/components/Edit/Features/ImportExisting/index.vue +5 -2
  28. package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue +10 -3
  29. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/Item.vue +2 -0
  30. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +4 -1
  31. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +14 -1
  32. package/dist/runtime/components/Edit/Features/Preview/index.vue +2 -1
  33. package/dist/runtime/components/Edit/Features/PreviewGrant/index.vue +2 -1
  34. package/dist/runtime/components/Edit/Features/Publish/index.vue +2 -0
  35. package/dist/runtime/components/Edit/Features/ResponsivePreview/index.vue +2 -1
  36. package/dist/runtime/components/Edit/Features/Selection/Overlay/fragment.glsl +78 -44
  37. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +8 -8
  38. package/dist/runtime/components/Edit/Features/Selection/Overlay/vertex.glsl +6 -1
  39. package/dist/runtime/components/Edit/Features/Settings/Dialog/FeatureSetting/index.vue +23 -2
  40. package/dist/runtime/components/Edit/Features/Settings/Dialog/index.vue +71 -38
  41. package/dist/runtime/components/Edit/Features/Settings/index.vue +4 -0
  42. package/dist/runtime/components/Edit/Features/Transform/index.vue +5 -1
  43. package/dist/runtime/components/Edit/Features/Translations/index.vue +24 -2
  44. package/dist/runtime/components/Edit/Features/index.vue +4 -0
  45. package/dist/runtime/components/Edit/InfoBox/index.vue +14 -0
  46. package/dist/runtime/components/Edit/Messages/index.vue +10 -12
  47. package/dist/runtime/components/Edit/PreviewProvider.vue +9 -2
  48. package/dist/runtime/components/Edit/index.d.ts +2 -1
  49. package/dist/runtime/components/Edit/index.js +3 -1
  50. package/dist/runtime/constants/index.d.ts +1 -1
  51. package/dist/runtime/constants/index.js +1 -0
  52. package/dist/runtime/css/output.css +1 -1
  53. package/dist/runtime/helpers/animationProvider.js +2 -1
  54. package/dist/runtime/helpers/featuresProvider.d.ts +7 -14
  55. package/dist/runtime/helpers/featuresProvider.js +29 -1
  56. package/dist/runtime/helpers/stateProvider.d.ts +1 -0
  57. package/dist/runtime/helpers/stateProvider.js +23 -4
  58. package/dist/runtime/helpers/uiProvider.d.ts +5 -1
  59. package/dist/runtime/helpers/uiProvider.js +10 -2
  60. package/dist/runtime/icons/diff.svg +1 -0
  61. package/dist/runtime/icons/info.svg +1 -0
  62. package/dist/runtime/types/index.d.ts +59 -1
  63. package/package.json +2 -1
@@ -84,11 +84,14 @@ fragment paragraphsBlokkliMutationResult on ParagraphsBlokkliMutationResult {
84
84
  query pbEditState(
85
85
  $entityType: EntityType!
86
86
  $entityUuid: String!
87
- $langcode: String
87
+ $langcode: String!
88
+ $historyIndex: Int
88
89
  ) {
89
90
  state: getParagraphsEditState(
90
91
  entityType: $entityType
91
92
  entityUuid: $entityUuid
93
+ langcode: $langcode
94
+ historyIndex: $historyIndex
92
95
  ) {
93
96
  ...paragraphsBlokkliEditState
94
97
  }
@@ -436,8 +439,16 @@ mutation pbUndo(
436
439
  }
437
440
  }
438
441
 
439
- query pbGetPreviewGrantUrl($entityType: EntityType!, $entityUuid: String!) {
440
- getParagraphsEditState(entityType: $entityType, entityUuid: $entityUuid) {
442
+ query pbGetPreviewGrantUrl(
443
+ $entityType: EntityType!
444
+ $entityUuid: String!
445
+ $langcode: String!
446
+ ) {
447
+ getParagraphsEditState(
448
+ entityType: $entityType
449
+ entityUuid: $entityUuid
450
+ langcode: $langcode
451
+ ) {
441
452
  previewUrl
442
453
  }
443
454
  }
@@ -13,10 +13,15 @@ fragment paragraphsBlokkliComment on CommentBlokkliNode {
13
13
  }
14
14
  }
15
15
 
16
- query pbComments($entityType: EntityType!, $entityUuid: String!) {
16
+ query pbComments(
17
+ $entityType: EntityType!
18
+ $entityUuid: String!
19
+ $langcode: String!
20
+ ) {
17
21
  state: getParagraphsEditState(
18
22
  entityType: $entityType
19
23
  entityUuid: $entityUuid
24
+ langcode: $langcode
20
25
  ) {
21
26
  comments {
22
27
  ...paragraphsBlokkliComment
@@ -1,5 +1,13 @@
1
- query pbGetTransformPlugins {
2
- paragraphsBlokkliGetTransformPlugins {
1
+ query pbGetTransformPlugins(
2
+ $entityType: EntityType!
3
+ $entityUuid: String!
4
+ $langcode: String!
5
+ ) {
6
+ paragraphsBlokkliGetTransformPlugins(
7
+ entityType: $entityType
8
+ entityUuid: $entityUuid
9
+ langcode: $langcode
10
+ ) {
3
11
  id
4
12
  label
5
13
  bundles
@@ -14,8 +14,10 @@ export default defineBlokkliEditAdapter(
14
14
  async (providedContext) => {
15
15
  const ctx = computed(() => {
16
16
  return {
17
- ...providedContext.value,
18
- entityType: providedContext.value.entityType.toUpperCase()
17
+ entityType: providedContext.value.entityType.toUpperCase(),
18
+ entityBundle: providedContext.value.entityBundle,
19
+ entityUuid: providedContext.value.entityUuid,
20
+ langcode: providedContext.value.language
19
21
  };
20
22
  });
21
23
  const config = await useGraphqlQuery("pbConfig", {
@@ -63,9 +65,18 @@ export default defineBlokkliEditAdapter(
63
65
  const getAllBundles = () => {
64
66
  return Promise.resolve(config.allTypes);
65
67
  };
66
- const loadState = (langcode) => useGraphqlQuery("pbEditState", {
68
+ const loadState = async () => {
69
+ const state = await useGraphqlQuery("pbEditState", {
70
+ ...ctx.value
71
+ }).then((v) => v?.data.state);
72
+ if (!state) {
73
+ throw new Error("Failed to load state.");
74
+ }
75
+ return state;
76
+ };
77
+ const loadStateAtIndex = (historyIndex) => useGraphqlQuery("pbEditState", {
67
78
  ...ctx.value,
68
- langcode: langcode || void 0
79
+ historyIndex
69
80
  }).then((v) => v?.data.state);
70
81
  const getDisabledFeatures = () => {
71
82
  const features = config.availableFeatures;
@@ -318,7 +329,7 @@ export default defineBlokkliEditAdapter(
318
329
  const getPreviewGrantUrl = () => useGraphqlQuery("pbGetPreviewGrantUrl", ctx.value).then(
319
330
  (v) => v.data.getParagraphsEditState?.previewUrl
320
331
  );
321
- const getTransformPlugins = () => useGraphqlQuery("pbGetTransformPlugins").then((v) => v.data.paragraphsBlokkliGetTransformPlugins || []).then(
332
+ const getTransformPlugins = () => useGraphqlQuery("pbGetTransformPlugins", ctx.value).then((v) => v.data.paragraphsBlokkliGetTransformPlugins || []).then(
322
333
  (plugins) => plugins.map((plugin) => {
323
334
  return {
324
335
  id: plugin.id,
@@ -345,9 +356,9 @@ export default defineBlokkliEditAdapter(
345
356
  const getLibraryItemEditUrl = (uuid) => {
346
357
  const url = buildFormUrl(
347
358
  ["blokkli", "library-item", uuid],
348
- ctx.value.language
359
+ ctx.value.langcode
349
360
  ).url;
350
- return `${url}&blokkliEditing=${uuid}&language=${ctx.value.language}`;
361
+ return `${url}&blokkliEditing=${uuid}&language=${ctx.value.langcode}`;
351
362
  };
352
363
  const formFrameBuilder = (e) => {
353
364
  const entityType = ctx.value.entityType.toLowerCase();
@@ -364,12 +375,12 @@ export default defineBlokkliEditAdapter(
364
375
  e.data.host.fieldName,
365
376
  e.data.afterUuid
366
377
  ],
367
- ctx.value.language
378
+ ctx.value.langcode
368
379
  );
369
380
  } else if (e.id === "block:edit") {
370
381
  return buildFormUrl(
371
382
  `/paragraphs_blokkli/${entityType}/${ctx.value.entityUuid}/edit/${e.data.uuid}`,
372
- ctx.value.language
383
+ ctx.value.langcode
373
384
  );
374
385
  } else if (e.id === "block:translate") {
375
386
  return buildFormUrl(
@@ -378,8 +389,8 @@ export default defineBlokkliEditAdapter(
378
389
  );
379
390
  } else if (e.id === "entity:edit") {
380
391
  return buildFormUrl(
381
- `/paragraphs_blokkli/${entityType}/${ctx.value.entityUuid}/edit_entity/${ctx.value.language}`,
382
- ctx.value.language
392
+ `/paragraphs_blokkli/${entityType}/${ctx.value.entityUuid}/edit_entity/${ctx.value.langcode}`,
393
+ ctx.value.langcode
383
394
  );
384
395
  } else if (e.id === "entity:translate") {
385
396
  return buildFormUrl(
@@ -389,7 +400,7 @@ export default defineBlokkliEditAdapter(
389
400
  } else if (e.id === "batchTranslate") {
390
401
  return buildFormUrl(
391
402
  `/paragraphs_blokkli/${entityType}/${ctx.value.entityUuid}/translate-paragraphs`,
392
- ctx.value.language
403
+ ctx.value.langcode
393
404
  );
394
405
  }
395
406
  };
@@ -404,7 +415,6 @@ export default defineBlokkliEditAdapter(
404
415
  };
405
416
  const updateFieldValue = (e) => useGraphqlMutation("pbUpdateFieldValue", {
406
417
  ...ctx.value,
407
- langcode: ctx.value.language,
408
418
  uuid: e.uuid,
409
419
  fieldName: e.fieldName,
410
420
  value: e.fieldValue
@@ -419,7 +429,7 @@ export default defineBlokkliEditAdapter(
419
429
  e.fieldName,
420
430
  e.uuid
421
431
  ].filter(falsy).join("/");
422
- return buildFormUrl(url, ctx.value.language).url;
432
+ return buildFormUrl(url, ctx.value.langcode).url;
423
433
  };
424
434
  const fragmentsAddBlock = (e) => useGraphqlMutation("pbAddFragmentParagraph", {
425
435
  ...ctx.value,
@@ -431,20 +441,17 @@ export default defineBlokkliEditAdapter(
431
441
  }).then(mapMutation);
432
442
  const mediaLibraryReplaceMedia = (e) => useGraphqlMutation("pbReplaceMedia", {
433
443
  ...ctx.value,
434
- langcode: providedContext.value.language,
435
444
  uuid: e.host.uuid,
436
445
  fieldName: e.host.fieldName,
437
446
  mediaId: e.mediaId
438
447
  }).then(mapMutation);
439
448
  const mediaLibraryReplaceEntityMedia = (e) => useGraphqlMutation("pbReplaceHostEntityMedia", {
440
449
  ...ctx.value,
441
- langcode: providedContext.value.language,
442
450
  fieldName: e.host.fieldName,
443
451
  mediaId: e.mediaId
444
452
  }).then(mapMutation);
445
453
  const updateEntityFieldValue = (e) => useGraphqlMutation("pbUpdateHostEntityFieldValue", {
446
454
  ...ctx.value,
447
- langcode: providedContext.value.language,
448
455
  fieldName: e.fieldName,
449
456
  value: e.fieldValue
450
457
  }).then(mapMutation);
@@ -666,7 +673,8 @@ export default defineBlokkliEditAdapter(
666
673
  clipboardMapBundle,
667
674
  addBlockFromClipboardItem,
668
675
  changeLanguage,
669
- getLibraryItemEditUrl
676
+ getLibraryItemEditUrl,
677
+ loadStateAtIndex
670
678
  };
671
679
  }
672
680
  );
@@ -139,9 +139,13 @@ export type BlokkliAdapterPublishOptions = {
139
139
  };
140
140
  export interface BlokkliAdapter<T> {
141
141
  /**
142
- * Load the state for the given langcode.
142
+ * Load the state.
143
143
  */
144
- loadState(langcode?: string | undefined | null): Promise<T | undefined>;
144
+ loadState(): Promise<T | undefined>;
145
+ /**
146
+ * Load the unchanged state.
147
+ */
148
+ loadStateAtIndex?: (index: number) => Promise<T | undefined>;
145
149
  mapState(state: T): MappedState;
146
150
  /**
147
151
  * Get disabled features at runtime.
@@ -73,6 +73,7 @@
73
73
  <div class="bk">
74
74
  <div class="bk-sidebar-title">
75
75
  <span>{{ title }}</span>
76
+ <div v-if="beta" class="bk-beta-indicator">BETA</div>
76
77
  <button v-if="!ui.isMobile.value" @click.prevent.stop="onDetach">
77
78
  <Icon name="expand" />
78
79
  </button>
@@ -116,6 +117,7 @@ const props = withDefaults(
116
117
  icon: BlokkliIcon
117
118
  weight?: string | number
118
119
  renderAlways?: boolean
120
+ disabled?: boolean
119
121
  region?: 'left' | 'right'
120
122
  minWidth?: number
121
123
  minHeight?: number
@@ -123,6 +125,7 @@ const props = withDefaults(
123
125
  meta?: boolean
124
126
  shift?: boolean
125
127
  keyCode?: string
128
+ beta?: boolean
126
129
  }>(),
127
130
  {
128
131
  region: 'right',
@@ -147,7 +150,7 @@ const detachedKey = computed(() => 'sidebar:detached:' + props.id)
147
150
  const storageKey = computed(() => 'sidebar:active:' + props.region)
148
151
  const isDetached = storage.use(detachedKey, false)
149
152
  const isDisabled = computed(
150
- () => props.editOnly && state.editMode.value !== 'editing',
153
+ () => props.editOnly && state.editMode.value !== 'editing' && !props.disabled,
151
154
  )
152
155
  const activeSidebar = storage.use(storageKey, '')
153
156
 
@@ -107,7 +107,7 @@ const isGlobalProxyMode = inject<ComputedRef<boolean> | null>(
107
107
  null,
108
108
  )
109
109
  const isInReusable = inject(INJECT_IS_IN_REUSABLE, false)
110
- const isPreview = inject<boolean>(INJECT_IS_PREVIEW, false)
110
+ const isPreview = inject<ComputedRef<boolean> | null>(INJECT_IS_PREVIEW, null)
111
111
  const isNested = inject(INJECT_IS_NESTED, false)
112
112
  const nestingLevel = inject<number>(INJECT_NESTING_LEVEL, 0)
113
113
  const mutatedFields = inject<Record<string, MutatedField> | null>(
@@ -179,7 +179,13 @@ function filterVisible(item?: FieldListItemTyped | FieldListItem): boolean {
179
179
  }
180
180
 
181
181
  const filteredList = computed<FieldListItemTyped[]>(() => {
182
- if (mutatedFields && !isInReusable && editContext && fieldKey.value) {
182
+ if (
183
+ mutatedFields &&
184
+ !isInReusable &&
185
+ editContext &&
186
+ fieldKey.value &&
187
+ (isPreview?.value || isEditing)
188
+ ) {
183
189
  return ((mutatedFields[fieldKey.value] || {}).list || [])
184
190
  .map((v) => {
185
191
  const mutatedOptions = editContext.mutatedOptions[v.uuid] || {}
@@ -15,6 +15,9 @@
15
15
  id="bk-blokkli-item-actions-controls"
16
16
  ref="controlsEl"
17
17
  class="bk-blokkli-item-actions-controls"
18
+ :class="{
19
+ 'bk-is-locked': ui.isTransforming.value,
20
+ }"
18
21
  >
19
22
  <div id="bk-blokkli-item-actions-title">
20
23
  <button
@@ -30,7 +33,8 @@
30
33
  @click.prevent="showDropdown = !showDropdown"
31
34
  >
32
35
  <div class="bk-blokkli-item-actions-title-icon">
33
- <ItemIcon v-if="bundleIcon" :bundle="bundleIcon" />
36
+ <Icon v-if="ui.isTransforming.value" name="loader" />
37
+ <ItemIcon v-else-if="bundleIcon" :bundle="bundleIcon" />
34
38
  <Icon v-else name="selection" />
35
39
  </div>
36
40
  <span class="bk-blokkli-item-actions-title-label">{{
@@ -79,7 +83,11 @@ import { getFragmentDefinition } from '#blokkli/definitions'
79
83
 
80
84
  const { selection, $t, types, state, ui, dom } = useBlokkli()
81
85
 
82
- const editingEnabled = computed(() => state.editMode.value === 'editing')
86
+ const editingEnabled = computed(
87
+ () =>
88
+ state.editMode.value === 'editing' ||
89
+ state.editMode.value === 'translating',
90
+ )
83
91
 
84
92
  const ACTIONS_HEIGHT = 50
85
93
 
@@ -105,6 +113,9 @@ const bundleIcon = computed(() => {
105
113
  })
106
114
 
107
115
  const title = computed(() => {
116
+ if (ui.transformLabel.value) {
117
+ return ui.transformLabel.value
118
+ }
108
119
  if (itemBundle.value) {
109
120
  if (itemBundle.value.id === 'blokkli_fragment') {
110
121
  const fragments = selection.uuids.value
@@ -189,7 +200,11 @@ onBeforeUnmount(() => {
189
200
  })
190
201
 
191
202
  onBlokkliEvent('canvas:draw', () => {
192
- if (!selection.blocks.value.length || ui.isMobile.value) {
203
+ if (
204
+ !selection.blocks.value.length ||
205
+ ui.isMobile.value ||
206
+ selection.isChangingOptions.value
207
+ ) {
193
208
  return
194
209
  }
195
210
 
@@ -221,8 +236,8 @@ onBlokkliEvent('canvas:draw', () => {
221
236
  const padding = ui.visibleViewportPadded.value
222
237
  const rect = limitPlacedRect(
223
238
  {
224
- x: minX,
225
- y: minY - ACTIONS_HEIGHT - 15,
239
+ x: minX - 5 * Math.min(scale, 1),
240
+ y: minY - ACTIONS_HEIGHT - 15 * Math.min(scale, 1),
226
241
  width: scrollWidth,
227
242
  height: ACTIONS_HEIGHT,
228
243
  },
@@ -238,7 +253,7 @@ onBlokkliEvent('canvas:draw', () => {
238
253
  if (el.value) {
239
254
  el.value.style.transform = ui.isMobile.value
240
255
  ? ''
241
- : `translate3d(${Math.round(ideal.x)}px, ${Math.round(ideal.y)}px, 0)`
256
+ : `translate3d(${ideal.x}px, ${ideal.y}px, 0)`
242
257
  }
243
258
  })
244
259
 
@@ -259,6 +274,12 @@ onBlokkliEvent('plugin:unmount', (e) => {
259
274
  }
260
275
  mountedPlugins.value = mountedPlugins.value.filter((v) => v.type !== e.id)
261
276
  })
277
+
278
+ watch(ui.isTransforming, function (isTransforming) {
279
+ if (isTransforming) {
280
+ showDropdown.value = false
281
+ }
282
+ })
262
283
  </script>
263
284
 
264
285
  <script lang="ts">
@@ -113,6 +113,7 @@ onBlokkliEvent('animationFrame', (e) => {
113
113
  ...e,
114
114
  artboardOffset: offset,
115
115
  artboardScale: scale,
116
+ time: e.time,
116
117
  })
117
118
  })
118
119
 
@@ -187,6 +187,9 @@ function onPointerDown(e: PointerEvent) {
187
187
  keyboard.setShortcutStateFromEvent(e)
188
188
 
189
189
  rootEl.removeEventListener('pointermove', onPointerMove)
190
+ if (state.isLoading.value) {
191
+ return
192
+ }
190
193
  rootEl.addEventListener('pointermove', onPointerMove)
191
194
 
192
195
  if (e.pointerType === 'touch') {
@@ -230,6 +233,10 @@ function onPointerUp(e: PointerEvent) {
230
233
  const wasMultiSelecting = selection.isMultiSelecting.value
231
234
  pointerDownElement = null
232
235
 
236
+ if (state.isLoading.value) {
237
+ return
238
+ }
239
+
233
240
  if (e.pointerType === 'touch') {
234
241
  return onTouchEnd(e)
235
242
  }
@@ -6,9 +6,27 @@
6
6
  screen
7
7
  />
8
8
  </Transition>
9
+
10
+ <div id="bk-banner-container">
11
+ <Messages />
12
+ <div v-if="!state.stateAvailable.value" class="bk-state-unavailable">
13
+ <h2>
14
+ {{
15
+ $t('stateUnavailableTitle', 'The edit state could not be loaded.')
16
+ }}
17
+ </h2>
18
+ <p>
19
+ {{
20
+ $t(
21
+ 'stateUnavailableText',
22
+ 'This could be due to missing permissions or a temporary problem. Please try again later.',
23
+ )
24
+ }}
25
+ </p>
26
+ </div>
27
+ </div>
9
28
  </Teleport>
10
29
  <Actions v-if="!isInitializing" />
11
- <Messages />
12
30
  <Toolbar @loaded="toolbarLoaded = true" />
13
31
  <AppMenu v-if="toolbarLoaded" />
14
32
  <Features
@@ -107,20 +125,20 @@ const toolbarLoaded = ref(false)
107
125
  const featuresLoaded = ref(false)
108
126
  const isInitializing = ref(true)
109
127
 
128
+ const $t = textProvider(context)
129
+ const state = await editStateProvider(adapter, context, $t)
110
130
  const storage = storageProvider()
111
131
  const debug = debugProvider(storage)
112
- const features = featuresProvider()
132
+ const features = featuresProvider(storage)
113
133
  const theme = themeProvider()
114
134
  const commands = commandsProvider()
115
135
  const tour = tourProvider()
116
136
  const dropAreas = dropAreasProvider()
117
137
  const broadcast = broadcastProvider()
118
- const ui = uiProvider(storage)
138
+ const ui = uiProvider(storage, state)
119
139
  const dom = domProvider(ui, debug)
120
140
  const animation = animationProvider(ui)
121
141
  const keyboard = keyboardProvider(animation)
122
- const $t = textProvider(context)
123
- const state = await editStateProvider(adapter, context, $t)
124
142
  const selection = selectionProvider(dom)
125
143
  const types = await typesProvider(adapter, selection, context)
126
144
 
@@ -82,6 +82,8 @@ const { settings } = defineBlokkliFeature({
82
82
  type: 'checkbox',
83
83
  default: true,
84
84
  label: 'Persist position and zoom',
85
+ description:
86
+ 'Stores and restores the last position and zoom factor of the artboard.',
85
87
  group: 'artboard',
86
88
  viewports: ['desktop'],
87
89
  },
@@ -89,6 +91,8 @@ const { settings } = defineBlokkliFeature({
89
91
  type: 'checkbox',
90
92
  default: true,
91
93
  label: 'Use smooth scrolling',
94
+ description:
95
+ 'Applies smooth animations when scrolling or zooming the artboard.',
92
96
  group: 'artboard',
93
97
  viewports: ['desktop'],
94
98
  },
@@ -83,6 +83,7 @@ const { settings } = defineBlokkliFeature({
83
83
  hideDisabledBlocks: {
84
84
  type: 'checkbox',
85
85
  label: "Hide blocks that can't be added",
86
+ description: `Hides blocks from the "Add List" if they can't be added to anywhere.`,
86
87
  group: 'appearance',
87
88
  default: false,
88
89
  },
@@ -92,7 +92,9 @@ const { settings, logger } = defineBlokkliFeature({
92
92
  openSidebarOnPaste: {
93
93
  type: 'checkbox',
94
94
  default: true,
95
- label: 'Open sidebar when pasting from clipboard',
95
+ label: 'Open sidebar when pasting',
96
+ description:
97
+ 'Automatically opens the sidebar when pasting content from the clipboard.',
96
98
  group: 'behavior',
97
99
  },
98
100
  },
@@ -4,6 +4,7 @@
4
4
  @keydown="onKeyDown"
5
5
  @keyup.stop
6
6
  @click.stop
7
+ @mousemove.once="hasUsedMouse = true"
7
8
  >
8
9
  <div class="bk-command-palette-input">
9
10
  <Icon name="command" />
@@ -25,7 +26,7 @@
25
26
  :visible-ids="visibleIds"
26
27
  :focused-id="focusedId"
27
28
  @close="$emit('close')"
28
- @focus="focusedId = $event"
29
+ @focus="onFocus"
29
30
  @select="onSelect($event)"
30
31
  />
31
32
  </div>
@@ -55,6 +56,14 @@ const emit = defineEmits(['close'])
55
56
  const inputEl = ref<HTMLInputElement | null>(null)
56
57
  const text = ref('')
57
58
  const focusedId = ref('')
59
+ const hasUsedMouse = ref(false)
60
+
61
+ function onFocus(id: string) {
62
+ if (!hasUsedMouse.value) {
63
+ return
64
+ }
65
+ focusedId.value = id
66
+ }
58
67
 
59
68
  type GroupedCommands = {
60
69
  id: CommandGroup
@@ -251,7 +260,10 @@ const onKeyDown = (e: KeyboardEvent) => {
251
260
  } else {
252
261
  focusNext()
253
262
  }
254
- } else if (e.code === 'ArrowDown') {
263
+ } else if (
264
+ e.code === 'ArrowDown' ||
265
+ (e.code === 'KeyJ' && (e.ctrlKey || e.metaKey))
266
+ ) {
255
267
  e.preventDefault()
256
268
  focusNext()
257
269
  } else if (e.code === 'ArrowUp') {
@@ -51,11 +51,25 @@
51
51
  <input
52
52
  :checked="overlay.active"
53
53
  type="checkbox"
54
- class="peer"
55
54
  @change="debug.toggleOverlay(overlay.id)"
56
55
  />
57
- <div />
58
- <span>{{ overlay.label }}</span>
56
+ <div class="bk-checkbox-toggle-toggle" />
57
+ <div class="bk-checkbox-toggle-label">
58
+ <div>{{ overlay.label }}</div>
59
+ </div>
60
+ </label>
61
+ </div>
62
+ <div>
63
+ <label class="bk-checkbox-toggle">
64
+ <input
65
+ :checked="ui.isTransforming.value"
66
+ type="checkbox"
67
+ @change="toggleTransforming"
68
+ />
69
+ <div class="bk-checkbox-toggle-toggle" />
70
+ <div class="bk-checkbox-toggle-label">
71
+ <div>Set transforming</div>
72
+ </div>
59
73
  </label>
60
74
  </div>
61
75
  </div>
@@ -124,7 +138,7 @@ const { logger } = defineBlokkliFeature({
124
138
  description: 'Provides debugging functionality.',
125
139
  })
126
140
 
127
- const { keyboard, selection, eventBus, features, debug } = useBlokkli()
141
+ const { keyboard, selection, eventBus, features, debug, ui } = useBlokkli()
128
142
 
129
143
  const iconItems = computed(() => Object.keys(icons) as BlokkliIcon[])
130
144
 
@@ -162,6 +176,14 @@ const onEvent = (name: string | number | symbol, data: any) => {
162
176
  logger.log('Event: ' + String(name), data)
163
177
  }
164
178
 
179
+ function toggleTransforming() {
180
+ if (ui.isTransforming.value) {
181
+ ui.setTransform()
182
+ } else {
183
+ ui.setTransform('Transform plugin label')
184
+ }
185
+ }
186
+
165
187
  onMounted(() => {
166
188
  eventBus.on('*', onEvent)
167
189
  })