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

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 (106) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +265 -83
  3. package/dist/modules/drupal/graphql/base/fragment.blokkliProps.graphql +1 -1
  4. package/dist/modules/drupal/graphql/features/comments.graphql +11 -8
  5. package/dist/modules/drupal/runtime/adapter/index.js +2 -2
  6. package/dist/runtime/blokkliPlugins/ItemAction/index.vue +1 -3
  7. package/dist/runtime/components/Blocks/FromLibrary/index.vue +4 -2
  8. package/dist/runtime/components/BlokkliEditable.vue +22 -4
  9. package/dist/runtime/components/BlokkliProvider.vue +29 -20
  10. package/dist/runtime/components/BlokkliProvider.vue.d.ts +2 -1
  11. package/dist/runtime/components/Edit/Actions/index.vue +9 -4
  12. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +420 -25
  13. package/dist/runtime/components/Edit/ArtboardTooltip/index.vue +80 -0
  14. package/dist/runtime/components/Edit/ArtboardTooltip/index.vue.d.ts +32 -0
  15. package/dist/runtime/components/Edit/Banner/index.vue +51 -0
  16. package/dist/runtime/components/Edit/Banner/index.vue.d.ts +18 -0
  17. package/dist/runtime/components/Edit/EditIndicator.vue +118 -44
  18. package/dist/runtime/components/Edit/EditIndicator.vue.d.ts +3 -0
  19. package/dist/runtime/components/Edit/EditProvider.vue +79 -22
  20. package/dist/runtime/components/Edit/EditProvider.vue.d.ts +2 -0
  21. package/dist/runtime/components/Edit/Features/Analyze/Overlay/index.vue +19 -20
  22. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +1 -1
  23. package/dist/runtime/components/Edit/Features/CommandPalette/index.vue +2 -0
  24. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue +35 -20
  25. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue.d.ts +5 -3
  26. package/dist/runtime/components/Edit/Features/Comments/CommentInput/index.vue +29 -0
  27. package/dist/runtime/components/Edit/Features/Comments/CommentInput/index.vue.d.ts +13 -0
  28. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue +22 -16
  29. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue.d.ts +1 -0
  30. package/dist/runtime/components/Edit/Features/Comments/Overlay/index.vue +15 -6
  31. package/dist/runtime/components/Edit/Features/Comments/index.vue +20 -8
  32. package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue +26 -35
  33. package/dist/runtime/components/Edit/Features/Debug/Renderer.vue +240 -0
  34. package/dist/runtime/components/Edit/Features/Debug/Renderer.vue.d.ts +6 -0
  35. package/dist/runtime/components/Edit/Features/Debug/index.vue +4 -165
  36. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +1 -1
  37. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +41 -37
  38. package/dist/runtime/components/Edit/Features/Edit/index.vue +1 -1
  39. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue +63 -3
  40. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Plaintext/index.vue +13 -9
  41. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue +17 -76
  42. package/dist/runtime/components/Edit/Features/EditableField/index.vue +1 -1
  43. package/dist/runtime/components/Edit/Features/History/index.vue +5 -2
  44. package/dist/runtime/components/Edit/Features/Hover/Overlay/fragment.glsl +139 -0
  45. package/dist/runtime/components/Edit/Features/Hover/Overlay/index.vue +270 -0
  46. package/dist/runtime/components/Edit/Features/Hover/Overlay/index.vue.d.ts +6 -0
  47. package/dist/runtime/components/Edit/Features/Hover/Overlay/vertex.glsl +117 -0
  48. package/dist/runtime/components/Edit/Features/Hover/index.vue +25 -0
  49. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/index.vue +19 -27
  50. package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue +27 -23
  51. package/dist/runtime/components/Edit/Features/Library/index.vue +2 -1
  52. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/index.vue +34 -27
  53. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +2 -4
  54. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue +6 -1
  55. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +1 -0
  56. package/dist/runtime/components/Edit/Features/Ownership/Renderer.vue +35 -0
  57. package/dist/runtime/components/Edit/Features/Ownership/Renderer.vue.d.ts +6 -0
  58. package/dist/runtime/components/Edit/Features/Ownership/index.vue +7 -25
  59. package/dist/runtime/components/Edit/Features/ProxyView/index.vue +5 -1
  60. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue +39 -74
  61. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue.d.ts +4 -2
  62. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/fragment.glsl +106 -0
  63. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/index.vue +417 -0
  64. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/index.vue.d.ts +32 -0
  65. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/vertex.glsl +102 -0
  66. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue +33 -106
  67. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +88 -29
  68. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue.d.ts +2 -0
  69. package/dist/runtime/components/Edit/Features/Selection/Overlay/vertex.glsl +11 -2
  70. package/dist/runtime/components/Edit/Features/Selection/index.vue +5 -12
  71. package/dist/runtime/components/Edit/Features/Translations/Banner/index.vue +17 -11
  72. package/dist/runtime/components/Edit/Features/Translations/index.vue +13 -16
  73. package/dist/runtime/components/Edit/Form/Text/index.vue +2 -1
  74. package/dist/runtime/components/Edit/Form/Text/index.vue.d.ts +1 -0
  75. package/dist/runtime/components/Edit/Indicators/index.vue +1 -1
  76. package/dist/runtime/components/Edit/Konami/Game/index.vue +5 -5
  77. package/dist/runtime/components/Edit/index.d.ts +5 -3
  78. package/dist/runtime/components/Edit/index.js +8 -4
  79. package/dist/runtime/composables/defineBlokkli.js +4 -2
  80. package/dist/runtime/css/output.css +1 -1
  81. package/dist/runtime/helpers/animationProvider.d.ts +34 -1
  82. package/dist/runtime/helpers/animationProvider.js +175 -48
  83. package/dist/runtime/helpers/composables/defineRenderer.d.ts +8 -0
  84. package/dist/runtime/helpers/composables/defineRenderer.js +8 -0
  85. package/dist/runtime/helpers/composables/useStickyToolbar.d.ts +4 -1
  86. package/dist/runtime/helpers/composables/useStickyToolbar.js +53 -35
  87. package/dist/runtime/helpers/dom/index.d.ts +1 -0
  88. package/dist/runtime/helpers/domProvider.d.ts +46 -0
  89. package/dist/runtime/helpers/domProvider.js +95 -6
  90. package/dist/runtime/helpers/editableProvider.d.ts +14 -0
  91. package/dist/runtime/helpers/editableProvider.js +144 -0
  92. package/dist/runtime/helpers/stateProvider.d.ts +6 -2
  93. package/dist/runtime/helpers/stateProvider.js +66 -3
  94. package/dist/runtime/helpers/storageProvider.d.ts +3 -2
  95. package/dist/runtime/helpers/storageProvider.js +6 -2
  96. package/dist/runtime/helpers/symbols.d.ts +1 -0
  97. package/dist/runtime/helpers/symbols.js +1 -0
  98. package/dist/runtime/helpers/uiProvider.d.ts +8 -1
  99. package/dist/runtime/helpers/uiProvider.js +34 -2
  100. package/dist/runtime/plugins/blokkliEditable.js +74 -3
  101. package/dist/runtime/types/index.d.ts +13 -1
  102. package/package.json +1 -1
  103. package/dist/runtime/components/Edit/DragInteractions/index.vue +0 -401
  104. package/dist/runtime/components/Edit/Features/Selection/AddButtons/AddButtonsField.vue +0 -54
  105. package/dist/runtime/components/Edit/Features/Selection/AddButtons/AddButtonsField.vue.d.ts +0 -14
  106. /package/dist/runtime/components/Edit/{DragInteractions → Features/Hover}/index.vue.d.ts +0 -0
