@blokkli/editor 2.0.0-alpha.16 → 2.0.0-alpha.18

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 (194) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +640 -137
  3. package/dist/modules/drupal/graphql/base/fragment.blokkliProps.graphql +1 -1
  4. package/dist/modules/drupal/graphql/base/fragment.paragraphsFieldItem.graphql +3 -1
  5. package/dist/modules/drupal/graphql/base/query.pbConfig.graphql +1 -10
  6. package/dist/modules/drupal/graphql/features/comments.graphql +11 -8
  7. package/dist/modules/drupal/graphql/mutations/set_paragraph_schedule.graphql +15 -0
  8. package/dist/modules/drupal/index.mjs +33 -0
  9. package/dist/modules/drupal/runtime/adapter/index.js +12 -4
  10. package/dist/runtime/adapter/index.d.ts +21 -0
  11. package/dist/runtime/blokkliPlugins/ContextMenu/Menu/index.vue +3 -0
  12. package/dist/runtime/blokkliPlugins/ItemAction/index.vue +23 -15
  13. package/dist/runtime/blokkliPlugins/ItemAction/index.vue.d.ts +20 -44
  14. package/dist/runtime/blokkliPlugins/TourItem/index.vue +10 -5
  15. package/dist/runtime/components/Blocks/FromLibrary/index.vue +4 -2
  16. package/dist/runtime/components/BlokkliEditable.vue +32 -14
  17. package/dist/runtime/components/BlokkliField.vue +3 -0
  18. package/dist/runtime/components/BlokkliField.vue.d.ts +3 -3
  19. package/dist/runtime/components/BlokkliItem.vue +1 -1
  20. package/dist/runtime/components/BlokkliItem.vue.d.ts +4 -2
  21. package/dist/runtime/components/BlokkliProvider.vue +41 -28
  22. package/dist/runtime/components/BlokkliProvider.vue.d.ts +2 -1
  23. package/dist/runtime/components/Edit/Actions/index.vue +36 -20
  24. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +436 -25
  25. package/dist/runtime/components/Edit/ArtboardTooltip/index.vue +83 -0
  26. package/dist/runtime/components/Edit/ArtboardTooltip/index.vue.d.ts +32 -0
  27. package/dist/runtime/components/Edit/Banner/index.vue +51 -0
  28. package/dist/runtime/components/Edit/Banner/index.vue.d.ts +18 -0
  29. package/dist/runtime/components/Edit/Dialog/index.vue +6 -4
  30. package/dist/runtime/components/Edit/DraggableList.vue +15 -7
  31. package/dist/runtime/components/Edit/DraggableList.vue.d.ts +5 -5
  32. package/dist/runtime/components/Edit/EditIndicator.vue +118 -44
  33. package/dist/runtime/components/Edit/EditIndicator.vue.d.ts +3 -0
  34. package/dist/runtime/components/Edit/EditProvider.vue +101 -31
  35. package/dist/runtime/components/Edit/EditProvider.vue.d.ts +3 -0
  36. package/dist/runtime/components/Edit/Features/AddList/index.vue +9 -11
  37. package/dist/runtime/components/Edit/Features/Analyze/Overlay/index.vue +28 -26
  38. package/dist/runtime/components/Edit/Features/Analyze/Renderer.vue +1 -1
  39. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItemNodesTarget.vue +15 -11
  40. package/dist/runtime/components/Edit/Features/Anchors/Renderer.vue +19 -102
  41. package/dist/runtime/components/Edit/Features/Artboard/Renderer.vue +3 -0
  42. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +29 -53
  43. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/ScheduleSection.vue +154 -0
  44. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/ScheduleSection.vue.d.ts +27 -0
  45. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/index.vue +222 -0
  46. package/dist/runtime/components/Edit/Features/{Selection/AddButtons/AddButtonsField.vue.d.ts → BlockScheduler/Dialog/index.vue.d.ts} +6 -9
  47. package/dist/runtime/components/Edit/Features/BlockScheduler/index.vue +96 -0
  48. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +15 -16
  49. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Item/index.vue +51 -0
  50. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/{Group → Item}/index.vue.d.ts +9 -13
  51. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +46 -66
  52. package/dist/runtime/components/Edit/Features/CommandPalette/index.vue +2 -0
  53. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue +35 -20
  54. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue.d.ts +5 -3
  55. package/dist/runtime/components/Edit/Features/Comments/CommentInput/index.vue +29 -0
  56. package/dist/runtime/components/Edit/Features/{Publish/Dialog/ScheduleDate.vue.d.ts → Comments/CommentInput/index.vue.d.ts} +2 -2
  57. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue +22 -16
  58. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue.d.ts +1 -0
  59. package/dist/runtime/components/Edit/Features/Comments/Overlay/index.vue +15 -6
  60. package/dist/runtime/components/Edit/Features/Comments/index.vue +21 -9
  61. package/dist/runtime/components/Edit/Features/Conversions/index.vue +4 -7
  62. package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue +26 -35
  63. package/dist/runtime/components/Edit/Features/Debug/Renderer.vue +240 -0
  64. package/dist/runtime/components/Edit/Features/Debug/Renderer.vue.d.ts +6 -0
  65. package/dist/runtime/components/Edit/Features/Debug/index.vue +7 -165
  66. package/dist/runtime/components/Edit/Features/Delete/index.vue +1 -1
  67. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +14 -6
  68. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +55 -48
  69. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +30 -18
  70. package/dist/runtime/components/Edit/Features/Duplicate/index.vue +6 -8
  71. package/dist/runtime/components/Edit/Features/Edit/index.vue +16 -22
  72. package/dist/runtime/components/Edit/Features/EditForm/index.vue +7 -6
  73. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue +69 -4
  74. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue.d.ts +2 -2
  75. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Plaintext/index.vue +13 -9
  76. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue +45 -87
  77. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue.d.ts +2 -2
  78. package/dist/runtime/components/Edit/Features/EditableField/index.vue +41 -43
  79. package/dist/runtime/components/Edit/Features/Fragments/Dialog/index.vue +11 -9
  80. package/dist/runtime/components/Edit/Features/Fragments/index.vue +3 -3
  81. package/dist/runtime/components/Edit/Features/History/index.vue +5 -2
  82. package/dist/runtime/components/Edit/Features/Hover/Overlay/fragment.glsl +139 -0
  83. package/dist/runtime/components/Edit/Features/Hover/Overlay/index.vue +261 -0
  84. package/dist/runtime/components/Edit/Features/Hover/Overlay/index.vue.d.ts +6 -0
  85. package/dist/runtime/components/Edit/Features/Hover/Overlay/vertex.glsl +117 -0
  86. package/dist/runtime/components/Edit/Features/Hover/index.vue +25 -0
  87. package/dist/runtime/components/Edit/Features/Hover/index.vue.d.ts +2 -0
  88. package/dist/runtime/components/Edit/Features/Library/EditReusable/index.vue +5 -7
  89. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/index.vue +19 -27
  90. package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue +32 -28
  91. package/dist/runtime/components/Edit/Features/Library/index.vue +28 -23
  92. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +6 -3
  93. package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue +15 -12
  94. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/index.vue +36 -29
  95. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +2 -4
  96. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue +6 -1
  97. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +8 -6
  98. package/dist/runtime/components/Edit/Features/Options/index.vue +6 -6
  99. package/dist/runtime/components/Edit/Features/Ownership/Renderer.vue +35 -0
  100. package/dist/runtime/components/Edit/Features/Ownership/Renderer.vue.d.ts +6 -0
  101. package/dist/runtime/components/Edit/Features/Ownership/index.vue +7 -25
  102. package/dist/runtime/components/Edit/Features/ProxyView/index.vue +5 -1
  103. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue +68 -15
  104. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Page/index.vue +15 -15
  105. package/dist/runtime/components/Edit/Features/Search/index.vue +4 -1
  106. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue +39 -74
  107. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue.d.ts +7 -5
  108. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/fragment.glsl +106 -0
  109. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/index.vue +440 -0
  110. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/index.vue.d.ts +32 -0
  111. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/vertex.glsl +102 -0
  112. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue +53 -125
  113. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue.d.ts +2 -2
  114. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +88 -29
  115. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue.d.ts +5 -3
  116. package/dist/runtime/components/Edit/Features/Selection/Overlay/vertex.glsl +11 -2
  117. package/dist/runtime/components/Edit/Features/Selection/OverlayFallback/index.vue +2 -2
  118. package/dist/runtime/components/Edit/Features/Selection/index.vue +66 -39
  119. package/dist/runtime/components/Edit/Features/Structure/List/Field/index.vue +2 -2
  120. package/dist/runtime/components/Edit/Features/Structure/List/Item/index.vue +13 -6
  121. package/dist/runtime/components/Edit/Features/Tour/Overlay/index.vue +3 -0
  122. package/dist/runtime/components/Edit/Features/Transform/index.vue +2 -27
  123. package/dist/runtime/components/Edit/Features/Translations/Banner/index.vue +17 -11
  124. package/dist/runtime/components/Edit/Features/Translations/index.vue +20 -23
  125. package/dist/runtime/components/Edit/Features/Validations/SidebarItem/index.vue +5 -5
  126. package/dist/runtime/components/Edit/Features/index.vue +17 -7
  127. package/dist/runtime/components/Edit/Form/Text/index.vue +2 -1
  128. package/dist/runtime/components/Edit/Form/Text/index.vue.d.ts +1 -0
  129. package/dist/runtime/components/Edit/Form/Toggle/index.vue +4 -3
  130. package/dist/runtime/components/Edit/Form/Toggle/index.vue.d.ts +12 -2
  131. package/dist/runtime/components/Edit/Indicators/index.vue +1 -1
  132. package/dist/runtime/components/Edit/InfoBox/index.vue +6 -2
  133. package/dist/runtime/components/Edit/InfoBox/index.vue.d.ts +12 -2
  134. package/dist/runtime/components/Edit/Konami/Game/index.vue +5 -5
  135. package/dist/runtime/components/Edit/{Features/Publish/Dialog/ScheduleDate.vue → ScheduleDate/index.vue} +6 -58
  136. package/dist/runtime/components/Edit/ScheduleDate/index.vue.d.ts +23 -0
  137. package/dist/runtime/components/Edit/ShortcutIndicator/index.vue +3 -0
  138. package/dist/runtime/components/Edit/Transition/Height.vue +95 -0
  139. package/dist/runtime/components/Edit/Transition/Height.vue.d.ts +36 -0
  140. package/dist/runtime/components/Edit/index.d.ts +7 -3
  141. package/dist/runtime/components/Edit/index.js +12 -4
  142. package/dist/runtime/composables/defineBlokkli.js +4 -2
  143. package/dist/runtime/css/output.css +1 -1
  144. package/dist/runtime/helpers/animationProvider.d.ts +35 -1
  145. package/dist/runtime/helpers/animationProvider.js +179 -48
  146. package/dist/runtime/helpers/composables/defineRenderer.d.ts +8 -0
  147. package/dist/runtime/helpers/composables/defineRenderer.js +8 -0
  148. package/dist/runtime/helpers/composables/useStateBasedCache.d.ts +4 -0
  149. package/dist/runtime/helpers/composables/useStateBasedCache.js +13 -0
  150. package/dist/runtime/helpers/composables/useStickyToolbar.d.ts +4 -1
  151. package/dist/runtime/helpers/composables/useStickyToolbar.js +53 -35
  152. package/dist/runtime/helpers/definitionProvider.d.ts +1 -1
  153. package/dist/runtime/helpers/dom/index.d.ts +1 -0
  154. package/dist/runtime/helpers/domProvider.d.ts +54 -14
  155. package/dist/runtime/helpers/domProvider.js +168 -134
  156. package/dist/runtime/helpers/index.d.ts +1 -8
  157. package/dist/runtime/helpers/index.js +1 -84
  158. package/dist/runtime/helpers/providers/blocks.d.ts +10 -0
  159. package/dist/runtime/helpers/providers/blocks.js +91 -0
  160. package/dist/runtime/helpers/providers/directive.d.ts +24 -0
  161. package/dist/runtime/helpers/providers/directive.js +205 -0
  162. package/dist/runtime/helpers/providers/element.d.ts +6 -0
  163. package/dist/runtime/helpers/providers/element.js +35 -0
  164. package/dist/runtime/helpers/providers/fields.d.ts +8 -0
  165. package/dist/runtime/helpers/providers/fields.js +47 -0
  166. package/dist/runtime/helpers/selectionProvider.d.ts +11 -11
  167. package/dist/runtime/helpers/selectionProvider.js +38 -45
  168. package/dist/runtime/helpers/stateProvider.d.ts +7 -2
  169. package/dist/runtime/helpers/stateProvider.js +83 -14
  170. package/dist/runtime/helpers/storageProvider.d.ts +3 -2
  171. package/dist/runtime/helpers/storageProvider.js +6 -2
  172. package/dist/runtime/helpers/symbols.d.ts +1 -0
  173. package/dist/runtime/helpers/symbols.js +1 -0
  174. package/dist/runtime/helpers/themeProvider.d.ts +2 -1
  175. package/dist/runtime/helpers/themeProvider.js +24 -14
  176. package/dist/runtime/helpers/typesProvider.js +10 -26
  177. package/dist/runtime/helpers/uiProvider.d.ts +11 -3
  178. package/dist/runtime/helpers/uiProvider.js +45 -17
  179. package/dist/runtime/icons/calendar.svg +1 -0
  180. package/dist/runtime/icons/clock.svg +1 -0
  181. package/dist/runtime/icons/comment_add.svg +1 -5
  182. package/dist/runtime/icons/delete.svg +1 -8
  183. package/dist/runtime/icons/duplicate.svg +1 -12
  184. package/dist/runtime/icons/edit.svg +1 -8
  185. package/dist/runtime/icons/reusable.svg +1 -5
  186. package/dist/runtime/plugins/blokkliDirectives.js +96 -0
  187. package/dist/runtime/types/index.d.ts +66 -35
  188. package/package.json +1 -1
  189. package/dist/runtime/components/Edit/DragInteractions/index.vue +0 -401
  190. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Group/index.vue +0 -63
  191. package/dist/runtime/components/Edit/Features/Selection/AddButtons/AddButtonsField.vue +0 -54
  192. package/dist/runtime/plugins/blokkliEditable.js +0 -31
  193. /package/dist/runtime/components/Edit/{DragInteractions → Features/BlockScheduler}/index.vue.d.ts +0 -0
  194. /package/dist/runtime/plugins/{blokkliEditable.d.ts → blokkliDirectives.d.ts} +0 -0
