windmill-components 1.82.10 → 1.82.12

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 (62) hide show
  1. package/components/ArgInput.svelte +0 -6
  2. package/components/FlowBuilder.svelte +5 -0
  3. package/components/LightweightArgInput.svelte +0 -5
  4. package/components/Toggle.svelte +1 -1
  5. package/components/Toggle.svelte.d.ts +0 -1
  6. package/components/apps/components/buttons/AppButton.svelte +1 -1
  7. package/components/apps/components/buttons/AppForm.svelte +0 -1
  8. package/components/apps/components/buttons/AppFormButton.svelte +0 -1
  9. package/components/apps/components/display/AppMap.svelte +1 -1
  10. package/components/apps/components/display/AppPdf.svelte +1 -1
  11. package/components/apps/components/display/table/AppAggridTable.svelte +1 -1
  12. package/components/apps/components/display/table/AppTable.svelte +6 -6
  13. package/components/apps/components/helpers/HiddenComponent.svelte +3 -2
  14. package/components/apps/components/helpers/HiddenComponent.svelte.d.ts +2 -1
  15. package/components/apps/components/helpers/RefreshButton.svelte +3 -10
  16. package/components/apps/components/helpers/RefreshButton.svelte.d.ts +1 -0
  17. package/components/apps/components/helpers/RunnableComponent.svelte +8 -7
  18. package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +1 -1
  19. package/components/apps/components/helpers/RunnableWrapper.svelte +1 -1
  20. package/components/apps/components/inputs/AppCheckbox.svelte +0 -4
  21. package/components/apps/components/inputs/AppDateInput.svelte +2 -2
  22. package/components/apps/components/inputs/AppMultiSelect.svelte +3 -3
  23. package/components/apps/components/inputs/AppNumberInput.svelte +3 -3
  24. package/components/apps/components/inputs/AppSelect.svelte +3 -4
  25. package/components/apps/components/inputs/AppSliderInputs.svelte +1 -1
  26. package/components/apps/components/inputs/AppTextInput.svelte +7 -10
  27. package/components/apps/components/inputs/currency/AppCurrencyInput.svelte +1 -1
  28. package/components/apps/components/layout/AppContainer.svelte +2 -2
  29. package/components/apps/components/layout/AppDrawer.svelte +1 -2
  30. package/components/apps/components/layout/AppSplitpanes.svelte +3 -3
  31. package/components/apps/components/layout/AppTabs.svelte +1 -1
  32. package/components/apps/editor/AppEditor.svelte +5 -6
  33. package/components/apps/editor/AppEditorHeader.svelte +5 -0
  34. package/components/apps/editor/AppPreview.svelte +5 -4
  35. package/components/apps/editor/ComponentHeader.svelte +1 -0
  36. package/components/apps/editor/ComponentHeader.svelte.d.ts +1 -1
  37. package/components/apps/editor/GridEditor.svelte +10 -9
  38. package/components/apps/editor/RecomputeAllComponents.svelte +5 -7
  39. package/components/apps/editor/SettingsPanel.svelte +3 -3
  40. package/components/apps/editor/SubGridEditor.svelte +11 -11
  41. package/components/apps/editor/component/Component.svelte +4 -3
  42. package/components/apps/editor/component/ComponentNavigation.svelte +55 -46
  43. package/components/apps/editor/componentsPanel/ComponentList.svelte +1 -1
  44. package/components/apps/editor/contextPanel/ComponentOutput.svelte +2 -2
  45. package/components/apps/editor/contextPanel/components/BackgroundScriptOutput.svelte +2 -2
  46. package/components/apps/editor/contextPanel/components/OutputHeader.svelte +6 -3
  47. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +3 -3
  48. package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +2 -2
  49. package/components/apps/editor/settingsPanel/ComponentPanel.svelte +4 -0
  50. package/components/apps/editor/settingsPanel/TableActions.svelte +3 -3
  51. package/components/apps/editor/settingsPanel/triggerLists/ComponentTriggerList.svelte +1 -1
  52. package/components/apps/svelte-grid/Grid.svelte +45 -26
  53. package/components/apps/svelte-grid/Grid.svelte.d.ts +13 -3
  54. package/components/apps/svelte-grid/MoveResize.svelte +74 -54
  55. package/components/apps/svelte-grid/MoveResize.svelte.d.ts +14 -1
  56. package/components/apps/svelte-grid/utils/helper.d.ts +0 -1
  57. package/components/apps/svelte-grid/utils/helper.js +0 -3
  58. package/components/apps/types.d.ts +6 -3
  59. package/components/apps/utils.d.ts +2 -0
  60. package/components/apps/utils.js +30 -1
  61. package/infer.js +3 -1
  62. package/package.json +1 -1
