windmill-components 1.60.2 → 1.60.4

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 (73) hide show
  1. package/components/AppConnect.svelte +4 -0
  2. package/components/ArgInput.svelte +0 -1
  3. package/components/ArgInput.svelte.d.ts +0 -2
  4. package/components/DisplayResult.svelte +9 -6
  5. package/components/FlowMetadata.svelte +19 -3
  6. package/components/FlowPreviewContent.svelte +15 -9
  7. package/components/FolderEditor.svelte +1 -1
  8. package/components/InputTransformForm.svelte +1 -2
  9. package/components/JobArgs.svelte +1 -1
  10. package/components/ModulePreview.svelte +2 -1
  11. package/components/Popover.model.d.ts +4 -0
  12. package/components/Popover.model.js +3 -0
  13. package/components/Popover.svelte +0 -2
  14. package/components/Popover.svelte.d.ts +2 -1
  15. package/components/ResourceEditor.svelte +11 -1
  16. package/components/ResourcePicker.svelte +10 -1
  17. package/components/RunForm.svelte +41 -37
  18. package/components/RunForm.svelte.d.ts +1 -0
  19. package/components/ScriptBuilder.svelte +3 -1
  20. package/components/ScriptEditor.svelte +1 -0
  21. package/components/TemplateEditor.svelte +14 -1
  22. package/components/TestJobLoader.svelte +1 -1
  23. package/components/Tooltip.svelte +8 -3
  24. package/components/Tooltip.svelte.d.ts +5 -0
  25. package/components/UserSettings.svelte +14 -25
  26. package/components/apps/components/buttons/AppButton.svelte +16 -0
  27. package/components/apps/components/dataDisplay/AppHtml.svelte +22 -14
  28. package/components/apps/components/dataDisplay/AppHtml.svelte.d.ts +0 -2
  29. package/components/apps/components/dataDisplay/VegaLiteHtml.svelte +53 -0
  30. package/components/apps/components/dataDisplay/VegaLiteHtml.svelte.d.ts +23 -0
  31. package/components/apps/components/helpers/InputValue.svelte +24 -5
  32. package/components/apps/components/helpers/InputValue.svelte.d.ts +1 -0
  33. package/components/apps/components/helpers/RunnableComponent.svelte +5 -2
  34. package/components/apps/components/selectInputs/AppSelect.svelte +11 -3
  35. package/components/apps/components/table/AppTable.svelte +16 -12
  36. package/components/apps/editor/AppEditor.svelte +7 -2
  37. package/components/apps/editor/AppPreview.svelte +26 -4
  38. package/components/apps/editor/AppPreview.svelte.d.ts +2 -0
  39. package/components/apps/editor/ComponentEditor.svelte +7 -0
  40. package/components/apps/editor/componentsPanel/ComponentList.svelte +2 -1
  41. package/components/apps/editor/componentsPanel/data.js +39 -0
  42. package/components/apps/editor/contextPanel/ContextPanel.svelte +3 -2
  43. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +4 -1
  44. package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +8 -56
  45. package/components/apps/editor/inlineScriptsPanel/utils.d.ts +15 -0
  46. package/components/apps/editor/inlineScriptsPanel/utils.js +28 -0
  47. package/components/apps/editor/settingsPanel/ComponentPanel.svelte +9 -14
  48. package/components/apps/editor/settingsPanel/ComponentPanel.svelte.d.ts +0 -3
  49. package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte +6 -2
  50. package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte.d.ts +4 -2
  51. package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +8 -7
  52. package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte.d.ts +1 -1
  53. package/components/apps/editor/settingsPanel/Recompute.svelte +1 -1
  54. package/components/apps/editor/settingsPanel/TableActions.svelte +7 -2
  55. package/components/apps/editor/settingsPanel/common/PanelSection.svelte +10 -1
  56. package/components/apps/editor/settingsPanel/common/PanelSection.svelte.d.ts +1 -0
  57. package/components/apps/editor/settingsPanel/inputEditor/EvalInputEditor.svelte +25 -0
  58. package/components/apps/editor/settingsPanel/inputEditor/EvalInputEditor.svelte.d.ts +19 -0
  59. package/components/apps/editorUtils.js +39 -0
  60. package/components/apps/inputType.d.ts +8 -1
  61. package/components/apps/types.d.ts +5 -3
  62. package/components/apps/utils.d.ts +2 -0
  63. package/components/apps/utils.js +15 -0
  64. package/components/common/button/Button.svelte +1 -1
  65. package/components/common/kbd/Kbd.svelte +6 -6
  66. package/components/common/table/Row.svelte +1 -1
  67. package/components/flows/content/CapturePayload.svelte +3 -3
  68. package/components/flows/content/FlowModuleComponent.svelte +4 -2
  69. package/components/flows/utils.js +1 -1
  70. package/components/propertyPicker/PropPicker.svelte +7 -1
  71. package/package.json +7 -3
  72. package/script_helpers.d.ts +3 -3
  73. package/script_helpers.js +18 -19
