@blokkli/editor 1.1.3 → 1.3.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/dist/module.json +1 -1
- package/dist/module.mjs +1693 -41
- package/dist/runtime/adapter/drupal/graphql/base.graphql +40 -3
- package/dist/runtime/adapter/drupal/graphql/comments.graphql +6 -1
- package/dist/runtime/adapter/drupal/graphql/transform.graphql +10 -2
- package/dist/runtime/adapter/drupal/graphqlMiddleware.js +44 -18
- package/dist/runtime/adapter/index.d.ts +15 -2
- package/dist/runtime/blokkliPlugins/Sidebar/index.vue +4 -1
- package/dist/runtime/components/BlokkliField.vue +8 -2
- package/dist/runtime/components/Edit/Actions/index.vue +27 -6
- package/dist/runtime/components/Edit/AnimationCanvas/index.vue +1 -0
- package/dist/runtime/components/Edit/DragInteractions/index.vue +7 -0
- package/dist/runtime/components/Edit/EditProvider.vue +23 -5
- package/dist/runtime/components/Edit/Features/Artboard/index.vue +4 -0
- package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +1 -0
- package/dist/runtime/components/Edit/Features/Clipboard/index.vue +3 -1
- package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +14 -2
- package/dist/runtime/components/Edit/Features/Debug/index.vue +26 -4
- package/dist/runtime/components/Edit/Features/Diff/DiffView/index.vue +236 -0
- package/dist/runtime/components/Edit/Features/Diff/index.vue +37 -0
- package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +14 -4
- package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +3 -0
- package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +20 -6
- package/dist/runtime/components/Edit/Features/EditForm/Frame/index.vue +8 -1
- package/dist/runtime/components/Edit/Features/EditableField/index.vue +11 -5
- package/dist/runtime/components/Edit/Features/EntityTitle/index.vue +1 -0
- package/dist/runtime/components/Edit/Features/History/index.vue +3 -1
- package/dist/runtime/components/Edit/Features/ImportExisting/index.vue +5 -2
- package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue +10 -3
- package/dist/runtime/components/Edit/Features/MediaLibrary/Library/Item.vue +46 -0
- package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +66 -34
- package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +4 -1
- package/dist/runtime/components/Edit/Features/Options/Form/index.vue +14 -1
- package/dist/runtime/components/Edit/Features/Preview/index.vue +2 -1
- package/dist/runtime/components/Edit/Features/PreviewGrant/index.vue +2 -1
- package/dist/runtime/components/Edit/Features/Publish/index.vue +2 -0
- package/dist/runtime/components/Edit/Features/ResponsivePreview/index.vue +2 -1
- package/dist/runtime/components/Edit/Features/Selection/Overlay/fragment.glsl +78 -44
- package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +8 -8
- package/dist/runtime/components/Edit/Features/Selection/Overlay/vertex.glsl +6 -1
- package/dist/runtime/components/Edit/Features/Settings/Dialog/FeatureSetting/index.vue +23 -2
- package/dist/runtime/components/Edit/Features/Settings/Dialog/index.vue +71 -38
- package/dist/runtime/components/Edit/Features/Settings/index.vue +4 -0
- package/dist/runtime/components/Edit/Features/Transform/index.vue +5 -1
- package/dist/runtime/components/Edit/Features/Translations/index.vue +24 -2
- package/dist/runtime/components/Edit/Features/index.vue +4 -0
- package/dist/runtime/components/Edit/InfoBox/index.vue +14 -0
- package/dist/runtime/components/Edit/Messages/index.vue +10 -12
- package/dist/runtime/components/Edit/PreviewProvider.vue +9 -2
- package/dist/runtime/components/Edit/Sortli/index.vue +6 -1
- package/dist/runtime/components/Edit/index.d.ts +2 -1
- package/dist/runtime/components/Edit/index.js +3 -1
- package/dist/runtime/constants/index.d.ts +1 -1
- package/dist/runtime/constants/index.js +1 -0
- package/dist/runtime/css/output.css +1 -1
- package/dist/runtime/helpers/animationProvider.js +2 -1
- package/dist/runtime/helpers/featuresProvider.d.ts +7 -14
- package/dist/runtime/helpers/featuresProvider.js +29 -1
- package/dist/runtime/helpers/stateProvider.d.ts +1 -0
- package/dist/runtime/helpers/stateProvider.js +23 -4
- package/dist/runtime/helpers/uiProvider.d.ts +5 -1
- package/dist/runtime/helpers/uiProvider.js +10 -2
- package/dist/runtime/icons/diff.svg +1 -0
- package/dist/runtime/icons/info.svg +1 -0
- package/dist/runtime/types/generatedModuleTypes.d.ts +4 -4
- package/dist/runtime/types/index.d.ts +59 -1
- package/package.json +2 -1
|
@@ -50,30 +50,24 @@
|
|
|
50
50
|
class="bk-media-library-items bk-scrollbar-light"
|
|
51
51
|
:class="[{ 'bk-is-sortli': isSortli }, 'bk-is-' + listView]"
|
|
52
52
|
>
|
|
53
|
-
<
|
|
54
|
-
<
|
|
53
|
+
<Sortli v-if="isSortli" no-transition :get-drag-items="getDragItems">
|
|
54
|
+
<Item
|
|
55
55
|
v-for="item in items"
|
|
56
56
|
:key="item.mediaId"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<div class="bk-media-library-items-item-text">
|
|
72
|
-
<h3>{{ item.label }}</h3>
|
|
73
|
-
<p>{{ item.context }}</p>
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
</Component>
|
|
57
|
+
v-bind="item"
|
|
58
|
+
v-model="selected"
|
|
59
|
+
/>
|
|
60
|
+
</Sortli>
|
|
61
|
+
|
|
62
|
+
<div v-else>
|
|
63
|
+
<Item v-for="item in items" :key="item.mediaId" v-bind="item" />
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div v-if="selected.length" class="bk-media-library-cancel">
|
|
68
|
+
<button class="bk-button bk-is-primary" @click.prevent="selected = []">
|
|
69
|
+
{{ $t('cancelSelection', 'Cancel selection') }}
|
|
70
|
+
</button>
|
|
77
71
|
</div>
|
|
78
72
|
|
|
79
73
|
<div class="bk-pagination">
|
|
@@ -100,20 +94,60 @@ import {
|
|
|
100
94
|
import { Sortli, Icon } from '#blokkli/components'
|
|
101
95
|
import type { MediaLibraryFilter, MediaLibraryGetResults } from './../types'
|
|
102
96
|
import type { BlokkliIcon } from '#blokkli/icons'
|
|
97
|
+
import Item from './Item.vue'
|
|
98
|
+
import type { DraggableItem, DraggableMediaLibraryItem } from '#blokkli/types'
|
|
99
|
+
import { buildDraggableItem, falsy } from '#blokkli/helpers'
|
|
100
|
+
import onBlokkliEvent from '#blokkli/helpers/composables/onBlokkliEvent'
|
|
103
101
|
|
|
104
|
-
|
|
102
|
+
defineProps<{
|
|
105
103
|
isSortli?: boolean
|
|
106
104
|
modelValue?: string
|
|
107
105
|
}>()
|
|
108
106
|
|
|
109
|
-
const
|
|
107
|
+
const { adapter, storage, $t } = useBlokkli()
|
|
108
|
+
|
|
109
|
+
const selected = ref<string[]>([])
|
|
110
|
+
const listEl = ref<HTMLDivElement | null>(null)
|
|
111
|
+
const page = ref(0)
|
|
112
|
+
const key = computed(() => Object.values(filterValues.value).join(','))
|
|
113
|
+
|
|
114
|
+
function getDragItems(activeItem?: DraggableItem): DraggableItem[] | null {
|
|
115
|
+
if (!selected.value.length || !listEl.value) {
|
|
116
|
+
return null
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const activeId =
|
|
120
|
+
activeItem?.itemType === 'media_library' ? activeItem.mediaId : null
|
|
121
|
+
|
|
122
|
+
const items: DraggableMediaLibraryItem[] = selected.value
|
|
123
|
+
.map((id) => {
|
|
124
|
+
const el = listEl.value?.querySelector(
|
|
125
|
+
`[data-sortli-id="media_library_${id}"]`,
|
|
126
|
+
)
|
|
127
|
+
if (!(el instanceof HTMLElement)) {
|
|
128
|
+
return null
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const item = buildDraggableItem(el)
|
|
132
|
+
if (item?.itemType === 'media_library') {
|
|
133
|
+
return item
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return null
|
|
137
|
+
})
|
|
138
|
+
.filter(falsy)
|
|
139
|
+
|
|
140
|
+
if (!activeId) {
|
|
141
|
+
return items
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const activeIsInSelection = items.find((v) => v.mediaId === activeId)
|
|
110
145
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return
|
|
146
|
+
if (activeIsInSelection) {
|
|
147
|
+
return items
|
|
114
148
|
}
|
|
115
149
|
|
|
116
|
-
|
|
150
|
+
return null
|
|
117
151
|
}
|
|
118
152
|
|
|
119
153
|
type RenderedFilter = {
|
|
@@ -121,8 +155,6 @@ type RenderedFilter = {
|
|
|
121
155
|
filter: MediaLibraryFilter
|
|
122
156
|
}
|
|
123
157
|
|
|
124
|
-
const { adapter, storage } = useBlokkli()
|
|
125
|
-
|
|
126
158
|
const listView = storage.use<'horizontal' | 'grid'>(
|
|
127
159
|
'mediaLibraryListView',
|
|
128
160
|
'grid',
|
|
@@ -142,10 +174,6 @@ const toggleListView = () => {
|
|
|
142
174
|
|
|
143
175
|
const filterValues = ref<Record<string, any>>({})
|
|
144
176
|
|
|
145
|
-
const listEl = ref<HTMLDivElement | null>(null)
|
|
146
|
-
const page = ref(0)
|
|
147
|
-
const key = computed(() => Object.values(filterValues.value).join(','))
|
|
148
|
-
|
|
149
177
|
watch(key, () => {
|
|
150
178
|
page.value = 0
|
|
151
179
|
})
|
|
@@ -182,4 +210,8 @@ const perPage = computed(() => data.value?.perPage || 0)
|
|
|
182
210
|
const totalPages = computed(() => {
|
|
183
211
|
return Math.ceil(total.value / perPage.value)
|
|
184
212
|
})
|
|
213
|
+
|
|
214
|
+
onBlokkliEvent('item:dropped', function () {
|
|
215
|
+
selected.value = []
|
|
216
|
+
})
|
|
185
217
|
</script>
|
|
@@ -29,7 +29,10 @@ const gl = animation.gl()
|
|
|
29
29
|
|
|
30
30
|
const enabled = computed(
|
|
31
31
|
() =>
|
|
32
|
-
!selection.editableActive.value &&
|
|
32
|
+
!selection.editableActive.value &&
|
|
33
|
+
(state.editMode.value === 'editing' ||
|
|
34
|
+
state.editMode.value === 'translating') &&
|
|
35
|
+
gl,
|
|
33
36
|
)
|
|
34
37
|
|
|
35
38
|
const shouldRender = ref(false)
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
v-if="availableOptions.length"
|
|
4
4
|
class="bk-blokkli-item-options"
|
|
5
5
|
@pointerup="onPointerUp"
|
|
6
|
-
@mouseleave="
|
|
6
|
+
@mouseleave="onMouseLeave"
|
|
7
|
+
@mouseenter="onMouseEnter"
|
|
7
8
|
>
|
|
8
9
|
<OptionsFormItem
|
|
9
10
|
v-for="plugin in singleVisibleOptions"
|
|
@@ -102,6 +103,18 @@ const props = defineProps<{
|
|
|
102
103
|
}>()
|
|
103
104
|
|
|
104
105
|
let pointerTimeout: null | number = null
|
|
106
|
+
let mouseLeaveTimeout: null | number = null
|
|
107
|
+
|
|
108
|
+
function onMouseLeave() {
|
|
109
|
+
onMouseEnter()
|
|
110
|
+
mouseLeaveTimeout = window.setTimeout(stopChangingOptions, 500)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function onMouseEnter() {
|
|
114
|
+
if (mouseLeaveTimeout) {
|
|
115
|
+
window.clearTimeout(mouseLeaveTimeout)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
105
118
|
|
|
106
119
|
function onPointerUp(e: PointerEvent) {
|
|
107
120
|
if (pointerTimeout) {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
:title="$t('previewNewWindow', 'Preview (new window)')"
|
|
5
5
|
region="after-menu"
|
|
6
6
|
icon="open_in_new"
|
|
7
|
+
:disabled="!state.canEdit.value"
|
|
7
8
|
:tour-text="
|
|
8
9
|
$t(
|
|
9
10
|
'previewNewWindowTourText',
|
|
@@ -25,7 +26,7 @@ defineBlokkliFeature({
|
|
|
25
26
|
description: 'Provides a button to open a preview in a new window.',
|
|
26
27
|
})
|
|
27
28
|
|
|
28
|
-
const { $t } = useBlokkli()
|
|
29
|
+
const { $t, state } = useBlokkli()
|
|
29
30
|
|
|
30
31
|
const route = useRoute()
|
|
31
32
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
v-if="!ui.isMobile.value"
|
|
4
4
|
id="preview_with_smartphone"
|
|
5
5
|
:title="$t('previewWithSmartphone', 'Preview (with smartphone)')"
|
|
6
|
+
:disabled="!state.canEdit.value"
|
|
6
7
|
:tour-text="
|
|
7
8
|
$t(
|
|
8
9
|
'previewWithSmartphoneTourText',
|
|
@@ -54,7 +55,7 @@ const { adapter } = defineBlokkliFeature({
|
|
|
54
55
|
viewports: ['desktop'],
|
|
55
56
|
})
|
|
56
57
|
|
|
57
|
-
const { $t, ui } = useBlokkli()
|
|
58
|
+
const { $t, ui, state } = useBlokkli()
|
|
58
59
|
|
|
59
60
|
const qrCodeVisible = ref(false)
|
|
60
61
|
const previewGrantUrl = ref<string | undefined | null>('')
|
|
@@ -27,6 +27,8 @@ const { adapter, settings } = defineBlokkliFeature({
|
|
|
27
27
|
closeAfterPublish: {
|
|
28
28
|
type: 'checkbox',
|
|
29
29
|
label: 'Close editor after publishing',
|
|
30
|
+
description:
|
|
31
|
+
'Immediately closes the editor after successfully publishing or saving.',
|
|
30
32
|
default: true,
|
|
31
33
|
group: 'behavior',
|
|
32
34
|
},
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
v-slot="{ width, height, isDetached }"
|
|
5
5
|
:title="$t('responsivePreviewTitle', 'Responsive Preview')"
|
|
6
6
|
:tour-text="tourText"
|
|
7
|
+
:disabled="!state.canEdit.value"
|
|
7
8
|
:min-width="375"
|
|
8
9
|
:min-height="375"
|
|
9
10
|
:size="size"
|
|
@@ -83,7 +84,7 @@ defineBlokkliFeature({
|
|
|
83
84
|
'Provides a responsive preview of the current edit state in an iframe.',
|
|
84
85
|
})
|
|
85
86
|
|
|
86
|
-
const { $t, storage } = useBlokkli()
|
|
87
|
+
const { $t, storage, state } = useBlokkli()
|
|
87
88
|
|
|
88
89
|
const selectedViewportId = storage.use('mobile-preview:viewport', 'iphone-se')
|
|
89
90
|
const isRotated = storage.use('mobile-preview:rotated', false)
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
precision mediump float;
|
|
2
|
-
|
|
3
2
|
varying vec4 v_quad;
|
|
4
3
|
varying vec3 v_color;
|
|
5
4
|
varying vec4 v_rect_radius;
|
|
6
5
|
varying float v_thickness;
|
|
6
|
+
varying float v_rect_id;
|
|
7
7
|
varying vec2 v_rect_size;
|
|
8
8
|
varying vec2 v_rect_center;
|
|
9
|
-
varying float
|
|
9
|
+
varying float v_rect_width;
|
|
10
10
|
|
|
11
|
+
varying float v_transition;
|
|
11
12
|
uniform float u_scale;
|
|
12
13
|
uniform float u_dpi;
|
|
14
|
+
uniform float u_time;
|
|
15
|
+
uniform float u_is_transforming;
|
|
13
16
|
uniform vec2 u_resolution;
|
|
14
17
|
|
|
18
|
+
#define PI (3.141592653589793)
|
|
19
|
+
|
|
15
20
|
int pseudoQuadrant(vec2 p) {
|
|
16
21
|
return int(floor(step(0.0, p.x) + 2.0 * step(0.0, -p.y)));
|
|
17
22
|
}
|
|
@@ -19,79 +24,108 @@ int pseudoQuadrant(vec2 p) {
|
|
|
19
24
|
float sdRoundBox(vec2 p, vec2 b, vec4 radii) {
|
|
20
25
|
int idx = pseudoQuadrant(p);
|
|
21
26
|
float cr;
|
|
22
|
-
|
|
23
|
-
// Use correct radius. Bottom left and bottom right are flipped.
|
|
24
27
|
if (idx == 0) cr = radii[0];
|
|
25
28
|
else if (idx == 1) cr = radii[1];
|
|
26
29
|
else if (idx == 2) cr = radii[3];
|
|
27
30
|
else cr = radii[2];
|
|
28
|
-
|
|
29
31
|
vec2 q = abs(p) - b + cr;
|
|
30
32
|
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - cr;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
float
|
|
35
|
-
float
|
|
36
|
-
|
|
37
|
-
vec2 size = v_rect_size + u_borderThickness * 2.0 * v_transition;
|
|
35
|
+
float bounceOut(float t) {
|
|
36
|
+
const float a = 4.0 / 11.0;
|
|
37
|
+
const float b = 8.0 / 11.0;
|
|
38
|
+
const float c = 9.0 / 10.0;
|
|
38
39
|
|
|
39
|
-
float
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const float ca = 4356.0 / 361.0;
|
|
41
|
+
const float cb = 35442.0 / 1805.0;
|
|
42
|
+
const float cc = 16061.0 / 1805.0;
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
float u_borderSoftness = 1.0 + v_transition; // How soft the border should be (in pixels)
|
|
44
|
+
float t2 = t * t;
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
return t < a
|
|
47
|
+
? 7.5625 * t2
|
|
48
|
+
: t < b
|
|
49
|
+
? 9.075 * t2 - 9.9 * t + 3.4
|
|
50
|
+
: t < c
|
|
51
|
+
? ca * t2 - cb * t + cc
|
|
52
|
+
: 10.8 * t * t - 20.52 * t + 10.72;
|
|
53
|
+
}
|
|
47
54
|
|
|
48
|
-
|
|
55
|
+
float exponentialIn(float t) {
|
|
56
|
+
return t == 0.0
|
|
57
|
+
? t
|
|
58
|
+
: pow(2.0, 10.0 * (t - 1.0));
|
|
59
|
+
}
|
|
49
60
|
|
|
50
|
-
|
|
61
|
+
float getStripePattern(vec2 quadRelativePos, float time) {
|
|
62
|
+
float d = 300.0 * u_scale;
|
|
51
63
|
|
|
52
|
-
|
|
53
|
-
float distance =
|
|
54
|
-
sdRoundBox(gl_FragCoord.xy - v_rect_center, size / 2.0, r) +
|
|
55
|
-
u_borderThickness;
|
|
64
|
+
float t = mod(u_time + v_rect_id * 1000.0, 1200.0) / 1200.0;
|
|
56
65
|
|
|
57
|
-
|
|
58
|
-
float smoothedAlpha = 1.0 - smoothstep(0.0, u_edgeSoftness, distance);
|
|
66
|
+
float movement = t * 2.0 * PI;
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
smoothstep(
|
|
65
|
-
u_borderThickness - u_borderSoftness,
|
|
66
|
-
u_borderThickness,
|
|
67
|
-
abs(distance - u_borderThickness)
|
|
68
|
-
);
|
|
68
|
+
float normalizedSin =
|
|
69
|
+
(sin((quadRelativePos.y + quadRelativePos.x) / d + movement + v_rect_id) +
|
|
70
|
+
1.0) /
|
|
71
|
+
2.0;
|
|
69
72
|
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
return normalizedSin * 0.2 + 0.5;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
vec4 drawBox(float thickness, vec4 bg, vec4 fill, vec4 border, float offset) {
|
|
77
|
+
float borderThickness = max(thickness, 2.0);
|
|
78
|
+
|
|
79
|
+
float t = exponentialIn(
|
|
80
|
+
(sin(u_time / 270.0 - v_rect_id + offset) + 1.0) / 2.0
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (u_is_transforming >= 0.5) {
|
|
84
|
+
borderThickness = (t * 0.7 + 0.5) * borderThickness;
|
|
85
|
+
}
|
|
86
|
+
vec2 size = v_rect_size + borderThickness * 2.0 * v_transition;
|
|
87
|
+
float u_edgeSoftness = 1.0 + v_transition;
|
|
88
|
+
vec4 radius = v_rect_radius * u_scale + vec4(borderThickness);
|
|
89
|
+
vec4 u_cornerRadii = min(radius, min(size.x, size.y) / 2.0) * v_transition;
|
|
90
|
+
float u_borderSoftness = 1.0 + v_transition;
|
|
91
|
+
|
|
92
|
+
vec4 r = u_cornerRadii;
|
|
93
|
+
|
|
94
|
+
vec2 posRelativeToQuad = gl_FragCoord.xy - v_rect_center;
|
|
95
|
+
|
|
96
|
+
float mainDist = sdRoundBox(posRelativeToQuad, size / 2.0, r);
|
|
97
|
+
float innerDist = mainDist;
|
|
98
|
+
|
|
99
|
+
float fillAlpha = 1.0 - smoothstep(-u_edgeSoftness, 0.0, innerDist);
|
|
100
|
+
float borderAlpha =
|
|
101
|
+
1.0 - smoothstep(-u_borderSoftness, 0.0, abs(mainDist) - borderThickness);
|
|
72
102
|
|
|
73
|
-
|
|
74
|
-
|
|
103
|
+
vec4 stripedFill = vec4(1.0, 1.0, 1.0, 0.0);
|
|
104
|
+
if (u_is_transforming >= 0.5) {
|
|
105
|
+
stripedFill = fill;
|
|
106
|
+
stripedFill.a = getStripePattern(posRelativeToQuad, u_time);
|
|
107
|
+
borderAlpha *= t + 0.6;
|
|
108
|
+
}
|
|
75
109
|
|
|
76
|
-
|
|
77
|
-
return mix(
|
|
110
|
+
vec4 res_with_fill = mix(bg, stripedFill, fillAlpha * stripedFill.a);
|
|
111
|
+
return mix(res_with_fill, border, borderAlpha * border.a);
|
|
78
112
|
}
|
|
79
113
|
|
|
80
114
|
void main() {
|
|
81
|
-
// Red border that should be below the blue border.
|
|
82
115
|
vec4 borderBottom = drawBox(
|
|
83
116
|
v_transition * (v_thickness * 2.0),
|
|
84
117
|
vec4(v_color, 0.0),
|
|
85
|
-
vec4(v_color, 0.5
|
|
86
|
-
vec4(v_color, 0.4)
|
|
118
|
+
vec4(v_color, 0.5),
|
|
119
|
+
vec4(v_color, 0.4),
|
|
120
|
+
0.0
|
|
87
121
|
);
|
|
88
122
|
|
|
89
|
-
// Blue border that should be on top of the red border.
|
|
90
123
|
vec4 borderTop = drawBox(
|
|
91
124
|
v_thickness,
|
|
92
125
|
vec4(v_color, 0.0),
|
|
93
126
|
vec4(v_color, 0.0),
|
|
94
|
-
vec4(v_color, 1.0)
|
|
127
|
+
vec4(v_color, 1.0),
|
|
128
|
+
-0.2
|
|
95
129
|
);
|
|
96
130
|
|
|
97
131
|
vec4 finalColor = mix(borderBottom, borderTop, borderTop.a);
|
|
@@ -22,7 +22,7 @@ const props = defineProps<{
|
|
|
22
22
|
gl: WebGLRenderingContext
|
|
23
23
|
}>()
|
|
24
24
|
|
|
25
|
-
const { animation, theme, dom } = useBlokkli()
|
|
25
|
+
const { animation, theme, dom, ui } = useBlokkli()
|
|
26
26
|
|
|
27
27
|
const programInfo = animation.registerProgram('selection', props.gl, [vs, fs])
|
|
28
28
|
|
|
@@ -99,15 +99,15 @@ class SelectionRectangleBufferCollector extends RectangleBufferCollector<Selecti
|
|
|
99
99
|
|
|
100
100
|
const collector = new SelectionRectangleBufferCollector(props.gl)
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
u_color_default: toShaderColor(theme.accent.value[600]),
|
|
104
|
-
u_color_inverted: [255, 255, 255],
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
onBlokkliEvent('canvas:draw', () => {
|
|
102
|
+
onBlokkliEvent('canvas:draw', (e) => {
|
|
108
103
|
props.gl.useProgram(programInfo.program)
|
|
109
104
|
|
|
110
|
-
setUniforms(programInfo,
|
|
105
|
+
setUniforms(programInfo, {
|
|
106
|
+
u_color_default: toShaderColor(theme.accent.value[600]),
|
|
107
|
+
u_color_inverted: [255, 255, 255],
|
|
108
|
+
u_is_transforming: ui.isTransforming.value ? 1 : 0,
|
|
109
|
+
u_time: e.time,
|
|
110
|
+
})
|
|
111
111
|
animation.setSharedUniforms(props.gl, programInfo)
|
|
112
112
|
const { info, hasChanged } = collector.getBufferInfo()
|
|
113
113
|
|
|
@@ -27,11 +27,13 @@ varying float v_thickness;
|
|
|
27
27
|
varying vec2 v_rect_size;
|
|
28
28
|
varying vec2 v_rect_center;
|
|
29
29
|
varying float v_transition;
|
|
30
|
+
varying float v_rect_id;
|
|
31
|
+
varying float v_rect_width;
|
|
30
32
|
|
|
31
33
|
void main() {
|
|
32
34
|
// Define the increase size in viewport terms (not affected by u_scale)
|
|
33
35
|
float thickness = (0.5 + smoothstep(0.3, 1.0, u_scale) * 2.5) * u_dpi;
|
|
34
|
-
float increaseSize = max(thickness,
|
|
36
|
+
float increaseSize = max(thickness, 25.0);
|
|
35
37
|
|
|
36
38
|
// Calculate the new dimensions of the quad
|
|
37
39
|
vec4 adjusted_quad = a_quad;
|
|
@@ -75,10 +77,13 @@ void main() {
|
|
|
75
77
|
);
|
|
76
78
|
v_quad = transformed_quad;
|
|
77
79
|
|
|
80
|
+
v_rect_width = adjusted_quad.x;
|
|
81
|
+
|
|
78
82
|
// Set color and other varying variables
|
|
79
83
|
v_color = a_rect_type > 0.5 ? u_color_inverted : u_color_default;
|
|
80
84
|
v_rect_radius = a_rect_radius * u_dpi;
|
|
81
85
|
v_thickness = thickness;
|
|
86
|
+
v_rect_id = a_rect_id;
|
|
82
87
|
v_rect_size = vec2(v_quad.z, v_quad.w);
|
|
83
88
|
v_rect_center = vec2(v_quad.x + v_quad.z / 2.0, v_quad.y + v_quad.w / 2.0); // The pixel-space rectangle center location
|
|
84
89
|
v_transition = smoothstep(0.5, 0.8, u_scale);
|
|
@@ -7,8 +7,13 @@
|
|
|
7
7
|
class="peer"
|
|
8
8
|
@change="toggleCheckbox"
|
|
9
9
|
/>
|
|
10
|
-
<div />
|
|
11
|
-
<
|
|
10
|
+
<div class="bk-checkbox-toggle-toggle" />
|
|
11
|
+
<div class="bk-checkbox-toggle-label">
|
|
12
|
+
<div>{{ settingLabel }}</div>
|
|
13
|
+
<div v-if="settingDescription">
|
|
14
|
+
{{ settingDescription }}
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
12
17
|
</label>
|
|
13
18
|
<div v-else-if="setting.type === 'radios'">
|
|
14
19
|
<h3 class="bk-form-label">
|
|
@@ -80,6 +85,22 @@ const settingLabel = computed(() => {
|
|
|
80
85
|
)
|
|
81
86
|
})
|
|
82
87
|
|
|
88
|
+
const settingDescription = computed(() => {
|
|
89
|
+
const translated = textTranslation(
|
|
90
|
+
'feature_' +
|
|
91
|
+
props.featureId +
|
|
92
|
+
'_setting_' +
|
|
93
|
+
props.settingsKey +
|
|
94
|
+
'_description',
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
if (!translated && 'description' in props.setting) {
|
|
98
|
+
return props.setting.description
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return translated
|
|
102
|
+
})
|
|
103
|
+
|
|
83
104
|
const getOptionLabel = (key: string, defaultLabel: string) => {
|
|
84
105
|
return (
|
|
85
106
|
textTranslation(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<DialogModal
|
|
3
3
|
:title="$t('settingsDialogTitle', 'Change settings')"
|
|
4
|
-
:width="
|
|
4
|
+
:width="900"
|
|
5
5
|
hide-buttons
|
|
6
6
|
icon="cog"
|
|
7
7
|
@cancel="$emit('cancel')"
|
|
@@ -10,14 +10,17 @@
|
|
|
10
10
|
<div v-for="group in groups" :key="group.key" class="bk-form-section">
|
|
11
11
|
<h3 class="bk-settings-group-title">
|
|
12
12
|
<span>{{ group.label }}</span>
|
|
13
|
+
<span v-if="group.id === 'beta'" class="bk-beta-indicator">BETA</span>
|
|
13
14
|
</h3>
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
<div>
|
|
16
|
+
<FeatureSetting
|
|
17
|
+
v-for="setting in group.settings"
|
|
18
|
+
:key="group.key + setting.settingsKey"
|
|
19
|
+
:feature-id="setting.featureId"
|
|
20
|
+
:settings-key="setting.settingsKey"
|
|
21
|
+
:setting="setting.setting"
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
21
24
|
</div>
|
|
22
25
|
</div>
|
|
23
26
|
</DialogModal>
|
|
@@ -35,6 +38,8 @@ import { settingsOverride } from '#blokkli/config'
|
|
|
35
38
|
|
|
36
39
|
const { $t, features, ui } = useBlokkli()
|
|
37
40
|
|
|
41
|
+
const getTranslation = $t
|
|
42
|
+
|
|
38
43
|
type FeatureSetting = {
|
|
39
44
|
featureId: ValidFeatureKey
|
|
40
45
|
settingsKey: string
|
|
@@ -58,6 +63,8 @@ const getGroupLabel = (key: SettingsGroup): string => {
|
|
|
58
63
|
return $t('settingsAdvanced', 'Advanced')
|
|
59
64
|
} else if (key === 'artboard') {
|
|
60
65
|
return $t('settingsArtboard', 'Artboard')
|
|
66
|
+
} else if (key === 'beta') {
|
|
67
|
+
return $t('settingsBeta', 'New Features')
|
|
61
68
|
}
|
|
62
69
|
return key
|
|
63
70
|
}
|
|
@@ -90,37 +97,63 @@ const shouldRenderSetting = (
|
|
|
90
97
|
const settingTypeOrder = ['checkbox', 'slider', 'method']
|
|
91
98
|
|
|
92
99
|
const groups = computed<GroupedSettings[]>(() => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
100
|
+
const settingGroups = features.features.value.reduce<
|
|
101
|
+
Partial<Record<SettingsGroup, GroupedSettings>>
|
|
102
|
+
>((acc, feature) => {
|
|
103
|
+
Object.entries(feature.settings || {}).forEach(([settingsKey, setting]) => {
|
|
104
|
+
const key: any = `feature:${feature.id}:${settingsKey}`
|
|
105
|
+
if (shouldRenderSetting(key, setting)) {
|
|
106
|
+
const group = setting.group || 'advanced'
|
|
107
|
+
if (!acc[group]) {
|
|
108
|
+
acc[group] = {
|
|
109
|
+
id: group as any,
|
|
110
|
+
key: group,
|
|
111
|
+
label: getGroupLabel(group),
|
|
112
|
+
icon: getGroupIcon(group),
|
|
113
|
+
settings: [],
|
|
114
|
+
}
|
|
115
|
+
}
|
|
110
116
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
)
|
|
123
|
-
|
|
117
|
+
acc[group].settings.push({
|
|
118
|
+
featureId: feature.id,
|
|
119
|
+
settingsKey,
|
|
120
|
+
setting,
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
return acc
|
|
125
|
+
}, {})
|
|
126
|
+
|
|
127
|
+
if (features.betaFeatures.value.length) {
|
|
128
|
+
if (!settingGroups.beta) {
|
|
129
|
+
settingGroups.beta = {
|
|
130
|
+
id: 'beta',
|
|
131
|
+
key: 'betaFeatures',
|
|
132
|
+
label: getGroupLabel('beta'),
|
|
133
|
+
icon: 'bug',
|
|
134
|
+
settings: [],
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
features.betaFeatures.value.forEach((v) => {
|
|
139
|
+
const label = getTranslation(`feature_${v.id}_label`) || v.label
|
|
140
|
+
const description =
|
|
141
|
+
getTranslation(`feature_${v.id}_description`) || v.description
|
|
142
|
+
settingGroups.beta!.settings.push({
|
|
143
|
+
featureId: 'settings',
|
|
144
|
+
settingsKey: 'beta:' + v.id,
|
|
145
|
+
setting: {
|
|
146
|
+
type: 'checkbox',
|
|
147
|
+
default: false,
|
|
148
|
+
label,
|
|
149
|
+
description,
|
|
150
|
+
group: 'beta',
|
|
151
|
+
},
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return Object.values(settingGroups)
|
|
124
157
|
.map((group) => {
|
|
125
158
|
group.settings
|
|
126
159
|
.sort((a, b) => b.settingsKey.localeCompare(a.settingsKey))
|