@@ -23,36 +23,40 @@
23
23
  )
24
24
  "
25
25
  />
26
- <label for="reusable_label" class="bk-form-label">{{
27
- $t("libraryDialogDescriptionLabel", "Description")
28
- }}</label>
29
- <input
30
- id="reusable_label"
31
- v-model="label"
32
- type="text"
33
- class="bk-form-input"
34
- :placeholder="
35
- $t('libraryDialogTitleInputPlaceholder', 'e.g. Teaser Campaign 2024')
26
+ <FormItem>
27
+ <FormText
28
+ id="reusable_label"
29
+ v-model="label"
30
+ :label="$t('libraryDialogDescriptionLabel', 'Description')"
31
+ type="text"
32
+ :placeholder="
33
+ $t(
34
+ 'libraryDialogTitleInputPlaceholder',
35
+ 'e.g. Teaser Campaign 2024'
36
+ )
36
37
  "
37
- required
38
- />
39
- </div>
40
- <div class="bk-form-label">
41
- {{ $t("libraryPreviewLabel", "Preview") }}
42
- </div>
43
- <div
44
- class="bk-dialog-content-element"
45
- :class="[backgroundClass, { 'bk-default-bg': !backgroundClass }]"
46
- :style="backgroundClass ? {} : { backgroundColor }"
47
- >
48
- <div ref="previewEl" />
38
+ required
39
+ />
40
+ </FormItem>
41
+ <FormItem>
42
+ <div class="bk-form-label">
43
+ {{ $t("libraryPreviewLabel", "Preview") }}
44
+ </div>
45
+ <div
46
+ class="bk-dialog-content-element"
47
+ :class="[backgroundClass, { 'bk-default-bg': !backgroundClass }]"
48
+ :style="backgroundClass ? {} : { backgroundColor }"
49
+ >
50
+ <div ref="previewEl" />
51
+ </div>
52
+ </FormItem>
49
53
  </div>