@@ -2,22 +2,30 @@
2
2
  import RunnableWrapper from '../helpers/RunnableWrapper.svelte';
3
3
  export let id;
4
4
  export let componentInput;
5
- export let horizontalAlignment = 'left';
6
- export let verticalAlignment = undefined;
7
5
  export let configuration;
8
6
  export const staticOutputs = ['result', 'loading'];
9
7
  let result = undefined;
8
+ let h = undefined;
9
+ let w = undefined;
10
10
  </script>
11
11
 
12
- <RunnableWrapper flexWrap bind:componentInput {id} bind:result>
13
- <AlignWrapper {horizontalAlignment} {verticalAlignment}>
14
- <div
15
- on:pointerdown={(e) => {
16
- e?.preventDefault()
17
- }}
18
- class="h-full relative w-full overflow-hidden"
19
- >
20
- {@html result ?? 'No html'}
21
- </div>
22
- </AlignWrapper>
23
- </RunnableWrapper>
12
+ <div
13
+ on:pointerdown={(e) => {
14
+ e?.preventDefault()
15
+ }}
16
+ class="h-full w-full"
17
+ bind:clientHeight={h}
18
+ bind:clientWidth={w}
19
+ >
20
+ <RunnableWrapper autoRefresh flexWrap bind:componentInput {id} bind:result>
21
+ {#key result}
22
+ <iframe
23
+ frameborder="0"
24
+ style="height: {h}px; width: {w}px"
25
+ class="p-0"
26
+ title="sandbox"
27
+ srcdoc={result ? '<scr' + `ipt src="/tailwind.css"></script>` + result : 'No html'}
28
+ />
29
+ {/key}
30
+ </RunnableWrapper>
31
+ </div>
@@ -4,8 +4,6 @@ declare const __propDef: {
4
4
  props: {
5
5
  id: string;
6
6
  componentInput: AppInput | undefined;
7
- horizontalAlignment?: 'left' | 'center' | 'right' | undefined;
8
- verticalAlignment?: 'top' | 'center' | 'bottom' | undefined;
9
7
  configuration: Record<string, AppInput>;
10
8
  staticOutputs?: string[] | undefined;
11
9
  };
@@ -0,0 +1,53 @@
1
+ <script>import { Loader2 } from 'lucide-svelte';
2
+ import { parse } from 'path';
3
+ import { onMount } from 'svelte';
4
+ import AlignWrapper from '../helpers/AlignWrapper.svelte';
5
+ import InputValue from '../helpers/InputValue.svelte';
6
+ import RunnableWrapper from '../helpers/RunnableWrapper.svelte';
7
+ export let id;
8
+ export let componentInput;
9
+ export let configuration;
10
+ export const staticOutputs = ['result', 'loading'];
11
+ let result = undefined;
12
+ let divEl = null;
13
+ let vegaEmbed;
14
+ onMount(async () => {
15
+ if (divEl) {
16
+ //@ts-ignore
17
+ await import('https://cdn.jsdelivr.net/npm/vega@5.22.1');
18
+ //@ts-ignore
19
+ await import('https://cdn.jsdelivr.net/npm/vega-lite@5.6.0');
20
+ //@ts-ignore
21
+ await import('https://cdn.jsdelivr.net/npm/vega-embed@6.21.0');
22
+ vegaEmbed = window['vegaEmbed'];
23
+ }
24
+ });
25
+ let h = undefined;
26
+ let w = undefined;
27
+ let canvas = false;
28
+ $: vegaEmbed &&
29
+ result &&
30
+ divEl &&
31
+ h &&
32
+ w &&
33
+ vegaEmbed(divEl, { ...result, ...{ width: w - 100 } }, {
34
+ mode: 'vega-lite',
35
+ actions: false,
36
+ renderer: canvas ? 'canvas' : 'svg',
37
+ height: h - 75,
38
+ width: w - 75
39
+ });
40
+ </script>
41
+
42
+ <InputValue {id} input={configuration.canvas} bind:value={canvas} />
43
+
44
+ <div class="w-full h-full" bind:clientHeight={h} bind:clientWidth={w}>
45
+ <RunnableWrapper flexWrap bind:componentInput {id} bind:result>
46
+ {#if !vegaEmbed}
47
+ <div class="p-2">
48
+ <Loader2 class="animate-spin" />
49
+ </div>
50
+ {/if}
51
+ <div on:pointerdown bind:this={divEl} />
52
+ </RunnableWrapper>
53
+ </div>
@@ -0,0 +1,23 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { AppInput } from '../../inputType';
3
+ declare const __propDef: {
4
+ props: {
5
+ id: string;
6
+ componentInput: AppInput | undefined;
7
+ configuration: Record<string, AppInput>;
8
+ staticOutputs?: string[] | undefined;
9
+ };
10
+ events: {
11
+ pointerdown: PointerEvent;
12
+ } & {
13
+ [evt: string]: CustomEvent<any>;
14
+ };
15
+ slots: {};
16
+ };
17
+ export type VegaLiteHtmlProps = typeof __propDef.props;
18
+ export type VegaLiteHtmlEvents = typeof __propDef.events;
19
+ export type VegaLiteHtmlSlots = typeof __propDef.slots;
20
+ export default class VegaLiteHtml extends SvelteComponentTyped<VegaLiteHtmlProps, VegaLiteHtmlEvents, VegaLiteHtmlSlots> {
21
+ get staticOutputs(): string[];
22
+ }
23
+ export {};
@@ -1,28 +1,44 @@
1
1
  <script>import { isCodeInjection } from '../../../flows/utils';
2
- import { createEventDispatcher, getContext, onMount } from 'svelte';
2
+ import { getContext } from 'svelte';
3
3
  import { accessPropertyByPath } from '../../utils';
4
4
  export let input;
5
5
  export let value;
6
6
  export let id = undefined;
7
7
  export let row = {};
8
+ export let error = '';
8
9
  const { worldStore } = getContext('AppEditorContext');
9
10
  $: state = $worldStore?.state;
10
11
  $: input && $worldStore && row && handleConnection();
11
- $: input && $state && input.type == 'template' && (value = getValue(input));
12
+ $: input && input.type == 'template' && $state && (value = getValue(input));
13
+ $: input && input.type == 'eval' && $state && (value = evalExpr(input));
12
14
  function handleConnection() {
13
15
  if (input.type === 'connected') {
14
16
  $worldStore?.connect(input, onValueChange);
15
17
  }
16
18
  else if (input.type === 'row') {
17
- setTimeout(() => (value = row[input['column']]), 0);
19
+ setTimeout(() => (value = row?.[input['column']]), 0);
18
20
  }
19
21
  else if (input.type === 'static' || input.type == 'template') {
20
22
  setTimeout(() => (value = getValue(input)), 0);
21
23
  }
24
+ else if (input.type == 'eval') {
25
+ setTimeout(() => ((value = evalExpr(input)), 0));
26
+ }
22
27
  else {
23
28
  setTimeout(() => (value = undefined), 0);
24
29
  }
25
30
  }
31
+ function evalExpr(input) {
32
+ try {
33
+ const r = eval_like(input.expr, computeGlobalContext());
34
+ error = '';
35
+ return r;
36
+ }
37
+ catch (e) {
38
+ error = e.message;
39
+ return value;
40
+ }
41
+ }
26
42
  function computeGlobalContext() {
27
43
  return Object.fromEntries(Object.entries($worldStore?.outputsById ?? {})
28
44
  .filter(([k, _]) => k != id)
@@ -31,12 +47,15 @@ function computeGlobalContext() {
31
47
  key,
32
48
  Object.fromEntries(Object.entries(value ?? {}).map((x) => [x[0], x[1].peak()]))
33
49
  ];
34
- }));
50
+ })
51
+ .concat(row ? [['row', row]] : []));
35
52
  }
