@blokkli/editor 2.0.0-alpha.17 → 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 (139) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +380 -59
  3. package/dist/modules/drupal/graphql/base/fragment.paragraphsFieldItem.graphql +3 -1
  4. package/dist/modules/drupal/graphql/base/query.pbConfig.graphql +1 -10
  5. package/dist/modules/drupal/graphql/mutations/set_paragraph_schedule.graphql +15 -0
  6. package/dist/modules/drupal/index.mjs +33 -0
  7. package/dist/modules/drupal/runtime/adapter/index.js +10 -2
  8. package/dist/runtime/adapter/index.d.ts +21 -0
  9. package/dist/runtime/blokkliPlugins/ContextMenu/Menu/index.vue +3 -0
  10. package/dist/runtime/blokkliPlugins/ItemAction/index.vue +23 -13
  11. package/dist/runtime/blokkliPlugins/ItemAction/index.vue.d.ts +20 -44
  12. package/dist/runtime/blokkliPlugins/TourItem/index.vue +10 -5
  13. package/dist/runtime/components/BlokkliEditable.vue +13 -13
  14. package/dist/runtime/components/BlokkliField.vue +3 -0
  15. package/dist/runtime/components/BlokkliField.vue.d.ts +3 -3
  16. package/dist/runtime/components/BlokkliItem.vue +1 -1
  17. package/dist/runtime/components/BlokkliItem.vue.d.ts +4 -2
  18. package/dist/runtime/components/BlokkliProvider.vue +12 -8
  19. package/dist/runtime/components/Edit/Actions/index.vue +27 -16
  20. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +26 -10
  21. package/dist/runtime/components/Edit/ArtboardTooltip/index.vue +3 -0
  22. package/dist/runtime/components/Edit/Dialog/index.vue +6 -4
  23. package/dist/runtime/components/Edit/DraggableList.vue +15 -7
  24. package/dist/runtime/components/Edit/DraggableList.vue.d.ts +5 -5
  25. package/dist/runtime/components/Edit/EditProvider.vue +29 -16
  26. package/dist/runtime/components/Edit/EditProvider.vue.d.ts +1 -0
  27. package/dist/runtime/components/Edit/Features/AddList/index.vue +9 -11
  28. package/dist/runtime/components/Edit/Features/Analyze/Overlay/index.vue +9 -6
  29. package/dist/runtime/components/Edit/Features/Analyze/Renderer.vue +1 -1
  30. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItemNodesTarget.vue +15 -11
  31. package/dist/runtime/components/Edit/Features/Anchors/Renderer.vue +19 -102
  32. package/dist/runtime/components/Edit/Features/Artboard/Renderer.vue +3 -0
  33. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +28 -52
  34. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/ScheduleSection.vue +154 -0
  35. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/ScheduleSection.vue.d.ts +27 -0
  36. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/index.vue +222 -0
  37. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/index.vue.d.ts +11 -0
  38. package/dist/runtime/components/Edit/Features/BlockScheduler/index.vue +96 -0
  39. package/dist/runtime/components/Edit/Features/BlockScheduler/index.vue.d.ts +2 -0
  40. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +15 -16
  41. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Item/index.vue +51 -0
  42. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/{Group → Item}/index.vue.d.ts +9 -13
  43. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +46 -66
  44. package/dist/runtime/components/Edit/Features/Comments/index.vue +1 -1
  45. package/dist/runtime/components/Edit/Features/Conversions/index.vue +4 -7
  46. package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue +2 -2
  47. package/dist/runtime/components/Edit/Features/Debug/index.vue +4 -1
  48. package/dist/runtime/components/Edit/Features/Delete/index.vue +1 -1
  49. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +13 -5
  50. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +14 -11
  51. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +30 -18
  52. package/dist/runtime/components/Edit/Features/Duplicate/index.vue +6 -8
  53. package/dist/runtime/components/Edit/Features/Edit/index.vue +15 -21
  54. package/dist/runtime/components/Edit/Features/EditForm/index.vue +7 -6
  55. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue +8 -3
  56. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue.d.ts +2 -2
  57. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue +29 -12
  58. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue.d.ts +2 -2
  59. package/dist/runtime/components/Edit/Features/EditableField/index.vue +40 -42
  60. package/dist/runtime/components/Edit/Features/Fragments/Dialog/index.vue +11 -9
  61. package/dist/runtime/components/Edit/Features/Fragments/index.vue +3 -3
  62. package/dist/runtime/components/Edit/Features/Hover/Overlay/index.vue +16 -25
  63. package/dist/runtime/components/Edit/Features/Library/EditReusable/index.vue +5 -7
  64. package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue +5 -5
  65. package/dist/runtime/components/Edit/Features/Library/index.vue +27 -23
  66. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +6 -3
  67. package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue +15 -12
  68. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/index.vue +2 -2
  69. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +7 -6
  70. package/dist/runtime/components/Edit/Features/Options/index.vue +6 -6
  71. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue +68 -15
  72. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Page/index.vue +15 -15
  73. package/dist/runtime/components/Edit/Features/Search/index.vue +4 -1
  74. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue.d.ts +3 -3
  75. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/index.vue +34 -11
  76. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue +21 -20
  77. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue.d.ts +2 -2
  78. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue.d.ts +3 -3
  79. package/dist/runtime/components/Edit/Features/Selection/OverlayFallback/index.vue +2 -2
  80. package/dist/runtime/components/Edit/Features/Selection/index.vue +61 -27
  81. package/dist/runtime/components/Edit/Features/Structure/List/Field/index.vue +2 -2
  82. package/dist/runtime/components/Edit/Features/Structure/List/Item/index.vue +13 -6
  83. package/dist/runtime/components/Edit/Features/Tour/Overlay/index.vue +3 -0
  84. package/dist/runtime/components/Edit/Features/Transform/index.vue +2 -27
  85. package/dist/runtime/components/Edit/Features/Translations/index.vue +7 -7
  86. package/dist/runtime/components/Edit/Features/Validations/SidebarItem/index.vue +5 -5
  87. package/dist/runtime/components/Edit/Features/index.vue +17 -7
  88. package/dist/runtime/components/Edit/Form/Toggle/index.vue +4 -3
  89. package/dist/runtime/components/Edit/Form/Toggle/index.vue.d.ts +12 -2
  90. package/dist/runtime/components/Edit/InfoBox/index.vue +6 -2
  91. package/dist/runtime/components/Edit/InfoBox/index.vue.d.ts +12 -2
  92. package/dist/runtime/components/Edit/{Features/Publish/Dialog/ScheduleDate.vue → ScheduleDate/index.vue} +6 -58
  93. package/dist/runtime/components/Edit/{Features/Publish/Dialog/ScheduleDate.vue.d.ts → ScheduleDate/index.vue.d.ts} +11 -1
  94. package/dist/runtime/components/Edit/ShortcutIndicator/index.vue +3 -0
  95. package/dist/runtime/components/Edit/Transition/Height.vue +95 -0
  96. package/dist/runtime/components/Edit/Transition/Height.vue.d.ts +36 -0
  97. package/dist/runtime/components/Edit/index.d.ts +3 -1
  98. package/dist/runtime/components/Edit/index.js +5 -1
  99. package/dist/runtime/css/output.css +1 -1
  100. package/dist/runtime/helpers/animationProvider.d.ts +2 -1
  101. package/dist/runtime/helpers/animationProvider.js +6 -2
  102. package/dist/runtime/helpers/composables/useStateBasedCache.d.ts +4 -0
  103. package/dist/runtime/helpers/composables/useStateBasedCache.js +13 -0
  104. package/dist/runtime/helpers/definitionProvider.d.ts +1 -1
  105. package/dist/runtime/helpers/dom/index.d.ts +1 -1
  106. package/dist/runtime/helpers/domProvider.d.ts +10 -16
  107. package/dist/runtime/helpers/domProvider.js +80 -135
  108. package/dist/runtime/helpers/index.d.ts +1 -8
  109. package/dist/runtime/helpers/index.js +1 -84
  110. package/dist/runtime/helpers/providers/blocks.d.ts +10 -0
  111. package/dist/runtime/helpers/providers/blocks.js +91 -0
  112. package/dist/runtime/helpers/providers/directive.d.ts +24 -0
  113. package/dist/runtime/helpers/{editableProvider.js → providers/directive.js} +90 -29
  114. package/dist/runtime/helpers/providers/element.d.ts +6 -0
  115. package/dist/runtime/helpers/providers/element.js +35 -0
  116. package/dist/runtime/helpers/providers/fields.d.ts +8 -0
  117. package/dist/runtime/helpers/providers/fields.js +47 -0
  118. package/dist/runtime/helpers/selectionProvider.d.ts +11 -11
  119. package/dist/runtime/helpers/selectionProvider.js +38 -45
  120. package/dist/runtime/helpers/stateProvider.d.ts +1 -0
  121. package/dist/runtime/helpers/stateProvider.js +21 -15
  122. package/dist/runtime/helpers/themeProvider.d.ts +2 -1
  123. package/dist/runtime/helpers/themeProvider.js +24 -14
  124. package/dist/runtime/helpers/typesProvider.js +10 -26
  125. package/dist/runtime/helpers/uiProvider.d.ts +3 -2
  126. package/dist/runtime/helpers/uiProvider.js +11 -15
  127. package/dist/runtime/icons/calendar.svg +1 -0
  128. package/dist/runtime/icons/clock.svg +1 -0
  129. package/dist/runtime/icons/comment_add.svg +1 -5
  130. package/dist/runtime/icons/delete.svg +1 -8
  131. package/dist/runtime/icons/duplicate.svg +1 -12
  132. package/dist/runtime/icons/edit.svg +1 -8
  133. package/dist/runtime/icons/reusable.svg +1 -5
  134. package/dist/runtime/plugins/{blokkliEditable.js → blokkliDirectives.js} +14 -20
  135. package/dist/runtime/types/index.d.ts +55 -36
  136. package/package.json +1 -1
  137. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Group/index.vue +0 -63
  138. package/dist/runtime/helpers/editableProvider.d.ts +0 -14
  139. /package/dist/runtime/plugins/{blokkliEditable.d.ts → blokkliDirectives.d.ts} +0 -0