@@ -28,7 +28,6 @@ const connectingInput = writable({
28
28
  input: undefined,
29
29
  hoveredComponent: undefined
30
30
  });
31
- const runnableComponents = writable({});
32
31
  const parentWidth = writable(0);
33
32
  setContext('AppViewerContext', {
34
33
  worldStore: buildWorld(context),
@@ -38,7 +37,7 @@ setContext('AppViewerContext', {
38
37
  mode,
39
38
  connectingInput,
40
39
  breakpoint,
41
- runnableComponents,
40
+ runnableComponents: writable({}),
42
41
  appPath,
43
42
  workspace,
44
43
  onchange: undefined,
@@ -100,7 +99,7 @@ $: lockedClasses = isLocked ? '!max-h-[400px] overflow-hidden pointer-events-non
100
99
  >
101
100
  <div>
102
101
  <GridViewer
103
- onTopId={$selectedComponent}
102
+ onTopId={$selectedComponent?.[0]}
104
103
  items={app.grid}
105
104
  let:dataItem
106
105
  rowHeight={36}
@@ -110,7 +109,7 @@ $: lockedClasses = isLocked ? '!max-h-[400px] overflow-hidden pointer-events-non
110
109
  <!-- svelte-ignore a11y-click-events-have-key-events -->
111
110
  <div
112
111
  class={'h-full w-full center-center'}
113
- on:pointerdown={() => ($selectedComponent = dataItem.id)}
112
+ on:pointerdown={() => ($selectedComponent = [dataItem.id])}
114
113
  >
115
114
  <Component render={true} component={dataItem.data} selected={false} locked={true} />
116
115
  </div>
@@ -141,6 +140,8 @@ $: lockedClasses = isLocked ? '!max-h-[400px] overflow-hidden pointer-events-non
141
140
  inlineScript={script.inlineScript}
142
141
  name={script.name}
143
142
  fields={script.fields}
143
+ doNotRecomputeOnInputChanged={script.doNotRecomputeOnInputChanged ?? false}
144
+ recomputableByRefreshButton={script.autoRefresh ?? false}
144
145
  />
145
146
  {/if}
146
147
  {/each}
@@ -21,6 +21,7 @@ function openDebugRuns() {
21
21
 
22
22
  {#if selected || hover}
23
23
  <span
24
+ on:mousedown|stopPropagation|capture
24
25
  draggable="false"
25
26
  title={`Id: ${component.id}`}
26
27
  class={twMerge(
@@ -8,8 +8,8 @@ declare const __propDef: {
8
8
  hover?: boolean | undefined;
9
9
  };
10
10
  events: {
11
- pointerdown: PointerEvent;
12
11
  mousedown: MouseEvent;
12
+ pointerdown: PointerEvent;
13
13
  expand: CustomEvent<any>;
14
14
  lock: CustomEvent<any>;
15
15
  } & {
@@ -8,7 +8,7 @@ import Component from './component/Component.svelte';
8
8
  import { push } from '../../../history';
9
9
  import { expandGriditem, findGridItem } from './appUtils';
10
10
  import Grid from '../svelte-grid/Grid.svelte';
11
- import Toggle from '../../Toggle.svelte';
11
+ import { selectId } from '../utils';
12
12
  export let policy;
13
13
  const { selectedComponent, app, mode, connectingInput, runnableComponents, summary, focusedGrid, parentWidth, breakpoint } = getContext('AppViewerContext');
14
14
  const { history } = getContext('AppEditorContext');
@@ -37,9 +37,9 @@ function removeGridElement(component) {
37
37
  $selectedComponent = undefined;
38
38
  }
39
39
  }
40
- function selectComponent(id) {
40
+ function selectComponent(e, id) {
41
41
  if (!$connectingInput.opened) {
42
- $selectedComponent = id;
42
+ selectId(e, id, selectedComponent, $app);
43
43
  if ($focusedGrid?.parentComponentId != id) {
44
44
  $focusedGrid = undefined;
45
45
  }
@@ -81,7 +81,7 @@ function selectComponent(id) {
81
81
  >
82
82
  <div class={!$focusedGrid && $mode !== 'preview' ? 'border-gray-400 border border-dashed' : ''}>
83
83
  <Grid
84
- onTopId={$selectedComponent}
84
+ selectedIds={$selectedComponent}
85
85
  items={$app.grid}
86
86
  on:redraw={(e) => {
87
87
  push(history, $app)
@@ -109,16 +109,16 @@ function selectComponent(id) {
109
109
  {/if}
110
110
  <!-- svelte-ignore a11y-click-events-have-key-events -->
111
111
  <div
112
- on:pointerdown={() => selectComponent(dataItem.id)}
112
+ on:pointerdown={(e) => selectComponent(e, dataItem.id)}
113
113
  class={classNames(
114
114
  'h-full w-full center-center',
115
- $selectedComponent === dataItem.id ? 'active-grid-item' : ''
115
+ Boolean($selectedComponent?.includes(dataItem.id)) ? 'active-grid-item' : ''
116
116
  )}
117
117
  >
118
118
  <Component
119
119
  render={true}
120
120
  component={dataItem.data}
121
- selected={$selectedComponent === dataItem.id}
121
+ selected={Boolean($selectedComponent?.includes(dataItem.id))}
122
122
  locked={isFixed(dataItem)}
123
123
  on:delete={() => removeGridElement(dataItem.data)}
124
124
  on:lock={() => {
@@ -130,7 +130,7 @@ function selectComponent(id) {
130
130
  }}
131
131
  on:expand={() => {
132
132
  push(history, $app)
133
- $selectedComponent = dataItem.id
133
+ $selectedComponent = [dataItem.id]
134
134
  expandGriditem($app.grid, dataItem.id, $breakpoint)
135
135
  $app = $app
136
136
  }}
@@ -149,7 +149,8 @@ function selectComponent(id) {
149
149
  inlineScript={script.inlineScript}
150
150
  name={script.name}
151
151
  fields={script.fields}
152
- doNotRecomputeOnInputChanged={script.doNotRecomputeOnInputChanged}
152
+ doNotRecomputeOnInputChanged={script.doNotRecomputeOnInputChanged ?? false}
153
+ recomputableByRefreshButton={script.autoRefresh ?? false}
153
154
  />
154
155
  {/if}
155
156
  {/each}
@@ -13,7 +13,7 @@ $: !firstLoad &&
13
13
  $worldStore.initializedOutputs ==
14
14
  allItems($app.grid, $app.subgrids).length + $app.hiddenInlineScripts.length &&
15
15
  refresh();
16
- $: componentNumber = Object.keys($runnableComponents).length;
16
+ $: componentNumber = Object.values($runnableComponents).filter((x) => x.autoRefresh).length;
17
17
  function onClick(stopAfterClear = true) {
18
18
  if (timeout) {
19
19
  clearInterval(timeout);
@@ -39,13 +39,10 @@ function refresh() {
39
39
  }
40
40
  loading = true;
41
41
  Promise.all(Object.keys($runnableComponents).map((id) => {
42
- if (id.startsWith('bg_')) {
43
- let index = parseInt(id.split('_')[1]);
44
- if (!$app.hiddenInlineScripts[index]?.autoRefresh) {
45
- return;
46
- }
42
+ if (!$runnableComponents?.[id]?.autoRefresh) {
43
+ return;
47
44
  }
48
- return $runnableComponents?.[id]?.();
45
+ return $runnableComponents?.[id]?.cb?.();
49
46
  })).finally(() => {
50
47
  loading = false;
51
48
  });
@@ -74,6 +71,7 @@ onMount(() => {
74
71
 
75
72
  <div class="flex items-center">
76
73
  <Button
74
+ disabled={componentNumber == 0}
77
75
  on:click={() => onClick()}
78
76
  color={timeout ? 'blue' : 'light'}
79
77
  variant={timeout ? 'contained' : 'border'}
@@ -10,9 +10,9 @@ import BackgroundScriptTriggerList from './settingsPanel/triggerLists/Background
10
10
  const { selectedComponent, app, stateId } = getContext('AppViewerContext');
11
11
  $: hiddenInlineScript = $app?.hiddenInlineScripts
12
12
  ?.map((x, i) => ({ script: x, index: i }))
13
- .find(({ script, index }) => `bg_${index}` === $selectedComponent);
14
- $: componentSettings = findComponentSettings($app, $selectedComponent);
15
- $: tableActionSettings = findTableActionSettings($app, $selectedComponent);
13
+ .find(({ script, index }) => $selectedComponent?.includes(`bg_${index}`));
14
+ $: componentSettings = findComponentSettings($app, $selectedComponent?.[0]);
15
+ $: tableActionSettings = findTableActionSettings($app, $selectedComponent?.[0]);
16
16
  function findTableActionSettings(app, id) {
17
17
  return allItems(app.grid, app.subgrids)
18
18
  .map((x) => {
@@ -7,6 +7,7 @@ import { expandGriditem, findGridItem } from './appUtils';
7
7
  import { push } from '../../../history';
8
8
  import Grid from '../svelte-grid/Grid.svelte';
9
9
  import GridViewer from './GridViewer.svelte';
10
+ import { selectId } from '../utils';
10
11
  export let containerHeight = undefined;
11
12
  export let containerWidth = undefined;
12
13
  let classes = '';
@@ -25,10 +26,9 @@ $: highlight = id === $focusedGrid?.parentComponentId && shouldHighlight;
25
26
  const onpointerdown = (e) => {
26
27
  dispatch('focus');
27
28
  };
28
- function selectComponent(id) {
29
+ function selectComponent(e, id) {
29
30
  if (!$connectingInput.opened) {
30
- dispatch('focus');
31
- $selectedComponent = id;
31
+ selectId(e, id, selectedComponent, $app);
32
32
  }
33
33
  }
34
34
  function lock(dataItem) {
@@ -67,7 +67,7 @@ let container = undefined;
67
67
  $app.subgrids[subGridId] = e.detail
68
68
  }
69
69
  }}
70
- onTopId={$selectedComponent}
70
+ selectedIds={$selectedComponent}
71
71
  let:dataItem
72
72
  rowHeight={36}
73
73
  cols={columnConfiguration}
@@ -94,17 +94,17 @@ let container = undefined;
94
94
 
95
95
  <!-- svelte-ignore a11y-click-events-have-key-events -->
96
96
  <div
97
- on:pointerdown={() => selectComponent(dataItem.id)}
97
+ on:pointerdown={(e) => selectComponent(e, dataItem.id)}
98
98
  class={classNames(
99
99
  'h-full w-full center-center',
100
- $selectedComponent === dataItem.id ? 'active-grid-item' : '',
100
+ $selectedComponent?.includes(dataItem.id) ? 'active-grid-item' : '',
101
101
  'top-0'
102
102
  )}
103
103
  >
104
104
  <Component
105
105
  render={visible}
106
106
  component={dataItem.data}
107
- selected={$selectedComponent === dataItem.id}
107
+ selected={Boolean($selectedComponent?.includes(dataItem.id))}
108
108
  locked={isFixed(dataItem)}
109
109
  on:lock={() => lock(dataItem)}
110
110
  on:expand={() => {
@@ -113,7 +113,7 @@ let container = undefined;
113
113
  if (!parentGridItem) {
114
114
  return
115
115
  }
116
- $selectedComponent = dataItem.id
116
+ $selectedComponent = [dataItem.id]
117
117
  push(editorContext?.history, $app)
118
118
 
119
119
  expandGriditem(
@@ -130,7 +130,7 @@ let container = undefined;
130
130
  </div>
131
131
  {:else}
132
132
  <GridViewer
133
- onTopId={$selectedComponent}
133
+ onTopId={$selectedComponent?.[0]}
134
134
  items={$app.subgrids?.[subGridId] ?? []}
135
135
  let:dataItem
136
136
  rowHeight={36}
@@ -141,13 +141,13 @@ let container = undefined;
141
141
  >
142
142
  <!-- svelte-ignore a11y-click-events-have-key-events -->
143
143
  <div
144
- on:pointerdown={() => selectComponent(dataItem.id)}
144
+ on:pointerdown|stopPropagation={(e) => selectComponent(e, dataItem.id)}
145
145
  class={classNames('h-full w-full center-center', 'top-0')}
146
146
  >
147
147
  <Component
148
148
  render={visible}
149
149
  component={dataItem.data}
150
- selected={$selectedComponent === dataItem.id}
150
+ selected={Boolean($selectedComponent?.includes(dataItem.id))}
151
151
  locked={isFixed(dataItem)}
152
152
  />
153
153
  </div>
@@ -11,8 +11,9 @@ export let locked = false;
11
11
  export let render;
12
12
  const { mode, app, errorByComponent, hoverStore } = getContext('AppViewerContext');
13
13
  const editorContext = getContext('AppEditorContext');
14
- const movingcomponent = editorContext?.movingcomponent;
15
- $: ismoving = movingcomponent != undefined && $mode == 'dnd' && $movingcomponent === component.id;
14
+ const movingcomponents = editorContext?.movingcomponents;
15
+ $: ismoving =
16
+ movingcomponents != undefined && $mode == 'dnd' && $movingcomponents?.includes(component.id);
16
17
  let initializing = undefined;
17
18
  let componentContainerHeight = 0;
18
19
  $: componentWithErrors = Object.values($errorByComponent).map((e) => e.componentId);
@@ -50,7 +51,7 @@ $: hasError = componentWithErrors.includes(component.id);
50
51
  <button
51
52
  class="border p-0.5 text-xs"
52
53
  on:click={() => {
53
- $movingcomponent = undefined
54
+ $movingcomponents = undefined
54
55
  }}>Cancel move</button
55
56
  >
56
57
  </div>
@@ -4,9 +4,9 @@ import { push } from '../../../../history';
4
4
  import { sendUserToast } from '../../../../utils';
5
5
  import { gridColumns } from '../../gridUtils';
6
6
  const { app, selectedComponent, worldStore, focusedGrid, componentControl } = getContext('AppViewerContext');
7
- const { history, movingcomponent } = getContext('AppEditorContext');
8
- let tempGridItem = undefined;
9
- let copiedGridItem = undefined;
7
+ const { history, movingcomponents } = getContext('AppEditorContext');
8
+ let tempGridItems = undefined;
9
+ let copiedGridItems = undefined;
10
10
  function getSortedGridItemsOfChildren() {
11
11
  if (!$focusedGrid) {
12
12
  return $app.grid;
@@ -17,48 +17,48 @@ function getSortedGridItemsOfChildren() {
17
17
  return $app.subgrids[`${$focusedGrid.parentComponentId}-${$focusedGrid.subGridIndex}`] ?? [];
18
18
  }
19
19
  function getGridItems() {
20
- if ($app.grid.find((item) => item.id === $selectedComponent)) {
20
+ if ($app.grid.find((item) => item.id === $selectedComponent?.[0])) {
21
21
  return $app.grid;
22
22
  }
23
23
  if (!$app.subgrids) {
24
24
  return [];
25
25
  }
26
- return (Object.values($app.subgrids ?? {}).find((grid) => grid.find((item) => item.id === $selectedComponent)) ?? []);
26
+ return (Object.values($app.subgrids ?? {}).find((grid) => grid.find((item) => item.id === $selectedComponent?.[0])) ?? []);
27
27
  }
28
28
  function left(event) {
29
- if (!$componentControl[$selectedComponent]?.left?.()) {
29
+ if (!$componentControl[$selectedComponent?.[0] ?? '']?.left?.()) {
30
30
  const sortedGridItems = getGridItems();
31
- const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent);
31
+ const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent?.[0] ?? '');
32
32
  if (currentIndex !== -1 && currentIndex > 0) {
33
33
  const left = sortedGridItems[currentIndex - 1];
34
34
  if (left.data.type === 'tablecomponent' && left.data.actionButtons.length >= 1) {
35
- $selectedComponent = left.data.actionButtons[left.data.actionButtons.length - 1].id;
35
+ $selectedComponent = [left.data.actionButtons[left.data.actionButtons.length - 1].id];
36
36
  }
37
37
  else {
38
- $selectedComponent = left.id;
38
+ $selectedComponent = [left.id];
39
39
  }
40
40
  }
41
41
  }
42
42
  event.preventDefault();
43
43
  }
44
44
  function right(event) {
45
- let r = $componentControl[$selectedComponent]?.right?.();
45
+ let r = $componentControl[$selectedComponent?.[0] ?? '']?.right?.();
46
46
  if (typeof r === 'string') {
47
- $selectedComponent = r;
47
+ $selectedComponent = [r];
48
48
  r = $componentControl[r]?.right?.(true);
49
49
  }
50
50
  if (!r) {
51
51
  const sortedGridItems = getGridItems();
52
- const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent);
52
+ const currentIndex = sortedGridItems.findIndex((item) => item.id === $selectedComponent?.[0] ?? '');
53
53
  if (currentIndex !== -1 && currentIndex < sortedGridItems.length - 1) {
54
- $selectedComponent = sortedGridItems[currentIndex + 1].id;
54
+ $selectedComponent = [sortedGridItems[currentIndex + 1].id];
55
55
  }
56
56
  }
57
57
  event.preventDefault();
58
58
  }
59
59
  function down(event) {
60
60
  if (!$focusedGrid) {
61
- $selectedComponent = getSortedGridItemsOfChildren()[0]?.id;
61
+ $selectedComponent = [getSortedGridItemsOfChildren()[0]?.id];
62
62
  event.preventDefault();
63
63
  }
64
64
  else if ($app.subgrids) {
@@ -68,7 +68,7 @@ function down(event) {
68
68
  return;
69
69
  }
70
70
  if (subgrid) {
71
- $selectedComponent = subgrid[0].id;
71
+ $selectedComponent = [subgrid[0].id];
72
72
  }
73
73
  event.preventDefault();
74
74
  }
@@ -81,9 +81,9 @@ function handleEscape(event) {
81
81
  function handleArrowUp(event) {
82
82
  if (!$selectedComponent)
83
83
  return;
84
- let parentId = findGridItemParentGrid($app, $selectedComponent)?.split('-')[0];
84
+ let parentId = findGridItemParentGrid($app, $selectedComponent?.[0])?.split('-')[0];
85
85
  if (parentId) {
86
- $selectedComponent = parentId;
86
+ $selectedComponent = [parentId];
87
87
  }
88
88
  else {
89
89
  $selectedComponent = undefined;
@@ -94,49 +94,58 @@ function handleCopy(event) {
94
94
  if (!$selectedComponent) {
95
95
  return;
96
96
  }
97
- tempGridItem = undefined;
98
- copiedGridItem = findGridItem($app, $selectedComponent);
97
+ tempGridItems = undefined;
98
+ copiedGridItems = $selectedComponent
99
+ .map((x) => findGridItem($app, x))
100
+ .filter((x) => x != undefined);
99
101
  }
100
102
  function handleCut(event) {
101
103
  if (!$selectedComponent) {
102
104
  return;
103
105
  }
104
- $movingcomponent = $selectedComponent;
106
+ $movingcomponents = JSON.parse(JSON.stringify($selectedComponent));
105
107
  push(history, $app);
106
- const gridItem = findGridItem($app, $selectedComponent);
107
- copiedGridItem = gridItem;
108
- if (!gridItem) {
108
+ let gridItems = $selectedComponent
109
+ .map((x) => findGridItem($app, x))
110
+ .filter((x) => x != undefined);
111
+ copiedGridItems = gridItems;
112
+ if (!gridItems) {
109
113
  return;
110
114
  }
111
115
  // Store the grid item in a temp variable so we can paste it later
112
- tempGridItem = gridItem;
116
+ tempGridItems = gridItems;
113
117
  }
114
118
  function handlePaste(event) {
115
119
  push(history, $app);
116
- $movingcomponent = undefined;
117
- if (tempGridItem != undefined) {
118
- if ($focusedGrid &&
119
- getAllSubgridsAndComponentIds($app, tempGridItem.data)[0].includes(`${$focusedGrid.parentComponentId}-${$focusedGrid.subGridIndex}`)) {
120
- sendUserToast('Cannot paste a component into itself', true);
121
- return;
122
- }
123
- let parentGrid = findGridItemParentGrid($app, tempGridItem.id);
124
- if (parentGrid) {
125
- $app.subgrids &&
126
- ($app.subgrids[parentGrid] = $app.subgrids[parentGrid].filter((item) => item.id !== tempGridItem?.id));
120
+ $movingcomponents = undefined;
121
+ if (tempGridItems != undefined) {
122
+ for (let tempGridItem of tempGridItems) {
123
+ if ($focusedGrid &&
124
+ getAllSubgridsAndComponentIds($app, tempGridItem.data)[0].includes(`${$focusedGrid.parentComponentId}-${$focusedGrid.subGridIndex}`)) {
125
+ sendUserToast('Cannot paste a component into itself', true);
126
+ return;
127
+ }
128
+ let parentGrid = findGridItemParentGrid($app, tempGridItem.id);
129
+ if (parentGrid) {
130
+ $app.subgrids &&
131
+ ($app.subgrids[parentGrid] = $app.subgrids[parentGrid].filter((item) => item.id !== tempGridItem?.id));
132
+ }
133
+ else {
134
+ $app.grid = $app.grid.filter((item) => item.id !== tempGridItem?.id);
135
+ }
136
+ const gridItem = tempGridItem;
137
+ insertNewGridItem($app, (id) => ({ ...gridItem.data, id }), $focusedGrid, Object.fromEntries(gridColumns.map((column) => [column, gridItem[column]])), tempGridItem.id);
127
138
  }
128
- else {
129
- $app.grid = $app.grid.filter((item) => item.id !== tempGridItem?.id);
139
+ copiedGridItems = tempGridItems;
140
+ $selectedComponent = tempGridItems.map((x) => x.id);
141
+ tempGridItems = undefined;
142
+ }
143
+ else if (copiedGridItems) {
144
+ let nitems = [];
145
+ for (let copiedGridItem of copiedGridItems) {
146
+ nitems.push(insertNewGridItem($app, (id) => ({ ...copiedGridItem.data, id }), $focusedGrid, Object.fromEntries(gridColumns.map((column) => [column, copiedGridItem[column]]))));
130
147
  }
131
- const gridItem = tempGridItem;
132
- insertNewGridItem($app, (id) => ({ ...gridItem.data, id }), $focusedGrid, Object.fromEntries(gridColumns.map((column) => [column, gridItem[column]])), tempGridItem.id);
133
- copiedGridItem = tempGridItem;
134
- $selectedComponent = tempGridItem.id;
135
- tempGridItem = undefined;
136
- }
137
- else if (copiedGridItem) {
138
- const gridItem = copiedGridItem;
139
- $selectedComponent = insertNewGridItem($app, (id) => ({ ...gridItem.data, id }), $focusedGrid, Object.fromEntries(gridColumns.map((column) => [column, gridItem[column]])));
148
+ $selectedComponent = nitems.map((x) => x);
140
149
  }
141
150
  $worldStore = $worldStore;
142
151
  $app = $app;
@@ -13,7 +13,7 @@ function addComponent(appComponentType) {
13
13
  push(history, $app);
14
14
  $dirtyStore = true;
15
15
  const id = insertNewGridItem($app, appComponentFromType(appComponentType), $focusedGrid);
16
- $selectedComponent = id;
16
+ $selectedComponent = [id];
17
17
  $app = $app;
18
18
  $worldStore = $worldStore;
19
19
  }
@@ -30,14 +30,14 @@ $: subGrids = Array.from({ length: gridItem.data.numberOfSubgrids ?? 0 }).map((_
30
30
  function onHeaderClick(manuallyOpen) {
31
31
  if (manuallyOpen) {
32
32
  if (parentId) {
33
- $selectedComponent = parentId;
33
+ $selectedComponent = [parentId];
34
34
  }
35
35
  else {
36
36
  $selectedComponent = undefined;
37
37
  }
38
38
  }
39
39
  else {
40
- $selectedComponent = gridItem.id;
40
+ $selectedComponent = [gridItem.id];
41
41
  }
42
42
  }
43
43
  </script>
@@ -9,14 +9,14 @@ export let first = false;
9
9
  function onHeaderClick(manuallyOpen) {
10
10
  if (manuallyOpen) {
11
11
  if (id) {
12
- $selectedComponent = id;
12
+ $selectedComponent = [id];
13
13
  }
14
14
  else {
15
15
  $selectedComponent = undefined;
16
16
  }
17
17
  }
18
18
  else {
19
- $selectedComponent = id;
19
+ $selectedComponent = [id];
20
20
  }
21
21
  }
22
22
  </script>
@@ -15,7 +15,10 @@ $: inSearch =
15
15
  ($hasResult[id] ||
16
16
  Object.entries($hasResult).some(([key, value]) => value && subids.includes(key)));
17
17
  $: open =
18
- $expanded || subids.includes($selectedComponent ?? '') || $manuallyOpened[id] || inSearch;
18
+ $expanded ||
19
+ subids.some((x) => $selectedComponent?.includes(x)) ||
20
+ $manuallyOpened[id] ||
21
+ inSearch;
19
22
  const dispatch = createEventDispatcher();
20
23
  const hoverColor = {
21
24
  blue: 'hover:bg-blue-300 hover:text-blue-600',
@@ -52,7 +55,7 @@ const idClass = {
52
55
  class={classNames(
53
56
  'flex items-center justify-between p-1 cursor-pointer border-b gap-1 truncate',
54
57
  hoverColor[color],
55
- $selectedComponent == id ? openBackground[color] : 'bg-white',
58
+ $selectedComponent?.includes(id) ? openBackground[color] : 'bg-white',
56
59
  first ? 'border-t' : '',
57
60
  nested ? 'border-l' : ''
58
61
  )}
@@ -64,7 +67,7 @@ const idClass = {
64
67
  <div
65
68
  class={classNames(
66
69
  'text-2xs ml-0.5 font-bold px-2 py-0.5 rounded-sm',
67
- $selectedComponent == id ? idClass[color] : ' bg-gray-100'
70
+ $selectedComponent?.includes(id) ? idClass[color] : ' bg-gray-100'
68
71
  )}
69
72
  >
70
73
  {id}
@@ -163,7 +163,7 @@ function handleRefreshOn(refreshOn) {
163
163
  btnClasses="!px-2 !py-1 !bg-gray-700 !text-white hover:!bg-gray-900"
164
164
  on:click={async () => {
165
165
  runLoading = true
166
- await $runnableComponents[id]?.(!transformer ? inlineScript : undefined)
166
+ await $runnableComponents[id]?.cb?.(!transformer ? inlineScript : undefined)
167
167
  runLoading = false
168
168
  }}
169
169
  >
@@ -199,7 +199,7 @@ function handleRefreshOn(refreshOn) {
199
199
  inlineScript.content = editor?.getCode() ?? ''
200
200
  }
201
201
  runLoading = true
202
- await $runnableComponents[id]?.(inlineScript)
202
+ await $runnableComponents[id]?.cb?.(inlineScript)
203
203
  runLoading = false
204
204
  }}
205
205
  on:change={async (e) => {
@@ -222,7 +222,7 @@ function handleRefreshOn(refreshOn) {
222
222
  bind:this={simpleEditor}
223
223
  cmdEnterAction={async () => {
224
224
  runLoading = true
225
- await $runnableComponents[id]?.(!transformer ? inlineScript : undefined)
225
+ await $runnableComponents[id]?.cb?.(!transformer ? inlineScript : undefined)
226
226
  runLoading = false
227
227
  }}
228
228
  class="h-full"
@@ -11,14 +11,14 @@ const { selectedComponentInEditor } = getContext('AppEditorContext');
11
11
  function selectScript(id) {
12
12
  $selectedComponentInEditor = id;
13
13
  if (!id.startsWith('unused-') || !id.startsWith('bg_')) {
14
- $selectedComponent = $selectedComponentInEditor.split('_transformer')[0];
14
+ $selectedComponent = [$selectedComponentInEditor.split('_transformer')[0]];
15
15
  }
16
16
  }
17
17
  $: runnables = getAppScripts($app.grid, $app.subgrids);
18
18
  // When selected component changes, update selectedScriptComponentId
19
19
  $: if ($selectedComponent != $selectedComponentInEditor &&
20
20
  !$selectedComponentInEditor?.includes('_transformer')) {
21
- $selectedComponentInEditor = $selectedComponent;
21
+ $selectedComponentInEditor = $selectedComponent?.[0];
22
22
  }
23
23
  function createBackgroundScript() {
24
24
  let index = 0;
@@ -266,6 +266,10 @@ $: componentSettings?.item?.data && ($app = $app);
266
266
  <Kbd>&uparrow;</Kbd><Kbd>&rightarrow;</Kbd>
267
267
  <Kbd>ESC</Kbd>
268
268
  </div>
269
+ <div>
270
+ <span class="text-gray-600 text-xs mr-2">Add to selection:</span>
271
+ <Kbd>&DoubleUpArrow;</Kbd>+<Kbd>click</Kbd>
272
+ </div>
269
273
  </div>
270
274
  </PanelSection>
271
275
  {/if}
@@ -24,7 +24,7 @@ function deleteComponent(cid) {
24
24
  components = components.filter((x) => x.id !== cid);
25
25
  $errorByComponent = clearErrorByComponentId(cid, $errorByComponent);
26
26
  $jobs = clearJobsByComponentId(cid, $jobs);
27
- $selectedComponent = id;
27
+ $selectedComponent = [id];
28
28
  $app = $app;
29
29
  }
30
30
  </script>
@@ -49,10 +49,10 @@ function deleteComponent(cid) {
49
49
  class={classNames(
50
50
  'w-full text-xs font-bold gap-1 truncate py-1.5 px-2 cursor-pointer transition-all justify-between flex items-center border border-gray-3 rounded-md',
51
51
  'bg-white border-gray-300 hover:bg-gray-100 focus:bg-gray-100 text-gray-700',
52
- $selectedComponent === component.id ? 'outline outline-blue-500 bg-red-400' : ''
52
+ $selectedComponent?.includes(component.id) ? 'outline outline-blue-500 bg-red-400' : ''
53
53
  )}
54
54
  on:click={() => {
55
- $selectedComponent = component.id
55
+ $selectedComponent = [component.id]
56
56
  }}
57
57
  on:keypress
58
58
  >
@@ -19,6 +19,6 @@ $: onLoad =
19
19
  bind:inlineScript={runnable.inlineScript}
20
20
  {onLoad}
21
21
  {doNotRecomputeOnInputChanged}
22
- id={$selectedComponent}
22
+ id={$selectedComponent?.[0]}
23
23
  {onClick}
24
24
  />