windmill-components 1.405.0 → 1.406.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/package/assets/app.css +20 -0
- package/package/components/AppConnectLightweightResourcePicker.svelte +66 -0
- package/package/components/AppConnectLightweightResourcePicker.svelte.d.ts +21 -0
- package/package/components/ArgInput.svelte +6 -2
- package/package/components/ArgInput.svelte.d.ts +1 -0
- package/package/components/CustomPopover.svelte +1 -1
- package/package/components/DisplayResult.svelte +1 -1
- package/package/components/FlowBuilder.svelte +2 -0
- package/package/components/FlowBuilder.svelte.d.ts +1 -0
- package/package/components/FlowInputViewer.svelte +25 -0
- package/package/components/FlowInputViewer.svelte.d.ts +19 -0
- package/package/components/FlowJobResult.svelte +8 -1
- package/package/components/FlowJobResult.svelte.d.ts +1 -0
- package/package/components/FlowMetadata.svelte +2 -2
- package/package/components/FlowPreviewContent.svelte +2 -1
- package/package/components/FlowStatusViewer.svelte +3 -1
- package/package/components/FlowStatusViewer.svelte.d.ts +1 -0
- package/package/components/FlowStatusViewerInner.svelte +4 -1
- package/package/components/FlowViewer.svelte +2 -21
- package/package/components/LightweightResourcePicker.svelte +34 -30
- package/package/components/LogViewer.svelte +4 -3
- package/package/components/LogViewer.svelte.d.ts +1 -0
- package/package/components/ManualPopover.svelte +1 -1
- package/package/components/ObjectResourceInput.svelte +5 -2
- package/package/components/ObjectResourceInput.svelte.d.ts +2 -0
- package/package/components/Popover.svelte +1 -1
- package/package/components/Portal.svelte +7 -8
- package/package/components/Portal.svelte.d.ts +3 -7
- package/package/components/QueueMetricsDrawer.svelte +368 -3
- package/package/components/QueueMetricsDrawer.svelte.d.ts +2 -0
- package/package/components/ResourceEditor.svelte +4 -5
- package/package/components/ResourcePicker.svelte +14 -9
- package/package/components/ResourcePicker.svelte.d.ts +1 -0
- package/package/components/RunForm.svelte +1 -1
- package/package/components/SavedInputs.svelte +2 -2
- package/package/components/ScriptVersionHistory.svelte +54 -59
- package/package/components/TestConnection.svelte +1 -0
- package/package/components/TimeAgo.svelte +5 -6
- package/package/components/TimeAgo.svelte.d.ts +1 -1
- package/package/components/apps/components/buttons/AppButton.svelte +1 -1
- package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +1 -1
- package/package/components/apps/components/inputs/AppMultiSelect.svelte +1 -1
- package/package/components/apps/components/inputs/AppMultiSelectV2.svelte +1 -1
- package/package/components/apps/components/layout/AppDrawer.svelte +1 -1
- package/package/components/apps/components/layout/AppModal.svelte +1 -1
- package/package/components/apps/editor/AppEditor.svelte +11 -3
- package/package/components/apps/editor/GridEditor.svelte +57 -4
- package/package/components/apps/editor/GridEditor.svelte.d.ts +8 -0
- package/package/components/apps/editor/GridEditorMenu.svelte +1 -1
- package/package/components/apps/editor/SubGridEditor.svelte +82 -3
- package/package/components/apps/editor/SubGridEditor.svelte.d.ts +16 -0
- package/package/components/apps/editor/appUtils.d.ts +19 -2
- package/package/components/apps/editor/appUtils.js +103 -7
- package/package/components/apps/editor/component/Component.svelte +36 -8
- package/package/components/apps/editor/component/Component.svelte.d.ts +3 -1
- package/package/components/apps/editor/contextPanel/components/OutputHeader.svelte +1 -1
- package/package/components/apps/svelte-grid/Grid.svelte +235 -12
- package/package/components/apps/svelte-grid/Grid.svelte.d.ts +7 -7
- package/package/components/apps/svelte-grid/MoveResize.svelte +104 -11
- package/package/components/apps/svelte-grid/MoveResize.svelte.d.ts +7 -0
- package/package/components/apps/svelte-grid/utils/item.d.ts +4 -1
- package/package/components/apps/svelte-grid/utils/item.js +2 -3
- package/package/components/apps/svelte-select/lib/ConditionalPortal.svelte +1 -1
- package/package/components/apps/svelte-select/lib/ConditionalPortalGlobal.svelte +1 -1
- package/package/components/common/button/ButtonDropdown.svelte +1 -1
- package/package/components/common/drawer/ConditionalPortal.svelte +1 -1
- package/package/components/common/menu/MenuV2.svelte +1 -1
- package/package/components/common/modal/AlwaysMountedModal.svelte +1 -1
- package/package/components/common/popup/PopupV2.svelte +1 -1
- package/package/components/copilot/StepGenQuick.svelte +3 -2
- package/package/components/copilot/StepGenQuick.svelte.d.ts +1 -0
- package/package/components/custom_ui.d.ts +1 -0
- package/package/components/details/Menu.svelte +1 -1
- package/package/components/flows/CreateActionsApp.svelte +1 -1
- package/package/components/flows/FlowEditor.svelte +2 -1
- package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
- package/package/components/flows/FlowHistory.svelte +10 -195
- package/package/components/flows/FlowHistory.svelte.d.ts +0 -1
- package/package/components/flows/FlowHistoryInner.svelte +200 -0
- package/package/components/flows/FlowHistoryInner.svelte.d.ts +19 -0
- package/package/components/flows/content/FlowEditorPanel.svelte +2 -1
- package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +1 -0
- package/package/components/flows/content/FlowInput.svelte +66 -58
- package/package/components/flows/content/FlowInput.svelte.d.ts +1 -0
- package/package/components/flows/content/FlowModuleScript.svelte +1 -1
- package/package/components/flows/header/FlowYamlEditor.svelte +6 -2
- package/package/components/flows/map/FlowModuleSchemaMap.svelte +3 -2
- package/package/components/flows/map/InsertModuleButton.svelte +1 -1
- package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte +1 -1
- package/package/components/graph/model.d.ts +1 -0
- package/package/components/icons/WindmillIcon.svelte +119 -105
- package/package/components/icons/store.d.ts +4 -0
- package/package/components/icons/store.js +1 -0
- package/package/components/multiselect/MultiSelectWrapper.svelte +1 -1
- package/package/components/propertyPicker/ObjectViewer.svelte +1 -1
- package/package/components/runs/RunRow.svelte +3 -7
- package/package/components/schema/FlowPropertyEditor.svelte +1 -0
- package/package/components/search/GlobalSearchModal.svelte +1 -1
- package/package/script_helpers.d.ts +37 -38
- package/package/script_helpers.js +100 -38
- package/package.json +23 -1
- package/package/init_scripts/python_failure_module.d.ts +0 -2
- package/package/init_scripts/python_failure_module.js +0 -8
- package/package/init_scripts/python_init_code.d.ts +0 -2
- package/package/init_scripts/python_init_code.js +0 -40
- package/package/init_scripts/python_init_code_clear.d.ts +0 -2
- package/package/init_scripts/python_init_code_clear.js +0 -5
- package/package/init_scripts/python_init_code_trigger.d.ts +0 -2
- package/package/init_scripts/python_init_code_trigger.js +0 -14
|
@@ -77,14 +77,17 @@ import AppDisplayComponentByJobId from '../../components/display/AppRecomputeAll
|
|
|
77
77
|
import AppRecomputeAll from '../../components/display/AppRecomputeAll.svelte';
|
|
78
78
|
import AppUserResource from '../../components/inputs/AppUserResource.svelte';
|
|
79
79
|
import { Anchor } from 'lucide-svelte';
|
|
80
|
+
import { findGridItemParentGrid, isContainer } from '../appUtils';
|
|
80
81
|
export let component;
|
|
81
82
|
export let selected;
|
|
82
83
|
export let locked = false;
|
|
83
84
|
export let render;
|
|
84
85
|
export let hidden;
|
|
85
86
|
export let fullHeight;
|
|
86
|
-
export let overlapped =
|
|
87
|
-
|
|
87
|
+
export let overlapped = undefined;
|
|
88
|
+
export let moveMode = undefined;
|
|
89
|
+
export let componentDraggedId = undefined;
|
|
90
|
+
const { mode, app, hoverStore, connectingInput } = getContext('AppViewerContext');
|
|
88
91
|
const editorContext = getContext('AppEditorContext');
|
|
89
92
|
const componentActive = editorContext?.componentActive;
|
|
90
93
|
const movingcomponents = editorContext?.movingcomponents;
|
|
@@ -108,6 +111,26 @@ function mouseOut() {
|
|
|
108
111
|
}
|
|
109
112
|
}, 50);
|
|
110
113
|
}
|
|
114
|
+
function componentDraggedIsNotChild(componentDraggedId, componentId) {
|
|
115
|
+
let parentGrid = findGridItemParentGrid($app, componentDraggedId);
|
|
116
|
+
return !parentGrid?.startsWith(`${componentId}-`);
|
|
117
|
+
}
|
|
118
|
+
function areOnTheSameSubgrid(componentDraggedId, componentId) {
|
|
119
|
+
return (findGridItemParentGrid($app, componentDraggedId) === findGridItemParentGrid($app, componentId));
|
|
120
|
+
}
|
|
121
|
+
let cachedComponentDraggedIsNotChild;
|
|
122
|
+
let cachedAreOnTheSameSubgrid;
|
|
123
|
+
function updateCache(componentDraggedId) {
|
|
124
|
+
if (componentDraggedId) {
|
|
125
|
+
cachedComponentDraggedIsNotChild = componentDraggedIsNotChild(componentDraggedId, component.id);
|
|
126
|
+
cachedAreOnTheSameSubgrid = areOnTheSameSubgrid(componentDraggedId, component.id);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
cachedComponentDraggedIsNotChild = undefined;
|
|
130
|
+
cachedAreOnTheSameSubgrid = undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
$: updateCache(componentDraggedId);
|
|
111
134
|
</script>
|
|
112
135
|
|
|
113
136
|
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
|
@@ -126,18 +149,23 @@ function mouseOut() {
|
|
|
126
149
|
hidden && $mode === 'preview' ? 'hidden' : ''
|
|
127
150
|
)}
|
|
128
151
|
>
|
|
129
|
-
{#if locked && componentActive && $componentActive &&
|
|
152
|
+
{#if locked && componentActive && $componentActive && moveMode === 'move' && componentDraggedId && componentDraggedId !== component.id && cachedAreOnTheSameSubgrid}
|
|
130
153
|
<div
|
|
131
|
-
class={twMerge(
|
|
132
|
-
'absolute inset-0 bg-locked center-center flex-col z-50',
|
|
133
|
-
overlapped ? 'bg-locked-hover' : ''
|
|
134
|
-
)}
|
|
154
|
+
class={twMerge('absolute inset-0 bg-locked center-center flex-col z-50', 'bg-locked-hover')}
|
|
135
155
|
>
|
|
136
156
|
<div class="bg-surface p-2 shadow-sm rounded-md flex center-center flex-col gap-2">
|
|
137
157
|
<Anchor size={24} class="text-primary " />
|
|
138
|
-
<div class="text-xs">Anchored: The component cannot be moved</div>
|
|
158
|
+
<div class="text-xs"> Anchored: The component cannot be moved. </div>
|
|
139
159
|
</div>
|
|
140
160
|
</div>
|
|
161
|
+
{:else if moveMode === 'insert' && isContainer(component.type) && componentDraggedId && componentDraggedId !== component.id && cachedComponentDraggedIsNotChild}
|
|
162
|
+
<div
|
|
163
|
+
class={twMerge(
|
|
164
|
+
'absolute inset-0 flex-col rounded-md bg-blue-100 dark:bg-gray-800 bg-opacity-50',
|
|
165
|
+
'outline-dashed outline-offset-2 outline-2 outline-blue-300 dark:outline-blue-700',
|
|
166
|
+
overlapped === component?.id ? 'bg-draggedover dark:bg-draggedover-dark' : ''
|
|
167
|
+
)}
|
|
168
|
+
/>
|
|
141
169
|
{/if}
|
|
142
170
|
{#if $mode !== 'preview'}
|
|
143
171
|
<ComponentHeader
|
|
@@ -8,7 +8,9 @@ declare const __propDef: {
|
|
|
8
8
|
render: boolean;
|
|
9
9
|
hidden: boolean;
|
|
10
10
|
fullHeight: boolean;
|
|
11
|
-
overlapped?:
|
|
11
|
+
overlapped?: string | undefined;
|
|
12
|
+
moveMode?: string | undefined;
|
|
13
|
+
componentDraggedId?: string | undefined;
|
|
12
14
|
};
|
|
13
15
|
events: {
|
|
14
16
|
lock: CustomEvent<any>;
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script context="module">import { writable } from 'svelte/store';
|
|
2
|
+
const componentDraggedIdStore = writable(undefined);
|
|
3
|
+
const componentDraggedParentIdStore = writable(undefined);
|
|
4
|
+
const overlappedStore = writable(undefined);
|
|
5
|
+
const fakeShadowStore = writable(undefined);
|
|
6
|
+
const isCtrlOrMetaPressedStore = writable(false);
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<script>import gridHelp from './utils/helper';
|
|
10
|
+
import { twMerge } from 'tailwind-merge';
|
|
11
|
+
import { getContainerHeight } from './utils/container';
|
|
2
12
|
import { moveItem, getItemById, specifyUndefinedColumns } from './utils/item';
|
|
3
|
-
import { onMount, createEventDispatcher } from 'svelte';
|
|
13
|
+
import { onMount, createEventDispatcher, getContext } from 'svelte';
|
|
4
14
|
import { getColumn, throttle } from './utils/other';
|
|
5
15
|
import MoveResize from './MoveResize.svelte';
|
|
6
|
-
import { ROW_GAP_X, ROW_GAP_Y, ROW_HEIGHT, sortGridItemsPosition } from '../editor/appUtils';
|
|
16
|
+
import { areShadowsTheSame, findGridItemParentGrid, getDeltaXByComponent, getDeltaYByComponent, isContainer, ROW_GAP_X, ROW_GAP_Y, ROW_HEIGHT, sortGridItemsPosition, subGridIndexKey } from '../editor/appUtils';
|
|
7
17
|
const dispatch = createEventDispatcher();
|
|
18
|
+
const { app, worldStore } = getContext('AppViewerContext');
|
|
8
19
|
export let items;
|
|
9
20
|
export let rowHeight = ROW_HEIGHT;
|
|
10
21
|
export let cols;
|
|
@@ -16,6 +27,7 @@ export let allIdsInPath;
|
|
|
16
27
|
export let containerWidth = undefined;
|
|
17
28
|
export let scroller = undefined;
|
|
18
29
|
export let sensor = 20;
|
|
30
|
+
export let root = false;
|
|
19
31
|
export let parentWidth = undefined;
|
|
20
32
|
let getComputedCols;
|
|
21
33
|
let container;
|
|
@@ -59,6 +71,16 @@ onMount(() => {
|
|
|
59
71
|
});
|
|
60
72
|
let sortedItems = [];
|
|
61
73
|
$: sortedItems = JSON.parse(JSON.stringify(items)).sort((a, b) => a.id.localeCompare(b.id));
|
|
74
|
+
let resizing = false;
|
|
75
|
+
function handleKeyUp(event) {
|
|
76
|
+
if ((event.key === 'Control' || event.key === 'Meta') && $isCtrlOrMetaPressedStore) {
|
|
77
|
+
setTimeout(() => {
|
|
78
|
+
$isCtrlOrMetaPressedStore = false;
|
|
79
|
+
$fakeShadowStore = undefined;
|
|
80
|
+
}, 50);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const initialFixedStates = new Map();
|
|
62
84
|
let initItems = undefined;
|
|
63
85
|
const updateMatrix = ({ detail }) => {
|
|
64
86
|
let isPointerUp = detail.isPointerUp;
|
|
@@ -93,9 +115,37 @@ const updateMatrix = ({ detail }) => {
|
|
|
93
115
|
...shadows[id]
|
|
94
116
|
}
|
|
95
117
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
118
|
+
if ($isCtrlOrMetaPressedStore) {
|
|
119
|
+
if ($componentDraggedParentIdStore === $overlappedStore) {
|
|
120
|
+
const fixedContainer = sortedItems.map((item) => {
|
|
121
|
+
if (isContainer(item.data['type'])) {
|
|
122
|
+
initialFixedStates.set(item.id, {
|
|
123
|
+
item3Fixed: item[3].fixed,
|
|
124
|
+
item12Fixed: item[12].fixed
|
|
125
|
+
});
|
|
126
|
+
item[3].fixed = true;
|
|
127
|
+
item[12].fixed = true;
|
|
128
|
+
}
|
|
129
|
+
return item;
|
|
130
|
+
});
|
|
131
|
+
let { items } = moveItem(activeItem, fixedContainer, getComputedCols);
|
|
132
|
+
items = items.map((item) => {
|
|
133
|
+
if (initialFixedStates.has(item.id)) {
|
|
134
|
+
const initialState = initialFixedStates.get(item.id);
|
|
135
|
+
if (initialState) {
|
|
136
|
+
item[3].fixed = initialState.item3Fixed;
|
|
137
|
+
item[12].fixed = initialState.item12Fixed;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return item;
|
|
141
|
+
});
|
|
142
|
+
sortedItems = items;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
let { items } = moveItem(activeItem, sortedItems, getComputedCols);
|
|
147
|
+
sortedItems = items;
|
|
148
|
+
}
|
|
99
149
|
}
|
|
100
150
|
}
|
|
101
151
|
for (let id of nselectedIds ?? []) {
|
|
@@ -109,6 +159,7 @@ const updateMatrix = ({ detail }) => {
|
|
|
109
159
|
};
|
|
110
160
|
const throttleMatrix = throttle(updateMatrix, throttleResize);
|
|
111
161
|
//let hiddenComponents = writable({})
|
|
162
|
+
let lastDetail = undefined;
|
|
112
163
|
const handleRepaint = ({ detail }) => {
|
|
113
164
|
if (!detail.isPointerUp) {
|
|
114
165
|
throttleMatrix({ detail });
|
|
@@ -125,6 +176,18 @@ const handleRepaint = ({ detail }) => {
|
|
|
125
176
|
}, 0)
|
|
126
177
|
*/
|
|
127
178
|
};
|
|
179
|
+
function handleKeyDown(event) {
|
|
180
|
+
if ((event.key === 'Control' || event.key === 'Meta') && !$isCtrlOrMetaPressedStore) {
|
|
181
|
+
if (resizing) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
$isCtrlOrMetaPressedStore = true;
|
|
185
|
+
if (lastDetail) {
|
|
186
|
+
throttleMatrix({ detail: lastDetail });
|
|
187
|
+
lastDetail = undefined;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
128
191
|
let moveResizes = {};
|
|
129
192
|
let shadows = {};
|
|
130
193
|
export function handleMove({ detail }) {
|
|
@@ -133,31 +196,183 @@ export function handleMove({ detail }) {
|
|
|
133
196
|
moveResize?.updateMove(JSON.parse(JSON.stringify(detail.cordDiff)), detail.eventY);
|
|
134
197
|
}
|
|
135
198
|
});
|
|
199
|
+
lastDetail = detail;
|
|
136
200
|
throttleMatrix({ detail: { isPointerUp: false, activate: false } });
|
|
201
|
+
if (!$isCtrlOrMetaPressedStore) {
|
|
202
|
+
$overlappedStore = undefined;
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (
|
|
206
|
+
// We don't display the fake shadow if the dragged component is a child of the overlapped component
|
|
207
|
+
$componentDraggedParentIdStore !== $overlappedStore &&
|
|
208
|
+
detail.shadow &&
|
|
209
|
+
// only update the fake shadow if the are different
|
|
210
|
+
!areShadowsTheSame($fakeShadowStore, detail.shadow)) {
|
|
211
|
+
const draggedItem = sortedItems.find((item) => item.id === $componentDraggedIdStore);
|
|
212
|
+
if (draggedItem) {
|
|
213
|
+
draggedItem[getComputedCols].x = detail.shadow.x;
|
|
214
|
+
draggedItem[getComputedCols].y = detail.shadow.y;
|
|
215
|
+
}
|
|
216
|
+
let items = [];
|
|
217
|
+
if ($overlappedStore) {
|
|
218
|
+
const div = document.getElementById(`component-${$overlappedStore}`);
|
|
219
|
+
const type = div?.getAttribute('data-componenttype');
|
|
220
|
+
if (!$app.subgrids) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const index = type ? subGridIndexKey(type, $overlappedStore, $worldStore) : 0;
|
|
224
|
+
items = $app.subgrids[`${$overlappedStore}-${index}`] ?? [];
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
items = $app.grid ?? [];
|
|
228
|
+
}
|
|
229
|
+
if (!draggedItem) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const freeSpace = gridHelp.findSpace(draggedItem, items, getComputedCols);
|
|
233
|
+
$fakeShadowStore = {
|
|
234
|
+
x: freeSpace.x,
|
|
235
|
+
y: freeSpace.y,
|
|
236
|
+
xPerPx: detail.shadow.xPerPx,
|
|
237
|
+
yPerPx: detail.shadow.yPerPx,
|
|
238
|
+
w: detail.shadow.w,
|
|
239
|
+
h: detail.shadow.h
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
// When leaving the overlapped component, we clear the fake shadow
|
|
243
|
+
// to avoid rendering it with the wrong position at the next intersection
|
|
244
|
+
if (detail.intersectingElement !== $overlappedStore) {
|
|
245
|
+
$fakeShadowStore = undefined;
|
|
246
|
+
}
|
|
247
|
+
// Update the overlapped component
|
|
248
|
+
$overlappedStore = detail.intersectingElement;
|
|
137
249
|
}
|
|
138
|
-
export function handleInitMove(
|
|
250
|
+
export function handleInitMove(id) {
|
|
251
|
+
$componentDraggedIdStore = id;
|
|
252
|
+
$componentDraggedParentIdStore = findGridItemParentGrid($app, id)?.split('-')[0] ?? undefined;
|
|
139
253
|
Object.entries(moveResizes).forEach(([id, moveResize]) => {
|
|
140
254
|
if (selectedIds?.includes(id)) {
|
|
141
255
|
moveResize?.initmove();
|
|
142
256
|
}
|
|
143
257
|
});
|
|
144
258
|
}
|
|
145
|
-
let overlapped = undefined;
|
|
146
259
|
</script>
|
|
147
260
|
|
|
148
|
-
<
|
|
261
|
+
<svelte:window on:keydown={handleKeyDown} on:keyup={handleKeyUp} />
|
|
262
|
+
|
|
263
|
+
<div
|
|
264
|
+
class="svlt-grid-container"
|
|
265
|
+
style="height: {containerHeight}px"
|
|
266
|
+
bind:this={container}
|
|
267
|
+
id={root ? 'root-grid' : undefined}
|
|
268
|
+
data-xperpx={xPerPx}
|
|
269
|
+
>
|
|
270
|
+
<!-- ROOT SHADOW-->
|
|
271
|
+
{#if $isCtrlOrMetaPressedStore && root && $overlappedStore !== $componentDraggedParentIdStore}
|
|
272
|
+
<div
|
|
273
|
+
class={twMerge(
|
|
274
|
+
'absolute inset-0 flex-col rounded-md bg-blue-100 dark:bg-gray-800 bg-opacity-50',
|
|
275
|
+
'outline-dashed outline-offset-2 outline-2 outline-blue-300 dark:outline-blue-700',
|
|
276
|
+
$componentDraggedIdStore && $overlappedStore === undefined
|
|
277
|
+
? 'bg-draggedover dark:bg-draggedover-dark'
|
|
278
|
+
: ''
|
|
279
|
+
)}
|
|
280
|
+
/>
|
|
281
|
+
{#if $overlappedStore === undefined && $componentDraggedIdStore && $fakeShadowStore}
|
|
282
|
+
{@const columnGap = gapX}
|
|
283
|
+
<!-- gap between the columns in px -->
|
|
284
|
+
{@const containerBorder = 0.5 * 16}
|
|
285
|
+
<!-- 0.5rem converted to px (1rem = 16px) -->
|
|
286
|
+
{@const gridTotalWidth = containerWidth ? containerWidth - 2 * containerBorder : 0}
|
|
287
|
+
<!-- subtract borders -->
|
|
288
|
+
{@const availableWidth = gridTotalWidth - 11 * columnGap}
|
|
289
|
+
<!-- subtract gaps between the 12 columns (11 gaps) -->
|
|
290
|
+
{@const columnWidthPx = availableWidth / 12}
|
|
291
|
+
<!-- divide by the number of columns -->
|
|
292
|
+
{@const maxX = Math.floor(availableWidth / columnWidthPx) - $fakeShadowStore.w}
|
|
293
|
+
|
|
294
|
+
<div class="absolute inset-0">
|
|
295
|
+
<div class="relative h-full w-full">
|
|
296
|
+
<div
|
|
297
|
+
class="absolute bg-blue-300 transition-all"
|
|
298
|
+
style={`
|
|
299
|
+
left:${Math.min(maxX, $fakeShadowStore.x) * xPerPx + gapX}px ;
|
|
300
|
+
top: ${$fakeShadowStore.y * yPerPx + gapY}px;
|
|
301
|
+
width: ${$fakeShadowStore.w * xPerPx - gapX}px;
|
|
302
|
+
height: ${$fakeShadowStore.h * yPerPx - gapY}px;
|
|
303
|
+
`}
|
|
304
|
+
/>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
{/if}
|
|
308
|
+
{/if}
|
|
309
|
+
|
|
149
310
|
{#each sortedItems as item (item.id)}
|
|
150
311
|
{#if item[getComputedCols] != undefined}
|
|
312
|
+
{#if $isCtrlOrMetaPressedStore && item.id === $overlappedStore && $componentDraggedIdStore && $componentDraggedParentIdStore !== item.id && $fakeShadowStore}
|
|
313
|
+
{@const columnGap = gapX}
|
|
314
|
+
<!-- gap between the columns in px -->
|
|
315
|
+
{@const containerBorder = 0.5 * 16}
|
|
316
|
+
<!-- 0.5rem converted to px (1rem = 16px) -->
|
|
317
|
+
{@const gridTotalWidth = containerWidth ? containerWidth - 2 * containerBorder : 0}
|
|
318
|
+
<!-- subtract borders -->
|
|
319
|
+
{@const availableWidth = gridTotalWidth - 11 * columnGap}
|
|
320
|
+
<!-- subtract gaps between the 12 columns (11 gaps) -->
|
|
321
|
+
{@const columnWidthPx = availableWidth / 12}
|
|
322
|
+
<!-- divide by the number of columns -->
|
|
323
|
+
{@const maxX = Math.floor(availableWidth / columnWidthPx) - $fakeShadowStore.w}
|
|
324
|
+
|
|
325
|
+
<div
|
|
326
|
+
class="absolute"
|
|
327
|
+
style={`
|
|
328
|
+
left: ${item[getComputedCols].x * xPerPx + gapX}px;
|
|
329
|
+
top: ${item[getComputedCols].y * yPerPx + gapY}px;
|
|
330
|
+
`}
|
|
331
|
+
>
|
|
332
|
+
<div class="relative h-full w-full">
|
|
333
|
+
<div
|
|
334
|
+
class={twMerge('absolute transition-all duration-[50ms] bg-blue-300')}
|
|
335
|
+
style={`
|
|
336
|
+
left: calc(${
|
|
337
|
+
Math.min($fakeShadowStore.x, maxX) * $fakeShadowStore.xPerPx + gapX
|
|
338
|
+
}px + 0.5rem + ${getDeltaXByComponent(item.data['type'])});
|
|
339
|
+
top: calc(${
|
|
340
|
+
$fakeShadowStore.y * $fakeShadowStore.yPerPx + gapY
|
|
341
|
+
}px + 0.5rem + ${getDeltaYByComponent(item.data['type'])});
|
|
342
|
+
width: ${$fakeShadowStore.w * $fakeShadowStore.xPerPx - gapX * 2}px;
|
|
343
|
+
height: ${$fakeShadowStore.h * $fakeShadowStore.yPerPx - gapY * 2}px;
|
|
344
|
+
`}
|
|
345
|
+
/>
|
|
346
|
+
</div>
|
|
347
|
+
</div>
|
|
348
|
+
{/if}
|
|
349
|
+
|
|
151
350
|
<MoveResize
|
|
152
|
-
on:initmove={handleInitMove}
|
|
351
|
+
on:initmove={() => handleInitMove(item.id)}
|
|
153
352
|
on:move={handleMove}
|
|
154
353
|
bind:shadow={shadows[item.id]}
|
|
155
354
|
bind:this={moveResizes[item.id]}
|
|
156
355
|
on:repaint={handleRepaint}
|
|
356
|
+
on:resizeStart={() => (resizing = true)}
|
|
357
|
+
on:resizeEnd={() => (resizing = false)}
|
|
157
358
|
onTop={Boolean(allIdsInPath?.includes(item.id))}
|
|
158
359
|
id={item.id}
|
|
159
360
|
{xPerPx}
|
|
160
361
|
{yPerPx}
|
|
362
|
+
fakeShadow={$fakeShadowStore}
|
|
363
|
+
on:dropped={(e) => {
|
|
364
|
+
$componentDraggedIdStore = undefined
|
|
365
|
+
$componentDraggedParentIdStore = undefined
|
|
366
|
+
$overlappedStore = undefined
|
|
367
|
+
$fakeShadowStore = undefined
|
|
368
|
+
lastDetail = undefined
|
|
369
|
+
|
|
370
|
+
if (!$isCtrlOrMetaPressedStore) {
|
|
371
|
+
return
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
dispatch('dropped', e.detail)
|
|
375
|
+
}}
|
|
161
376
|
width={xPerPx == 0
|
|
162
377
|
? 0
|
|
163
378
|
: Math.min(getComputedCols, item[getComputedCols] && item[getComputedCols].w) * xPerPx -
|
|
@@ -172,10 +387,18 @@ let overlapped = undefined;
|
|
|
172
387
|
{sensor}
|
|
173
388
|
container={scroller}
|
|
174
389
|
nativeContainer={container}
|
|
175
|
-
{
|
|
390
|
+
overlapped={$overlappedStore}
|
|
391
|
+
moveMode={$isCtrlOrMetaPressedStore ? 'insert' : 'move'}
|
|
392
|
+
type={item.data['type']}
|
|
176
393
|
>
|
|
177
394
|
{#if item[getComputedCols]}
|
|
178
|
-
<slot
|
|
395
|
+
<slot
|
|
396
|
+
dataItem={item}
|
|
397
|
+
hidden={false}
|
|
398
|
+
overlapped={$overlappedStore}
|
|
399
|
+
moveMode={$isCtrlOrMetaPressedStore ? 'insert' : 'move'}
|
|
400
|
+
componentDraggedId={$componentDraggedIdStore}
|
|
401
|
+
/>
|
|
179
402
|
{/if}
|
|
180
403
|
</MoveResize>
|
|
181
404
|
{/if}
|
|
@@ -13,15 +13,15 @@ declare class __sveltets_Render<T> {
|
|
|
13
13
|
containerWidth?: number | undefined;
|
|
14
14
|
scroller?: HTMLElement | undefined;
|
|
15
15
|
sensor?: number | undefined;
|
|
16
|
+
root?: boolean | undefined;
|
|
16
17
|
parentWidth?: number | undefined;
|
|
17
18
|
handleMove?: (({ detail }: {
|
|
18
19
|
detail: any;
|
|
19
20
|
}) => void) | undefined;
|
|
20
|
-
handleInitMove?: ((
|
|
21
|
-
detail: any;
|
|
22
|
-
}) => void) | undefined;
|
|
21
|
+
handleInitMove?: ((id: string) => void) | undefined;
|
|
23
22
|
};
|
|
24
23
|
events(): {
|
|
24
|
+
dropped: CustomEvent<any>;
|
|
25
25
|
resize: CustomEvent<any>;
|
|
26
26
|
mount: CustomEvent<any>;
|
|
27
27
|
redraw: CustomEvent<any>;
|
|
@@ -32,7 +32,9 @@ declare class __sveltets_Render<T> {
|
|
|
32
32
|
default: {
|
|
33
33
|
dataItem: FilledItem<T>;
|
|
34
34
|
hidden: boolean;
|
|
35
|
-
overlapped: undefined;
|
|
35
|
+
overlapped: string | undefined;
|
|
36
|
+
moveMode: string;
|
|
37
|
+
componentDraggedId: string | undefined;
|
|
36
38
|
};
|
|
37
39
|
};
|
|
38
40
|
}
|
|
@@ -43,8 +45,6 @@ export default class Grid<T> extends SvelteComponent<GridProps<T>, GridEvents<T>
|
|
|
43
45
|
get handleMove(): ({ detail }: {
|
|
44
46
|
detail: any;
|
|
45
47
|
}) => void;
|
|
46
|
-
get handleInitMove(): (
|
|
47
|
-
detail: any;
|
|
48
|
-
}) => void;
|
|
48
|
+
get handleInitMove(): (id: string) => void;
|
|
49
49
|
}
|
|
50
50
|
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script>import { createEventDispatcher, getContext, onMount } from 'svelte';
|
|
2
2
|
import { writable } from 'svelte/store';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { computePosition, findGridItemParentGrid, isContainer } from '../editor/appUtils';
|
|
5
|
+
import { throttle } from './utils/other';
|
|
4
6
|
const dispatch = createEventDispatcher();
|
|
5
7
|
export let sensor;
|
|
6
8
|
export let width;
|
|
@@ -19,8 +21,11 @@ export let nativeContainer;
|
|
|
19
21
|
export let onTop;
|
|
20
22
|
export let shadow = undefined;
|
|
21
23
|
export let overlapped = undefined;
|
|
24
|
+
export let moveMode = 'move';
|
|
25
|
+
export let type = undefined;
|
|
26
|
+
export let fakeShadow = undefined;
|
|
22
27
|
const ctx = getContext('AppEditorContext');
|
|
23
|
-
const { mode } = getContext('AppViewerContext');
|
|
28
|
+
const { mode, app } = getContext('AppViewerContext');
|
|
24
29
|
const scale = ctx ? ctx.scale : writable(100);
|
|
25
30
|
const divId = `component-${id}`;
|
|
26
31
|
let shadowElement;
|
|
@@ -128,7 +133,7 @@ function computeRect() {
|
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
135
|
let dragClosure = undefined;
|
|
131
|
-
const pointerdown = ({ clientX, clientY
|
|
136
|
+
const pointerdown = ({ clientX, clientY }) => {
|
|
132
137
|
dragClosure = () => {
|
|
133
138
|
dragClosure = undefined;
|
|
134
139
|
ctx.componentActive.set(true);
|
|
@@ -173,14 +178,35 @@ const update = () => {
|
|
|
173
178
|
}
|
|
174
179
|
}
|
|
175
180
|
};
|
|
181
|
+
// Shared state for the shadow position
|
|
182
|
+
let currentShadowPosition = undefined;
|
|
183
|
+
let currentIntersectingElementId = undefined;
|
|
184
|
+
let moving = false;
|
|
176
185
|
const pointermove = (event) => {
|
|
177
186
|
dragClosure && dragClosure();
|
|
178
187
|
event.preventDefault();
|
|
179
188
|
event.stopPropagation();
|
|
180
189
|
event.stopImmediatePropagation();
|
|
190
|
+
moving = true;
|
|
181
191
|
const { clientX, clientY } = event;
|
|
182
192
|
const cordDiff = { x: (clientX / $scale) * 100 - initX, y: (clientY / $scale) * 100 - initY };
|
|
183
|
-
|
|
193
|
+
if (moveMode === 'move') {
|
|
194
|
+
dispatch('move', {
|
|
195
|
+
cordDiff,
|
|
196
|
+
clientY,
|
|
197
|
+
intersectingElement: undefined,
|
|
198
|
+
shadow: undefined
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
throttledComputeShadow(clientX, clientY);
|
|
203
|
+
dispatch('move', {
|
|
204
|
+
cordDiff,
|
|
205
|
+
clientY,
|
|
206
|
+
intersectingElement: currentIntersectingElementId,
|
|
207
|
+
shadow: currentShadowPosition,
|
|
208
|
+
overlapped
|
|
209
|
+
});
|
|
184
210
|
};
|
|
185
211
|
export function updateMove(newCoordDiff, clientY) {
|
|
186
212
|
if (!active) {
|
|
@@ -220,6 +246,37 @@ export function updateMove(newCoordDiff, clientY) {
|
|
|
220
246
|
update();
|
|
221
247
|
}
|
|
222
248
|
}
|
|
249
|
+
let element = undefined;
|
|
250
|
+
function computeShadow(clientX, clientY) {
|
|
251
|
+
const elementsAtPoint = document.elementsFromPoint(clientX, clientY);
|
|
252
|
+
const intersectingElement = elementsAtPoint.find((el) => el.id !== divId &&
|
|
253
|
+
el.classList.contains('svlt-grid-item') &&
|
|
254
|
+
el.getAttribute('data-iscontainer') === 'true');
|
|
255
|
+
const newOverlapped = intersectingElement ? intersectingElement?.id.split('-')[1] : undefined;
|
|
256
|
+
const container = newOverlapped
|
|
257
|
+
? intersectingElement?.querySelector('.svlt-grid-container')
|
|
258
|
+
: document.getElementById('root-grid');
|
|
259
|
+
const xPerPxComputed = Number(container?.getAttribute('data-xperpx')) ?? xPerPx;
|
|
260
|
+
const position = computePosition(clientX, clientY, xPerPxComputed, yPerPx, newOverlapped, element);
|
|
261
|
+
if (overlapped !== newOverlapped) {
|
|
262
|
+
currentShadowPosition = undefined;
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
// Update shared state
|
|
266
|
+
currentShadowPosition = {
|
|
267
|
+
x: position.x,
|
|
268
|
+
y: position.y,
|
|
269
|
+
xPerPx: xPerPxComputed,
|
|
270
|
+
yPerPx,
|
|
271
|
+
h: item.h,
|
|
272
|
+
w: item.w
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
currentIntersectingElementId = newOverlapped;
|
|
276
|
+
}
|
|
277
|
+
const throttledComputeShadow = throttle((clientX, clientY) => {
|
|
278
|
+
computeShadow(clientX, clientY);
|
|
279
|
+
}, 50);
|
|
223
280
|
const pointerup = (e) => {
|
|
224
281
|
ctx.componentActive.set(false);
|
|
225
282
|
stopAutoscroll();
|
|
@@ -232,6 +289,19 @@ const pointerup = (e) => {
|
|
|
232
289
|
else {
|
|
233
290
|
dragClosure = undefined;
|
|
234
291
|
}
|
|
292
|
+
if (!moving) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const parent = findGridItemParentGrid($app, id);
|
|
296
|
+
if (overlapped && (overlapped === parent || parent?.startsWith(overlapped))) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
dispatch('dropped', {
|
|
300
|
+
id,
|
|
301
|
+
overlapped,
|
|
302
|
+
x: fakeShadow?.x,
|
|
303
|
+
y: fakeShadow?.y
|
|
304
|
+
});
|
|
235
305
|
};
|
|
236
306
|
let resizeInitPos = { x: 0, y: 0 };
|
|
237
307
|
let initSize = { width: 0, height: 0 };
|
|
@@ -252,6 +322,7 @@ const resizePointerDown = (e, o) => {
|
|
|
252
322
|
scrollElement = getScroller(container);
|
|
253
323
|
window.addEventListener('pointermove', resizePointerMove);
|
|
254
324
|
window.addEventListener('pointerup', resizePointerUp);
|
|
325
|
+
dispatch('resizeStart');
|
|
255
326
|
};
|
|
256
327
|
const resizePointerMove = ({ pageX, pageY }) => {
|
|
257
328
|
if (shadow) {
|
|
@@ -281,15 +352,33 @@ const resizePointerUp = (e) => {
|
|
|
281
352
|
repaint(true, true);
|
|
282
353
|
window.removeEventListener('pointermove', resizePointerMove);
|
|
283
354
|
window.removeEventListener('pointerup', resizePointerUp);
|
|
355
|
+
dispatch('resizeEnd');
|
|
284
356
|
};
|
|
357
|
+
function shouldDisplayShadow(moveMode, overlapped) {
|
|
358
|
+
if (moveMode === 'move') {
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
const parent = findGridItemParentGrid($app, id);
|
|
362
|
+
if (parent === undefined) {
|
|
363
|
+
return overlapped === undefined;
|
|
364
|
+
}
|
|
365
|
+
else if (overlapped) {
|
|
366
|
+
return parent.startsWith(overlapped);
|
|
367
|
+
}
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
285
370
|
</script>
|
|
286
371
|
|
|
287
372
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
373
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
288
374
|
<div
|
|
375
|
+
bind:this={element}
|
|
289
376
|
draggable="false"
|
|
290
377
|
on:pointerdown|stopPropagation|preventDefault={pointerdown}
|
|
291
378
|
id={divId}
|
|
292
379
|
class="svlt-grid-item"
|
|
380
|
+
data-iscontainer={type ? isContainer(type) : false}
|
|
381
|
+
data-componenttype={type}
|
|
293
382
|
class:svlt-grid-active={active || (trans && rect)}
|
|
294
383
|
style="width: {xPerPx == 0 ? 0 : active ? newSize.width : width}px; height:{xPerPx == 0
|
|
295
384
|
? 0
|
|
@@ -308,16 +397,24 @@ const resizePointerUp = (e) => {
|
|
|
308
397
|
} transform: translate(${left}px, ${top}px); `} "
|
|
309
398
|
>
|
|
310
399
|
<slot />
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
400
|
+
{#if moveMode === 'move'}
|
|
401
|
+
<div
|
|
402
|
+
class="svlt-grid-resizer-bottom"
|
|
403
|
+
on:pointerdown={(e) => resizePointerDown(e, 'vertical')}
|
|
404
|
+
/>
|
|
405
|
+
<div
|
|
406
|
+
class="svlt-grid-resizer-side"
|
|
407
|
+
on:pointerdown={(e) => resizePointerDown(e, 'horizontal')}
|
|
408
|
+
/>
|
|
409
|
+
<div class="svlt-grid-resizer" on:pointerdown={(e) => resizePointerDown(e, 'both')} />
|
|
410
|
+
{/if}
|
|
314
411
|
</div>
|
|
315
412
|
|
|
316
413
|
{#if xPerPx > 0 && (active || trans) && shadow}
|
|
317
414
|
<div
|
|
318
415
|
class={twMerge(
|
|
319
416
|
'svlt-grid-shadow shadow-active',
|
|
320
|
-
overlapped ? '
|
|
417
|
+
shouldDisplayShadow(moveMode, overlapped) ? '' : 'hidden'
|
|
321
418
|
)}
|
|
322
419
|
style="width: {shadow.w * xPerPx - gapX * 2}px; height: {shadow.h * yPerPx -
|
|
323
420
|
gapY * 2}px; transform: translate({shadow.x * xPerPx + gapX}px, {shadow.y * yPerPx +
|
|
@@ -408,8 +505,4 @@ const resizePointerUp = (e) => {
|
|
|
408
505
|
backface-visibility: hidden;
|
|
409
506
|
-webkit-backface-visibility: hidden;
|
|
410
507
|
background: #93c4fdd0;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
.svlte-grid-shadow-forbidden {
|
|
414
|
-
background: rgba(255, 99, 71, 0.2) !important;
|
|
415
508
|
}</style>
|