50
54
  </DialogModal>
51
55
  </template>
52
56
 
53
57
  <script setup>
54
58
  import { ref, useBlokkli, onMounted } from "#imports";
55
- import { DialogModal, InfoBox } from "#blokkli/components";
59
+ import { DialogModal, InfoBox, FormText, FormItem } from "#blokkli/components";
56
60
  import { realBackgroundColor } from "#blokkli/helpers";
57
61
  defineEmits(["confirm", "cancel"]);
58
62
  const { dom, $t } = useBlokkli();
@@ -4,6 +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
8
  multiple
8
9
  :weight="-70"
9
10
  @click="onDetach"
@@ -11,7 +12,7 @@
11
12
  <PluginItemAction
12
13
  v-else-if="!isReusable"
13
14
  id="library_make_reusable"
14
- :title="$t('libraryAdd', 'Add to library')"
15
+ :title="$t('libraryAdd', 'Add to library...')"
15
16
  :disabled="!canMakeReusable || state.editMode.value !== 'editing'"
16
17
  icon="reusable"
17
18
  :weight="-70"
@@ -7,7 +7,7 @@
7
7
  <script setup>
8
8
  import { useBlokkli, onBeforeUnmount } from "#imports";
9
9
  import { intersects, toShaderColor } from "#blokkli/helpers";
10
- import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
10
+ import defineRenderer from "#blokkli/helpers/composables/defineRenderer";
11
11
  import vs from "./vertex.glsl?raw";
12
12
  import fs from "./fragment.glsl?raw";
13
13
  import {
@@ -181,32 +181,40 @@ function getSelectRect(offset, scale) {
181
181
  };
182
182
  return { shader, check };
183
183
  }