36
53
  export function getValue(input) {
37
54
  if (input.type === 'template' && isCodeInjection(input.eval)) {
38
55
  try {
39
- return eval_like('`' + input.eval + '`', computeGlobalContext());
56
+ const r = eval_like('`' + input.eval + '`', computeGlobalContext());
57
+ error = '';
58
+ return r;
40
59
  }
41
60
  catch (e) {
42
61
  return e.message;
@@ -6,6 +6,7 @@ declare const __propDef: {
6
6
  value: string | number | boolean | Record<string | number, any> | undefined;
7
7
  id?: string | undefined;
8
8
  row?: Record<string, any> | undefined;
9
+ error?: string | undefined;
9
10
  getValue?: ((input: AppInput) => any) | undefined;
10
11
  };
11
12
  events: {
@@ -257,12 +257,15 @@ let lastStartedAt = Date.now();
257
257
  <div class="p-2">
258
258
  <Alert type="error" title="Error during execution">
259
259
  See "Debug Runs" on the top right for more details
260
- <pre title={result.error} class=" mt-2 text-2xs whitespace-pre-wrap">{result.error}</pre>
260
+ <pre
261
+ title={JSON.stringify(result.error, null, 4)}
262
+ class=" mt-2 text-2xs whitespace-pre-wrap">{JSON.stringify(result.error, null, 4)}</pre
263
+ >
261
264
  </Alert>
262
265
  <slot />
263
266
  </div>
264
267
  {:else}
265
- <div class="grow min-w-1/2 {noMinH ? '' : 'min-h-[66%]'}">
268
+ <div class="block w-full h-full">
266
269
  <slot />
267
270
  </div>
268
271
  {/if}
@@ -12,10 +12,13 @@ let label;
12
12
  let items;
13
13
  let itemKey;
14
14
  $: outputs = $worldStore?.outputsById[id];
15
- function onChange({ detail }) {
16
- outputs?.result.set(detail?.[itemKey] || undefined);
15
+ function onChange(e) {
16
+ e?.stopPropagation();
17
+ window.dispatchEvent(new Event('pointerup'));
18
+ outputs?.result.set(e.detail?.[itemKey] || undefined);
17
19
  }
18
- const dispatch = createEventDispatcher();
20
+ let value = undefined;
21
+ $: items?.[0]?.['value'] != value && (value = items?.[0]?.['value']);
19
22
  </script>
20
23
 
21
24
  <InputValue {id} input={configuration.label} bind:value={label} />
@@ -28,7 +31,12 @@ const dispatch = createEventDispatcher();
28
31
  class="select"
29
32
  on:clear={onChange}
30
33
  on:change={onChange}
34
+ on:focus={(e) => {
35
+ e?.stopPropagation()
36
+ window.dispatchEvent(new Event('pointerup'))
37
+ }}
31
38
  {items}
39
+ {value}
32
40
  placeholder="Select an item"
33
41
  on:click={() => {
34
42
  if (!$connectingInput.opened) {
@@ -1,4 +1,4 @@
1
- <script>import { getContext } from 'svelte';
1
+ <script>import { getContext, onMount } from 'svelte';
2
2
  import InputValue from '../helpers/InputValue.svelte';
3
3
  import RunnableWrapper from '../helpers/RunnableWrapper.svelte';
4
4
  import { writable } from 'svelte/store';
@@ -31,15 +31,21 @@ let table = createSvelteTable(options);
31
31
  const { worldStore, staticOutputs: staticOutputsStore } = getContext('AppEditorContext');
32
32
  let selectedRowIndex = -1;
33
33
  function toggleRow(row, rowIndex) {
34
- if (selectedRowIndex === rowIndex) {
35
- selectedRowIndex = -1;
36
- outputs.selectedRow.set(null);
37
- }
38
- else {
34
+ if (selectedRowIndex !== rowIndex) {
39
35
  selectedRowIndex = rowIndex;
40
36
  outputs?.selectedRow.set(row.original);
41
37
  }
42
38
  }
39
+ let mounted = false;
40
+ onMount(() => {
41
+ mounted = true;
42
+ });
43
+ $: selectedRowIndex === -1 &&
44
+ Array.isArray(result) &&
45
+ result.length > 0 &&
46
+ // We need to wait until the component is mounted so the world is created
47
+ mounted &&
48
+ toggleRow({ original: result[0] }, 0);
43
49
  function setOptions(filteredResult) {
44
50
  if (!Array.isArray(result)) {
45
51
  return;
@@ -101,7 +107,7 @@ $: result && rerender();
101
107
 
102
108
  <div class="overflow-x-auto flex-1 w-full">
103
109
  <table class="relative w-full border-b border-b-gray-200">
104
- <thead class="sticky top-0 bg-gray-50 text-left">
110
+ <thead class="sticky top-0 z-40 bg-gray-50 text-left">
105
111
  {#each $table.getHeaderGroups() as headerGroup}
106
112
  <tr class="divide-x">
107
113
  {#each headerGroup.headers as header}
@@ -121,9 +127,7 @@ $: result && rerender();
121
127
  {/each}
122
128
  {#if actionButtons.length > 0}
123
129
  <th class="!p-0">
124
- <span class="block px-4 py-4 text-sm font-semibold border-b">
125
- Actions
126
- </span>
130
+ <span class="block px-4 py-4 text-sm font-semibold border-b"> Actions </span>
127
131
  </th>
128
132
  {/if}
129
133
  </tr>
@@ -133,11 +137,11 @@ $: result && rerender();
133
137
  {#each $table.getRowModel().rows as row, rowIndex (row.id)}
134
138
  <tr
135
139
  class={classNames(
140
+ 'last-of-type:!border-b-0',
136
141
  selectedRowIndex === rowIndex
137
142
  ? 'bg-blue-100 hover:bg-blue-200'
138
143
  : 'hover:bg-blue-50',
139
- 'divide-x',
140
- 'border-b w-full',
144
+ 'divide-x w-full',
141
145
  selectedRowIndex === rowIndex
142
146
  ? 'divide-blue-200 hover:divide-blue-300'
143
147
  : 'divide-gray-200'
@@ -19,6 +19,7 @@ import InlineScriptsPanel from './inlineScriptsPanel/InlineScriptsPanel.svelte';
19
19
  import SettingsPanel from './SettingsPanel.svelte';
20
20
  import { fly } from 'svelte/transition';
21
21
  import UnsavedConfirmationModal from '../../common/confirmationModal/UnsavedConfirmationModal.svelte';
22
+ import { page } from '$app/stores';
22
23
  export let app;
23
24
  export let path;
24
25
  export let initialMode = 'dnd';
@@ -73,7 +74,11 @@ let mounted = false;
73
74
  onMount(() => {
74
75
  mounted = true;
75
76
  });
76
- $: context = { email: $userStore?.email, username: $userStore?.username };
77
+ $: context = {
78
+ email: $userStore?.email,
79
+ username: $userStore?.username,
80
+ query: Object.fromEntries($page.url.searchParams.entries())
81
+ };
77
82
  $: mounted && ($worldStore = buildWorld($staticOutputs, $worldStore, context));
78
83
  $: previewing = $mode === 'preview';
79
84
  $: width = $breakpoint === 'sm' ? 'min-w-[400px] max-w-[656px]' : 'min-w-[710px] w-full';
@@ -170,7 +175,7 @@ else {
170
175
  {#if $connectingInput.opened}
171
176
  <div
172
177
  class="fixed top-32 p-2 z-50 flex justify-center items-center"
173
- transition:fly={{ duration: 100, y: -100 }}
178
+ transition:fly|local={{ duration: 100, y: -100 }}
174
179
  >
175
180
  <Alert title="Connecting" type="info">
176
181
  <div class="flex gap-2 flex-col">
@@ -1,8 +1,12 @@
1
1
  <script>import { onMount, setContext } from 'svelte';
2
+ import { fade } from 'svelte/transition';
3
+ import { cubicOut } from 'svelte/easing';
2
4
  import { writable } from 'svelte/store';
3
5
  import { buildWorld } from '../rx';
4
6
  import GridEditor from './GridEditor.svelte';
5
7
  import { classNames } from '../../../utils';
8
+ import Button from '../../common/button/Button.svelte';
9
+ import { Unlock } from 'lucide-svelte';
6
10
  export let app;
7
11
  export let appPath;
8
12
  export let breakpoint;
@@ -12,6 +16,7 @@ export let workspace;
12
16
  export let isEditor;
13
17
  export let context;
14
18
  export let noBackend = false;
19
+ export let isLocked = false;
15
20
  const appStore = writable(app);
16
21
  const worldStore = writable(undefined);
17
22
  const staticOutputs = writable({});
@@ -48,12 +53,29 @@ onMount(() => {
48
53
  });
49
54
  $: mounted && ($worldStore = buildWorld($staticOutputs, undefined, context));
50
55
  $: width = $breakpoint === 'sm' ? 'max-w-[640px]' : 'w-full ';
56
+ $: lockedClasses = isLocked ? '!max-h-[400px] overflow-hidden pointer-events-none' : '';
51
57
  </script>
52
58
 
53
- <div class="h-full w-full {app.fullscreen ? '' : 'max-w-6xl'} mx-auto">
54
- {#if $appStore.grid}
55
- <div class={classNames('mx-auto pb-4', width)}>
56
- <GridEditor {policy} />
59
+ <div class="relative">
60
+ <div class="{$$props.class} {lockedClasses} h-full max-h-[calc(100%-41px)] overflow-auto
61
+ w-full {app.fullscreen ? '' : 'max-w-6xl'} mx-auto">
62
+ {#if $appStore.grid}
63
+ <div class={classNames('mx-auto pb-4', width)}>
64
+ <GridEditor {policy} />
65
+ </div>
66
+ {/if}
67
+ </div>
68
+ {#if isLocked}
69
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
70
+ <div
71
+ transition:fade|local={{ duration: 200, easing: cubicOut }}
72
+ on:click={() => isLocked = false}
73
+ class="absolute inset-0 center-center bg-black/20 z-50 backdrop-blur-[1px] cursor-pointer"
74
+ >
75
+ <Button on:click={() => isLocked = false}>
76
+ Unlock preview
77
+ <Unlock size={18} class="ml-1" strokeWidth={2.5} />
78
+ </Button>
57
79
  </div>
58
80
  {/if}
59
81
  </div>
@@ -4,6 +4,7 @@ import type { App, EditorBreakpoint } from '../types';
4
4
  import type { Policy } from '../../../gen';
5
5
  declare const __propDef: {
6
6
  props: {
7
+ [x: string]: any;
7
8
  app: App;
8
9
  appPath: string;
9
10
  breakpoint: Writable<EditorBreakpoint>;
@@ -13,6 +14,7 @@ declare const __propDef: {
13
14
  isEditor: boolean;
14
15
  context: Record<string, any>;
15
16
  noBackend?: boolean | undefined;
17
+ isLocked?: boolean | undefined;
16
18
  };
17
19
  events: {
18
20
  [evt: string]: CustomEvent<any>;
@@ -17,6 +17,7 @@ import AppScatterChart from '../components/dataDisplay/AppScatterChart.svelte';
17
17
  import AppTimeseries from '../components/dataDisplay/AppTimeseries.svelte';
18
18
  import AppHtml from '../components/dataDisplay/AppHtml.svelte';
19
19
  import AppSliderInputs from '../components/numberInputs/AppSliderInputs.svelte';
20
+ import VegaLiteHtml from '../components/dataDisplay/VegaLiteHtml.svelte';
20
21
  export let component;
21
22
  export let selected;
22
23
  export let locked = false;
@@ -74,6 +75,12 @@ const { staticOutputs, mode, connectingInput } = getContext('AppEditorContext');
74
75
  bind:componentInput={component.componentInput}
75
76
  bind:staticOutputs={$staticOutputs[component.id]}
76
77
  />
78
+ {:else if component.type === 'vegalitecomponent'}
79
+ <VegaLiteHtml
80
+ {...component}
81
+ bind:componentInput={component.componentInput}
82
+ bind:staticOutputs={$staticOutputs[component.id]}
83
+ />
77
84
  {:else if component.type === 'scatterchartcomponent'}
78
85
  <AppScatterChart
79
86
  {...component}
@@ -29,7 +29,8 @@ function getRecommendedDimensionsByComponent(componentType, column) {
29
29
  'barchartcomponent',
30
30
  'piechartcomponent',
31
31
  'displaycomponent',
32
- 'scatterchartcomponent'
32
+ 'scatterchartcomponent',
33
+ 'vegalitecomponent'
33
34
  ],
34
35
  '3:10-6:10': ['tablecomponent']
35
36
  };
@@ -167,6 +167,11 @@ const buttons = {
167
167
  onlyStatic: true,
168
168
  optionValuesKey: 'buttonSizeOptions',
169
169
  value: 'xs'
170
+ },
171
+ disabled: {
172
+ fieldType: 'boolean',
173
+ type: 'eval',
174
+ expr: 'false'
170
175
  }
171
176
  },
172
177
  card: false
@@ -227,6 +232,40 @@ const display = {
227
232
  configuration: {},
228
233
  card: false
229
234
  },
235
+ {
236
+ softWrap: false,
237
+ id: 'vegalitecomponent',
238
+ type: 'vegalitecomponent',
239
+ componentInput: {
240
+ type: 'static',
241
+ fieldType: 'object',
242
+ value: {
243
+ data: {
244
+ values: [
245
+ { a: 'A', b: 28 },
246
+ { a: 'B', b: 55 },
247
+ { a: 'C', b: 43 },
248
+ { a: 'D', b: 91 },
249
+ ]
250
+ },
251
+ mark: 'bar',
252
+ encoding: {
253
+ x: { field: 'a', type: 'ordinal' },
254
+ y: { field: 'b', type: 'quantitative' }
255
+ }
256
+ }
257
+ },
258
+ configuration: {
259
+ canvas: {
260
+ type: 'static',
261
+ onlyStatic: true,
262
+ fieldType: 'boolean',
263
+ value: false,
264
+ tooltip: "use the canvas renderer instead of the svg one for more interactive plots"
265
+ }
266
+ },
267
+ card: false
268
+ },
230
269
  {
231
270
  softWrap: true,
232
271
  horizontalAlignment: 'left',
@@ -1,4 +1,5 @@
1
- <script>import { classNames } from '../../../../utils';
1
+ <script>import { page } from '$app/stores';
2
+ import { classNames } from '../../../../utils';
2
3
  import { getContext } from 'svelte';
3
4
  import { key } from 'svelte-awesome/icons';
4
5
  import { displayData } from '../../utils';
@@ -32,7 +33,7 @@ function getComponentNameById(componentId) {
32
33
  return 'Table action';
33
34
  }
34
35
  }
35
- $: panels = [['ctx', ['email', 'username']]].concat(Object.entries($staticOutputs));
36
+ $: panels = [['ctx', ['email', 'username', 'query']]].concat(Object.entries($staticOutputs));
36
37
  </script>
37
38
 
38
39
  <PanelSection noPadding titlePadding="px-4 pt-2" title="Outputs">
@@ -38,7 +38,7 @@ let runLoading = false;
38
38
 
39
39
  <InlineScriptEditorDrawer {editor} bind:this={inlineScriptEditorDrawer} bind:inlineScript />
40
40
 
41
- <div class="h-full flex flex-col gap-1" transition:fly={{ duration: 50 }}>
41
+ <div class="h-full flex flex-col gap-1" transition:fly|local={{ duration: 50 }}>
42
42
  <div class="flex justify-between w-full gap-1 px-2 pt-1 flex-row items-center">
43
43
  {#if name !== undefined}
44
44
  <input bind:value={name} placeholder="Inline script name" />
@@ -119,6 +119,9 @@ let runLoading = false;
119
119
  on:change={async (e) => {
120
120
  if (inlineScript) {
121
121
  const oldSchema = JSON.stringify(inlineScript.schema)
122
+ if (inlineScript.schema == undefined) {
123
+ inlineScript.schema = emptySchema()
124
+ }
122
125
  await inferInlineScriptSchema(inlineScript?.language, e.detail, inlineScript.schema)
123
126
  if (JSON.stringify(inlineScript.schema) != oldSchema) {
124
127
  inlineScript = inlineScript
@@ -2,6 +2,7 @@
2
2
  import { classNames } from '../../../../utils';
3
3
  import { getContext } from 'svelte';
4
4
  import PanelSection from '../settingsPanel/common/PanelSection.svelte';
5
+ import { getAppScripts } from './utils';
5
6
  export let selectedScriptComponentId = undefined;
6
7
  const { app, selectedComponent, lazyGrid } = getContext('AppEditorContext');
7
8
  function selectInlineScript(id) {
@@ -10,56 +11,7 @@ function selectInlineScript(id) {
10
11
  $selectedComponent = selectedScriptComponentId;
11
12
  }
12
13
  }
13
- $: runnablesByName = $lazyGrid.reduce((acc, gridComponent) => {
14
- const component = gridComponent.data;
15
- if (component.type === 'tablecomponent') {
16
- component.actionButtons.forEach((actionButton) => {
17
- if (actionButton.componentInput?.type === 'runnable') {
18
- if (actionButton.componentInput.runnable?.type === 'runnableByName') {
19
- acc.push({
20
- name: actionButton.componentInput.runnable.name,
21
- id: actionButton.id
22
- });
23
- }
24
- }
25
- });
26
- }
27
- const componentInput = component.componentInput;
28
- if (componentInput?.type === 'runnable') {
29
- if (componentInput.runnable?.type === 'runnableByName') {
30
- acc.push({
31
- name: componentInput.runnable.name,
32
- id: gridComponent.id
33
- });
34
- }
35
- }
36
- return acc;
37
- }, []);
38
- $: runnablesByPath = $lazyGrid.reduce((acc, gridComponent) => {
39
- const component = gridComponent.data;
40
- if (component.type === 'tablecomponent') {
41
- component.actionButtons.forEach((actionButton) => {
42
- if (actionButton.componentInput?.type === 'runnable') {
43
- if (actionButton.componentInput.runnable?.type === 'runnableByPath') {
44
- acc.push({
45
- name: actionButton.componentInput.runnable.path,
46
- id: actionButton.id
47
- });
48
- }
49
- }
50
- });
51
- }
52
- const componentInput = component.componentInput;
53
- if (componentInput?.type === 'runnable') {
54
- if (componentInput.runnable?.type === 'runnableByPath') {
55
- acc.push({
56
- name: componentInput.runnable.path,
57
- id: gridComponent.id
58
- });
59
- }
60
- }
61
- return acc;
62
- }, []);
14
+ $: runnables = getAppScripts($lazyGrid);
63
15
  // When seleced component changes, update selectedScriptComponentId
64
16
  $: {
65
17
  if (selectedComponent) {
@@ -71,9 +23,9 @@ $: {
71
23
  <div class="min-h-full flex flex-col gap-4">
72
24
  <PanelSection title="Inline scripts" smallPadding>
73
25
  <div class="flex flex-col gap-2 w-full">
74
- {#if runnablesByName.length > 0}
26
+ {#if runnables.inline.length > 0}
75
27
  <div class="flex gap-2 flex-col ">
76
- {#each runnablesByName as { name, id }, index (index)}
28
+ {#each runnables.inline as { name, id }, index (index)}
77
29
  <!-- svelte-ignore a11y-click-events-have-key-events -->
78
30
  <div
79
31
  class="{classNames(
@@ -109,17 +61,17 @@ $: {
109
61
  </div>
110
62
  {/if}
111
63
 
112
- {#if runnablesByName.length == 0 && $app.unusedInlineScripts?.length == 0}
64
+ {#if runnables.inline.length == 0 && $app.unusedInlineScripts?.length == 0}
113
65
  <div class="text-sm text-gray-500">No inline scripts</div>
114
66
  {/if}
115
67
  </div>
116
68
  </PanelSection>
117
69
 
118
- <PanelSection title="Others" smallPadding>
70
+ <PanelSection title="Imported scripts" smallPadding>
119
71
  <div class="flex flex-col gap-2 w-full">
120
- {#if runnablesByPath.length > 0}
72
+ {#if runnables.imported.length > 0}
121
73
  <div class="flex gap-2 flex-col ">
122
- {#each runnablesByPath as { name, id }, index (index)}
74
+ {#each runnables.imported as { name, id }, index (index)}
123
75
  <!-- svelte-ignore a11y-click-events-have-key-events -->
124
76
  <div
125
77
  class="{classNames(
@@ -0,0 +1,15 @@
1
+ import type { AppComponent, GridItem } from "../../types";
2
+ export interface AppScriptsList {
3
+ inline: {
4
+ name: string;
5
+ id: string;
6
+ }[];
7
+ imported: {
8
+ name: string;
9
+ id: string;
10
+ }[];
11
+ }
12
+ export declare function getAppScripts(grid: GridItem[]): FilledItem<{
13
+ data: AppComponent;
14
+ id: string;
15
+ }>;