@@ -1,7 +1,12 @@
1
1
  <template>
2
2
  <Teleport to="body">
3
- <BlokkliTransition name="editable" :enabled="hasTransition">
4
- <Overlay v-if="editable" v-bind="editable" :key="key" @close="close" />
3
+ <BlokkliTransition name="caret-tooltip" :enabled="hasTransition">
4
+ <Overlay
5
+ v-if="selectedEditable"
6
+ v-bind="selectedEditable"
7
+ :key="key"
8
+ @close="close"
9
+ />
5
10
  </BlokkliTransition>
6
11
  </Teleport>
7
12
  </template>
@@ -19,6 +24,7 @@ import { BlokkliTransition } from "#blokkli/components";
19
24
  import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
20
25
  import defineCommands from "#blokkli/helpers/composables/defineCommands";
21
26
  import { falsy } from "#blokkli/helpers";
27
+ import { itemEntityType } from "#blokkli-build/config";
22
28
  defineBlokkliFeature({
23
29
  id: "editable-field",
24
30
  icon: "textbox",
@@ -26,41 +32,47 @@ defineBlokkliFeature({
26
32
  requiredAdapterMethods: ["updateFieldValue", "getEditableFieldConfig"],
27
33
  description: "Implements a form overlay to edit a single field of a block."
28
34
  });
29
- const { selection, adapter, types, $t, dom, runtimeConfig, state } = useBlokkli();
30
- const editable = ref(null);
35
+ const { selection, adapter, types, $t, state, directive, blocks, context } = useBlokkli();
36
+ const selectedEditable = ref(null);
31
37
  const hasTransition = ref(false);
32
38
  const key = computed(() => {
33
- if (!editable.value) {
39
+ if (!selectedEditable.value) {
34
40
  return "";
35
41
  }
36
- return editable.value.host.uuid + editable.value.fieldName;
42
+ return selectedEditable.value.host.uuid + selectedEditable.value.fieldName;
37
43
  });
38
44
  const getHost = (uuid) => {
39
45
  if (uuid) {
40
- const block = dom.findBlock(uuid);
46
+ const block = blocks.getBlock(uuid);
41
47
  if (block) {
42
- return block;
48
+ return {
49
+ type: itemEntityType,
50
+ bundle: block.bundle,
51
+ uuid: block.uuid
52
+ };
43
53
  }
44
54
  }
45
- return dom.findClosestEntityContext(dom.getActiveProviderElement());
55
+ return {
56
+ type: context.value.entityType,
57
+ bundle: context.value.entityBundle,
58
+ uuid: context.value.entityUuid
59
+ };
46
60
  };
47
61
  const buildEditable = (fieldName, uuid) => {
48
62
  const host = getHost(uuid);
49
63
  if (!host) {
50
64
  return;
51
65
  }
52
- const hostEntityType = "type" in host ? host.type : runtimeConfig.itemEntityType;
53
- const hostEntityBundle = "bundle" in host ? host.bundle : host.itemBundle;
54
- if (hostEntityBundle === "from_library") {
66
+ if (host.bundle === "from_library") {
55
67
  return;
56
68
  }
57
69
  const config = types.editableFieldConfig.forName(
58
- hostEntityType,
59
- hostEntityBundle,
70
+ host.type,
71
+ host.bundle,
60
72
  fieldName
61
73
  );
62
74
  if (!config) {
63
- let message = `Failed to load editable field config for field "${fieldName}" on entity type "${hostEntityType}" of bundle "${hostEntityBundle}"`;
75
+ let message = `Failed to load editable field config for field "${fieldName}" on entity type "${host.type}" of bundle "${host.bundle}"`;
64
76
  if (uuid) {
65
77
  message += ` with uuid "${uuid}"`;
66
78
  }
@@ -69,10 +81,7 @@ const buildEditable = (fieldName, uuid) => {
69
81
  if (config.type === "frame" && !adapter.buildEditableFrameUrl) {
70
82
  return;
71
83
  }
72
- const hostElement = "itemBundle" in host ? host.element() : dom.getActiveProviderElement();
73
- const element = hostElement.querySelector(
74
- `[data-blokkli-editable-field="${fieldName}"]`
75
- );
84
+ const element = directive.findEditableElement(fieldName, host);
76
85
  if (!(element instanceof HTMLElement)) {
77
86
  return;
78
87
  }
@@ -89,30 +98,19 @@ onBlokkliEvent("editable:focus", (e) => {
89
98
  if (!state.canEdit.value) {
90
99
  return;
91
100
  }
92
- hasTransition.value = !editable.value;
93
- editable.value = buildEditable(e.fieldName, e.uuid) || null;
94
- if (editable.value) {
101
+ hasTransition.value = !selectedEditable.value;
102
+ selectedEditable.value = buildEditable(e.fieldName, e.uuid) || null;
103
+ if (selectedEditable.value) {
95
104
  selection.editableActive.value = true;
96
105
  }
97
106
  });
98
107
  defineCommands(() => {
99
- const editables = selection.blocks.value.flatMap((v) => {
100
- return [...v.element().querySelectorAll("[data-blokkli-editable-field]")].map((el) => {
101
- if (!(el instanceof HTMLElement)) {
102
- return;
103
- }
104
- const block = el.closest("[data-uuid]");
105
- if (!(block instanceof HTMLElement)) {
106
- return;
107
- }
108
- if (block.dataset.uuid !== v.uuid) {
109
- return;
110
- }
111
- const name = el.dataset.blokkliEditableField;
112
- if (!name) {
113
- return;
114
- }
115
- return buildEditable(name, block.dataset.uuid);
108
+ if (selection.items.value.length > 5) {
109
+ return [];
110
+ }
111
+ const editables = selection.items.value.flatMap((item) => {
112
+ return directive.getEditablesForBlock(item.uuid).map((v) => {
113
+ return buildEditable(v.fieldName, item.uuid);
116
114
  }).filter(falsy);
117
115
  });
118
116
  return editables.map((v) => {
@@ -126,7 +124,7 @@ defineCommands(() => {
126
124
  icon: "textbox",
127
125
  disabled: false,
128
126
  callback: () => {
129
- editable.value = v;
127
+ selectedEditable.value = v;
130
128
  }
131
129
  };
132
130
  });
@@ -134,16 +132,16 @@ defineCommands(() => {
134
132
  watch(selection.editableActive, (isActive) => {
135
133
  if (!isActive) {
136
134
  hasTransition.value = true;
137
- editable.value = null;
135
+ selectedEditable.value = null;
138
136
  }
139
137
  });
140
- watch(editable, (v) => {
138
+ watch(selectedEditable, (v) => {
141
139
  if (!v && selection.editableActive.value) {
142
140
  selection.editableActive.value = false;
143
141
  }
144
142
  });
145
143
  const close = () => {
146
- editable.value = null;
144
+ selectedEditable.value = null;
147
145
  selection.editableActive.value = false;
148
146
  };
149
147
  </script>
@@ -37,14 +37,16 @@
37
37
  <ul class="bk-library-dialog-list">
38
38
  <li
39
39
  v-for="(item, index) in fragments"
40
+ v-show="visible === null || visible.includes(item.name)"
41
+ ref="itemElements"
40
42
  :key="item.name"
41
43
  :class="{
42
44
  'bk-is-selected': selectedItem === item.name
43
45
  }"
46
+ :data-bk-fragment-name="item.name"
44
47
  @click="selectedItem = item.name"
45
48
  >
46
49
  <FragmentItem
47
- v-show="visible === null || visible.includes(item.name)"
48
50
  :name="item.name"
49
51
  :label="item.label"
50
52
  :description="item.description"
@@ -65,7 +67,7 @@
65
67
  <script setup>
66
68
  import { FormOverlay } from "#blokkli/components";
67
69
  import { falsy } from "#blokkli/helpers";
68
- import { ref, useBlokkli, computed, watch } from "#imports";
70
+ import { ref, useBlokkli, computed, watch, useTemplateRef } from "#imports";
69
71
  import FragmentItem from "./Item/index.vue";
70
72
  const props = defineProps({
71
73
  field: { type: Object, required: true }
@@ -73,7 +75,7 @@ const props = defineProps({
73
75
  const { $t, definitions } = useBlokkli();
74
76
  const emit = defineEmits(["close", "submit"]);
75
77
  const searchText = ref("");
76
- const listEl = ref(null);
78
+ const itemElements = useTemplateRef("itemElements");
77
79
  const selectedItem = ref("");
78
80
  const allowedInField = computed(() => props.field.allowedFragments || []);
79
81
  const fragments = computed(
@@ -91,15 +93,15 @@ const onClose = () => {
91
93
  };
92
94
  const elements = ref([]);
93
95
  const buildElements = () => {
94
- if (!listEl.value) {
96
+ if (!itemElements.value) {
95
97
  return;
96
98
  }
97
- elements.value = [...listEl.value.querySelectorAll(".bk-library-list-item")].map((el) => {
99
+ elements.value = itemElements.value.map((el) => {
98
100
  if (el instanceof HTMLElement) {
99
- const uuid = el.dataset.libraryItemUuid;
100
- if (uuid) {
101
+ const name = el.dataset.bkFragmentName;
102
+ if (name) {
101
103
  return {
102
- uuid,
104
+ name,
103
105
  text: el.textContent?.toLowerCase() || ""
104
106
  };
105
107
  }
@@ -115,6 +117,6 @@ const visible = computed(() => {
115
117
  if (!searchText.value || !elements.value.length) {
116
118
  return null;
117
119
  }
118
- return elements.value.filter((v) => v.text.includes(searchText.value.toLowerCase())).map((v) => v.uuid);
120
+ return elements.value.filter((v) => v.text.includes(searchText.value.toLowerCase())).map((v) => v.name);
119
121
  });
120
122
  </script>
@@ -45,9 +45,9 @@ const { adapter } = defineBlokkliFeature({
45
45
  });
46
46
  const { state, $t, types, selection, dom } = useBlokkli();
47
47
  const isEnabled = computed(() => {
48
- if (selection.blocks.value.length === 1) {
49
- const block = selection.blocks.value[0];
50
- const field = dom.findField(block.hostUuid, block.hostFieldName);
48
+ const item = selection.item.value;
49
+ if (item) {
50
+ const field = dom.getRegisteredField(item.host.uuid, item.host.fieldName);
51
51
  return !!field?.allowedFragments.length;
52
52
  }
53
53
  return true;
@@ -3,6 +3,7 @@
3
3
  id="history"
4
4
  v-slot="{ scrolledToEnd }"
5
5
  :title="$t('history', 'History')"
6
+ edit-only
6
7
  :tour-text="
7
8
  $t(
8
9
  'historyTourText',
@@ -74,9 +75,11 @@ const { state, $t, ui, selection, eventBus } = useBlokkli();
74
75
  const { mutations, currentMutationIndex, mutateWithLoadingState } = state;
75
76
  const mutationsCount = computed(() => mutations.value.length);
76
77
  const useMouseForHistory = computed(() => settings.value.useMouseButtons);
77
- const canUndo = computed(() => currentMutationIndex.value >= 0);
78
+ const canUndo = computed(
79
+ () => currentMutationIndex.value >= 0 && state.canEdit.value
80
+ );
78
81
  const canRedo = computed(
79
- () => currentMutationIndex.value < mutationsCount.value - 1
82
+ () => currentMutationIndex.value < mutationsCount.value - 1 && state.canEdit.value
80
83
  );
81
84
  const selectionAtHistoryIndex = /* @__PURE__ */ new Map();
82
85
  function updateCurrentHistorySelection() {
@@ -0,0 +1,139 @@
1
+ precision highp float;
2
+
3
+ varying vec4 v_quad;
4
+ varying vec4 v_rect_radius;
5
+ varying vec2 v_rect_size;
6
+ varying vec2 v_rect_center;
7
+ varying float v_rect_type;
8
+ varying vec2 v_quad_artboard_pos;
9
+
10
+ uniform float u_dpi;
11
+ uniform float u_scale;
12
+ uniform float u_offset_x;
13
+ uniform float u_offset_y;
14
+ uniform vec2 u_resolution;
15
+ uniform vec3 u_color_mono;
16
+ uniform vec3 u_color_accent;
17
+ uniform vec3 u_color_teal;
18
+ uniform vec3 u_color_white;
19
+ uniform vec3 u_color_lime;
20
+
21
+ int pseudoQuadrant(vec2 p) {
22
+ return int(floor(step(0.0, p.x) + 2.0 * step(0.0, -p.y)));
23
+ }
24
+
25
+ float sdRoundBox(vec2 p, vec2 b, vec4 radii) {
26
+ int idx = pseudoQuadrant(p);
27
+ float cr;
28
+ if (idx == 0) cr = radii[0];
29
+ else if (idx == 1) cr = radii[1];
30
+ else if (idx == 2) cr = radii[3];
31
+ else cr = radii[2];
32
+ vec2 q = abs(p) - b + cr;
33
+ return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - cr;
34
+ }
35
+
36
+ void main() {
37
+ vec2 size = v_rect_size;
38
+ vec4 u_cornerRadii = min(v_rect_radius, min(size.x, size.y) / 2.0);
39
+ vec4 r = u_cornerRadii;
40
+
41
+ vec2 posRelativeToQuad = gl_FragCoord.xy - v_rect_center;
42
+
43
+ float mainDist = sdRoundBox(posRelativeToQuad, size / 2.0, r);
44
+
45
+ // For editable fields (type 2), render both fill and solid border
46
+ if (v_rect_type > 1.5 && v_rect_type < 2.5) {
47
+ float u_edgeSoftness = 1.0;
48
+ float borderThickness = 1.5 * u_dpi;
49
+ float u_borderSoftness = 1.0;
50
+
51
+ // Render fill
52
+ float fillAlpha = 1.0 - smoothstep(-u_edgeSoftness, 0.0, mainDist);
53
+ vec4 fillColor = vec4(u_color_teal, 0.2);
54
+
55
+ // Render solid border (non-dashed)
56
+ float borderAlpha =
57
+ 1.0 - smoothstep(-u_borderSoftness, 0.0, abs(mainDist) - borderThickness);
58
+ vec4 borderColor = vec4(u_color_teal, 1.0);
59
+
60
+ // Combine fill and border
61
+ vec4 combined = mix(
62
+ vec4(fillColor.rgb, fillAlpha * fillColor.a),
63
+ borderColor,
64
+ borderAlpha * borderColor.a
65
+ );
66
+
67
+ gl_FragColor = combined;
68
+ return;
69
+ }
70
+
71
+ // For blocks (type 0, 1, and 3), render border
72
+ float borderThickness = 1.5 * u_dpi;
73
+ float u_borderSoftness = 1.0;
74
+
75
+ float borderAlpha =
76
+ 1.0 - smoothstep(-u_borderSoftness, 0.0, abs(mainDist) - borderThickness);
77
+
78
+ // Select color based on type: 0 = mono, 1 = accent, 3 = white (inverted), 4 = lime (library)
79
+ vec3 color = u_color_mono;
80
+ if (v_rect_type > 3.5) {
81
+ color = u_color_lime;
82
+ } else if (v_rect_type > 2.5) {
83
+ color = u_color_white;
84
+ } else if (v_rect_type > 0.5) {
85
+ color = u_color_accent;
86
+ }
87
+
88
+ // Apply dashed pattern for all blocks
89
+ // Calculate actual perimeter distance for proper dashing
90
+ vec2 halfSize = size / 2.0;
91
+ vec2 p = posRelativeToQuad;
92
+ vec2 absP = abs(p);
93
+
94
+ // Determine which edge/corner we're on and calculate perimeter distance
95
+ float perimeterDistance = 0.0;
96
+
97
+ // Check which edge we're closest to
98
+ float dx = absP.x - halfSize.x;
99
+ float dy = absP.y - halfSize.y;
100
+
101
+ if (dy > dx) {
102
+ // Top or bottom edge
103
+ if (p.y > 0.0) {
104
+ // Bottom edge: start at bottom-left, go right
105
+ perimeterDistance = size.x + size.y + (p.x + halfSize.x);
106
+ } else {
107
+ // Top edge: start at top-right, go left
108
+ perimeterDistance = size.x + (halfSize.x - p.x);
109
+ }
110
+ } else {
111
+ // Left or right edge
112
+ if (p.x > 0.0) {
113
+ // Right edge: start at top-right, go down
114
+ perimeterDistance = p.y + halfSize.y;
115
+ } else {
116
+ // Left edge: start at bottom-left, go up
117
+ perimeterDistance = size.x + size.y + size.x + (halfSize.y - p.y);
118
+ }
119
+ }
120
+
121
+ float dashWidth = 7.0 * u_dpi;
122
+ float dashGap = 7.0 * u_dpi;
123
+ float dashCycle = dashWidth + dashGap;
124
+
125
+ float dashPosition = mod(perimeterDistance, dashCycle);
126
+ float dashFactor = step(dashPosition, dashWidth);
127
+
128
+ // Only show dashes
129
+ borderAlpha *= dashFactor;
130
+
131
+ vec4 borderColor = vec4(color, 1.0);
132
+ vec4 finalColor = mix(
133
+ vec4(0.0, 0.0, 0.0, 0.0),
134
+ borderColor,
135
+ borderAlpha * borderColor.a
136
+ );
137
+
138
+ gl_FragColor = finalColor;
139
+ }
@@ -0,0 +1,261 @@
1
+ <template>
2
+ <div />
3
+ </template>
4
+
5
+ <script setup>
6
+ import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
7
+ import defineRenderer from "#blokkli/helpers/composables/defineRenderer";
8
+ import { useBlokkli, computed, ref, watch } from "#imports";
9
+ import { setBuffersAndAttributes, drawBufferInfo, setUniforms } from "twgl.js";
10
+ import vs from "./vertex.glsl?raw";
11
+ import fs from "./fragment.glsl?raw";
12
+ import { RectangleBufferCollector } from "#blokkli/helpers/webgl";
13
+ import { toShaderColor, isInsideRect } from "#blokkli/helpers";
14
+ const props = defineProps({
15
+ gl: { type: null, required: true }
16
+ });
17
+ const { animation, theme, dom, selection, state, ui, directive, blocks } = useBlokkli();
18
+ const programInfo = animation.registerProgram("hover", props.gl, [vs, fs]);
19
+ const MAX_RECTS = 11;
20
+ function getDeepestUuid(uuids) {
21
+ if (uuids.length === 0) {
22
+ return null;
23
+ }
24
+ let deepestUuid = uuids[0];
25
+ let maxLevel = state.getNestingLevel(deepestUuid);
26
+ for (let i = 1; i < uuids.length; i++) {
27
+ const uuid = uuids[i];
28
+ const level = state.getNestingLevel(uuid);
29
+ if (level > maxLevel) {
30
+ maxLevel = level;
31
+ deepestUuid = uuid;
32
+ }
33
+ }
34
+ return deepestUuid;
35
+ }
36
+ function createHoverState() {
37
+ return {
38
+ positions: new Float32Array(MAX_RECTS * 4),
39
+ radii: new Float32Array(MAX_RECTS * 4),
40
+ types: new Float32Array(MAX_RECTS),
41
+ visible: new Float32Array(MAX_RECTS)
42
+ };
43
+ }
44
+ const hoverState = createHoverState();
45
+ let previousHoveredUuids = [];
46
+ let previousDeepestUuid = null;
47
+ let previousEditableFieldRect = null;
48
+ const isHoveringEditableField = ref(false);
49
+ const isHoveringSelectedBlock = ref(false);
50
+ class HoverRectangleBufferCollector extends RectangleBufferCollector {
51
+ }
52
+ const collector = new HoverRectangleBufferCollector(props.gl);
53
+ for (let i = 0; i < MAX_RECTS; i++) {
54
+ collector.addRectangle(
55
+ {
56
+ id: `hover-rect-${i}`,
57
+ x: 0,
58
+ y: 0,
59
+ width: 100,
60
+ height: 100,
61
+ radius: [0, 0, 0, 0]
62
+ },
63
+ 0
64
+ );
65
+ }
66
+ const bufferInfo = collector.createBufferInfo();
67
+ function resetHoverState() {
68
+ previousHoveredUuids = [];
69
+ previousDeepestUuid = null;
70
+ previousEditableFieldRect = null;
71
+ hoverState.visible.fill(0);
72
+ isHoveringEditableField.value = false;
73
+ isHoveringSelectedBlock.value = false;
74
+ }
75
+ watch(selection.isChangingOptions, (isChanging) => {
76
+ if (!isChanging) {
77
+ resetHoverState();
78
+ }
79
+ });
80
+ watch(selection.uuids, () => {
81
+ resetHoverState();
82
+ });
83
+ function updateHoverState(mouseX, mouseY, offset, scale, artboardSize) {
84
+ const artboardRect = {
85
+ x: offset.x,
86
+ y: offset.y,
87
+ width: artboardSize.width * scale,
88
+ height: artboardSize.height * scale
89
+ };
90
+ const isOutsideArtboard = mouseX < artboardRect.x || mouseX > artboardRect.x + artboardRect.width || mouseY < artboardRect.y || mouseY > artboardRect.y + artboardRect.height;
91
+ if (isOutsideArtboard) {
92
+ const needsUpdate = previousHoveredUuids.length > 0 || previousEditableFieldRect !== null || isHoveringEditableField.value || isHoveringSelectedBlock.value;
93
+ hoverState.visible.fill(0);
94
+ isHoveringEditableField.value = false;
95
+ isHoveringSelectedBlock.value = false;
96
+ previousHoveredUuids = [];
97
+ previousDeepestUuid = null;
98
+ previousEditableFieldRect = null;
99
+ return needsUpdate;
100
+ }
101
+ const artboardMouseX = mouseX / scale - offset.x / scale;
102
+ const artboardMouseY = mouseY / scale - offset.y / scale;
103
+ const hoveredUuids = [];
104
+ const visibleBlocks = dom.getVisibleBlocks();
105
+ for (let i = 0; i < visibleBlocks.length; i++) {
106
+ const uuid = visibleBlocks[i];
107
+ if (!uuid) continue;
108
+ const rawRect = dom.getBlockRect(uuid);
109
+ if (!rawRect) continue;
110
+ const rect = ui.getViewportRelativeRect(rawRect, scale, offset);
111
+ const blockRect = {
112
+ x: rect.x / scale - offset.x / scale,
113
+ y: rect.y / scale - offset.y / scale,
114
+ width: rect.width / scale,
115
+ height: rect.height / scale
116
+ };
117
+ if (isInsideRect(artboardMouseX, artboardMouseY, blockRect)) {
118
+ hoveredUuids.push(uuid);
119
+ }
120
+ }
121
+ const deepestUuid = getDeepestUuid(hoveredUuids);
122
+ const selectedUuids = selection.uuids.value;
123
+ const unselectedHoveredUuids = hoveredUuids.filter(
124
+ (uuid) => !selectedUuids.includes(uuid)
125
+ );
126
+ const hoveredChanged = unselectedHoveredUuids.length !== previousHoveredUuids.length || unselectedHoveredUuids.some(
127
+ (uuid, i) => uuid !== previousHoveredUuids[i]
128
+ ) || deepestUuid !== previousDeepestUuid;
129
+ let hoveredEditableFieldRect = null;
130
+ const editableRects = directive.getVisible("editable");
131
+ for (let i = 0; i < editableRects.length; i++) {
132
+ const editableRect = editableRects[i];
133
+ if (isInsideRect(artboardMouseX, artboardMouseY, editableRect)) {
134
+ hoveredEditableFieldRect = editableRect;
135
+ break;
136
+ }
137
+ }
138
+ if (!hoveredChanged) {
139
+ const editableFieldChanged = hoveredEditableFieldRect === null !== (previousEditableFieldRect === null) || hoveredEditableFieldRect && previousEditableFieldRect && (hoveredEditableFieldRect.x !== previousEditableFieldRect.x || hoveredEditableFieldRect.y !== previousEditableFieldRect.y || hoveredEditableFieldRect.width !== previousEditableFieldRect.width || hoveredEditableFieldRect.height !== previousEditableFieldRect.height);
140
+ if (!editableFieldChanged) {
141
+ return false;
142
+ }
143
+ }
144
+ const shouldHighlightDeepest = deepestUuid && unselectedHoveredUuids.includes(deepestUuid);
145
+ hoverState.visible.fill(0);
146
+ const nestingMap = /* @__PURE__ */ new Map();
147
+ for (let i = 0; i < unselectedHoveredUuids.length; i++) {
148
+ const uuid = unselectedHoveredUuids[i];
149
+ const level = Math.min(state.getNestingLevel(uuid), 9);
150
+ if (!nestingMap.has(level)) {
151
+ nestingMap.set(level, uuid);
152
+ }
153
+ }
154
+ for (const [level, uuid] of nestingMap) {
155
+ const rect = dom.getBlockRect(uuid);
156
+ const block = blocks.getBlock(uuid);
157
+ if (!rect || !block) continue;
158
+ const el = dom.getDragElement(block);
159
+ if (!el) continue;
160
+ const style = theme.getDraggableStyle(el);
161
+ const isDeepest = shouldHighlightDeepest && uuid === deepestUuid;
162
+ hoverState.positions[level * 4 + 0] = rect.x;
163
+ hoverState.positions[level * 4 + 1] = rect.y;
164
+ hoverState.positions[level * 4 + 2] = rect.width;
165
+ hoverState.positions[level * 4 + 3] = rect.height;
166
+ hoverState.radii[level * 4 + 0] = style.radius[0];
167
+ hoverState.radii[level * 4 + 1] = style.radius[1];
168
+ hoverState.radii[level * 4 + 2] = style.radius[2];
169
+ hoverState.radii[level * 4 + 3] = style.radius[3];
170
+ let type = 0;
171
+ if (isDeepest) {
172
+ const isFromLibrary = state.fromLibraryUuids.value.includes(uuid);
173
+ if (isFromLibrary) {
174
+ type = 4;
175
+ } else {
176
+ type = style.isInverted ? 3 : 1;
177
+ }
178
+ }
179
+ hoverState.types[level] = type;
180
+ hoverState.visible[level] = 1;
181
+ }
182
+ if (hoveredEditableFieldRect) {
183
+ const inset = 2;
184
+ hoverState.positions[10 * 4 + 0] = hoveredEditableFieldRect.x + inset;
185
+ hoverState.positions[10 * 4 + 1] = hoveredEditableFieldRect.y + inset;
186
+ hoverState.positions[10 * 4 + 2] = hoveredEditableFieldRect.width - inset * 2;
187
+ hoverState.positions[10 * 4 + 3] = hoveredEditableFieldRect.height - inset * 2;
188
+ hoverState.radii[10 * 4 + 0] = 0;
189
+ hoverState.radii[10 * 4 + 1] = 0;
190
+ hoverState.radii[10 * 4 + 2] = 0;
191
+ hoverState.radii[10 * 4 + 3] = 0;
192
+ hoverState.types[10] = 2;
193
+ hoverState.visible[10] = 1;
194
+ }
195
+ previousHoveredUuids = unselectedHoveredUuids;
196
+ previousDeepestUuid = deepestUuid;
197
+ previousEditableFieldRect = hoveredEditableFieldRect;
198
+ isHoveringEditableField.value = hoveredEditableFieldRect !== null;
199
+ isHoveringSelectedBlock.value = deepestUuid !== null && selectedUuids.includes(deepestUuid);
200
+ return true;
201
+ }
202
+ const uniforms = computed(() => {
203
+ return {
204
+ u_color_mono: toShaderColor(theme.mono.value[300]),
205
+ u_color_accent: toShaderColor(theme.accent.value[600]),
206
+ u_color_teal: toShaderColor(theme.teal.value.normal),
207
+ u_color_white: toShaderColor([255, 255, 255]),
208
+ u_color_lime: toShaderColor(theme.lime.value.normal)
209
+ };
210
+ });
211
+ onBlokkliEvent("state:reloaded", () => {
212
+ resetHoverState();
213
+ });
214
+ onBlokkliEvent("ui:resized", () => {
215
+ resetHoverState();
216
+ });
217
+ defineRenderer("hover-overlay", {
218
+ zIndex: 200,
219
+ enabled: () => !selection.isChangingOptions.value,
220
+ cursor: () => {
221
+ if (isHoveringEditableField.value && state.editMode.value !== "readonly") {
222
+ return "text";
223
+ }
224
+ if (isHoveringSelectedBlock.value && state.editMode.value === "editing") {
225
+ return "grab";
226
+ }
227
+ return null;
228
+ },
229
+ render: (ctx) => {
230
+ if (!bufferInfo) {
231
+ return;
232
+ }
233
+ if (!ui.openTooltip.value) {
234
+ updateHoverState(
235
+ ctx.mouseX,
236
+ ctx.mouseY,
237
+ ctx.artboardOffset,
238
+ ctx.artboardScale,
239
+ ctx.artboardSize
240
+ );
241
+ }
242
+ props.gl.useProgram(programInfo.program);
243
+ setUniforms(programInfo, uniforms.value);
244
+ setUniforms(programInfo, {
245
+ u_hover_positions: hoverState.positions,
246
+ u_hover_radii: hoverState.radii,
247
+ u_hover_types: hoverState.types,
248
+ u_hover_visible: hoverState.visible
249
+ });
250
+ animation.setSharedUniforms(props.gl, programInfo);
251
+ setBuffersAndAttributes(props.gl, programInfo, bufferInfo);
252
+ drawBufferInfo(props.gl, bufferInfo, props.gl.TRIANGLES);
253
+ }
254
+ });
255
+ </script>
256
+
257
+ <script>
258
+ export default {
259
+ name: "HoverOverlay"
260
+ };
261
+ </script>
@@ -0,0 +1,6 @@
1
+ declare const _default: import("vue").DefineComponent<{
2
+ gl: WebGLRenderingContext;
3
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
4
+ gl: WebGLRenderingContext;
5
+ }> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
6
+ export default _default;