@@ -59,7 +59,7 @@ import { ref, useBlokkli, onMounted } from "#imports";
59
59
  import { DialogModal, InfoBox, FormText, FormItem } from "#blokkli/components";
60
60
  import { realBackgroundColor } from "#blokkli/helpers";
61
61
  defineEmits(["confirm", "cancel"]);
62
- const { dom, $t } = useBlokkli();
62
+ const { dom, $t, blocks } = useBlokkli();
63
63
  const props = defineProps({
64
64
  uuid: { type: String, required: true },
65
65
  backgroundClass: { type: String, required: false }
@@ -70,14 +70,14 @@ const previewEl = ref(null);
70
70
  const backgroundColor = ref("");
71
71
  onMounted(() => {
72
72
  if (previewEl.value) {
73
- const item = dom.findBlock(props.uuid);
73
+ const item = blocks.getBlock(props.uuid);
74
74
  if (!item) {
75
75
  return;
76
76
  }
77
- if (item.editTitle) {
78
- label.value = item.editTitle.substring(0, 40);
77
+ const element = dom.getDragElement(item);
78
+ if (!element) {
79
+ return;
79
80
  }
80
- const element = item.element();
81
81
  const markup = dom.getDropElementMarkup(item);
82
82
  width.value = element.getBoundingClientRect().width + 40;
83
83
  const clone = document.createElement("div");
@@ -4,7 +4,7 @@
4
4
  id="library_detach"
5
5
  :title="$t('libraryDetach', 'Detach from library')"
6
6
  icon="detach"
7
- :disabled="state.editMode.value !== 'editing'"
7
+ edit-only
8
8
  multiple
9
9
  :weight="-70"
10
10
  @click="onDetach"
@@ -13,7 +13,8 @@
13
13
  v-else-if="!isReusable"
14
14
  id="library_make_reusable"
15
15
  :title="$t('libraryAdd', 'Add to library...')"
16
- :disabled="!canMakeReusable || state.editMode.value !== 'editing'"
16
+ :disabled="!canMakeReusable"
17
+ edit-only
17
18
  icon="reusable"
18
19
  :weight="-70"
19
20
  @click="showReusableDialog = true"
@@ -41,8 +42,8 @@
41
42
  <Teleport to="body">
42
43
  <BlokkliTransition name="slide-up">
43
44
  <ReusableDialog
44
- v-if="showReusableDialog && selectedItem"
45
- :uuid="selectedItem.uuid"
45
+ v-if="showReusableDialog && selection.item.value"
46
+ :uuid="selection.item.value.uuid"
46
47
  :background-class="definition?.editor?.previewBackgroundClass"
47
48
  @confirm="onMakeReusable"
48
49
  @cancel="showReusableDialog = false"
@@ -87,12 +88,6 @@ const { adapter } = defineBlokkliFeature({
87
88
  });
88
89
  const { selection, state, types, $t, eventBus, definitions } = useBlokkli();
89
90
  const showReusableDialog = ref(false);
90
- const selectedItem = computed(() => {
91
- if (selection.blocks.value.length !== 1) {
92
- return;
93
- }
94
- return selection.blocks.value[0];
95
- });
96
91
  const onDetach = async () => {
97
92
  if (!adapter.detachReusableBlock || !selection.uuids.value.length) {
98
93
  return;
@@ -118,28 +113,37 @@ const onAddLibraryItem = async (uuid) => {
118
113
  );
119
114
  placedAction.value = null;
120
115
  };
121
- const definition = computed(
122
- () => selectedItem?.value ? definitions.getBlockDefinition(
123
- selectedItem.value.itemBundle,
124
- selectedItem.value.hostFieldListType,
125
- selectedItem.value.parentBlockBundle
126
- ) : null
127
- );
128
- const itemBundle = computed(
129
- () => selectedItem?.value ? types.getBlockBundleDefinition(selectedItem.value.itemBundle) : null
130
- );
116
+ const definition = computed(() => {
117
+ const item = selection.item.value;
118
+ if (!item) {
119
+ return null;
120
+ }
121
+ return definitions.getBlockDefinition(
122
+ item.bundle,
123
+ item.fieldListType,
124
+ item.parentBlockBundle
125
+ );
126
+ });
127
+ const itemBundle = computed(() => {
128
+ const item = selection.item.value;
129
+ if (!item) {
130
+ return null;
131
+ }
132
+ return types.getBlockBundleDefinition(item.bundle);
133
+ });
131
134
  const isReusable = computed(
132
- () => selection.blocks.value.length && selection.blocks.value.every((v) => v.itemBundle === BUNDLE_FROM_LIBRARY)
135
+ () => selection.bundles.value.every((bundle) => bundle === BUNDLE_FROM_LIBRARY)
133
136
  );
134
137
  async function onMakeReusable(label) {
135
138
  showReusableDialog.value = false;
136
- if (!selectedItem?.value?.uuid) {
139
+ const item = selection.item.value;
140
+ if (!item) {
137
141
  return;
138
142
  }
139
143
  await state.mutateWithLoadingState(
140
144
  () => adapter.makeBlockReusable({
141
145
  label,
142
- uuid: selectedItem.value.uuid
146
+ uuid: item.uuid
143
147
  }),
144
148
  $t("libraryError", "Failed to add block to library.")
145
149
  );
@@ -88,7 +88,7 @@ defineProps({
88
88
  isSortli: { type: Boolean, required: false },
89
89
  modelValue: { type: String, required: false }
90
90
  });
91
- const { adapter, storage, $t } = useBlokkli();
91
+ const { adapter, storage, $t, element } = useBlokkli();
92
92
  const selected = ref([]);
93
93
  const listEl = ref(null);
94
94
  const page = ref(0);
@@ -97,10 +97,13 @@ function getDragItems(activeItem) {
97
97
  if (!selected.value.length || !listEl.value) {
98
98
  return null;
99
99
  }
100
+ const listElement = listEl.value;
100
101
  const activeId = activeItem?.itemType === "media_library" ? activeItem.mediaId : null;
101
102
  const items2 = selected.value.map((id) => {
102
- const el = listEl.value?.querySelector(
103
- `[data-sortli-id="media_library_${id}"]`
103
+ const el = element.query(
104
+ listElement,
105
+ `[data-sortli-id="media_library_${id}"]`,
106
+ "Find media library drag item."
104
107
  );
105
108
  if (!(el instanceof HTMLElement)) {
106
109
  return null;
@@ -32,6 +32,7 @@ import { PluginSidebar, PluginDroppableEdit } from "#blokkli/plugins";
32
32
  import Library from "./Library/index.vue";
33
33
  import defineDropAreas from "#blokkli/helpers/composables/defineDropAreas";
34
34
  import { falsy } from "#blokkli/helpers";
35
+ import { itemEntityType } from "#blokkli-build/config";
35
36
  defineBlokkliFeature({
36
37
  id: "media-library",
37
38
  icon: "image",
@@ -39,7 +40,7 @@ defineBlokkliFeature({
39
40
  description: "Implements a media library to easily drag and drop media like images or videos.",
40
41
  requiredAdapterMethods: ["mediaLibraryGetResults", "mediaLibraryAddBlock"]
41
42
  });
42
- const { $t, dom, adapter, state, runtimeConfig, types } = useBlokkli();
43
+ const { $t, adapter, state, runtimeConfig, types, directive } = useBlokkli();
43
44
  const selected = ref("");
44
45
  const ERROR_MESSAGE = $t(
45
46
  "mediaLibraryReplaceFailed",
@@ -49,11 +50,12 @@ const onDroppableEditSave = async (e) => {
49
50
  if (!selected.value) {
50
51
  return;
51
52
  }
52
- if ("itemBundle" in e.host && adapter.mediaLibraryReplaceMedia) {
53
+ if ("itemType" in e.host && adapter.mediaLibraryReplaceMedia) {
54
+ const host = e.host;
53
55
  await state.mutateWithLoadingState(
54
56
  () => adapter.mediaLibraryReplaceMedia({
55
57
  host: {
56
- uuid: e.host.uuid,
58
+ uuid: host.block.uuid,
57
59
  type: runtimeConfig.itemEntityType,
58
60
  fieldName: e.fieldName
59
61
  },
@@ -62,11 +64,12 @@ const onDroppableEditSave = async (e) => {
62
64
  ERROR_MESSAGE
63
65
  );
64
66
  } else if ("type" in e.host && adapter.mediaLibraryReplaceEntityMedia) {
65
- const type = e.host.type;
67
+ const host = e.host;
68
+ const type = host.type;
66
69
  await state.mutateWithLoadingState(
67
70
  () => adapter.mediaLibraryReplaceEntityMedia({
68
71
  host: {
69
- uuid: e.host.uuid,
72
+ uuid: host.uuid,
70
73
  type,
71
74
  fieldName: e.fieldName
72
75
  },
@@ -87,18 +90,18 @@ defineDropAreas((dragItems) => {
87
90
  if (item.itemType !== "media_library") {
88
91
  return;
89
92
  }
90
- return dom.getAllDroppableFields().map((field) => {
91
- const config = types.getDroppableFieldConfig(field.fieldName, field.host);
93
+ return directive.getDroppableElements().map((field) => {
94
+ const config = types.getDroppableFieldConfig(field.fieldName, field);
92
95
  if (config.allowedEntityType !== "media") {
93
96
  return;
94
97
  }
95
98
  if (!config.allowedBundles.includes(item.mediaBundle)) {
96
99
  return;
97
100
  }
98
- const isBlock = "itemBundle" in field.host;
101
+ const isBlock = field.type === itemEntityType;
99
102
  const draggableHost = {
100
- uuid: field.host.uuid,
101
- type: "itemBundle" in field.host ? runtimeConfig.itemEntityType : field.host.type,
103
+ uuid: field.uuid,
104
+ type: field.type,
102
105
  fieldName: field.fieldName
103
106
  };
104
107
  const label = $t("mediaLibraryReplaceMedia", "Replace @field").replace(
@@ -107,7 +110,7 @@ defineDropAreas((dragItems) => {
107
110
  );
108
111
  if (adapter.mediaLibraryReplaceMedia && isBlock) {
109
112
  return {
110
- id: `replace-media:${field.host.uuid}:${field.fieldName}`,
113
+ id: `replace-media:${field.uuid}:${field.fieldName}`,
111
114
  label,
112
115
  element: field.element,
113
116
  icon: "swap-horizontal",
@@ -123,7 +126,7 @@ defineDropAreas((dragItems) => {
123
126
  };
124
127
  } else if (adapter.mediaLibraryReplaceEntityMedia && !isBlock) {
125
128
  return {
126
- id: `replace-entity-media:${field.host.uuid}:${field.fieldName}`,
129
+ id: `replace-entity-media:${field.uuid}:${field.fieldName}`,
127
130
  label,
128
131
  element: field.element,
129
132
  icon: "swap-horizontal",
@@ -17,7 +17,7 @@ import {
17
17
  } from "twgl.js";
18
18
  import { RectangleBufferCollector } from "#blokkli/helpers/webgl";
19
19
  import useDebugLogger from "#blokkli/helpers/composables/useDebugLogger";
20
- const { eventBus, dom, theme, animation, ui } = useBlokkli();
20
+ const { eventBus, dom, theme, animation, ui, blocks } = useBlokkli();
21
21
  const logger = useDebugLogger();
22
22
  const props = defineProps({
23
23
  startX: { type: Number, required: true },
@@ -39,7 +39,7 @@ class MultiSelectRectangleBufferCollector extends RectangleBufferCollector {
39
39
  if (this.added.has(uuid)) {
40
40
  continue;
41
41
  }
42
- const block = dom.findBlock(uuid);
42
+ const block = blocks.getBlock(uuid);
43
43
  if (!block) {
44
44
  continue;
45
45
  }
@@ -56,6 +56,7 @@ import {
56
56
  BK_VISIBLE_LANGUAGES
57
57
  } from "#blokkli/helpers/symbols";
58
58
  import { BUNDLE_FROM_LIBRARY } from "#blokkli/constants";
59
+ import { itemEntityType } from "#blokkli-build/config";
59
60
  if (import.meta.hot) {
60
61
  import.meta.hot.accept("#blokkli/runtime-helpers", () => {
61
62
  });
@@ -94,11 +95,11 @@ const {
94
95
  eventBus,
95
96
  state,
96
97
  selection,
97
- runtimeConfig,
98
98
  dom,
99
99
  theme,
100
100
  context,
101
- definitions
101
+ definitions,
102
+ blocks
102
103
  } = useBlokkli();
103
104
  const props = defineProps({
104
105
  uuids: { type: [Array, String], required: true },
@@ -136,7 +137,7 @@ function stopChangingOptions() {
136
137
  if (Array.isArray(props.uuids)) {
137
138
  props.uuids.forEach((uuid) => {
138
139
  dom.refreshBlockRect(uuid);
139
- const block = dom.findBlock(uuid);
140
+ const block = blocks.getBlock(uuid);
140
141
  if (block) {
141
142
  const el = dom.getDragElement(block);
142
143
  if (el) {
@@ -248,11 +249,11 @@ const visibleOptions = computed(() => {
248
249
  }
249
250
  const uuid = props.uuids[0];
250
251
  const item = state.getFieldListItem(uuid);
251
- const block = selection.blocks.value.find((v) => v.uuid === uuid);
252
+ const block = selection.items.value.find((v) => v.uuid === uuid);
252
253
  if (!item) {
253
254
  return [];
254
255
  }
255
- const parentType = block?.hostType === runtimeConfig.itemEntityType ? block.parentBlockBundle : void 0;
256
+ const parentType = block?.host.type === itemEntityType ? block.parentBlockBundle : void 0;
256
257
  const ctxProps = item?.bundle === BUNDLE_FROM_LIBRARY ? item?.props?.libraryItem?.block?.props : item?.props;
257
258
  const visibleKeys = (
258
259
  // We have to cast to any here because the types are guaranteed to be correct.
@@ -261,7 +262,7 @@ const visibleOptions = computed(() => {
261
262
  parentType,
262
263
  props: ctxProps,
263
264
  entity: context.value,
264
- fieldListType: block?.hostFieldListType || "default"
265
+ fieldListType: block?.fieldListType ?? "default"
265
266
  })
266
267
  );
267
268
  return availableOptions.value.filter(
@@ -24,7 +24,7 @@ defineBlokkliFeature({
24
24
  });
25
25
  const { selection, state, ui, definitions, context } = useBlokkli();
26
26
  const uuids = computed(() => {
27
- const uuids2 = selection.blocks.value.map((v) => v.uuid);
27
+ const uuids2 = selection.items.value.map((v) => v.uuid);
28
28
  if (uuids2.length) {
29
29
  return uuids2;
30
30
  } else if (selection.hasHostSelected.value) {
@@ -47,14 +47,14 @@ const definition = computed(() => {
47
47
  context.value.entityBundle
48
48
  );
49
49
  }
50
- const bundles = selection.blocks.value.map((v) => v.reusableBundle || v.itemBundle).filter(onlyUnique);
50
+ const bundles = selection.items.value.map((v) => v.library?.reusableBundle || v.bundle).filter(onlyUnique);
51
51
  if (bundles.length !== 1) {
52
52
  return;
53
53
  }
54
54
  const bundle = bundles[0];
55
55
  if (bundle === "blokkli_fragment") {
56
- const fragments = selection.blocks.value.filter(
57
- (v) => v.itemBundle === "blokkli_fragment"
56
+ const fragments = selection.items.value.filter(
57
+ (v) => v.bundle === "blokkli_fragment"
58
58
  );
59
59
  const fragmentNames = fragments.map((v) => {
60
60
  const props = state.getFieldListItem(v.uuid)?.props;
@@ -67,10 +67,10 @@ const definition = computed(() => {
67
67
  }
68
68
  return definitions.getFragmentDefinition(fragmentNames[0]);
69
69
  }
70
- return selection.blocks.value.map((block) => {
70
+ return selection.items.value.map((block) => {
71
71
  return definitions.getBlockDefinition(
72
72
  bundle,
73
- block.hostFieldListType,
73
+ block.fieldListType,
74
74
  block.parentBlockBundle
75
75
  );
76
76
  }).filter(falsy).at(0);
@@ -37,23 +37,24 @@
37
37
  </label>
38
38
  <div class="bk-publish-schedule-date-wrapper">
39
39
  <div v-if="isAlreadyScheduled" class="bk-publish-scheduled-display">
40
- {{
41
- ui.formatDate(scheduleDate, {
42
- weekday: "long",
43
- year: "numeric",
44
- month: "2-digit",
45
- day: "2-digit",
46
- hour: "2-digit",
47
- minute: "2-digit"
48
- })
49
- }}
40
+ {{ formatScheduleDate(scheduleDate) }}
50
41
  </div>
51
42
  <ScheduleDate
52
43
  v-else
53
44
  v-model="scheduleDate"
54
45
  :disabled="isLoading"
55
46
  :error="scheduleDateError"
56
- />
47
+ >
48
+ <div
49
+ class="bk-schedule-date-info"
50
+ v-text="
51
+ $t(
52
+ 'publishScheduledInfo',
53
+ 'You can still make changes until the scheduled publication date.'
54
+ )
55
+ "
56
+ />
57
+ </ScheduleDate>
57
58
  <button
58
59
  v-if="isAlreadyScheduled"
59
60
  type="button"
@@ -90,6 +91,16 @@
90
91
  />
91
92
  </FormItem>
92
93
 
94
+ <FormItem v-if="publishMode !== 'save' && scheduledBlocks.length">
95
+ <InfoBox>
96
+ <p
97
+ v-for="(text, index) in scheduledBlocks"
98
+ :key="'infobox' + index"
99
+ v-html="text"
100
+ />
101
+ </InfoBox>
102
+ </FormItem>
103
+
93
104
  <FormItem v-if="successItems.length && showTable">
94
105
  <h2 class="bk-heading-2">
95
106
  {{ $t("publishSuccessfullyPublished", "Successfully published") }}
@@ -171,14 +182,29 @@ import {
171
182
  onMounted,
172
183
  onUnmounted
173
184
  } from "#imports";
174
- import { DialogModal, FormTextarea, FormItem } from "#blokkli/components";
185
+ import {
186
+ DialogModal,
187
+ FormTextarea,
188
+ FormItem,
189
+ ScheduleDate,
190
+ InfoBox
191
+ } from "#blokkli/components";
175
192
  import { emitMessage } from "#blokkli/helpers/eventBus";
176
193
  import Item from "./Item.vue";
177
194
  import PublishOption, {} from "./PublishOption.vue";
178
195
  import Summary from "./Summary.vue";
179
- import ScheduleDate from "./ScheduleDate.vue";
180
196
  const showTable = false;
181
197
  const { adapter, $t, state, context, ui } = useBlokkli();
198
+ const formatScheduleDate = (date) => {
199
+ return ui.formatDate(date, {
200
+ weekday: "long",
201
+ year: "numeric",
202
+ month: "long",
203
+ day: "numeric",
204
+ hour: "2-digit",
205
+ minute: "2-digit"
206
+ });
207
+ };
182
208
  const isMutating = ref(false);
183
209
  const mutationStatusItems = ref({});
184
210
  const publishedIds = ref([]);
@@ -205,6 +231,33 @@ const {
205
231
  } = await useAsyncData(() => {
206
232
  return adapter.getPublishOptions();
207
233
  });
234
+ const scheduledBlocks = computed(() => {
235
+ const referenceTimestamp = publishMode.value === "scheduled" && scheduleDate.value ? new Date(scheduleDate.value).getTime() : currentTimestamp.value;
236
+ const grouped = state.getAllUuids().reduce((acc, uuid) => {
237
+ const item = state.getFieldListItem(uuid);
238
+ if (!item?.editContext?.publishOn) {
239
+ return acc;
240
+ }
241
+ const publishDate = new Date(item.editContext.publishOn).getTime();
242
+ if (publishDate <= referenceTimestamp) {
243
+ return acc;
244
+ }
245
+ const dateKey = item.editContext.publishOn;
246
+ acc[dateKey] = (acc[dateKey] || 0) + 1;
247
+ return acc;
248
+ }, {});
249
+ return Object.entries(grouped).map(([date, count]) => {
250
+ const formattedDate = formatScheduleDate(date);
251
+ const message = count === 1 ? $t(
252
+ "publishScheduledBlockSingular",
253
+ "1 block is scheduled to be published on @date"
254
+ ) : $t(
255
+ "publishScheduledBlockPlural",
256
+ "@count blocks are scheduled to be published on @date"
257
+ );
258
+ return message.replace("@count", count.toString()).replace("@date", `<strong>${formattedDate}</strong>`);
259
+ });
260
+ });
208
261
  const canSchedule = computed(() => !!publishOptions.value?.canSchedule);
209
262
  const publishOn = computed(
210
263
  () => publishOptions.value?.publishOn ?? null
@@ -403,7 +456,7 @@ const resultStateLabel = computed(() => {
403
456
  );
404
457
  }
405
458
  if (publishMode.value === "scheduled" && scheduleDate.value) {
406
- const formattedDate = ui.formatDate(scheduleDate.value);
459
+ const formattedDate = formatScheduleDate(scheduleDate.value);
407
460
  if (isCurrentlyPublished.value) {
408
461
  return $t(
409
462
  "publishResultScheduledChanges",
@@ -500,7 +553,7 @@ async function onSubmit() {
500
553
  return;
501
554
  }
502
555
  if (publishMode.value === "scheduled") {
503
- const formattedDate = ui.formatDate(scheduleDate.value);
556
+ const formattedDate = formatScheduleDate(scheduleDate.value);
504
557
  const message = $t(
505
558
  "publishScheduleSuccess",
506
559
  "Publication scheduled for @date"
@@ -10,7 +10,7 @@
10
10
  @mouseenter="index = i"
11
11
  >
12
12
  <div class="bk-search-item-icon">
13
- <ItemIcon :bundle="item.item.itemBundle" />
13
+ <ItemIcon :bundle="item.item.bundle" />
14
14
  </div>
15
15
  <div class="bk-search-item-content">
16
16
  <Highlight
@@ -49,7 +49,7 @@ const props = defineProps({
49
49
  search: { type: String, required: true },
50
50
  tab: { type: String, required: true }
51
51
  });
52
- const { eventBus, state, types, dom } = useBlokkli();
52
+ const { eventBus, state, types, dom, blocks, element } = useBlokkli();
53
53
  const buildForKey = ref("");
54
54
  const items = ref([]);
55
55
  const index = ref(0);
@@ -92,28 +92,28 @@ const scrollItemIntoView = () => {
92
92
  }
93
93
  };
94
94
  const buildSearchText = (el) => {
95
- let text = el.textContent || "";
96
- el.querySelectorAll("img").forEach((img) => {
97
- if (img.alt) {
98
- text += " " + img.alt;
99
- }
100
- if (img.title) {
101
- text += " " + img.title;
95
+ if (!el) {
96
+ return "";
97
+ }
98
+ const altTexts = element.queryAll(el, "img", "buildSearchText", (el2) => {
99
+ if (el2 instanceof HTMLImageElement) {
100
+ return [el2.alt, el2.title].filter(Boolean).join("");
102
101
  }
103
- });
104
- return text;
102
+ }).join(" ");
103
+ return (el.textContent ?? "") + altTexts;
105
104
  };
106
105
  const buildIndex = () => {
107
106
  if (buildForKey.value === state.refreshKey.value) {
108
107
  return;
109
108
  }
110
- const newItems = dom.getAllBlocks().map((item) => {
111
- const title = types.getBlockBundleDefinition(item.itemBundle)?.label || item.itemBundle;
109
+ const newItems = blocks.getAllBlocks().map((item) => {
110
+ const title = types.getBlockBundleDefinition(item.bundle)?.label || item.bundle;
111
+ const element2 = dom.getDragElement(item);
112
112
  return {
113
113
  item,
114
- title: item.editTitle || title,
114
+ title,
115
115
  context: title,
116
- text: buildSearchText(item.element())
116
+ text: buildSearchText(element2)
117
117
  };
118
118
  }).filter(falsy);
119
119
  items.value = newItems;
@@ -46,7 +46,7 @@ defineBlokkliFeature({
46
46
  label: "Search",
47
47
  description: "Provides an overlay with shortcut to search for blocks on the current page or existing content to add as blocks."
48
48
  });
49
- const { $t, selection } = useBlokkli();
49
+ const { $t, selection, ui } = useBlokkli();
50
50
  const isRendered = ref(false);
51
51
  const isVisible = ref(false);
52
52
  const overlay = ref(null);
@@ -60,6 +60,9 @@ function onClick() {
60
60
  });
61
61
  }
62
62
  onBlokkliEvent("keyPressed", (e) => {
63
+ if (ui.hasDialogOpen.value) {
64
+ return;
65
+ }
63
66
  if (e.code === "Escape") {
64
67
  isVisible.value = false;
65
68
  }
@@ -6,12 +6,12 @@ type __VLS_Props = {
6
6
  label: string;
7
7
  };
8
8
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
- select: (id: string) => void;
10
9
  action: (id: string) => void;
10
+ select: (id: string) => void;
11
11
  close: () => void;
12
12
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
13
- onClose?: (() => any) | undefined;
14
- onSelect?: ((id: string) => any) | undefined;
15
13
  onAction?: ((id: string) => any) | undefined;
14
+ onSelect?: ((id: string) => any) | undefined;
15
+ onClose?: (() => any) | undefined;
16
16
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
17
  export default _default;
@@ -30,7 +30,19 @@ import {
30
30
  determineCanAddChildren
31
31
  } from "#blokkli/helpers/dropTargets";
32
32
  import { isInternalBundle } from "#blokkli/helpers/bundles";
33
- const { animation, theme, dom, selection, state, types, ui, $t } = useBlokkli();
33
+ import { itemEntityType } from "#blokkli-build/config";
34
+ const {
35
+ animation,
36
+ theme,
37
+ dom,
38
+ selection,
39
+ state,
40
+ types,
41
+ ui,
42
+ $t,
43
+ blocks,
44
+ fields
45
+ } = useBlokkli();
34
46
  const emptyFieldTooltips = ref([]);
35
47
  const currentUuid = ref("");
36
48
  const currentBundleLabel = ref("");
@@ -146,9 +158,9 @@ const blockStateCache = /* @__PURE__ */ new Map();
146
158
  function getOrientationForUuid(uuid) {
147
159
  let cached = orientationCache.get(uuid);
148
160
  if (!cached) {
149
- const block = dom.findBlock(uuid);
150
- if (block) {
151
- const field = dom.findField(block.hostUuid, block.hostFieldName);
161
+ const item = blocks.getBlock(uuid);
162
+ if (item) {
163
+ const field = fields.find(item.host.uuid, item.host.fieldName);
152
164
  if (field) {
153
165
  cached = getChildrenOrientation(field.element);
154
166
  orientationCache.set(uuid, cached);
@@ -162,7 +174,7 @@ function getBlockState(uuid) {
162
174
  if (!cached) {
163
175
  let canShowBeforeAfter = false;
164
176
  let singleAllowedBundleLabel = null;
165
- const block = dom.findBlock(uuid);
177
+ const block = blocks.getBlock(uuid);
166
178
  if (!block) {
167
179
  return {
168
180
  canShowBeforeAfter: false,
@@ -173,7 +185,7 @@ function getBlockState(uuid) {
173
185
  };
174
186
  }
175
187
  if (block) {
176
- const field = dom.findField(block.hostUuid, block.hostFieldName);
188
+ const field = fields.find(block.host.uuid, block.host.fieldName);
177
189
  if (!field) {
178
190
  return {
179
191
  canShowBeforeAfter: false,
@@ -208,13 +220,13 @@ function getBlockState(uuid) {
208
220
  }
209
221
  }
210
222
  }
211
- const bundleLabel = block ? types.getBlockBundleDefinition(block.itemBundle)?.label || block.itemBundle : "";
223
+ const bundleLabel = block ? types.getBlockBundleDefinition(block.bundle)?.label || block.bundle : "";
212
224
  const emptyFieldKeys = [];
213
225
  const emptyFieldTooltips2 = [];
214
226
  if (block) {
215
227
  const fieldConfigs = types.fieldConfig.forEntityTypeAndBundle(
216
- block.entityType,
217
- block.itemBundle
228
+ itemEntityType,
229
+ block.bundle
218
230
  );
219
231
  for (const fieldConfig of fieldConfigs) {
220
232
  const key = getFieldKey(uuid, fieldConfig.name);
@@ -222,7 +234,7 @@ function getBlockState(uuid) {
222
234
  if (count === 0) {
223
235
  emptyFieldKeys.push(key);
224
236
  const fieldLabel = fieldConfig.label || fieldConfig.name;
225
- const fieldElement = dom.findField(uuid, fieldConfig.name);
237
+ const fieldElement = fields.find(uuid, fieldConfig.name);
226
238
  if (fieldElement) {
227
239
  const allowedBundles = fieldElement.allowedBundles.filter(
228
240
  (bundle) => !isInternalBundle(bundle)
@@ -301,7 +313,18 @@ function getCircleAtPoint(x, y) {
301
313
  if (gl && programInfo && bufferInfo) {
302
314
  defineRenderer("add-buttons", {
303
315
  zIndex: 1e3,
304
- enabled: () => selection.uuids.value.length === 1,
316
+ enabled: () => {
317
+ if (selection.uuids.value.length !== 1) {
318
+ return false;
319
+ }
320
+ if (ui.openTooltip.value && ui.openTooltip.value !== "add-buttons") {
321
+ return false;
322
+ }
323
+ if (ui.hasTransformOverlayOpen.value) {
324
+ return false;
325
+ }
326
+ return true;
327
+ },
305
328
  cursor: () => hoveredCircle.value >= 0 ? "pointer" : null,
306
329
  onClick: ({ mouseArtboard }) => {
307
330
  if (selection.uuids.value.length !== 1) {