@blokkli/editor 1.0.3 → 1.1.0
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.
- package/README.md +0 -6
- package/dist/module.json +1 -1
- package/dist/module.mjs +344 -11
- package/dist/runtime/adapter/drupal/graphql/base.graphql +2 -1
- package/dist/runtime/adapter/drupal/graphqlMiddleware.js +4 -1
- package/dist/runtime/adapter/index.d.ts +12 -1
- package/dist/runtime/blokkliPlugins/Sidebar/Detached/index.vue +41 -39
- package/dist/runtime/blokkliPlugins/Sidebar/index.vue +10 -16
- package/dist/runtime/blokkliPlugins/ViewOption/index.vue +2 -0
- package/dist/runtime/components/BlokkliField.vue +76 -18
- package/dist/runtime/components/BlokkliItem.vue +34 -6
- package/dist/runtime/components/BlokkliProvider.vue +18 -1
- package/dist/runtime/components/Edit/BlockProxy/index.vue +102 -0
- package/dist/runtime/components/Edit/DragInteractions/index.vue +49 -25
- package/dist/runtime/components/Edit/DraggableList.vue +139 -29
- package/dist/runtime/components/Edit/EditProvider.vue +4 -0
- package/dist/runtime/components/Edit/Features/AddList/index.vue +3 -0
- package/dist/runtime/components/Edit/Features/Artboard/Overview/index.vue +111 -0
- package/dist/runtime/components/Edit/Features/Artboard/Scrollbar/index.vue +47 -0
- package/dist/runtime/components/Edit/Features/Artboard/index.vue +301 -9
- package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +3 -4
- package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue +27 -0
- package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +24 -3
- package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/fragment.glsl +56 -24
- package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +184 -29
- package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/vertex.glsl +36 -16
- package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +4 -0
- package/dist/runtime/components/Edit/Features/Duplicate/index.vue +1 -13
- package/dist/runtime/components/Edit/Features/EditableMask/index.vue +2 -2
- package/dist/runtime/components/Edit/Features/History/index.vue +1 -1
- package/dist/runtime/components/Edit/Features/Options/Form/Checkbox/index.vue +2 -2
- package/dist/runtime/components/Edit/Features/Options/Form/Checkboxes/index.vue +28 -25
- package/dist/runtime/components/Edit/Features/Options/Form/Color/index.vue +1 -1
- package/dist/runtime/components/Edit/Features/Options/Form/Item.vue +67 -39
- package/dist/runtime/components/Edit/Features/Options/Form/Number/index.vue +6 -2
- package/dist/runtime/components/Edit/Features/Options/Form/Radios/index.vue +1 -1
- package/dist/runtime/components/Edit/Features/Options/Form/Range/index.vue +2 -2
- package/dist/runtime/components/Edit/Features/Options/Form/Text/index.vue +2 -1
- package/dist/runtime/components/Edit/Features/Options/Form/index.vue +84 -33
- package/dist/runtime/components/Edit/Features/ProxyView/index.vue +38 -0
- package/dist/runtime/components/Edit/Features/Publish/index.vue +53 -6
- package/dist/runtime/components/Edit/Features/Search/Overlay/index.vue +3 -13
- package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +1 -1
- package/dist/runtime/components/Edit/Features/Settings/Dialog/index.vue +2 -0
- package/dist/runtime/components/Edit/Features/Structure/List/Field/index.vue +3 -3
- package/dist/runtime/components/Edit/Features/Structure/index.vue +3 -3
- package/dist/runtime/components/Edit/ScrollBoundary/index.vue +24 -0
- package/dist/runtime/components/Edit/index.d.ts +2 -1
- package/dist/runtime/components/Edit/index.js +3 -1
- package/dist/runtime/composables/defineBlokkli.js +10 -5
- package/dist/runtime/constants/index.d.ts +1 -1
- package/dist/runtime/constants/index.js +6 -1
- package/dist/runtime/css/output.css +1 -1
- package/dist/runtime/helpers/animationProvider.js +10 -4
- package/dist/runtime/helpers/domProvider.d.ts +4 -2
- package/dist/runtime/helpers/domProvider.js +42 -19
- package/dist/runtime/helpers/featuresProvider.d.ts +1 -1
- package/dist/runtime/helpers/runtimeHelpers/index.d.ts +6 -0
- package/dist/runtime/helpers/runtimeHelpers/index.js +25 -0
- package/dist/runtime/helpers/selectionProvider.d.ts +2 -1
- package/dist/runtime/helpers/selectionProvider.js +7 -8
- package/dist/runtime/helpers/symbols.d.ts +7 -0
- package/dist/runtime/helpers/symbols.js +7 -0
- package/dist/runtime/helpers/typesProvider.d.ts +1 -1
- package/dist/runtime/helpers/uiProvider.d.ts +1 -0
- package/dist/runtime/helpers/uiProvider.js +16 -3
- package/dist/runtime/helpers/webgl/index.d.ts +6 -1
- package/dist/runtime/helpers/webgl/index.js +38 -5
- package/dist/runtime/icons/eye.svg +1 -0
- package/dist/runtime/types/generatedModuleTypes.d.ts +12 -4
- package/dist/runtime/types/index.d.ts +39 -3
- package/package.json +7 -5
- package/dist/runtime/components/Edit/Features/Artboard/Manager/Artboard.d.ts +0 -204
- package/dist/runtime/components/Edit/Features/Artboard/Manager/Artboard.js +0 -748
- package/dist/runtime/components/Edit/Features/Artboard/Manager/Scrollbar/index.vue +0 -176
- package/dist/runtime/components/Edit/Features/Artboard/Manager/index.vue +0 -317
- package/dist/runtime/helpers/Artboard/index.d.ts +0 -16
- package/dist/runtime/helpers/Artboard/index.js +0 -20
|
@@ -1,14 +1,76 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
:
|
|
5
|
-
|
|
2
|
+
<PluginToolbarButton
|
|
3
|
+
id="artboard_reset_zoom"
|
|
4
|
+
:title="$t('artboardResetZoom', 'Reset zoom')"
|
|
5
|
+
:shortcut-group="$t('artboard', 'Artboard')"
|
|
6
|
+
:tour-text="
|
|
7
|
+
$t(
|
|
8
|
+
'artboardToolbarButtonTourText',
|
|
9
|
+
'Shows the current zoom factor. Click on it to reset the zoom back to 100%.',
|
|
10
|
+
)
|
|
11
|
+
"
|
|
12
|
+
icon="magnifier"
|
|
13
|
+
meta
|
|
14
|
+
key-code="0"
|
|
15
|
+
region="view-options"
|
|
16
|
+
weight="100"
|
|
17
|
+
@click="resetZoom"
|
|
18
|
+
>
|
|
19
|
+
<div class="bk-feature-canvas-button">
|
|
20
|
+
<span>{{ zoomLevel }}</span>
|
|
21
|
+
</div>
|
|
22
|
+
</PluginToolbarButton>
|
|
23
|
+
|
|
24
|
+
<PluginViewOption
|
|
25
|
+
id="artboardOverview"
|
|
26
|
+
v-slot="{ isActive }"
|
|
27
|
+
:label="$t('artboardOverviewToggle', 'Toggle overview')"
|
|
28
|
+
:title-on="$t('artboardOverviewShow', 'Show overview')"
|
|
29
|
+
:title-off="$t('artboardOverviewHide', 'Hide overview')"
|
|
30
|
+
:tour-text="
|
|
31
|
+
$t(
|
|
32
|
+
'artboardOverviewTourText',
|
|
33
|
+
`Displays a top level overview of your content.`,
|
|
34
|
+
)
|
|
35
|
+
"
|
|
36
|
+
icon="eye"
|
|
37
|
+
key-code="O"
|
|
38
|
+
weight="90"
|
|
39
|
+
>
|
|
40
|
+
<Teleport v-if="isActive" to="body">
|
|
41
|
+
<Overview :artboard="artboard" />
|
|
42
|
+
</Teleport>
|
|
43
|
+
</PluginViewOption>
|
|
44
|
+
|
|
45
|
+
<Scrollbar :artboard="artboard" orientation="y" />
|
|
6
46
|
</template>
|
|
7
47
|
|
|
8
48
|
<script lang="ts" setup>
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
49
|
+
import {
|
|
50
|
+
watch,
|
|
51
|
+
computed,
|
|
52
|
+
useBlokkli,
|
|
53
|
+
onMounted,
|
|
54
|
+
onBeforeUnmount,
|
|
55
|
+
defineBlokkliFeature,
|
|
56
|
+
} from '#imports'
|
|
57
|
+
import type { Coord } from '#blokkli/types'
|
|
58
|
+
import { PluginToolbarButton, PluginViewOption } from '#blokkli/plugins'
|
|
59
|
+
import Overview from './Overview/index.vue'
|
|
60
|
+
import Scrollbar from './Scrollbar/index.vue'
|
|
61
|
+
import onBlokkliEvent from '#blokkli/helpers/composables/onBlokkliEvent'
|
|
62
|
+
import defineShortcut from '#blokkli/helpers/composables/defineShortcut'
|
|
63
|
+
import {
|
|
64
|
+
createArtboard,
|
|
65
|
+
type ArtboardOptions,
|
|
66
|
+
type Artboard,
|
|
67
|
+
type PluginWheelOptions,
|
|
68
|
+
touch,
|
|
69
|
+
wheel,
|
|
70
|
+
mouse,
|
|
71
|
+
dom as domPlugin,
|
|
72
|
+
type PluginWheel,
|
|
73
|
+
} from 'artboard-deluxe'
|
|
12
74
|
const { settings } = defineBlokkliFeature({
|
|
13
75
|
id: 'artboard',
|
|
14
76
|
label: 'Artboard',
|
|
@@ -20,14 +82,21 @@ const { settings } = defineBlokkliFeature({
|
|
|
20
82
|
type: 'checkbox',
|
|
21
83
|
default: true,
|
|
22
84
|
label: 'Persist position and zoom',
|
|
23
|
-
group: '
|
|
85
|
+
group: 'artboard',
|
|
86
|
+
viewports: ['desktop'],
|
|
87
|
+
},
|
|
88
|
+
momentum: {
|
|
89
|
+
type: 'checkbox',
|
|
90
|
+
default: true,
|
|
91
|
+
label: 'Use smooth scrolling',
|
|
92
|
+
group: 'artboard',
|
|
24
93
|
viewports: ['desktop'],
|
|
25
94
|
},
|
|
26
95
|
scrollSpeed: {
|
|
27
96
|
type: 'slider',
|
|
28
97
|
default: 1,
|
|
29
98
|
label: 'Artboard scroll speed',
|
|
30
|
-
group: '
|
|
99
|
+
group: 'artboard',
|
|
31
100
|
viewports: ['desktop'],
|
|
32
101
|
min: 0.5,
|
|
33
102
|
max: 1.5,
|
|
@@ -36,6 +105,229 @@ const { settings } = defineBlokkliFeature({
|
|
|
36
105
|
},
|
|
37
106
|
screenshot: 'feature-artboard.jpg',
|
|
38
107
|
})
|
|
108
|
+
|
|
109
|
+
const { context, storage, ui, animation, $t, dom } = useBlokkli()
|
|
110
|
+
|
|
111
|
+
const zoomLevel = computed(() => Math.round(ui.artboardScale.value * 100) + '%')
|
|
112
|
+
|
|
113
|
+
const PADDING = 50
|
|
114
|
+
|
|
115
|
+
const options = computed<ArtboardOptions>(() => {
|
|
116
|
+
return {
|
|
117
|
+
maxScale: ui.isMobile.value ? 1 : 3,
|
|
118
|
+
direction: ui.isMobile.value ? 'vertical' : 'both',
|
|
119
|
+
minScale: 0.1,
|
|
120
|
+
overscrollBounds: {
|
|
121
|
+
top: ui.visibleViewport.value.y + PADDING,
|
|
122
|
+
left: ui.visibleViewport.value.x + PADDING,
|
|
123
|
+
right:
|
|
124
|
+
ui.viewport.value.width -
|
|
125
|
+
ui.visibleViewport.value.width -
|
|
126
|
+
ui.visibleViewport.value.x +
|
|
127
|
+
PADDING,
|
|
128
|
+
bottom: PADDING,
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
watch(options, function (newOptions) {
|
|
134
|
+
artboard.setOptions(newOptions)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
type SavedState = {
|
|
138
|
+
offset: Coord
|
|
139
|
+
scale: number
|
|
140
|
+
}
|
|
141
|
+
const storageKey = computed(() => 'artboard:' + context.value.entityUuid)
|
|
142
|
+
const savedState = storage.use<SavedState | null>(storageKey, null)
|
|
143
|
+
|
|
144
|
+
const saveState = () => {
|
|
145
|
+
if (!settings.value.persist) {
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
savedState.value = {
|
|
149
|
+
offset: artboard.getOffset(),
|
|
150
|
+
scale: artboard.getScale(),
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let pluginWheel: PluginWheel | null = null
|
|
155
|
+
|
|
156
|
+
const wheelOptions = computed<PluginWheelOptions>(() => {
|
|
157
|
+
return {
|
|
158
|
+
useMomentumZoom: settings.value.momentum,
|
|
159
|
+
useMomentumScroll: settings.value.momentum,
|
|
160
|
+
interceptWheel: true,
|
|
161
|
+
scrollSpeed: settings.value.scrollSpeed,
|
|
162
|
+
wheelZoomFactor: settings.value.scrollSpeed,
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
watch(wheelOptions, function (newOptions) {
|
|
167
|
+
if (pluginWheel) {
|
|
168
|
+
pluginWheel.options.setAll(newOptions)
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
function getArtboard(): Artboard {
|
|
173
|
+
pluginWheel = wheel(wheelOptions.value)
|
|
174
|
+
return createArtboard(
|
|
175
|
+
ui.rootElement(),
|
|
176
|
+
[
|
|
177
|
+
mouse(),
|
|
178
|
+
touch(),
|
|
179
|
+
pluginWheel,
|
|
180
|
+
domPlugin({
|
|
181
|
+
element: ui.artboardElement(),
|
|
182
|
+
setInitTransformFromRect: !savedState.value || !settings.value.persist,
|
|
183
|
+
precision: 0.1,
|
|
184
|
+
restoreStyles: true,
|
|
185
|
+
}),
|
|
186
|
+
],
|
|
187
|
+
{
|
|
188
|
+
initTransform:
|
|
189
|
+
savedState.value && settings.value.persist
|
|
190
|
+
? {
|
|
191
|
+
x: savedState.value.offset.x,
|
|
192
|
+
y: savedState.value.offset.y,
|
|
193
|
+
scale: savedState.value?.scale || 1,
|
|
194
|
+
}
|
|
195
|
+
: undefined,
|
|
196
|
+
...options.value,
|
|
197
|
+
},
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const artboard = getArtboard()
|
|
202
|
+
|
|
203
|
+
watch(options, function (newOptions) {
|
|
204
|
+
artboard.setOptions(newOptions)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
onBlokkliEvent('animationFrame:before', (time) => {
|
|
208
|
+
artboard.loop(time)
|
|
209
|
+
const artboardSize = artboard.getArtboardSize()
|
|
210
|
+
if (artboardSize) {
|
|
211
|
+
ui.artboardSize.value.height = artboardSize.height
|
|
212
|
+
ui.artboardSize.value.width = artboardSize.width
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const offset = artboard.getOffset()
|
|
216
|
+
|
|
217
|
+
// We don't need much precision here, so we can round it.
|
|
218
|
+
// This also prevents updating rects in WebGL buffers for small changes.
|
|
219
|
+
ui.artboardOffset.value.x = Math.ceil(offset.x)
|
|
220
|
+
ui.artboardOffset.value.y = Math.ceil(offset.y)
|
|
221
|
+
ui.artboardScale.value = artboard.getScale()
|
|
222
|
+
animation.requestDraw()
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
onMounted(() => {
|
|
226
|
+
window.addEventListener('beforeunload', saveState)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
onBeforeUnmount(() => {
|
|
230
|
+
saveState()
|
|
231
|
+
artboard.destroy()
|
|
232
|
+
window.removeEventListener('beforeunload', saveState)
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
const resetZoom = () => {
|
|
236
|
+
artboard.resetZoom({
|
|
237
|
+
duration: 500,
|
|
238
|
+
})
|
|
239
|
+
animation.requestDraw()
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
onBlokkliEvent('keyPressed', (e) => {
|
|
243
|
+
if (e.code === 'Home') {
|
|
244
|
+
e.originalEvent.preventDefault()
|
|
245
|
+
artboard.scrollToTop()
|
|
246
|
+
animation.requestDraw()
|
|
247
|
+
} else if (e.code === 'End') {
|
|
248
|
+
e.originalEvent.preventDefault()
|
|
249
|
+
artboard.scrollToEnd()
|
|
250
|
+
animation.requestDraw()
|
|
251
|
+
} else if (e.code === 'PageUp') {
|
|
252
|
+
e.originalEvent.preventDefault()
|
|
253
|
+
artboard.scrollPageUp()
|
|
254
|
+
animation.requestDraw()
|
|
255
|
+
} else if (e.code === 'PageDown') {
|
|
256
|
+
e.originalEvent.preventDefault()
|
|
257
|
+
artboard.scrollPageDown()
|
|
258
|
+
animation.requestDraw()
|
|
259
|
+
} else if (e.code === 'ArrowUp') {
|
|
260
|
+
e.originalEvent.preventDefault()
|
|
261
|
+
artboard.scrollUp()
|
|
262
|
+
animation.requestDraw()
|
|
263
|
+
} else if (e.code === 'ArrowDown') {
|
|
264
|
+
e.originalEvent.preventDefault()
|
|
265
|
+
artboard.scrollDown()
|
|
266
|
+
animation.requestDraw()
|
|
267
|
+
} else if (e.code === '0' && e.meta) {
|
|
268
|
+
e.originalEvent.preventDefault()
|
|
269
|
+
resetZoom()
|
|
270
|
+
} else if (e.code === '1' && e.meta) {
|
|
271
|
+
e.originalEvent.preventDefault()
|
|
272
|
+
artboard.scaleToFit()
|
|
273
|
+
animation.requestDraw()
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
defineShortcut(
|
|
278
|
+
[
|
|
279
|
+
{
|
|
280
|
+
code: 'Home',
|
|
281
|
+
label: $t('artboardScrollToTop', 'Scroll to top'),
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
code: 'End',
|
|
285
|
+
label: $t('artboardScrollToEnd', 'Scroll to end'),
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
code: 'PageUp',
|
|
289
|
+
label: $t('artboardScrollOnePageUp', 'Scroll one page up'),
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
code: 'PageDown',
|
|
293
|
+
label: $t('artboardScrollOnePageDown', 'Scroll one page down'),
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
code: 'ArrowUp',
|
|
297
|
+
label: $t('artboardScrollUp', 'Scroll up'),
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
code: 'ArrowDown',
|
|
301
|
+
label: $t('artboardScrollDown', 'Scroll down'),
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
code: '1',
|
|
305
|
+
label: $t('artboardScaleToFit', 'Scale to fit'),
|
|
306
|
+
meta: true,
|
|
307
|
+
},
|
|
308
|
+
].map((v) => {
|
|
309
|
+
return { ...v, group: $t('artboard', 'Artboard') }
|
|
310
|
+
}),
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
onBlokkliEvent('scrollIntoView', (e) => {
|
|
314
|
+
const rect = dom.getBlockRect(e.uuid)
|
|
315
|
+
if (!rect) {
|
|
316
|
+
return
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (dom.isBlockVisible(e.uuid)) {
|
|
320
|
+
return
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// @TODO: Prevent scrolling into view when already
|
|
324
|
+
|
|
325
|
+
artboard.scrollIntoView(rect, {
|
|
326
|
+
scale: 'none',
|
|
327
|
+
axis: 'y',
|
|
328
|
+
behavior: e.immediate ? 'instant' : 'auto',
|
|
329
|
+
})
|
|
330
|
+
})
|
|
39
331
|
</script>
|
|
40
332
|
|
|
41
333
|
<script lang="ts">
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<ScrollBoundary
|
|
3
3
|
class="bk-command-palette bk-control"
|
|
4
|
-
@wheel.passive.stop
|
|
5
4
|
@keydown.stop="onKeyDown"
|
|
6
5
|
@keyup.stop
|
|
7
6
|
@click.stop
|
|
@@ -30,7 +29,7 @@
|
|
|
30
29
|
@select="onSelect($event)"
|
|
31
30
|
/>
|
|
32
31
|
</div>
|
|
33
|
-
</
|
|
32
|
+
</ScrollBoundary>
|
|
34
33
|
</template>
|
|
35
34
|
|
|
36
35
|
<script lang="ts" setup>
|
|
@@ -43,7 +42,7 @@ import {
|
|
|
43
42
|
nextTick,
|
|
44
43
|
onBeforeUnmount,
|
|
45
44
|
} from '#imports'
|
|
46
|
-
import { Icon } from '#blokkli/components'
|
|
45
|
+
import { Icon, ScrollBoundary } from '#blokkli/components'
|
|
47
46
|
import type { Command, CommandGroup } from '#blokkli/types'
|
|
48
47
|
import Group from './Group/index.vue'
|
|
49
48
|
import { falsy } from '#blokkli/helpers'
|
|
@@ -32,6 +32,7 @@ onBlokkliEvent('canvas:draw', (e) => {
|
|
|
32
32
|
return
|
|
33
33
|
}
|
|
34
34
|
ctx.clearRect(0, 0, ui.viewport.value.width, ui.viewport.value.height)
|
|
35
|
+
ctx.strokeStyle = 'blue'
|
|
35
36
|
const blockRects = dom.getBlockRects()
|
|
36
37
|
const viewport = ui.visibleViewport.value
|
|
37
38
|
|
|
@@ -47,6 +48,32 @@ onBlokkliEvent('canvas:draw', (e) => {
|
|
|
47
48
|
height: rect.height * e.artboardScale,
|
|
48
49
|
}
|
|
49
50
|
if (intersects(drawnRect, viewport)) {
|
|
51
|
+
ctx.beginPath()
|
|
52
|
+
ctx.rect(drawnRect.x, drawnRect.y, drawnRect.width, drawnRect.height)
|
|
53
|
+
ctx.stroke()
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
ctx.strokeStyle = 'red'
|
|
58
|
+
|
|
59
|
+
const visibleFieldRects = dom.getVisibleFields()
|
|
60
|
+
for (let i = 0; i < visibleFieldRects.length; i++) {
|
|
61
|
+
const key = visibleFieldRects[i]
|
|
62
|
+
|
|
63
|
+
const rect = dom.getFieldRect(key)
|
|
64
|
+
|
|
65
|
+
if (!rect) {
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const drawnRect = {
|
|
70
|
+
x: rect.x * e.artboardScale + e.artboardOffset.x,
|
|
71
|
+
y: rect.y * e.artboardScale + e.artboardOffset.y,
|
|
72
|
+
width: rect.width * e.artboardScale,
|
|
73
|
+
height: rect.height * e.artboardScale,
|
|
74
|
+
}
|
|
75
|
+
if (intersects(drawnRect, viewport)) {
|
|
76
|
+
ctx.beginPath()
|
|
50
77
|
ctx.rect(drawnRect.x, drawnRect.y, drawnRect.width, drawnRect.height)
|
|
51
78
|
ctx.stroke()
|
|
52
79
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
:style="{ backgroundColor: activeColor }"
|
|
12
12
|
>
|
|
13
13
|
<Icon name="cursor-move" />
|
|
14
|
-
<p v-html="
|
|
14
|
+
<p v-html="prevActiveLabel" />
|
|
15
15
|
</div>
|
|
16
16
|
</Transition>
|
|
17
17
|
<div
|
|
@@ -52,7 +52,14 @@
|
|
|
52
52
|
</template>
|
|
53
53
|
|
|
54
54
|
<script setup lang="ts">
|
|
55
|
-
import {
|
|
55
|
+
import {
|
|
56
|
+
ref,
|
|
57
|
+
watch,
|
|
58
|
+
computed,
|
|
59
|
+
useBlokkli,
|
|
60
|
+
onMounted,
|
|
61
|
+
onBeforeUnmount,
|
|
62
|
+
} from '#imports'
|
|
56
63
|
import type { Coord, DraggableItem, Rectangle } from '#blokkli/types'
|
|
57
64
|
import {
|
|
58
65
|
isInsideRect,
|
|
@@ -93,6 +100,17 @@ const props = defineProps<{
|
|
|
93
100
|
activeLabel?: string
|
|
94
101
|
}>()
|
|
95
102
|
|
|
103
|
+
const prevActiveLabel = ref('')
|
|
104
|
+
|
|
105
|
+
watch(
|
|
106
|
+
() => props.activeLabel,
|
|
107
|
+
function (label) {
|
|
108
|
+
if (label) {
|
|
109
|
+
prevActiveLabel.value = label
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
)
|
|
113
|
+
|
|
96
114
|
const width = ref(10)
|
|
97
115
|
const height = ref(10)
|
|
98
116
|
|
|
@@ -122,7 +140,10 @@ const style = computed(() => {
|
|
|
122
140
|
width: width.value + 'px',
|
|
123
141
|
height: height.value + 'px',
|
|
124
142
|
transform: `translate(${translateX.value}px, ${translateY.value}px)`,
|
|
125
|
-
'--bk-active-color':
|
|
143
|
+
'--bk-active-color':
|
|
144
|
+
props.activeColor && props.activeLabel
|
|
145
|
+
? props.activeColor
|
|
146
|
+
: 'rgba(255,255,255,0)',
|
|
126
147
|
}
|
|
127
148
|
})
|
|
128
149
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
precision mediump float;
|
|
2
2
|
|
|
3
3
|
varying float v_intersecting;
|
|
4
|
+
varying float v_is_hover_area;
|
|
4
5
|
varying vec4 v_quad;
|
|
5
|
-
varying vec3
|
|
6
|
-
varying vec3 v_color_active;
|
|
6
|
+
varying vec3 v_color;
|
|
7
7
|
|
|
8
8
|
uniform float u_scale;
|
|
9
9
|
uniform float u_dpi;
|
|
@@ -14,10 +14,16 @@ float roundedBoxSDF(vec2 CenterPosition, vec2 Size, float Radius) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
void main() {
|
|
17
|
-
|
|
17
|
+
bool isHoverArea = v_is_hover_area >= 1.0;
|
|
18
|
+
float stroke = isHoverArea ? 0.75 : 2.0;
|
|
19
|
+
float radiusBase = stroke * u_scale;
|
|
20
|
+
|
|
18
21
|
float thickness = max(min(1.0 * u_scale, 3.0), 0.5);
|
|
19
|
-
float inset = max(min(2.0 * u_scale, 1.0), 2.0) * thickness;
|
|
20
22
|
|
|
23
|
+
// Calculate the resulting inset so that we draw the rounded box and border *inside* the quad (vs. that it would bleed outside the quad).
|
|
24
|
+
float inset = max(min(2.0 * u_scale, 1.0), 3.0) * thickness + stroke;
|
|
25
|
+
|
|
26
|
+
// Rectangle dimensions with inset.
|
|
21
27
|
float u_rect_x = v_quad.x + inset;
|
|
22
28
|
float u_rect_y = v_quad.y + inset;
|
|
23
29
|
float u_rectWidth = v_quad.z - 2.0 * inset;
|
|
@@ -25,34 +31,60 @@ void main() {
|
|
|
25
31
|
|
|
26
32
|
vec2 size = vec2(u_rectWidth, u_rectHeight);
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
vec2
|
|
34
|
+
// Center position of the rectangle.
|
|
35
|
+
vec2 offsetPosition = vec2(u_rect_x + size.x / 2.0, u_rect_y + size.y / 2.0);
|
|
36
|
+
vec2 location = offsetPosition;
|
|
37
|
+
|
|
38
|
+
// Make sure the edges of the border are not too harsh.
|
|
39
|
+
float edgeSoftness = 0.5 * u_dpi;
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
float borderWidth = stroke * u_scale * u_dpi;
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
float
|
|
36
|
-
min(
|
|
43
|
+
// Different radius for inner and outer.
|
|
44
|
+
float radiusOutside =
|
|
45
|
+
min(radiusBase * u_dpi, min(size.x, size.y)) + thickness;
|
|
46
|
+
float radiusInside = radiusOutside - borderWidth;
|
|
37
47
|
|
|
38
|
-
|
|
48
|
+
vec2 sizeInner = size - 2.0 * borderWidth;
|
|
49
|
+
|
|
50
|
+
// Compute different distance for inside and outside.
|
|
51
|
+
float distanceOuter = roundedBoxSDF(
|
|
39
52
|
location - gl_FragCoord.xy,
|
|
40
53
|
size / 2.0,
|
|
41
|
-
|
|
54
|
+
radiusOutside
|
|
55
|
+
);
|
|
56
|
+
float distanceInner = roundedBoxSDF(
|
|
57
|
+
location - gl_FragCoord.xy,
|
|
58
|
+
sizeInner / 2.0,
|
|
59
|
+
radiusInside
|
|
42
60
|
);
|
|
43
61
|
|
|
44
|
-
|
|
62
|
+
float alphaOuter =
|
|
63
|
+
1.0 - smoothstep(-edgeSoftness, edgeSoftness, distanceOuter - thickness);
|
|
64
|
+
float alphaInner =
|
|
65
|
+
1.0 - smoothstep(-edgeSoftness, edgeSoftness, distanceInner - thickness);
|
|
45
66
|
|
|
46
|
-
|
|
47
|
-
float
|
|
67
|
+
// Alpha value for the border.
|
|
68
|
+
float alphaBorder = clamp(alphaOuter - alphaInner, 0.0, 1.0);
|
|
48
69
|
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
// Adjust alphas based on intersection.
|
|
71
|
+
float adjustedAlphaFill =
|
|
72
|
+
v_intersecting >= 0.5
|
|
73
|
+
? alphaInner * 0.95
|
|
74
|
+
: alphaInner * 0.2;
|
|
51
75
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
76
|
+
if (v_is_hover_area >= 1.0) {
|
|
77
|
+
adjustedAlphaFill *= 0.12;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (alphaBorder > 0.0) {
|
|
81
|
+
float a = isHoverArea ? 0.6 : 1.0;
|
|
82
|
+
gl_FragColor = vec4(v_color, a);
|
|
83
|
+
return;
|
|
84
|
+
} else if (adjustedAlphaFill > 0.0) {
|
|
85
|
+
gl_FragColor = vec4(v_color, adjustedAlphaFill);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
discard;
|
|
58
90
|
}
|