mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-08 16:02:30 +00:00
fix(frontend): Add more app custom css (#1229)
* fix(frontend): Add container custom css * fix(frontend): Add form custom css * fix(frontend): Add form button custom css * feat(frontend): Add css quick reset button * feat(frontend): Filter component css by usage * fix(frontend): Save state of unused component display * fix(frontend): Add pie chart custom css * fix(frontend): Add bar chart custom css * fix(frontend): Update vega lite and plotly loading * fix(frontend): Add html and timeseries custom css * fix(frontend): Add scatter chart custom css * fix(frontend): Add table custom css * fix(frontend): Revert container custom styles * fix(frontend): Add toggle custom css * fix(frontend): Add text input custom css * fix(frontend): Update * fix(frontend): Remove undefined css customizations
This commit is contained in:
Generated
+48
-62
@@ -30,7 +30,7 @@
|
||||
"svelte-autosize": "^1.0.1",
|
||||
"svelte-chartjs": "^3.1.0",
|
||||
"svelte-portal": "^2.2.0",
|
||||
"svelte-select": "^5.0.2",
|
||||
"svelte-select": "^5.3.1",
|
||||
"tailwind-merge": "^1.9.1",
|
||||
"vscode-ws-jsonrpc": "^2.0.1"
|
||||
},
|
||||
@@ -604,16 +604,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.0.5.tgz",
|
||||
"integrity": "sha512-iDdOsaCHZH/0FM0yNBYt+cJxJF9S5jrYWNtDZOiDFMiZ7uxMJ/71h8eTwoVifEAruv9p9rlMPYCGIgMjOz95FQ=="
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.1.tgz",
|
||||
"integrity": "sha512-LSqwPZkK3rYfD7GKoIeExXOyYx6Q1O4iqZWwIehDNuv3Dv425FIAE8PRwtAx1imEolFTHgBEcoFHm9MDnYgPCg=="
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.0.tgz",
|
||||
"integrity": "sha512-TSogMPVxbRe77QCj1dt8NmRiJasPvuc+eT5jnJ6YpLqgOD2zXc5UA3S1qwybN+GVCDNdKfpKy1oj8RpzLJvh6A==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.1.tgz",
|
||||
"integrity": "sha512-Rt45SmRiV8eU+xXSB9t0uMYiQ/ZWGE/jumse2o3i5RGlyvcbqOF4q+1qBnzLE2kZ5JGhq0iMkcGXUKbFe7MpTA==",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.0.5"
|
||||
"@floating-ui/core": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-common-types": {
|
||||
@@ -2458,7 +2458,8 @@
|
||||
"node_modules/dedent-js": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
|
||||
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ=="
|
||||
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/deep-extend": {
|
||||
"version": "0.6.0",
|
||||
@@ -3873,6 +3874,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
@@ -4268,6 +4270,7 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
|
||||
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lower-case": "^2.0.2",
|
||||
"tslib": "^2.0.3"
|
||||
@@ -4502,6 +4505,7 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
||||
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"no-case": "^3.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
@@ -6206,25 +6210,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-floating-ui": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-1.1.6.tgz",
|
||||
"integrity": "sha512-lJfrc34+xSxKs+5AtnYj32uRIjaxGjhT92cOiNL3zEqaJ755JxUqXCf6tk+9G1wkCuqkK9A8tscVBsyY3iLmVQ==",
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-1.2.8.tgz",
|
||||
"integrity": "sha512-8Ifi5CD2Ui7FX7NjJRmutFtXjrB8T/FMNoS2H8P81t5LHK4I9G4NIs007rLWG/nRl7y+zJUXa3tWuTjYXw/O5A==",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.0.4",
|
||||
"svelte2tsx": "^0.5.11"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-floating-ui/node_modules/svelte2tsx": {
|
||||
"version": "0.5.23",
|
||||
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.5.23.tgz",
|
||||
"integrity": "sha512-jYFnugTQRFmUpvLXPQrKzVYcW5ErT+0QCxg027Zx9BuvYefMZFuoBSTDYe7viPEFGrPPiLgT2m7f5n9khE7f7Q==",
|
||||
"dependencies": {
|
||||
"dedent-js": "^1.0.1",
|
||||
"pascal-case": "^3.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": "^3.24",
|
||||
"typescript": "^4.1.2"
|
||||
"@floating-ui/core": "^1.1.0",
|
||||
"@floating-ui/dom": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-highlight": {
|
||||
@@ -6348,12 +6339,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/svelte-select": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte-select/-/svelte-select-5.0.2.tgz",
|
||||
"integrity": "sha512-SsyIwcRVl38041xk7HoPCAew8D6ypTrMvoNcwOgAEWz9Yycgd/uZ58gMSubxSDtkW/ohuYmmHf5OlGCKIqn9Cw==",
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte-select/-/svelte-select-5.3.1.tgz",
|
||||
"integrity": "sha512-TKlH22FEOr/KYNX4dzBJntNzeI0v0eZYU3VEo2uz/gar6xZdhQ3KT81hvD595GfSB7wiFdYc9SO42wrcgm9W4Q==",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.0.10",
|
||||
"svelte-floating-ui": "1.1.6"
|
||||
"@floating-ui/dom": "^1.2.1",
|
||||
"svelte-floating-ui": "1.2.8"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-splitpanes": {
|
||||
@@ -6691,6 +6682,7 @@
|
||||
"version": "4.9.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
|
||||
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -7486,16 +7478,16 @@
|
||||
}
|
||||
},
|
||||
"@floating-ui/core": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.0.5.tgz",
|
||||
"integrity": "sha512-iDdOsaCHZH/0FM0yNBYt+cJxJF9S5jrYWNtDZOiDFMiZ7uxMJ/71h8eTwoVifEAruv9p9rlMPYCGIgMjOz95FQ=="
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.1.tgz",
|
||||
"integrity": "sha512-LSqwPZkK3rYfD7GKoIeExXOyYx6Q1O4iqZWwIehDNuv3Dv425FIAE8PRwtAx1imEolFTHgBEcoFHm9MDnYgPCg=="
|
||||
},
|
||||
"@floating-ui/dom": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.0.tgz",
|
||||
"integrity": "sha512-TSogMPVxbRe77QCj1dt8NmRiJasPvuc+eT5jnJ6YpLqgOD2zXc5UA3S1qwybN+GVCDNdKfpKy1oj8RpzLJvh6A==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.1.tgz",
|
||||
"integrity": "sha512-Rt45SmRiV8eU+xXSB9t0uMYiQ/ZWGE/jumse2o3i5RGlyvcbqOF4q+1qBnzLE2kZ5JGhq0iMkcGXUKbFe7MpTA==",
|
||||
"requires": {
|
||||
"@floating-ui/core": "^1.0.5"
|
||||
"@floating-ui/core": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
@@ -8781,7 +8773,8 @@
|
||||
"dedent-js": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
|
||||
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ=="
|
||||
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
|
||||
"dev": true
|
||||
},
|
||||
"deep-extend": {
|
||||
"version": "0.6.0",
|
||||
@@ -9869,6 +9862,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
@@ -10173,6 +10167,7 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
|
||||
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lower-case": "^2.0.2",
|
||||
"tslib": "^2.0.3"
|
||||
@@ -10344,6 +10339,7 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
||||
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"no-case": "^3.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
@@ -11539,23 +11535,12 @@
|
||||
}
|
||||
},
|
||||
"svelte-floating-ui": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-1.1.6.tgz",
|
||||
"integrity": "sha512-lJfrc34+xSxKs+5AtnYj32uRIjaxGjhT92cOiNL3zEqaJ755JxUqXCf6tk+9G1wkCuqkK9A8tscVBsyY3iLmVQ==",
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-1.2.8.tgz",
|
||||
"integrity": "sha512-8Ifi5CD2Ui7FX7NjJRmutFtXjrB8T/FMNoS2H8P81t5LHK4I9G4NIs007rLWG/nRl7y+zJUXa3tWuTjYXw/O5A==",
|
||||
"requires": {
|
||||
"@floating-ui/dom": "^1.0.4",
|
||||
"svelte2tsx": "^0.5.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"svelte2tsx": {
|
||||
"version": "0.5.23",
|
||||
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.5.23.tgz",
|
||||
"integrity": "sha512-jYFnugTQRFmUpvLXPQrKzVYcW5ErT+0QCxg027Zx9BuvYefMZFuoBSTDYe7viPEFGrPPiLgT2m7f5n9khE7f7Q==",
|
||||
"requires": {
|
||||
"dedent-js": "^1.0.1",
|
||||
"pascal-case": "^3.1.1"
|
||||
}
|
||||
}
|
||||
"@floating-ui/core": "^1.1.0",
|
||||
"@floating-ui/dom": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"svelte-highlight": {
|
||||
@@ -11621,12 +11606,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"svelte-select": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte-select/-/svelte-select-5.0.2.tgz",
|
||||
"integrity": "sha512-SsyIwcRVl38041xk7HoPCAew8D6ypTrMvoNcwOgAEWz9Yycgd/uZ58gMSubxSDtkW/ohuYmmHf5OlGCKIqn9Cw==",
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte-select/-/svelte-select-5.3.1.tgz",
|
||||
"integrity": "sha512-TKlH22FEOr/KYNX4dzBJntNzeI0v0eZYU3VEo2uz/gar6xZdhQ3KT81hvD595GfSB7wiFdYc9SO42wrcgm9W4Q==",
|
||||
"requires": {
|
||||
"@floating-ui/dom": "^1.0.10",
|
||||
"svelte-floating-ui": "1.1.6"
|
||||
"@floating-ui/dom": "^1.2.1",
|
||||
"svelte-floating-ui": "1.2.8"
|
||||
}
|
||||
},
|
||||
"svelte-splitpanes": {
|
||||
@@ -11877,7 +11862,8 @@
|
||||
"typescript": {
|
||||
"version": "4.9.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
|
||||
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg=="
|
||||
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.16.3",
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
"svelte-autosize": "^1.0.1",
|
||||
"svelte-chartjs": "^3.1.0",
|
||||
"svelte-portal": "^2.2.0",
|
||||
"svelte-select": "^5.0.2",
|
||||
"svelte-select": "^5.3.1",
|
||||
"tailwind-merge": "^1.9.1",
|
||||
"vscode-ws-jsonrpc": "^2.0.1"
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import Select from 'svelte-select'
|
||||
import AppConnect from './AppConnect.svelte'
|
||||
import ResourceEditor from './ResourceEditor.svelte'
|
||||
import { SELECT_INPUT_DEFAULT_STYLE } from '../defaults'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let resources: Resource[] = []
|
||||
@@ -59,12 +60,13 @@
|
||||
<div class="flex flex-row gap-x-1 w-full">
|
||||
<Select
|
||||
listAutoWidth={false}
|
||||
--height="34px"
|
||||
value={collection.find((x) => x.value == value)}
|
||||
bind:justValue={value}
|
||||
items={collection}
|
||||
class="text-clip grow min-w-0"
|
||||
placeholder="{resourceType} resource"
|
||||
inputStyles={SELECT_INPUT_DEFAULT_STYLE.inputStyles}
|
||||
containerStyles={SELECT_INPUT_DEFAULT_STYLE.containerStyles}
|
||||
/>
|
||||
{#if value && value != ''}
|
||||
<Button variant="border" size="xs" on:click={() => resourceEditor?.initEdit?.(value ?? '')}>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import { Button, Drawer, DrawerContent } from './common'
|
||||
import HighlightCode from './HighlightCode.svelte'
|
||||
import FlowPathViewer from './flows/content/FlowPathViewer.svelte'
|
||||
import { SELECT_INPUT_DEFAULT_STYLE } from '../defaults'
|
||||
|
||||
export let initialPath: string | undefined = undefined
|
||||
export let scriptPath: string | undefined = undefined
|
||||
@@ -87,6 +88,8 @@
|
||||
bind:justValue={scriptPath}
|
||||
{items}
|
||||
placeholder="Pick a {itemKind}"
|
||||
inputStyles={SELECT_INPUT_DEFAULT_STYLE.inputStyles}
|
||||
containerStyles={SELECT_INPUT_DEFAULT_STYLE.containerStyles}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export let options: {
|
||||
left?: string
|
||||
@@ -7,6 +8,8 @@
|
||||
} = {}
|
||||
export let checked: boolean = false
|
||||
export let disabled = false
|
||||
export let textClass = ''
|
||||
export let textStyle = ''
|
||||
|
||||
export let size: 'sm' | 'xs' = 'sm'
|
||||
const id = (Math.random() + 1).toString(36).substring(10)
|
||||
@@ -22,7 +25,13 @@
|
||||
>
|
||||
{#if Boolean(options?.left)}
|
||||
<span
|
||||
class="mr-2 text-sm font-medium duration-200 {disabled ? 'text-gray-600' : 'text-gray-900'}"
|
||||
class={twMerge(
|
||||
'ml-2 font-medium duration-200',
|
||||
disabled ? 'text-gray-500' : 'text-gray-900',
|
||||
size === 'xs' ? 'text-xs' : 'text-sm',
|
||||
textClass
|
||||
)}
|
||||
style={textStyle}
|
||||
>
|
||||
{options?.left}
|
||||
</span>
|
||||
@@ -51,9 +60,13 @@
|
||||
</div>
|
||||
{#if Boolean(options?.right)}
|
||||
<span
|
||||
class="ml-2 text-sm font-medium duration-200
|
||||
{disabled ? 'text-gray-500' : 'text-gray-900'}
|
||||
{size === 'xs' ? 'text-xs' : 'text-sm'}"
|
||||
class={twMerge(
|
||||
'ml-2 font-medium duration-200',
|
||||
disabled ? 'text-gray-500' : 'text-gray-900',
|
||||
size === 'xs' ? 'text-xs' : 'text-sm',
|
||||
textClass
|
||||
)}
|
||||
style={textStyle}
|
||||
>
|
||||
{options?.right}
|
||||
</span>
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
import { Icon } from 'svelte-awesome'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import type { Output } from '../../rx'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import type RunnableComponent from '../helpers/RunnableComponent.svelte'
|
||||
@@ -17,10 +18,11 @@
|
||||
export let recomputeIds: string[] | undefined = undefined
|
||||
export let extraQueryParams: Record<string, any> = {}
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'container' | 'button'> | undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result']
|
||||
|
||||
const { runnableComponents, worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
const { app, runnableComponents, worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let labelValue: string = 'Default label'
|
||||
let color: ButtonType.Color
|
||||
@@ -47,6 +49,8 @@
|
||||
isLoading = value
|
||||
}
|
||||
})
|
||||
|
||||
$: css = concatCustomCss($app.css?.formcomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.goto} bind:value={goto} />
|
||||
@@ -64,9 +68,13 @@
|
||||
autoRefresh={false}
|
||||
forceSchemaDisplay={true}
|
||||
runnableClass="!block"
|
||||
runnableStyle={css?.container.style}
|
||||
>
|
||||
<AlignWrapper {horizontalAlignment}>
|
||||
<div class="flex flex-col gap-2 px-4 w-full">
|
||||
<div
|
||||
class="flex flex-col gap-2 px-4 w-full {css?.container?.class ?? ''}"
|
||||
style={css?.container?.style ?? ''}
|
||||
>
|
||||
<div>
|
||||
{#if noInputs}
|
||||
<div class="text-gray-600 italic text-sm my-4">
|
||||
@@ -84,7 +92,8 @@
|
||||
{#if !noInputs}
|
||||
<Button
|
||||
loading={isLoading}
|
||||
btnClasses="my-1"
|
||||
btnClasses="my-1 {css?.button?.class ?? ''}"
|
||||
style={css?.button?.style ?? ''}
|
||||
on:pointerdown={(e) => {
|
||||
e?.stopPropagation()
|
||||
window.dispatchEvent(new Event('pointerup'))
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
import { Icon } from 'svelte-awesome'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import type { Output } from '../../rx'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import type RunnableComponent from '../helpers/RunnableComponent.svelte'
|
||||
import RunnableWrapper from '../helpers/RunnableWrapper.svelte'
|
||||
import Portal from 'svelte-portal'
|
||||
import Modal from '$lib/components/common/modal/Modal.svelte'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
@@ -20,10 +21,11 @@
|
||||
export let extraQueryParams: Record<string, any> = {}
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'button' | 'popup'> | undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result']
|
||||
|
||||
const { runnableComponents, worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
const { app, runnableComponents, worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let labelValue: string = 'Default label'
|
||||
let color: ButtonType.Color
|
||||
@@ -35,6 +37,8 @@
|
||||
let ownClick: boolean = false
|
||||
|
||||
let errors: Record<string, string> = {}
|
||||
let open: boolean = false
|
||||
|
||||
$: errorsMessage = Object.values(errors)
|
||||
.filter((x) => x != '')
|
||||
.join('\n')
|
||||
@@ -62,7 +66,7 @@
|
||||
|
||||
$: loading = isLoading && ownClick
|
||||
|
||||
let open: boolean = false
|
||||
$: css = concatCustomCss($app?.css?.formbuttoncomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.label} bind:value={labelValue} />
|
||||
@@ -79,6 +83,8 @@
|
||||
<Modal
|
||||
{open}
|
||||
title={labelValue}
|
||||
class={css?.popup.class}
|
||||
style={css?.popup.style}
|
||||
on:canceled={() => {
|
||||
open = false
|
||||
}}
|
||||
@@ -148,6 +154,8 @@
|
||||
{disabled}
|
||||
{size}
|
||||
{color}
|
||||
btnClasses={css?.button?.class ?? ''}
|
||||
style={css?.button?.style ?? ''}
|
||||
on:click={(e) => {
|
||||
open = true
|
||||
}}
|
||||
|
||||
@@ -15,13 +15,18 @@
|
||||
import RunnableWrapper from '../helpers/RunnableWrapper.svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let initializing: boolean | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'container'> | undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result']
|
||||
const { app } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
ChartJS.register(
|
||||
Title,
|
||||
@@ -77,17 +82,21 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
$: css = concatCustomCss($app.css?.barchartcomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.theme} bind:value={theme} />
|
||||
<InputValue {id} input={configuration.line} bind:value={lineChart} />
|
||||
|
||||
<RunnableWrapper flexWrap autoRefresh bind:componentInput {id} bind:initializing bind:result>
|
||||
{#if result}
|
||||
{#if lineChart}
|
||||
<Line {data} options={lineOptions} />
|
||||
{:else}
|
||||
<Bar {data} options={barOptions} />
|
||||
<div class="w-full h-full {css?.container?.class ?? ''}" style={css?.container?.style ?? ''}>
|
||||
{#if result}
|
||||
{#if lineChart}
|
||||
<Line {data} options={lineOptions} />
|
||||
{:else}
|
||||
<Bar {data} options={barOptions} />
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</RunnableWrapper>
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import RunnableWrapper from '../helpers/RunnableWrapper.svelte'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
export let initializing: boolean | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'container'> | undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = ['result', 'loading']
|
||||
const { app } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let result: string | undefined = undefined
|
||||
let h: number | undefined = undefined
|
||||
let w: number | undefined = undefined
|
||||
|
||||
$: css = concatCustomCss($app.css?.htmlcomponent, customCss)
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -25,8 +32,8 @@
|
||||
{#key result}
|
||||
<iframe
|
||||
frameborder="0"
|
||||
style="height: {h}px; width: {w}px"
|
||||
class="p-0"
|
||||
style="height: {h}px; width: {w}px; {css?.container?.style ?? ''}"
|
||||
class="p-0 {css?.container?.class ?? ''}"
|
||||
title="sandbox"
|
||||
srcdoc={result
|
||||
? '<scr' + `ipt type="application/javascript" src="/tailwind.js"></script>` + result
|
||||
|
||||
@@ -14,13 +14,18 @@
|
||||
import RunnableWrapper from '../helpers/RunnableWrapper.svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import { getContext } from 'svelte'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let initializing: boolean | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'container'> | undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result']
|
||||
const { app } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
ChartJS.register(
|
||||
Title,
|
||||
@@ -60,17 +65,21 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
$: css = concatCustomCss($app.css?.piechartcomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.theme} bind:value={theme} />
|
||||
<InputValue {id} input={configuration.doughnutStyle} bind:value={doughnut} />
|
||||
|
||||
<RunnableWrapper flexWrap autoRefresh bind:componentInput {id} bind:initializing bind:result>
|
||||
{#if result}
|
||||
{#if doughnut}
|
||||
<Doughnut {data} {options} />
|
||||
{:else}
|
||||
<Pie {data} {options} />
|
||||
<div class="w-full h-full {css?.container?.class ?? ''}" style={css?.container?.style ?? ''}>
|
||||
{#if result}
|
||||
{#if doughnut}
|
||||
<Doughnut {data} {options} />
|
||||
{:else}
|
||||
<Pie {data} {options} />
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</RunnableWrapper>
|
||||
|
||||
@@ -17,16 +17,21 @@
|
||||
import Scatter from 'svelte-chartjs/Scatter.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import type { ChartOptions, ChartData } from 'chart.js'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let initializing: boolean | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'container'> | undefined = undefined
|
||||
|
||||
let zoomable = false
|
||||
let pannable = false
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result']
|
||||
const { app } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
ChartJS.register(
|
||||
Title,
|
||||
@@ -66,13 +71,17 @@
|
||||
$: data = {
|
||||
datasets: result ?? []
|
||||
} as ChartData<'scatter', (number | Point)[], unknown>
|
||||
|
||||
$: css = concatCustomCss($app.css?.scatterchartcomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.zoomable} bind:value={zoomable} />
|
||||
<InputValue {id} input={configuration.pannable} bind:value={pannable} />
|
||||
|
||||
<RunnableWrapper flexWrap autoRefresh bind:componentInput {id} bind:initializing bind:result>
|
||||
{#if result}
|
||||
<Scatter {data} {options} />
|
||||
{/if}
|
||||
<div class="w-full h-full {css?.container?.class ?? ''}" style={css?.container?.style ?? ''}>
|
||||
{#if result}
|
||||
<Scatter {data} {options} />
|
||||
{/if}
|
||||
</div>
|
||||
</RunnableWrapper>
|
||||
|
||||
@@ -20,13 +20,18 @@
|
||||
import { Scatter } from 'svelte-chartjs'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import type { ChartOptions, ChartData } from 'chart.js'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
import { getContext } from 'svelte'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let initializing: boolean | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'container'> | undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result']
|
||||
const { app } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let logarithmicScale = false
|
||||
let zoomable = false
|
||||
@@ -80,6 +85,8 @@
|
||||
$: data = {
|
||||
datasets: result ?? []
|
||||
} as ChartData<'scatter', (number | Point)[], unknown>
|
||||
|
||||
$: css = concatCustomCss($app.css?.timeseriescomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.logarithmicScale} bind:value={logarithmicScale} />
|
||||
@@ -87,7 +94,9 @@
|
||||
<InputValue {id} input={configuration.pannable} bind:value={pannable} />
|
||||
|
||||
<RunnableWrapper flexWrap autoRefresh bind:componentInput {id} bind:initializing bind:result>
|
||||
{#if result}
|
||||
<Scatter {data} {options} />
|
||||
{/if}
|
||||
<div class="w-full h-full {css?.container?.class ?? ''}" style={css?.container?.style ?? ''}>
|
||||
{#if result}
|
||||
<Scatter {data} {options} />
|
||||
{/if}
|
||||
</div>
|
||||
</RunnableWrapper>
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import { onMount } from 'svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import RunnableWrapper from '../helpers/RunnableWrapper.svelte'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
export let configuration: Record<string, AppInput>
|
||||
// export let configuration: Record<string, AppInput>
|
||||
export let initializing: boolean | undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = ['result', 'loading']
|
||||
@@ -42,11 +41,6 @@
|
||||
|
||||
<div class="w-full h-full" bind:clientHeight={h} bind:clientWidth={w}>
|
||||
<RunnableWrapper flexWrap bind:componentInput {id} bind:initializing bind:result>
|
||||
{#if !Plotly}
|
||||
<div class="p-2">
|
||||
<Loader2 class="animate-spin" />
|
||||
</div>
|
||||
{/if}
|
||||
<div on:pointerdown bind:this={divEl} />
|
||||
</RunnableWrapper>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import { onMount } from 'svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
@@ -54,11 +53,6 @@
|
||||
|
||||
<div class="w-full h-full" bind:clientHeight={h} bind:clientWidth={w}>
|
||||
<RunnableWrapper flexWrap bind:componentInput {id} bind:initializing bind:result>
|
||||
{#if !vegaEmbed}
|
||||
<div class="p-2">
|
||||
<Loader2 class="animate-spin" />
|
||||
</div>
|
||||
{/if}
|
||||
<div on:pointerdown bind:this={divEl} />
|
||||
</RunnableWrapper>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import type { Output } from '../../../rx'
|
||||
import type { AppEditorContext, BaseAppComponent } from '../../../types'
|
||||
import type { AppEditorContext, BaseAppComponent, ComponentCustomCSS } from '../../../types'
|
||||
import InputValue from '../../helpers/InputValue.svelte'
|
||||
import type { AppInput } from '../../../inputType'
|
||||
import RunnableWrapper from '../../helpers/RunnableWrapper.svelte'
|
||||
@@ -14,12 +14,17 @@
|
||||
import { tableOptions } from './tableOptions'
|
||||
import Alert from '$lib/components/common/alert/Alert.svelte'
|
||||
import type { ButtonComponent } from '../../../editor/component'
|
||||
import { concatCustomCss } from '../../../utils'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export let id: string
|
||||
export let componentInput: AppInput | undefined
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let actionButtons: (BaseAppComponent & ButtonComponent)[]
|
||||
export let initializing: boolean | undefined = undefined
|
||||
export let customCss:
|
||||
| ComponentCustomCSS<'container' | 'tableHeader' | 'tableBody' | 'tableFooter'>
|
||||
| undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = [
|
||||
'selectedRow',
|
||||
@@ -51,8 +56,11 @@
|
||||
|
||||
let table = createSvelteTable(options)
|
||||
|
||||
const { worldStore, staticOutputs: staticOutputsStore } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
const {
|
||||
app,
|
||||
worldStore,
|
||||
staticOutputs: staticOutputsStore
|
||||
} = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let selectedRowIndex = -1
|
||||
|
||||
@@ -133,13 +141,22 @@
|
||||
}
|
||||
|
||||
$: result && rerender()
|
||||
|
||||
$: css = concatCustomCss($app.css?.tablecomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.search} bind:value={search} />
|
||||
|
||||
<RunnableWrapper flexWrap bind:componentInput {id} bind:initializing bind:result>
|
||||
{#if Array.isArray(result) && result.every(isObject)}
|
||||
<div class="border border-gray-300 shadow-sm divide-y divide-gray-300 flex flex-col h-full">
|
||||
<div
|
||||
class={twMerge(
|
||||
'border border-gray-300 shadow-sm divide-y divide-gray-300 h-full',
|
||||
css?.container?.class ?? '',
|
||||
'flex flex-col'
|
||||
)}
|
||||
style={css?.container?.style ?? ''}
|
||||
>
|
||||
{#if search !== 'Disabled'}
|
||||
<div class="px-2 py-1">
|
||||
<div class="flex items-center">
|
||||
@@ -152,7 +169,14 @@
|
||||
|
||||
<div class="overflow-x-auto flex-1 w-full">
|
||||
<table class="relative w-full border-b border-b-gray-200">
|
||||
<thead class="sticky top-0 z-40 bg-gray-50 text-left">
|
||||
<thead
|
||||
class={twMerge(
|
||||
'bg-gray-50 text-left',
|
||||
css?.tableHeader?.class ?? '',
|
||||
'sticky top-0 z-40'
|
||||
)}
|
||||
style={css?.tableHeader?.style ?? ''}
|
||||
>
|
||||
{#each $table.getHeaderGroups() as headerGroup}
|
||||
<tr class="divide-x">
|
||||
{#each headerGroup.headers as header}
|
||||
@@ -178,7 +202,10 @@
|
||||
</tr>
|
||||
{/each}
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 bg-white ">
|
||||
<tbody
|
||||
class={twMerge('divide-y divide-gray-200 bg-white', css?.tableBody?.class ?? '')}
|
||||
style={css?.tableBody?.style ?? ''}
|
||||
>
|
||||
{#each $table.getRowModel().rows as row, rowIndex (row.id)}
|
||||
<tr
|
||||
class={classNames(
|
||||
@@ -235,7 +262,13 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<AppTableFooter paginationEnabled={pagination} {result} {table} />
|
||||
<AppTableFooter
|
||||
paginationEnabled={pagination}
|
||||
{result}
|
||||
{table}
|
||||
class={css?.tableFooter.class}
|
||||
style={css?.tableFooter.style}
|
||||
/>
|
||||
</div>
|
||||
{:else if result != undefined}
|
||||
<Alert title="Parsing issues" type="error" size="xs">
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import type { Table } from '@tanstack/svelte-table'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
|
||||
import type { Readable } from 'svelte/store'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { tableOptions } from './tableOptions'
|
||||
|
||||
type T = Record<string, any>
|
||||
@@ -11,6 +12,9 @@
|
||||
export let result: Array<T>
|
||||
export let paginationEnabled: boolean = false
|
||||
export let table: Readable<Table<T>>
|
||||
let c = ''
|
||||
export { c as class }
|
||||
export let style = ''
|
||||
|
||||
function downloadResultAsJSON() {
|
||||
const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(result))
|
||||
@@ -23,7 +27,10 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="px-2 py-1 text-xs flex flex-row gap-2 items-center justify-between">
|
||||
<div
|
||||
class={twMerge('px-2 py-1 text-xs gap-2 items-center justify-between', c, 'flex flex-row')}
|
||||
{style}
|
||||
>
|
||||
{#if paginationEnabled && result.length > (tableOptions.initialState?.pagination?.pageSize ?? 25)}
|
||||
<div class="flex items-center gap-2 flex-row">
|
||||
<Button
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
export let defaultUserInput = false
|
||||
export let flexWrap = false
|
||||
export let wrapperClass = ''
|
||||
export let wrapperStyle = ''
|
||||
export let initializing: boolean | undefined = undefined
|
||||
export let gotoUrl: string | undefined = undefined
|
||||
|
||||
@@ -270,7 +271,7 @@
|
||||
bind:this={testJobLoader}
|
||||
/>
|
||||
|
||||
<div class="h-full flex relative flex-row flex-wrap {wrapperClass}">
|
||||
<div class="h-full flex relative flex-row flex-wrap {wrapperClass}" style={wrapperStyle}>
|
||||
{#if !initializing && autoRefresh === true}
|
||||
<div class="flex absolute top-1 right-1">
|
||||
<RefreshButton componentId={id} />
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
export let defaultUserInput = false
|
||||
export let flexWrap = false
|
||||
export let runnableClass = ''
|
||||
export let runnableStyle = ''
|
||||
export let goto: string | undefined = undefined
|
||||
|
||||
const { staticExporter, noBackend } = getContext<AppEditorContext>('AppEditorContext')
|
||||
@@ -55,6 +56,7 @@
|
||||
{forceSchemaDisplay}
|
||||
{initializing}
|
||||
wrapperClass={runnableClass}
|
||||
wrapperStyle={runnableStyle}
|
||||
>
|
||||
<slot />
|
||||
</RunnableComponent>
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import type { Output } from '../../rx'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
|
||||
@@ -11,8 +12,9 @@
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'text'> | undefined = undefined
|
||||
|
||||
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
const { app, worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
export const staticOutputs: string[] = ['result']
|
||||
|
||||
@@ -27,6 +29,8 @@
|
||||
}
|
||||
|
||||
$: defaultValue != undefined && outputs?.result.set(defaultValue)
|
||||
|
||||
$: css = concatCustomCss($app.css?.checkboxcomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.label} bind:value={labelValue} />
|
||||
@@ -40,6 +44,8 @@
|
||||
}}
|
||||
checked={defaultValue}
|
||||
options={{ right: labelValue }}
|
||||
textClass={css?.text?.class ?? ''}
|
||||
textStyle={css?.text?.style ?? ''}
|
||||
on:change={(e) => {
|
||||
outputs.result.set(e.detail)
|
||||
}}
|
||||
|
||||
@@ -3,17 +3,20 @@
|
||||
import Select from 'svelte-select'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import type { Output } from '../../rx'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import { SELECT_INPUT_DEFAULT_STYLE } from '../../../../defaults'
|
||||
|
||||
export const staticOutputs: string[] = ['result']
|
||||
export let id: string
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let customCss: ComponentCustomCSS<'input'> | undefined = undefined
|
||||
|
||||
const { worldStore, connectingInput, selectedComponent } =
|
||||
const { app, worldStore, connectingInput, selectedComponent } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
let items: { label: string; value: any }[]
|
||||
let multiple: boolean = false
|
||||
@@ -65,6 +68,8 @@
|
||||
} catch (_) {}
|
||||
outputs?.result.set(result)
|
||||
}
|
||||
|
||||
$: css = concatCustomCss($app.css?.selectcomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.items} bind:value={items} />
|
||||
@@ -72,13 +77,15 @@
|
||||
<InputValue {id} input={configuration.placeholder} bind:value={placeholder} />
|
||||
|
||||
<AlignWrapper {horizontalAlignment} {verticalAlignment}>
|
||||
<div class="app-select w-full" style="height: 34px" on:pointerdown|stopPropagation>
|
||||
<div class="app-select w-full mx-0.5" style="height: 34px" on:pointerdown|stopPropagation>
|
||||
<Select
|
||||
--height="34px"
|
||||
{multiple}
|
||||
on:clear={onChange}
|
||||
on:change={onChange}
|
||||
items={listItems}
|
||||
class={css?.input?.class ?? ''}
|
||||
inputStyles={SELECT_INPUT_DEFAULT_STYLE.inputStyles}
|
||||
containerStyles={SELECT_INPUT_DEFAULT_STYLE.containerStyles + css?.input.style}
|
||||
{value}
|
||||
{placeholder}
|
||||
on:click={() => {
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import type { Output } from '../../rx'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import type { AppEditorContext, ComponentCustomCSS } from '../../types'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import InputDefaultValue from '../helpers/InputDefaultValue.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
@@ -12,8 +13,9 @@
|
||||
export let inputType = 'text'
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export const staticOutputs: string[] = ['result']
|
||||
export let customCss: ComponentCustomCSS<'input'> | undefined = undefined
|
||||
|
||||
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
const { app, worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
let input: HTMLInputElement
|
||||
|
||||
let placeholder: string | undefined = undefined
|
||||
@@ -28,6 +30,8 @@
|
||||
}
|
||||
|
||||
$: input && handleInput()
|
||||
|
||||
$: css = concatCustomCss($app.css?.textinputcomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.placeholder} bind:value={placeholder} />
|
||||
@@ -36,7 +40,8 @@
|
||||
|
||||
<AlignWrapper {verticalAlignment}>
|
||||
<input
|
||||
class="mx-0.5"
|
||||
class="mx-0.5 {css?.input?.class ?? ''}"
|
||||
style={css?.input?.style ?? ''}
|
||||
on:focus={(e) => {
|
||||
e?.stopPropagation()
|
||||
window.dispatchEvent(new Event('pointerup'))
|
||||
|
||||
@@ -6,4 +6,4 @@ export { default as AppNumberInput } from './AppNumberInput.svelte'
|
||||
export { default as AppRangeInput } from './AppRangeInput.svelte'
|
||||
export { default as AppSelect } from './AppSelect.svelte'
|
||||
export { default as AppSliderInputs } from './AppSliderInputs.svelte'
|
||||
export { default as AppTextInput } from './AppTextInput.svelte'
|
||||
export { default as AppTextInput } from './AppTextInput.svelte'
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
import { getContext } from 'svelte'
|
||||
import SubGridEditor from '../../editor/SubGridEditor.svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import type { AppEditorContext, GridItem } from '../../types'
|
||||
import type { AppEditorContext, ComponentCustomCSS, GridItem } from '../../types'
|
||||
import { concatCustomCss } from '../../utils'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
|
||||
export let id: string
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let componentContainerHeight: number
|
||||
export let customCss: ComponentCustomCSS<'container'> | undefined = undefined
|
||||
|
||||
let noPadding: boolean | undefined = undefined
|
||||
|
||||
@@ -24,6 +26,8 @@
|
||||
}
|
||||
|
||||
$: $selectedComponent === id && onFocus()
|
||||
|
||||
$: css = concatCustomCss($app.css?.containercomponent, customCss)
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.noPadding} bind:value={noPadding} />
|
||||
@@ -32,6 +36,8 @@
|
||||
{#if $app.subgrids?.[`${id}-0`]}
|
||||
<SubGridEditor
|
||||
{noPadding}
|
||||
class={css?.container.class}
|
||||
style={css?.container.style}
|
||||
bind:subGrid={$app.subgrids[`${id}-0`]}
|
||||
containerHeight={componentContainerHeight}
|
||||
on:focus={() => {
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
import { classNames } from '$lib/utils'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import Grid from '@windmill-labs/svelte-grid'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { columnConfiguration, isFixed, toggleFixed } from '../gridUtils'
|
||||
import type { AppEditorContext, GridItem } from '../types'
|
||||
import Component from './component/Component.svelte'
|
||||
import { findGridItem } from './appUtils'
|
||||
|
||||
export let containerHeight: number
|
||||
let classes = ''
|
||||
export { classes as class }
|
||||
export let style = ''
|
||||
export let noPadding = false
|
||||
//export let id: string
|
||||
export let subGrid: GridItem[] = []
|
||||
@@ -64,12 +68,11 @@
|
||||
bind:this={container}
|
||||
>
|
||||
<div
|
||||
class:px-2={!noPadding}
|
||||
class="py-2 overflow-auto {$connectingInput?.opened ? '' : ''}"
|
||||
class={twMerge('py-2 overflow-auto', classes ?? '', noPadding ? 'px-0' : 'px-2')}
|
||||
on:pointerdown|stopPropagation={onpointerdown}
|
||||
on:pointerleave={onpointerup}
|
||||
on:pointerup={onpointerup}
|
||||
style="height: {containerHeight}px;"
|
||||
style="height: {containerHeight}px; {style ?? ''}"
|
||||
>
|
||||
<div>
|
||||
<Grid
|
||||
|
||||
@@ -175,6 +175,9 @@ export const components: Record<AppComponent['type'], AppComponentConfig> = {
|
||||
onlyStatic: true
|
||||
}
|
||||
},
|
||||
customCss: {
|
||||
container: { class: '', style: '' }
|
||||
} as const,
|
||||
componentInput: undefined,
|
||||
card: false,
|
||||
numberOfSubgrids: 1
|
||||
@@ -336,7 +339,10 @@ export const components: Record<AppComponent['type'], AppComponentConfig> = {
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
container: { class: '', style: '' },
|
||||
button: { class: '', style: '' }
|
||||
} as const,
|
||||
card: true
|
||||
}
|
||||
},
|
||||
@@ -377,7 +383,10 @@ export const components: Record<AppComponent['type'], AppComponentConfig> = {
|
||||
optionValuesKey: 'buttonSizeOptions'
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
button: { class: '', style: '' },
|
||||
popup: { class: '', style: '' }
|
||||
} as const,
|
||||
card: true
|
||||
}
|
||||
},
|
||||
@@ -408,7 +417,9 @@ export const components: Record<AppComponent['type'], AppComponentConfig> = {
|
||||
fieldType: 'object',
|
||||
value: { data: [25, 50, 25], labels: ['Pie', 'Charts', '<3'] }
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
container: { class: '', style: '' }
|
||||
} as const,
|
||||
card: true
|
||||
}
|
||||
},
|
||||
@@ -439,7 +450,9 @@ export const components: Record<AppComponent['type'], AppComponentConfig> = {
|
||||
fieldType: 'object',
|
||||
value: { data: [25, 50, 25], labels: ['Bar', 'Charts', '<3'] }
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
container: { class: '', style: '' }
|
||||
} as const,
|
||||
card: true
|
||||
}
|
||||
},
|
||||
@@ -462,7 +475,9 @@ Hello \${ctx.username}
|
||||
</h1>`
|
||||
},
|
||||
configuration: {},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
container: { class: '', style: '' }
|
||||
} as const,
|
||||
card: false
|
||||
}
|
||||
},
|
||||
@@ -604,7 +619,9 @@ Hello \${ctx.username}
|
||||
}
|
||||
]
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
container: { class: '', style: '' }
|
||||
} as const,
|
||||
card: true
|
||||
}
|
||||
},
|
||||
@@ -654,7 +671,9 @@ Hello \${ctx.username}
|
||||
}
|
||||
]
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
container: { class: '', style: '' }
|
||||
} as const,
|
||||
card: true
|
||||
}
|
||||
},
|
||||
@@ -691,7 +710,12 @@ Hello \${ctx.username}
|
||||
}
|
||||
]
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
container: { class: '', style: '' },
|
||||
tableHeader: { class: '', style: '' },
|
||||
tableBody: { class: '', style: '' },
|
||||
tableFooter: { class: '', style: '' }
|
||||
} as const,
|
||||
card: true,
|
||||
actionButtons: []
|
||||
}
|
||||
@@ -747,7 +771,7 @@ Hello \${ctx.username}
|
||||
]
|
||||
},
|
||||
customCss: {},
|
||||
card: true,
|
||||
card: true
|
||||
}
|
||||
},
|
||||
checkboxcomponent: {
|
||||
@@ -772,7 +796,9 @@ Hello \${ctx.username}
|
||||
fieldType: 'boolean'
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
text: { class: '', style: '' }
|
||||
} as const,
|
||||
card: false
|
||||
}
|
||||
},
|
||||
@@ -799,7 +825,9 @@ Hello \${ctx.username}
|
||||
fieldType: 'text'
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
input: { class: '', style: '' }
|
||||
} as const,
|
||||
card: false
|
||||
}
|
||||
},
|
||||
@@ -835,7 +863,9 @@ Hello \${ctx.username}
|
||||
onlyStatic: true
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: {
|
||||
input: { style: '' }
|
||||
} as const,
|
||||
card: false,
|
||||
softWrap: true
|
||||
}
|
||||
@@ -865,17 +895,17 @@ Hello \${ctx.username}
|
||||
min: {
|
||||
type: 'static',
|
||||
value: undefined,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
},
|
||||
max: {
|
||||
type: 'static',
|
||||
value: undefined,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
},
|
||||
step: {
|
||||
type: 'static',
|
||||
value: 1,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
@@ -943,17 +973,17 @@ Hello \${ctx.username}
|
||||
max: {
|
||||
type: 'static',
|
||||
value: 42,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
},
|
||||
defaultValue: {
|
||||
type: 'static',
|
||||
value: 20,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
},
|
||||
step: {
|
||||
type: 'static',
|
||||
value: 1,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
@@ -974,27 +1004,27 @@ Hello \${ctx.username}
|
||||
min: {
|
||||
type: 'static',
|
||||
value: 0,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
},
|
||||
max: {
|
||||
type: 'static',
|
||||
value: 42,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
},
|
||||
defaultLow: {
|
||||
type: 'static',
|
||||
value: 10,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
},
|
||||
defaultHigh: {
|
||||
type: 'static',
|
||||
value: 20,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
},
|
||||
step: {
|
||||
type: 'static',
|
||||
value: 1,
|
||||
fieldType: 'number',
|
||||
fieldType: 'number'
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
|
||||
@@ -1,34 +1,59 @@
|
||||
<script lang="ts">
|
||||
import type { ComponentCssProperty } from "../../types"
|
||||
import { X } from 'lucide-svelte'
|
||||
import { fade } from 'svelte/transition'
|
||||
import { addWhitespaceBeforeCapitals } from '../../../../utils'
|
||||
import type { ComponentCssProperty } from '../../types'
|
||||
|
||||
export let name: string
|
||||
export let value: ComponentCssProperty | undefined
|
||||
|
||||
function reset(property: keyof ComponentCssProperty) {
|
||||
if (value) {
|
||||
value[property] = ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="text-sm font-semibold text-gray-500 capitalize pt-2">
|
||||
{name}
|
||||
{addWhitespaceBeforeCapitals(name)}
|
||||
</div>
|
||||
{#if value}
|
||||
<div class="border-l border-gray-400/80 py-1 pl-3.5 mt-1 ml-0.5">
|
||||
<label class="block pb-2">
|
||||
<div class="text-xs font-medium pb-0.5">
|
||||
Style
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={value.style}
|
||||
on:focus
|
||||
/>
|
||||
</label>
|
||||
<label class="block">
|
||||
<div class="text-xs font-medium pb-0.5">
|
||||
Tailwind classes
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={value.class}
|
||||
on:focus
|
||||
/>
|
||||
</label>
|
||||
{#if value.style !== undefined}
|
||||
<label class="block pb-2">
|
||||
<div class="text-xs font-medium pb-0.5"> Style </div>
|
||||
<div class="relative">
|
||||
<input type="text" class="!pr-7" bind:value={value.style} on:focus />
|
||||
{#if value?.style}
|
||||
<button
|
||||
transition:fade={{ duration: 100 }}
|
||||
class="absolute z-10 top-1.5 right-1 rounded-full p-1 duration-200 hover:bg-gray-200"
|
||||
aria-label="Remove styles"
|
||||
on:click|preventDefault|stopPropagation={() => reset('style')}
|
||||
>
|
||||
<X size={14} />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</label>
|
||||
{/if}
|
||||
{#if value.class !== undefined}
|
||||
<label class="block">
|
||||
<div class="text-xs font-medium pb-0.5"> Tailwind classes </div>
|
||||
<div class="relative">
|
||||
<input type="text" class="!pr-7" bind:value={value.class} on:focus />
|
||||
{#if value?.class}
|
||||
<button
|
||||
transition:fade={{ duration: 100 }}
|
||||
class="absolute z-10 top-1.5 right-1 rounded-full p-1 duration-200 hover:bg-gray-200"
|
||||
aria-label="Remove classes"
|
||||
on:click|preventDefault|stopPropagation={() => reset('class')}
|
||||
>
|
||||
<X size={14} />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -9,15 +9,21 @@
|
||||
import { isOpenStore } from './store'
|
||||
import CssProperty from './CssProperty.svelte'
|
||||
import { components, type AppComponent } from '../component'
|
||||
import { slide } from 'svelte/transition'
|
||||
|
||||
const STATIC_ELEMENTS = ['app'] as const
|
||||
const TITLE_PREFIX = 'Css.' as const
|
||||
const SHOW_UNUSED_ID = 'Setting.ShowUnused' as const
|
||||
|
||||
type CustomCSSType = (typeof STATIC_ELEMENTS)[number] | AppComponent['type']
|
||||
|
||||
interface CustomCSSEntry {
|
||||
type: 'app' | AppComponent['type'];
|
||||
name: string;
|
||||
icon: any;
|
||||
ids: string[];
|
||||
type: CustomCSSType
|
||||
name: string
|
||||
icon: any
|
||||
ids: string[]
|
||||
}
|
||||
|
||||
const TITLE_PREFIX = 'Css.' as const
|
||||
const { app } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let rawCode = ''
|
||||
@@ -51,7 +57,7 @@
|
||||
icon: LayoutDashboardIcon,
|
||||
ids: ['viewer', 'grid', 'component']
|
||||
},
|
||||
...Object.values(components).map(({ name, icon, data: { type, customCss }}) => ({
|
||||
...Object.values(components).map(({ name, icon, data: { type, customCss } }) => ({
|
||||
type,
|
||||
name,
|
||||
icon,
|
||||
@@ -70,7 +76,7 @@
|
||||
}
|
||||
e.ids.forEach((id) => {
|
||||
if (!newCss[e.type][id]) {
|
||||
newCss[e.type][id] = { style: '', class: '' }
|
||||
newCss[e.type][id] = components?.[e.type]?.data?.customCss?.[id] ?? { class: '', style: '' }
|
||||
}
|
||||
})
|
||||
e.ids
|
||||
@@ -84,20 +90,32 @@
|
||||
//@ts-ignore
|
||||
$app.css = newCss
|
||||
|
||||
$: staticComponents = entries.filter(({ type }) => STATIC_ELEMENTS.includes(type as any))
|
||||
$: usedComponents = Object.keys(
|
||||
$app.grid.reduce((acc, { data }) => {
|
||||
acc[data.type] = true
|
||||
return acc
|
||||
}, {})
|
||||
)
|
||||
.map((type) => entries.find((entry) => entry.type === type))
|
||||
.filter(Boolean) as CustomCSSEntry[]
|
||||
$: unusedComponents = entries.filter(({ type }) => {
|
||||
return (
|
||||
!STATIC_ELEMENTS.includes(type as any) && !usedComponents.find((entry) => entry.type === type)
|
||||
)
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
isOpenStore.addItems(
|
||||
[{ name: 'App' }, ...Object.values(components)].map(component => {
|
||||
[{ name: 'App' }, ...Object.values(components)].map((component) => {
|
||||
return { [TITLE_PREFIX + component.name]: false }
|
||||
})
|
||||
)
|
||||
isOpenStore.addItems([{ [SHOW_UNUSED_ID]: false }])
|
||||
})
|
||||
</script>
|
||||
|
||||
<Tabs
|
||||
selected="ui"
|
||||
on:selected={(e) => switchTab(e.detail === 'json')}
|
||||
class="relative"
|
||||
>
|
||||
<Tabs selected="ui" on:selected={(e) => switchTab(e.detail === 'json')} class="relative">
|
||||
<Tab value="ui" size="xs" class="grow">
|
||||
<div class="m-1 center-center">
|
||||
<MousePointer2 size={16} />
|
||||
@@ -112,7 +130,7 @@
|
||||
</Tab>
|
||||
<div slot="content" class="h-full overflow-y-auto">
|
||||
<TabContent value="ui">
|
||||
{#each entries as { type, name, icon, ids }}
|
||||
{#each [...staticComponents, ...usedComponents] as { type, name, icon, ids }}
|
||||
{#if ids.length > 0}
|
||||
<ListItem title={name} prefix={TITLE_PREFIX}>
|
||||
<div slot="title" class="flex items-center">
|
||||
@@ -137,6 +155,44 @@
|
||||
</ListItem>
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="px-1 my-4">
|
||||
<button
|
||||
on:click|preventDefault|stopPropagation={() => isOpenStore.toggle(SHOW_UNUSED_ID)}
|
||||
class="w-full text-xs text-gray-500 text-center font-medium hover:underline p-2"
|
||||
>
|
||||
{$isOpenStore[SHOW_UNUSED_ID] ? 'Hide' : 'Show'} unused components
|
||||
</button>
|
||||
</div>
|
||||
{#if $isOpenStore[SHOW_UNUSED_ID]}
|
||||
<div transition:slide|local={{ duration: 300 }}>
|
||||
{#each unusedComponents as { type, name, icon, ids }}
|
||||
{#if ids.length > 0}
|
||||
<ListItem title={name} prefix={TITLE_PREFIX}>
|
||||
<div slot="title" class="flex items-center">
|
||||
<svelte:component this={icon} size={18} />
|
||||
<span class="ml-1">
|
||||
{name}
|
||||
</span>
|
||||
</div>
|
||||
<div class="pb-2">
|
||||
{#each ids as id}
|
||||
<div class="mb-3">
|
||||
{#if $app?.css?.[type][id]}
|
||||
{JSON.stringify($app.css[type][id])}
|
||||
<CssProperty
|
||||
name={id}
|
||||
bind:value={$app.css[type][id]}
|
||||
on:focus={() => (isCustom[type] = true)}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</ListItem>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</TabContent>
|
||||
<TabContent value="json">
|
||||
{#if !emptyString(jsonError)}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
$: isOpen = $isOpenStore[storeTitle]
|
||||
</script>
|
||||
|
||||
<section class="mt-1 mb-2 px-1">
|
||||
<section class="pt-1 pb-2 px-1">
|
||||
<button
|
||||
on:click|preventDefault={() => isOpenStore.toggle(storeTitle)}
|
||||
class="w-full flex justify-between items-center text-gray-700 px-2 py-1
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
<PanelSection title="Custom CSS">
|
||||
{#each Object.keys(component.customCss ?? {}) as name}
|
||||
{#if component?.customCss?.[name]}
|
||||
<div class="mb-2">
|
||||
<div class="w-full mb-2">
|
||||
<CssProperty {name} bind:value={component.customCss[name]} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -30,8 +30,8 @@ export interface GeneralAppInput {
|
||||
}
|
||||
|
||||
export type ComponentCssProperty = {
|
||||
class: string
|
||||
style: string
|
||||
class?: string
|
||||
style?: string
|
||||
}
|
||||
|
||||
export type ComponentCustomCSS<T extends string = string> = Record<T, ComponentCssProperty>
|
||||
|
||||
@@ -3,49 +3,14 @@ import { FlowService, ScriptService } from '$lib/gen'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import { emptySchema } from '$lib/utils'
|
||||
import type { AppComponent } from './editor/component'
|
||||
|
||||
import type { App, ComponentCssProperty, ComponentCustomCSS, GridItem } from './types'
|
||||
import { getRecommendedDimensionsByComponent } from './editor/component'
|
||||
import { gridColumns } from './gridUtils'
|
||||
import gridHelp from '@windmill-labs/svelte-grid/src/utils/helper'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import type { AppInput, InputType, ResultAppInput, StaticAppInput } from './inputType'
|
||||
import type { Output } from './rx'
|
||||
import type { App, GridItem } from './types'
|
||||
|
||||
/*
|
||||
export function deleteComponent(
|
||||
subgrid: string | undefined,
|
||||
component: AppComponent,
|
||||
app: App,
|
||||
staticOutputs: Record<string, any>,
|
||||
runnableComponents: Record<string, any>
|
||||
) {
|
||||
if (parentItems) {
|
||||
let index = parentItems.findIndex((item) => item.data?.id === component.id)
|
||||
if (index != -1) {
|
||||
parentItems.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
delete staticOutputs[component.id]
|
||||
delete runnableComponents[component.id]
|
||||
|
||||
if (
|
||||
component.componentInput?.type === 'runnable' &&
|
||||
component.componentInput?.runnable?.type === 'runnableByName'
|
||||
) {
|
||||
const { name, inlineScript } = component.componentInput.runnable
|
||||
|
||||
if (inlineScript) {
|
||||
if (!app.unusedInlineScripts) {
|
||||
app.unusedInlineScripts = []
|
||||
}
|
||||
|
||||
app.unusedInlineScripts.push({
|
||||
name,
|
||||
inlineScript
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
import { getNextId } from '../flows/flowStateUtils'
|
||||
|
||||
export function allItems(
|
||||
grid: GridItem[],
|
||||
@@ -273,3 +238,128 @@ export function toPascalCase(text: string) {
|
||||
export function toKebabCase(text: string) {
|
||||
return text.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
|
||||
}
|
||||
|
||||
export function findParent(root: GridItem[], id: string): GridItem | undefined {
|
||||
for (const a of root) {
|
||||
if (a.id === id) {
|
||||
return a
|
||||
}
|
||||
|
||||
if (a.data.subGrids) {
|
||||
// Recursively search the sub-grids
|
||||
for (const subGrid of a.data.subGrids) {
|
||||
const result = findParent(subGrid, id)
|
||||
if (result) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function insertNewGridItem(
|
||||
root: GridItem[],
|
||||
id: string,
|
||||
subGridIndex: number,
|
||||
newId: string,
|
||||
data: AppComponent
|
||||
): GridItem[] {
|
||||
const parentA = findParent(root, id)
|
||||
|
||||
if (!parentA) {
|
||||
throw new Error(`Parent A object with ID ${id} not found.`)
|
||||
}
|
||||
|
||||
const subGrid = parentA.data.subGrids[subGridIndex]
|
||||
|
||||
if (!subGrid) {
|
||||
throw new Error(`Sub-grid with index ${subGridIndex} not found.`)
|
||||
}
|
||||
|
||||
const newItem = createNewGridItem(subGrid ?? [], newId, data)
|
||||
subGrid.push(newItem)
|
||||
return root
|
||||
}
|
||||
|
||||
// The grid is needed to find a space for the new component
|
||||
export function createNewGridItem(grid: GridItem[], id: string, data: AppComponent): GridItem {
|
||||
const appComponent = data
|
||||
|
||||
appComponent.id = id
|
||||
|
||||
const newComponent = {
|
||||
fixed: false,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
customDragger: false,
|
||||
customResizer: false,
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let newData: AppComponent = JSON.parse(JSON.stringify(appComponent))
|
||||
|
||||
const newItem: GridItem = {
|
||||
data: newData,
|
||||
id: id
|
||||
}
|
||||
|
||||
gridColumns.forEach((column) => {
|
||||
const rec = getRecommendedDimensionsByComponent(appComponent.type, column)
|
||||
|
||||
newItem[column] = {
|
||||
...newComponent,
|
||||
min: { w: 1, h: 1 },
|
||||
max: { w: column, h: 100 },
|
||||
w: rec.w,
|
||||
h: rec.h
|
||||
}
|
||||
const position = gridHelp.findSpace(newItem, grid, column) as { x: number; y: number }
|
||||
newItem[column] = { ...newItem[column], ...position }
|
||||
})
|
||||
|
||||
return newItem
|
||||
}
|
||||
|
||||
function recursiveGetIds(gridItem: GridItem): string[] {
|
||||
const subGrids = gridItem.data.subGrids ?? []
|
||||
const subGridIds = subGrids
|
||||
.map((subGrid: GridItem[]) => subGrid.map(recursiveGetIds))
|
||||
.flat(Infinity)
|
||||
return [gridItem.data.id, ...subGridIds]
|
||||
}
|
||||
|
||||
export function getNextGridItemId(grid: GridItem[] = []): string {
|
||||
const gridItemIds = grid.map(recursiveGetIds).flat()
|
||||
const id = getNextId(gridItemIds)
|
||||
return id
|
||||
}
|
||||
|
||||
export function concatCustomCss<T extends string = string>(
|
||||
appCss?: ComponentCustomCSS<T>,
|
||||
componentCss?: ComponentCustomCSS<T>
|
||||
): Record<T, ComponentCssProperty> | undefined {
|
||||
if (!componentCss) return undefined
|
||||
|
||||
const customStyle = {} as Record<T, ComponentCssProperty>
|
||||
Object.keys(componentCss).forEach((key) => {
|
||||
const k = key as keyof typeof componentCss
|
||||
|
||||
// This is the general style of the component type
|
||||
const appStyle = appCss?.[k]?.style?.trim() || ''
|
||||
const appEnding = appStyle?.endsWith(';') || !appStyle ? ' ' : '; '
|
||||
|
||||
// This is the custom style of the component instance
|
||||
const compStyle = componentCss[k]?.style?.trim() || ''
|
||||
const compEnding = compStyle?.endsWith(';') || !compStyle ? ' ' : ';'
|
||||
|
||||
customStyle[k] = {
|
||||
style: (appStyle + appEnding + compStyle + compEnding).trim(),
|
||||
class: twMerge(appCss?.[k]?.class, componentCss[k]?.class)
|
||||
}
|
||||
})
|
||||
|
||||
return customStyle
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { fade } from 'svelte/transition'
|
||||
import Button from '../button/Button.svelte'
|
||||
import Badge from '../badge/Badge.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export let title: string
|
||||
export let open: boolean = false
|
||||
let c: string = ''
|
||||
export { c as class }
|
||||
export let style = ''
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -40,7 +43,7 @@
|
||||
role="dialog"
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
class={twMerge(
|
||||
'fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity',
|
||||
open ? 'ease-out duration-300 opacity-100' : 'ease-in duration-200 opacity-0'
|
||||
)}
|
||||
@@ -49,12 +52,14 @@
|
||||
<div class="fixed inset-0 z-10 overflow-y-auto">
|
||||
<div class="flex min-h-full items-center justify-center p-4">
|
||||
<div
|
||||
class={classNames(
|
||||
class={twMerge(
|
||||
'relative transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6',
|
||||
c,
|
||||
open
|
||||
? 'ease-out duration-300 opacity-100 translate-y-0 sm:scale-100'
|
||||
: 'ease-in duration-200 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95'
|
||||
)}
|
||||
{style}
|
||||
>
|
||||
<div class="flex">
|
||||
<div class="ml-4 text-left flex-1">
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export const SELECT_INPUT_DEFAULT_STYLE = {
|
||||
inputStyles: 'border-radius: 0;',
|
||||
containerStyles:
|
||||
'--height: 34px; --padding: 0 0 0 8px; --font-size: 0.875rem; --border: 1px solid #d1d5db;'
|
||||
} as const
|
||||
Reference in New Issue
Block a user