184
- onBlokkliEvent("canvas:draw", (e) => {
185
- mouseX = e.mouseX;
186
- mouseY = e.mouseY;
187
- const { shader, check } = getSelectRect(e.artboardOffset, e.artboardScale);
188
- const { nested } = collector.getSelectedUuids(check);
189
- const shouldSelectAll = props.isPressingControl || !nested.length;
190
- props.gl.useProgram(programInfo.program);
191
- const time = (Date.now() - startTimestamp) / 1e3;
192
- setUniforms(programInfo, uniforms);
193
- setUniforms(programInfo, {
194
- u_select_all: shouldSelectAll ? 1 : 0,
195
- u_select_rect: [shader.x, shader.y, shader.width, shader.height],
196
- u_time: time
197
- });
198
- animation.setSharedUniforms(props.gl, programInfo);
199
- const { info, hasChanged } = collector.getBufferInfo(
200
- e.artboardOffset,
201
- e.artboardScale
202
- );
203
- if (!info) {
204
- return;
205
- }
206
- if (hasChanged) {
207
- setBuffersAndAttributes(props.gl, programInfo, info);
184
+ defineRenderer("multiselect-overlay", {
185
+ zIndex: 450,
186
+ only: true,
187
+ cursor: () => "crosshair",
188
+ render: (ctx) => {
189
+ mouseX = ctx.mouseX;
190
+ mouseY = ctx.mouseY;
191
+ const { shader, check } = getSelectRect(
192
+ ctx.artboardOffset,
193
+ ctx.artboardScale
194
+ );
195
+ const { nested } = collector.getSelectedUuids(check);
196
+ const shouldSelectAll = props.isPressingControl || !nested.length;
197
+ ctx.gl.useProgram(programInfo.program);
198
+ const time = (Date.now() - startTimestamp) / 1e3;
199
+ setUniforms(programInfo, uniforms);
200
+ setUniforms(programInfo, {
201
+ u_select_all: shouldSelectAll ? 1 : 0,
202
+ u_select_rect: [shader.x, shader.y, shader.width, shader.height],
203
+ u_time: time
204
+ });
205
+ animation.setSharedUniforms(ctx.gl, programInfo);
206
+ const { info, hasChanged } = collector.getBufferInfo(
207
+ ctx.artboardOffset,
208
+ ctx.artboardScale
209
+ );
210
+ if (!info) {
211
+ return;
212
+ }
213
+ if (hasChanged) {
214
+ setBuffersAndAttributes(ctx.gl, programInfo, info);
215
+ }
216
+ drawBufferInfo(ctx.gl, info, ctx.gl.TRIANGLES);
208
217
  }
209
- drawBufferInfo(props.gl, info, props.gl.TRIANGLES);
210
218
  });
211
219
  function getUuidsToSelect() {
212
220
  const { check } = getSelectRect(
@@ -222,7 +230,6 @@ function getUuidsToSelect() {
222
230
  return nested;
223
231
  }
224
232
  onBeforeUnmount(() => {
225
- props.gl.clear(props.gl.COLOR_BUFFER_BIT);
226
233
  const diff = Date.now() - startTimestamp;
227
234
  if (diff > 175) {
228
235
  eventBus.emit("select:end", getUuidsToSelect());
@@ -20,11 +20,9 @@ defineBlokkliFeature({
20
20
  description: "Implements support for selecting multiple blocks using a select rectangle.",
21
21
  viewports: ["desktop"]
22
22
  });
23
- const { keyboard, eventBus, selection, state, animation } = useBlokkli();
23
+ const { keyboard, eventBus, selection, animation } = useBlokkli();
24
24
  const gl = animation.gl();
25
- const enabled = computed(
26
- () => !selection.editableActive.value && (state.editMode.value === "editing" || state.editMode.value === "translating") && gl
27
- );
25
+ const enabled = computed(() => !selection.editableActive.value && gl);
28
26
  const shouldRender = ref(false);
29
27
  const downX = ref(0);
30
28
  const downY = ref(0);
@@ -113,7 +113,12 @@ const showLabel = computed(() => {
113
113
  const label = computed(
114
114
  () => $blokkliText(`blockOption_${props.property}_label`, props.option.label)
115
115
  );
116
- const description = computed(() => props.option.description);
116
+ const description = computed(
117
+ () => $blokkliText(
118
+ `blockOption_${props.property}_description`,
119
+ props.option.description
120
+ )
121
+ );
117
122
  const checkboxOptions = computed(() => {
118
123
  if (props.option.type !== "checkboxes") {
119
124
  return [];
@@ -146,6 +146,7 @@ function stopChangingOptions() {
146
146
  });
147
147
  }
148
148
  selection.isChangingOptions.value = false;
149
+ eventBus.emit("option:finish-change");
149
150
  }
150
151
  class OptionCollector {
151
152
  options;
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <Banner
3
+ id="ownership"
4
+ icon="user"
5
+ :text
6
+ :button="$t('ownershipTakeOwnership', 'Assign to me')"
7
+ @click="$emit('submit')"
8
+ />
9
+ </template>
10
+
11
+ <script setup>
12
+ import { computed, useBlokkli, onMounted, onBeforeUnmount } from "#imports";
13
+ import { Banner } from "#blokkli/components";
14
+ defineEmits(["submit"]);
15
+ const { state, $t, ui } = useBlokkli();
16
+ const name = computed(() => {
17
+ const v = state.owner.value?.name;
18
+ if (v) {
19
+ return `<strong>${v}</strong>`;
20
+ }
21
+ return "";
22
+ });
23
+ const text = computed(() => {
24
+ return $t(
25
+ "ownershipNote",
26
+ "This page is currently being edited by @name. Changes can only be made by one person at a time."
27
+ ).replace("@name", name.value);
28
+ });
29
+ onMounted(() => {
30
+ ui.setSelectionColor("ownership", "mono");
31
+ });
32
+ onBeforeUnmount(() => {
33
+ ui.removeSelectionColor("ownership");
34
+ });
35
+ </script>
@@ -0,0 +1,6 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
2
+ submit: () => any;
3
+ }, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
4
+ onSubmit?: (() => any) | undefined;
5
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
6
+ export default _default;
@@ -1,26 +1,12 @@
1
1
  <template>
2
- <Teleport to="body">
3
- <div
4
- v-if="!state.owner.value?.currentUserIsOwner"
5
- class="bk-owner-indicator"
6
- >
7
- <p
8
- v-html="
9
- $t(
10
- 'ownershipNote',
11
- 'This page is currently being edited by @name. Changes can only be made by one person at a time.'
12
- ).replace('@name', name)
13
- "
14
- />
15
- <button class="bk-button bk-is-danger" @click="takeOwnership">
16
- {{ $t("ownershipTakeOwnership", "Assign to me") }}
17
- </button>
18
- </div>
2
+ <Teleport to="#bk-banner-list">
3
+ <Renderer v-if="shouldRender" @submit="takeOwnership" />
19
4
  </Teleport>
20
5
  </template>
21
6
 
22
7
  <script setup>
23
- import { computed, useBlokkli, defineBlokkliFeature } from "#imports";
8
+ import { useBlokkli, defineBlokkliFeature, computed } from "#imports";
9
+ import Renderer from "./Renderer.vue";
24
10
  const { adapter } = defineBlokkliFeature({
25
11
  id: "ownership",
26
12
  icon: "user",
@@ -29,18 +15,14 @@ const { adapter } = defineBlokkliFeature({
29
15
  description: "Renders a large button to take ownership of the current edit state."
30
16
  });
31
17
  const { state, $t } = useBlokkli();
18
+ const shouldRender = computed(
19
+ () => !state.owner.value?.currentUserIsOwner && state.permissions.value.includes("edit")
20
+ );
32
21
  const takeOwnership = () => state.mutateWithLoadingState(
33
22
  () => adapter.takeOwnership(),
34
23
  $t("ownershipError", "Error in assigning"),
35
24
  $t("ownershipSuccess", "You are now the owner.")
36
25
  );
37
- const name = computed(() => {
38
- const v = state.owner.value?.name;
39
- if (v) {
40
- return `<strong>${v}</strong>`;
41
- }
42
- return "";
43
- });
44
26
  </script>
45
27
 
46
28
  <script>
@@ -13,6 +13,7 @@
13
13
  "
14
14
  key-code="P"
15
15
  icon="tree"
16
+ @update:model-value="onToggleProxyMode"
16
17
  />
17
18
  </template>
18
19
 
@@ -26,7 +27,10 @@ defineBlokkliFeature({
26
27
  description: "Displays the blocks as a structure in the preview.",
27
28
  viewports: ["desktop"]
28
29
  });
29
- const { $t, ui } = useBlokkli();
30
+ const { $t, ui, eventBus } = useBlokkli();
31
+ function onToggleProxyMode() {
32
+ eventBus.emit("state:reloaded");
33
+ }
30
34
  </script>
31
35
 
32
36
  <script>
@@ -1,86 +1,57 @@
1
1
  <template>
2
- <div
3
- ref="el"
4
- class="bk bk-selection-add-overlay"
5
- :class="'bk-is-' + placementY"
6
- :style="{
7
- '--bk-caret-x': caretX
8
- }"
2
+ <ArtboardTooltip
3
+ id="add-buttons"
4
+ :title="label"
5
+ :anchor-el
6
+ :anchor-coordinates
7
+ class="bk-selection-add-overlay"
8
+ @close="$emit('close')"
9
9
  >
10
- <div class="bk bk-selection-add-overlay-inner bk-caret-tooltip-inner">
11
- <div v-if="label" class="bk-selection-add-overlay-label">
12
- <div v-html="label" />
13
- <button @click="$emit('close')">
14
- <Icon name="close" />
15
- </button>
16
- </div>
17
- <div
18
- ref="listEl"
19
- class="bk-selection-add-overlay-list bk-scrollbar-dark"
20
- @wheel="onWheel"
10
+ <div
11
+ ref="listEl"
12
+ class="bk-selection-add-overlay-list bk-scrollbar-dark"
13
+ @wheel="onWheel"
14
+ >
15
+ <button
16
+ v-for="item in items"
17
+ :key="item.bundle"
18
+ tabindex="-1"
19
+ @click.prevent="$emit('select', item.bundle)"
21
20
  >
22
- <button
23
- v-for="item in items"
24
- :key="item.bundle"
25
- tabindex="-1"
26
- @click.prevent="$emit('select', item.bundle)"
27
- >
28
- <AddListItemIcon
29
- :bundle="item.bundle"
30
- :color="item.isFavorite ? 'yellow' : 'default'"
31
- />
32
- <span>{{ item.label }}</span>
33
- </button>
34
- <button
35
- v-for="action in actions"
36
- :key="'action:' + action.id"
37
- tabindex="-1"
38
- @click.prevent="$emit('action', action.id)"
39
- >
40
- <AddListItemIcon :icon="action.icon" :color="action.color" />
41
- <span>{{ action.title }}</span>
42
- </button>
43
- </div>
21
+ <AddListItemIcon
22
+ :bundle="item.bundle"
23
+ :color="item.isFavorite ? 'yellow' : 'default'"
24
+ />
25
+ <span>{{ item.label }}</span>
26
+ </button>
27
+ <button
28
+ v-for="action in actions"
29
+ :key="'action:' + action.id"
30
+ tabindex="-1"
31
+ @click.prevent="$emit('action', action.id)"
32
+ >
33
+ <AddListItemIcon :icon="action.icon" :color="action.color" />
34
+ <span>{{ action.title }}</span>
35
+ </button>
44
36
  </div>
45
- </div>
37
+ </ArtboardTooltip>
46
38
  </template>
47
39
 
48
40
  <script setup>
49
- import useStickyToolbar from "#blokkli/helpers/composables/useStickyToolbar";
50
- import {
51
- useTemplateRef,
52
- useBlokkli,
53
- computed,
54
- onMounted,
55
- onBeforeUnmount
56
- } from "#imports";
57
- import { Icon, AddListItemIcon } from "#blokkli/components";
41
+ import { useTemplateRef, useBlokkli, computed } from "#imports";
42
+ import { AddListItemIcon, ArtboardTooltip } from "#blokkli/components";
58
43
  import { isInternalBundle } from "#blokkli/helpers/bundles";
59
44
  const props = defineProps({
60
45
  bundles: { type: Array, required: true },
61
- anchorEl: { type: null, required: true },
62
- label: { type: String, required: false }
46
+ anchorEl: { type: null, required: false },
47
+ anchorCoordinates: { type: Object, required: false },
48
+ label: { type: String, required: true }
63
49
  });
64
50
  defineEmits(["select", "action", "close"]);
65
- const el = useTemplateRef("el");
66
51
  const listEl = useTemplateRef("listEl");
67
52
  let hasScrollbar = null;
68
- const { types, ui, plugins, storage } = useBlokkli();
53
+ const { types, plugins, storage } = useBlokkli();
69
54
  const favorites = storage.use("blockFavorites", []);
70
- const { placementY, caretX } = useStickyToolbar(el, {
71
- getAnchorElement() {
72
- return props.anchorEl;
73
- },
74
- getPlacementY() {
75
- return "auto";
76
- },
77
- getPlacementX() {
78
- return "center";
79
- },
80
- getCaretWidth() {
81
- return 30;
82
- }
83
- });
84
55
  const items = computed(() => {
85
56
  return props.bundles.filter((bundle) => !isInternalBundle(bundle)).map((bundle) => {
86
57
  return {
@@ -111,10 +82,4 @@ const onWheel = (e) => {
111
82
  e.stopPropagation();
112
83
  }
113
84
  };
114
- onMounted(() => {
115
- ui.hasAddTooltipOpen.value = true;
116
- });
117
- onBeforeUnmount(() => {
118
- ui.hasAddTooltipOpen.value = false;
119
- });
120
85
  </script>
@@ -1,7 +1,9 @@
1
+ import type { Coord } from '#blokkli/types';
1
2
  type __VLS_Props = {
2
3
  bundles: string[];
3
- anchorEl: HTMLElement;
4
- label?: string;
4
+ anchorEl?: HTMLElement;
5
+ anchorCoordinates?: Coord;
6
+ label: string;
5
7
  };
6
8
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
9
  select: (id: string) => void;
@@ -0,0 +1,106 @@
1
+ precision highp float;
2
+
3
+ varying vec4 v_quad;
4
+ varying vec2 v_circle_center;
5
+ varying float v_visible;
6
+ varying float v_is_hovered;
7
+ varying float v_scale_fade;
8
+ varying float v_rect_id;
9
+
10
+ uniform float u_dpi;
11
+ uniform vec3 u_color;
12
+ uniform vec3 u_color_hover;
13
+ uniform vec3 u_color_field;
14
+ uniform vec3 u_color_field_hover;
15
+
16
+ void main() {
17
+ // Early exit if not visible or fully faded out
18
+ if (v_visible < 0.5 || v_scale_fade < 0.01) {
19
+ discard;
20
+ }
21
+
22
+ // Calculate distance from pixel to circle center
23
+ vec2 pixelPos = gl_FragCoord.xy;
24
+ float dist = distance(pixelPos, v_circle_center);
25
+
26
+ // Circle radius (includes border)
27
+ float radius = v_quad.z / 2.0;
28
+
29
+ // Border width in pixels (must match vertex shader) - scaled by DPI
30
+ float borderWidth = 4.0 * u_dpi;
31
+
32
+ // Inner circle radius (without border)
33
+ float innerRadius = radius - borderWidth;
34
+
35
+ // Anti-aliased circle
36
+ float edgeSoftness = 1.0 * u_dpi;
37
+ float alpha = 1.0 - smoothstep(radius - edgeSoftness, radius, dist);
38
+
39
+ if (alpha < 0.01) {
40
+ discard;
41
+ }
42
+
43
+ // Calculate position relative to circle center
44
+ vec2 offset = pixelPos - v_circle_center;
45
+
46
+ // Plus dimensions relative to inner circle radius
47
+ // Reduce thickness at low DPI (zoomed out)
48
+ float plusThicknessBase = u_dpi <= 0.5 ? 1.25 : 1.5;
49
+ float plusThickness = plusThicknessBase * u_dpi;
50
+ float plusLength = innerRadius * 0.5; // 50% of inner radius
51
+ float plusSoftness = 0.25 * u_dpi;
52
+
53
+ // Calculate soft plus factor (0 = not plus, 1 = fully plus)
54
+ float horizontalDist = max(abs(offset.y) - plusThickness, 0.0);
55
+ float verticalDist = max(abs(offset.x) - plusThickness, 0.0);
56
+
57
+ float horizontalBarFactor = 0.0;
58
+ if (abs(offset.x) < plusLength) {
59
+ horizontalBarFactor = 1.0 - smoothstep(0.0, plusSoftness, horizontalDist);
60
+ }
61
+
62
+ float verticalBarFactor = 0.0;
63
+ if (abs(offset.y) < plusLength) {
64
+ verticalBarFactor = 1.0 - smoothstep(0.0, plusSoftness, verticalDist);
65
+ }
66
+
67
+ float plusFactor = max(horizontalBarFactor, verticalBarFactor);
68
+
69
+ // Check if pixel is in the border area (outside the inner circle)
70
+ bool isBorder = dist >= innerRadius && dist <= radius;
71
+
72
+ // Determine base fill color
73
+ vec3 fillColor;
74
+ bool isFieldButton = v_rect_id >= 2.0;
75
+ if (isFieldButton) {
76
+ fillColor = v_is_hovered > 0.5 ? u_color_field_hover : u_color_field;
77
+ } else {
78
+ fillColor = v_is_hovered > 0.5 ? u_color_hover : u_color;
79
+ }
80
+
81
+ // Determine final color
82
+ vec3 finalColor;
83
+ if (isBorder) {
84
+ // Soft border transition - blend from fill color to white over 0.5px
85
+ float transitionRange = 0.5 * u_dpi;
86
+ float borderStart = innerRadius;
87
+ float borderEnd = innerRadius + transitionRange;
88
+
89
+ // Calculate blend factor (0 = fill color, 1 = white)
90
+ float blendFactor = smoothstep(borderStart, borderEnd, dist);
91
+
92
+ // Blend between fill color and white
93
+ finalColor = mix(fillColor, vec3(1.0, 1.0, 1.0), blendFactor);
94
+ } else {
95
+ // Circle background
96
+ finalColor = fillColor;
97
+ }
98
+
99
+ // Apply soft plus on top
100
+ if (plusFactor > 0.0) {
101
+ finalColor = mix(finalColor, vec3(1.0, 1.0, 1.0), plusFactor);
102
+ }
103
+
104
+ // Apply scale fade to alpha
105
+ gl_FragColor = vec4(finalColor, alpha);
106
+ }