builder ui changes - UI builder in progress

This commit is contained in:
michael shanks 2019-08-07 09:03:49 +01:00
parent ca63769204
commit 21224b119b
33 changed files with 2666 additions and 1003 deletions

View File

@ -1,4 +1,4 @@
{ module.exports = ({
"presets": ["@babel/preset-env"], "presets": ["@babel/preset-env"],
"sourceMaps": "inline", "sourceMaps": "inline",
"retainLines": true, "retainLines": true,
@ -9,4 +9,4 @@
} }
] ]
] ]
} });

View File

@ -25,7 +25,7 @@
"node_modules" "node_modules"
], ],
"transform": { "transform": {
"^.+\\.js$": "babel-jest" "^.+js$": "babel-jest"
}, },
"transformIgnorePatterns": [ "transformIgnorePatterns": [
"/node_modules/(?!svelte).+\\.js$" "/node_modules/(?!svelte).+\\.js$"
@ -41,7 +41,7 @@
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"shortid": "^2.2.8", "shortid": "^2.2.8",
"string_decoder": "^1.2.0", "string_decoder": "^1.2.0",
"uikit": "^3.1.5" "uikit": "^3.1.7"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.5.5", "@babel/core": "^7.5.5",

View File

@ -34,7 +34,7 @@ const production = !process.env.ROLLUP_WATCH;
const lodash_fp_exports = ["union", "reduce", "isUndefined", "cloneDeep", "split", "some", "map", "filter", "isEmpty", "countBy", "includes", "last", "find", "constant", const lodash_fp_exports = ["union", "reduce", "isUndefined", "cloneDeep", "split", "some", "map", "filter", "isEmpty", "countBy", "includes", "last", "find", "constant",
"take", "first", "intersection", "mapValues", "isNull", "has", "isNumber", "isString", "isBoolean", "isDate", "isArray", "isObject", "clone", "values", "keyBy", "take", "first", "intersection", "mapValues", "isNull", "has", "isNumber", "isString", "isBoolean", "isDate", "isArray", "isObject", "clone", "values", "keyBy",
"keys", "orderBy", "concat", "reverse", "difference", "merge", "flatten", "each", "pull", "join", "defaultCase", "uniqBy", "every", "uniqWith", "isFunction", "groupBy", "keys", "orderBy", "concat", "reverse", "difference", "merge", "flatten", "each", "pull", "join", "defaultCase", "uniqBy", "every", "uniqWith", "isFunction", "groupBy",
"differenceBy", "intersectionBy", "isEqual", "max", "sortBy", "assign", "uniq", "trimChars", "trimCharsStart"]; "differenceBy", "intersectionBy", "isEqual", "max", "sortBy", "assign", "uniq", "trimChars", "trimCharsStart", "isObjectLike"];
const lodash_exports = ["toNumber", "flow", "isArray", "join", "replace", "trim", "dropRight", "takeRight", "head", "isUndefined", "isNull", "isNaN", "reduce", "isEmpty", const lodash_exports = ["toNumber", "flow", "isArray", "join", "replace", "trim", "dropRight", "takeRight", "head", "isUndefined", "isNull", "isNaN", "reduce", "isEmpty",
"constant", "tail", "includes", "startsWith", "findIndex", "isInteger", "isDate", "isString", "split", "clone", "keys", "isFunction", "merge", "has", "isBoolean", "isNumber", "constant", "tail", "includes", "startsWith", "findIndex", "isInteger", "isDate", "isString", "split", "clone", "keys", "isFunction", "merge", "has", "isBoolean", "isNumber",

View File

@ -72,16 +72,19 @@ const permissionChanged = perm => ev => {
<ErrorsBox {errors} /> <ErrorsBox {errors} />
<Textbox label="Name" bind:text={clonedLevel.name} /> <form class="uk-form-horizontal">
{#each permissionMatrix as permission} <Textbox label="Name" bind:text={clonedLevel.name} />
<div>
<Checkbox label={getPermissionName(permission.permission)}
checked={permission.hasPermission}
on:change={permissionChanged(permission.permission)} />
</div>
{/each}
{#each permissionMatrix as permission}
<div>
<Checkbox label={getPermissionName(permission.permission)}
checked={permission.hasPermission}
on:change={permissionChanged(permission.permission)} />
</div>
{/each}
</form>
<ButtonGroup style="margin-top: 10px"> <ButtonGroup style="margin-top: 10px">
<Button color="primary" grouped on:click={save}>Save</Button> <Button color="primary" grouped on:click={save}>Save</Button>

View File

@ -70,10 +70,13 @@ const cancel = () => {
<ErrorsBox {errors} /> <ErrorsBox {errors} />
<Textbox label="Name" bind:text={clonedAction.name} /> <form class="uk-form-horizontal">
<Textbox label="Behaviour Source" bind:text={clonedAction.behaviourSource} />
<Textbox label="Behaviour" bind:text={clonedAction.behaviourName} />
<Textbox label="Name" bind:text={clonedAction.name} />
<Textbox label="Behaviour Source" bind:text={clonedAction.behaviourSource} />
<Textbox label="Behaviour" bind:text={clonedAction.behaviourName} />
</form>
<div class=" uk-form-stacked" style="margin-bottom: 20px"> <div class=" uk-form-stacked" style="margin-bottom: 20px">
<label class="uk-form-label">Default Options</label> <label class="uk-form-label">Default Options</label>

View File

@ -40,17 +40,21 @@ let save = () => {
<div> <div>
<ErrorsBox {errors} style="margin-bottom:20px"/> <ErrorsBox {errors} style="margin-bottom:20px"/>
<form class="uk-form-horizontal">
<Dropdown label="Event" <Dropdown label="Event"
options={["",...events]} options={["",...events]}
bind:selected={clonedTrigger.eventName} /> bind:selected={clonedTrigger.eventName} />
<Dropdown label="Action" <Dropdown label="Action"
options={["",...actionNames]} options={["",...actionNames]}
bind:selected={clonedTrigger.actionName} /> bind:selected={clonedTrigger.actionName} />
<CodeArea label="Condition (javascript)" <CodeArea label="Condition (javascript)"
bind:text={clonedTrigger.condition} /> bind:text={clonedTrigger.condition} />
<CodeArea label="Action Options Creator (javascript)" <CodeArea label="Action Options Creator (javascript)"
bind:text={clonedTrigger.optionsCreator} /> bind:text={clonedTrigger.optionsCreator} />
</form>
<ButtonGroup> <ButtonGroup>
<Button grouped on:click={save}>Save</Button> <Button grouped on:click={save}>Save</Button>

View File

@ -5,7 +5,7 @@ export let label = "";
</script> </script>
<div>{label}</div> <div>{label}</div>
<textarea bind:value={text}></textarea> <textarea class="uk-textarea" bind:value={text}></textarea>
<style> <style>

View File

@ -6,6 +6,9 @@ import { onMount } from 'svelte';
export let value; export let value;
export let label; export let label;
export let width = "medium";
export let size = "small";
let input; let input;
let fpInstance; let fpInstance;
@ -22,40 +25,12 @@ onMount(() => {
return fpInstance; return fpInstance;
}) })
</script> </script>
<div class="uk-margin">
<div class="container" > <label class="uk-form-label">{label}</label>
<div class="label">{label}</div> <div class="uk-form-controls">
<input class="control" bind:this={input} /> <input class="uk-input uk-form-width-{width} uk-form-{size}" bind:this={input} >
</div>
</div> </div>
<style>
.container {
display: grid;
grid-template-columns: [label] 100px [control] auto;
margin: 20px 0px;
}
.label {
grid-column-start: label;
align-self: center;
}
.control {
grid-column-start: control;
align-self: center;
margin: 0;
}
input {
width:300px;
}
</style>

View File

@ -7,53 +7,33 @@ export let options;
export let valueMember; export let valueMember;
export let textMember; export let textMember;
export let multiple=false; export let multiple=false;
export let width = "medium";
export let size = "small";
const dispatch =createEventDispatcher(); const dispatch =createEventDispatcher();
</script> </script>
<div class="container">
<div class="label">{label}</div>
{#if multiple} <div class="uk-margin">
<label class="uk-form-label">{label}</label>
<select class="control uk-select" multiple bind:value={selected} on:change> <div class="uk-form-controls">
{#each options as option} {#if multiple}
<option value={!valueMember ? option : valueMember(option)}>{!textMember ? option : textMember(option)}</option>
{/each} <select class="uk-select uk-form-width-{width} uk-form-{size}" multiple bind:value={selected} on:change>
</select> {#each options as option}
<option value={!valueMember ? option : valueMember(option)}>{!textMember ? option : textMember(option)}</option>
{/each}
</select>
{:else} {:else}
<select class="control uk-select" bind:value={selected} on:change>
{#each options as option}
<option value={!valueMember ? option : valueMember(option)}>{!textMember ? option : textMember(option)}</option>
{/each}
</select>
{/if}
<select class="uk-select uk-form-width-{width} uk-form-{size}" bind:value={selected} on:change>
{#each options as option}
<option value={!valueMember ? option : valueMember(option)}>{!textMember ? option : textMember(option)}</option>
{/each}
</select>
{/if}
</div>
</div> </div>
<style>
.container {
display: grid;
grid-template-columns: [label] 100px [control] auto;
margin: 20px 0px;
}
.label {
grid-column-start: label;
align-self: center;
}
.control {
grid-column-start: control;
align-self: center;
margin: 0;
}
select {
width:300px;
}
</style>

View File

@ -0,0 +1,30 @@
<script>
import getIcon from "./icon";
export let size = 18;
export let icon = "";
export let style = "";
export let color = "";
export let hoverColor = "";
$: borderClass = grouped
? ""
: "border-normal";
</script>
<button style="{style} color:{color}"
on:click>
{@html getIcon(icon, size)}
</button>
<style>
button {
border-style: none;
background-color: rgba(0,0,0,0);
cursor: pointer;
}
</style>

View File

@ -3,6 +3,7 @@ import UIkit from "uikit";
export let isOpen = false; export let isOpen = false;
export let onClosed = () => {}; export let onClosed = () => {};
export let id = "";
let ukModal; let ukModal;
let listenerAdded = false; let listenerAdded = false;
@ -24,7 +25,7 @@ $: {
</script> </script>
<div bind:this={ukModal} uk-modal > <div bind:this={ukModal} uk-modal {id}>
<div class="uk-modal-dialog uk-modal-body" uk-overflow-auto> <div class="uk-modal-dialog uk-modal-body" uk-overflow-auto>
<slot /> <slot />
</div> </div>

View File

@ -17,30 +17,10 @@ let numberText = value === null || value === undefined
</script> </script>
<div class="container"> <div class="uk-margin">
<div class="label">{label}</div> <label class="uk-form-label">{label}</label>
<input class="control" type="text" value={value} on:change={inputChanged} > <div class="uk-form-controls">
<input class="uk-input" value={value} on:change={inputChanged} >
</div>
</div> </div>
<style>
.container {
display: grid;
grid-template-columns: [label] 100px [control] auto;
margin: 20px 0px;
}
.label {
grid-column-start: label;
align-self: center;
}
.control {
grid-column-start: control;
align-self: center;
margin: 0;
}
input {
width:300px;
}
</style>

View File

@ -1,32 +1,14 @@
<script> <script>
export let text = ""; export let text = "";
export let label = ""; export let label = "";
export let width = "medium";
export let size = "small";
</script> </script>
<div class="container"> <div class="uk-margin">
<div class="label">{label}</div> <label class="uk-form-label">{label}</label>
<input class="control uk-input" bind:value={text} > <div class="uk-form-controls">
<input class="uk-input uk-form-width-{width} uk-form-{size}" bind:value={text} >
</div>
</div> </div>
<style>
.container {
display: grid;
grid-template-columns: [label] 100px [control] auto;
margin: 20px 0px;
}
.label {
grid-column-start: label;
align-self: center;
}
.control {
grid-column-start: control;
align-self: center;
margin: 0;
}
input {
width:300px;
}
</style>

View File

@ -17,28 +17,16 @@ $: valuesText = join("\n")(values);
</script> </script>
<div class="container">
<div class="label">{label}</div> <div class="uk-margin">
<textarea class="control" value={valuesText} on:change={inputChanged} ></textarea> <label class="uk-form-label">{label}</label>
<div class="uk-form-controls">
<textarea value={valuesText} on:change={inputChanged} ></textarea>
</div>
</div> </div>
<style> <style>
.container {
display: grid;
grid-template-columns: [label] 100px [control] auto;
margin: 20px 0px;
}
.label {
grid-column-start: label;
align-self: center;
}
.control {
grid-column-start: control;
align-self: center;
margin: 0;
}
textarea { textarea {
width:300px; width:300px;
height:200px; height:200px;

View File

@ -59,49 +59,53 @@ const save = () => {
<ErrorsBox errors={errors} /> <ErrorsBox errors={errors} />
<Dropdown label="Type" bind:selected={clonedField.type} options={keys(allTypes)} on:change={typeChanged} /> <form class="uk-form-horizontal">
{#if isNew} <Dropdown label="Type" bind:selected={clonedField.type} options={keys(allTypes)} on:change={typeChanged} />
<Textbox label="Field Name" bind:text={clonedField.name} />
{:else}
<div style="font-weight: bold">{clonedField.name}</div>
{/if}
<Textbox label="Label" bind:text={clonedField.label} /> {#if isNew}
<Textbox label="Field Name" bind:text={clonedField.name} />
{#if clonedField.type === "string"} {:else}
<NumberBox label="Max Length" bind:value={clonedField.typeOptions.maxLength} /> <div style="font-weight: bold">{clonedField.name}</div>
<ValuesList label="Values (options)" bind:values={clonedField.typeOptions.values} /> {/if}
<Checkbox label="Declared Values Only" bind:checked={clonedField.typeOptions.allowDeclaredValuesOnly} />
{:else if clonedField.type === "bool"}
<Checkbox label="Allow Null" bind:checked={clonedField.typeOptions.allowNulls} />
{:else if clonedField.type === "datetime"}
<DatePicker label="Min Value" bind:value={clonedField.typeOptions.minValue} />
<DatePicker label="Max Value" bind:value={clonedField.typeOptions.maxValue} />
{:else if clonedField.type === "number"}
<NumberBox label="Min Value" bind:value={clonedField.typeOptions.minValue} />
<NumberBox label="Max Value" bind:value={clonedField.typeOptions.maxValue} />
<NumberBox label="Decimal Places" bind:value={clonedField.typeOptions.decimalPlaces} />
{:else if clonedField.type === "reference"}
<Dropdown label="Lookup Index"
options={possibleReferenceIndexes}
valueMember={n => n.nodeKey()}
textMember={n => n.name}
bind:selected={clonedField.typeOptions.indexNodeKey} />
<Dropdown label="Reverse Reference Index" <Textbox label="Label" bind:text={clonedField.label} />
options={possibleReverseReferenceIndexes}
multiple=true {#if clonedField.type === "string"}
valueMember={n => n.nodeKey()} <NumberBox label="Max Length" bind:value={clonedField.typeOptions.maxLength} />
textMember={n => n.name} <ValuesList label="Values (options)" bind:values={clonedField.typeOptions.values} />
bind:selected={clonedField.typeOptions.reverseIndexNodeKeys} /> <Checkbox label="Declared Values Only" bind:checked={clonedField.typeOptions.allowDeclaredValuesOnly} />
{:else if clonedField.type === "bool"}
<Checkbox label="Allow Null" bind:checked={clonedField.typeOptions.allowNulls} />
{:else if clonedField.type === "datetime"}
<DatePicker label="Min Value" bind:value={clonedField.typeOptions.minValue} />
<DatePicker label="Max Value" bind:value={clonedField.typeOptions.maxValue} />
{:else if clonedField.type === "number"}
<NumberBox label="Min Value" bind:value={clonedField.typeOptions.minValue} />
<NumberBox label="Max Value" bind:value={clonedField.typeOptions.maxValue} />
<NumberBox label="Decimal Places" bind:value={clonedField.typeOptions.decimalPlaces} />
{:else if clonedField.type === "reference"}
<Dropdown label="Lookup Index"
options={possibleReferenceIndexes}
valueMember={n => n.nodeKey()}
textMember={n => n.name}
bind:selected={clonedField.typeOptions.indexNodeKey} />
<Textbox label="Display Value" bind:text={clonedField.typeOptions.displayValue} /> <Dropdown label="Reverse Reference Index"
options={possibleReverseReferenceIndexes}
multiple=true
valueMember={n => n.nodeKey()}
textMember={n => n.name}
bind:selected={clonedField.typeOptions.reverseIndexNodeKeys} />
{:else if clonedField.type.startsWith("array")} <Textbox label="Display Value" bind:text={clonedField.typeOptions.displayValue} />
<NumberBox label="Min Length" bind:value={clonedField.typeOptions.minLength} />
<NumberBox label="Max Length" bind:value={clonedField.typeOptions.maxLength} /> {:else if clonedField.type.startsWith("array")}
{/if} <NumberBox label="Min Length" bind:value={clonedField.typeOptions.minLength} />
<NumberBox label="Max Length" bind:value={clonedField.typeOptions.maxLength} />
{/if}
</form>
<ButtonGroup style="float: right;"> <ButtonGroup style="float: right;">
<Button color="primary" grouped on:click={save}>Save</Button> <Button color="primary" grouped on:click={save}>Save</Button>

View File

@ -37,7 +37,7 @@ const toggleAllowedRecord = record => {
</script> </script>
<div class="root"> <form class="uk-form-horizontal root">
<Textbox bind:text={index.name} label="Name"/> <Textbox bind:text={index.name} label="Name"/>
<div class="allowed-records"> <div class="allowed-records">
@ -56,7 +56,7 @@ const toggleAllowedRecord = record => {
<CodeArea bind:text={index.getShardName} label="Shard Name (javascript expression)"/> <CodeArea bind:text={index.getShardName} label="Shard Name (javascript expression)"/>
</div> </form>
<style> <style>

View File

@ -84,13 +84,16 @@ let getTypeOptions = typeOptions =>
<div class="root"> <div class="root">
<Textbox label="Name" bind:text={record.name} /> <form class="uk-form-horizontal">
<div>{record.nodeKey()}</div>
{#if !record.isSingle} <Textbox label="Name" bind:text={record.name} />
<Textbox label="Collection Name" bind:text={record.collectionName} /> <div>{record.nodeKey()}</div>
<Textbox label="Shard Factor" bind:text={record.allidsShardFactor} /> {#if !record.isSingle}
{/if} <Textbox label="Collection Name" bind:text={record.collectionName} />
<Textbox label="Shard Factor" bind:text={record.allidsShardFactor} />
{/if}
</form>
<h4> <h4>
Fields <span class="add-field-button" on:click={newField}>{@html getIcon("plus")}</span> Fields <span class="add-field-button" on:click={newField}>{@html getIcon("plus")}</span>
</h4> </h4>

View File

@ -32,6 +32,7 @@
--white: #FFFFFF; --white: #FFFFFF;
--darkslate: #5C6B82; --darkslate: #5C6B82;
--slate: #8B95A6; --slate: #8B95A6;
--lightslate: rgb(203, 212, 228);
--borderradius: 2px; --borderradius: 2px;
--borderradiusall: 2px 2px 2px 2px; --borderradiusall: 2px 2px 2px 2px;
@ -44,11 +45,10 @@
--bodytext: var(--fontnormal) "regular" var(--secondary100) 16pt; --bodytext: var(--fontnormal) "regular" var(--secondary100) 16pt;
--bigbodytext: var(--fontnormal) "regular" var(--secondary100) 20pt; --bigbodytext: var(--fontnormal) "regular" var(--secondary100) 20pt;
--smallbodytext: var(--fontnormal) "regular" var(--secondary100) 12pt; --smallbodytext: var(--fontnormal) "regular" var(--secondary100) 12pt;
--lightbodytext: var(--fontnormal) "regular" var(--darkslate) 16pt; --lightbodytext: "regular" "normal" 16pt var(--fontnormal);
--heavybodytext: var(--fontbold) "regular" var(--secondary100) 16pt; --heavybodytext: var(--fontbold) "regular" var(--secondary100) 16pt;
--quotation: var(--fontnormal) "italics" var(--darkslate) 16pt; --quotation: var(--fontnormal) "italics" var(--darkslate) 16pt;
--smallheavybodytext: var(--fontbold) "regular" var(--secondary100) 14pt; --smallheavybodytext: var(--fontbold) "regular" var(--secondary100) 14pt;
} }
html, body { html, body {

View File

@ -0,0 +1,56 @@
<script>
import { searchAllComponents } from "./pagesParsing/searchComponents";
export let allComponents = [];
export let onComponentChosen = () => {};
let phrase = "";
$: filteredComponents =
!phrase
? []
: searchAllComponents(allComponents, phrase);
</script>
<div class="root">
<input class="uk-input" bind:value={phrase}>
<div>
{#each filteredComponents as component}
<div class="component" on:click={() => onComponentChosen(component)}>
<div class="title">{component.name}</div>
<div class="description">{component.description}</div>
</div>
{/each}
</div>
</div>
<style>
.component {
padding:5px;
border-style: solid;
border-width: 0 0 1px 0;
border-color: var(--lightslate);
cursor: pointer;
}
.component:hover {
background-color: var(--primary10);
}
.component > .title {
font-size: 13pt;
color: var(--secondary100);
}
.component > .description {
font-size: 10pt;
color: var(--primary75);
font-style: italic;
}
</style>

View File

@ -0,0 +1,41 @@
<script>
import ComponentSearch from "./ComponentSearch.svelte";
import { store } from "../builderStore";
import PropsView from "./PropsView.svelte";
import Modal from "../common/Modal.svelte";
import Textbox from "../common/Textbox.svelte";
export let isCreatingNewComponent;
let basedOnComponent;
const onBasedOnChosen = component => {
basedOnComponent = component;
}
</script>
<Modal bind:isOpen={isCreatingNewComponent} id="search-component-modal">
<div class="uk-margin">
<form class="uk-form-horizontal">
{#if basedOnComponent}
<Textbox label="name"/>
{:else}
<label class="uk-form-label" for="form-stacked-text">Based On</label>
<div class="uk-form-controls">
<ComponentSearch allComponents={$store.allComponents}
onComponentChosen={onBasedOnChosen} />
</div>
{/if}
</form>
</div>
</Modal>
<style>
</style>

View File

@ -27,13 +27,15 @@ const getPage = (s, name) => {
<style> <style>
.root { .root {
padding-left: 20px; padding-bottom: 10px;
padding-bottom: 20px; padding-left: 10px;
font-size: 16px;
color: var(--secondary50); color: var(--secondary50);
} }
.hierarchy-item { .hierarchy-item {
cursor: pointer; cursor: pointer;
padding: 5px 0px;
} }
.hierarchy-item:hover { .hierarchy-item:hover {

View File

@ -13,8 +13,9 @@ import {
import { import {
getExactComponent getExactComponent
} from "./pagesParsing/searchComponents"; } from "./pagesParsing/searchComponents";
import Checkbox from "../common/Checkbox"; import Checkbox from "../common/Checkbox.svelte";
import Textbox from "../common/Textbox"; import Textbox from "../common/Textbox.svelte";
import Dropdown from "../common/Dropdown.svelte";
export let props; export let props;
export let allComponents; export let allComponents;
@ -28,19 +29,33 @@ let fields = pipe(propsDefinition,[
let component = getExactComponent(allComponents, props._component); let component = getExactComponent(allComponents, props._component);
let setProp = (name) => (ev) =>
props[name] = ev.target.checked !== undefined
? ev.target.checked
: ev.target.value;
</script> </script>
<div class="root"> <div class="root">
<div>{props.name}</div> <div class="title">{component.name}</div>
<div class="component-description">{component.description || ""}</div>
{#each propsDefinition as propDef} {#each propsDefinition as propDef}
<form class="uk-form-horizontal prop-row ">
{#if propDef.type === "bool"} {#if propDef.type === "bool"}
<Checkbox label={propDef.name} /> <Checkbox label={propDef.name}
{:else if true} checked={props[propDef.name]}
<!-- else if content here --> on:change={setProp(propDef.name)} />
{:else if propDef.type === "options"}
<Dropdown label={propDef.name}
selected={props[propDef.name]}
options={propDef.options}
on:change={setProp(propDef.name)}/>
{:else} {:else}
<!-- else content here --> <Textbox label={propDef.name}
bind:text={props[propDef.name]} />
{/if} {/if}
</form>
{/each} {/each}
@ -51,6 +66,19 @@ let component = getExactComponent(allComponents, props._component);
.root { .root {
padding: 10px; padding: 10px;
font-size:10pt;
}
.title {
font: var(--smallheavybodytext);
}
.prop-row {
padding: 7px 3px;
}
.component-description {
font: var(--lightbodytext);
} }
</style> </style>

View File

@ -2,8 +2,18 @@
import ComponentsHierarchy from "./ComponentsHierarchy.svelte"; import ComponentsHierarchy from "./ComponentsHierarchy.svelte";
import PagesList from "./PagesList.svelte" import PagesList from "./PagesList.svelte"
import PropsView from "./PropsView.svelte";
import { store } from "../builderStore"; import { store } from "../builderStore";
import getIcon from "../common/icon"; import getIcon from "../common/icon";
import { isRootComponent } from "./pagesParsing/searchComponents";
import IconButton from "../common/IconButton.svelte";
import Modal from "../common/Modal.svelte";
import NewComponent from "./NewComponent.svelte";
let isCreatingNewComponent = false;
const newComponent = () => {
isCreatingNewComponent = true;
}
</script> </script>
@ -12,19 +22,27 @@ import getIcon from "../common/icon";
<div class="ui-nav"> <div class="ui-nav">
<div class="components-list-container"> <div class="components-list-container">
<h5> <div class="nav-group-header">
{@html getIcon("sidebar","18")} <div>{@html getIcon("sidebar","18")}</div>
<span class="nav-title-inner">COMPONENTS</span> <span>COMPONENTS</span>
</h5> <div>
<ComponentsHierarchy components={$store.allComponents}/> <IconButton icon="plus"
on:click={newComponent} />
</div>
</div>
<div class="nav-items-container">
<ComponentsHierarchy components={$store.allComponents}/>
</div>
</div> </div>
<div class="pages-list-container"> <div class="pages-list-container">
<h5> <div class="nav-group-header">
{@html getIcon("grid","18")} <div>{@html getIcon("grid","18")}</div>
<span class="nav-title-inner">PAGES</span> <span>PAGES</span>
</h5> </div>
<PagesList /> <div class="nav-items-container">
<PagesList />
</div>
</div> </div>
</div> </div>
@ -37,13 +55,24 @@ import getIcon from "../common/icon";
{/if} {/if}
</div> </div>
<div class="properties-pane">
{#if $store.currentFrontEndItem && !isRootComponent($store.currentFrontEndItem)}
<PropsView allComponents={$store.allComponents}
props={$store.currentFrontEndItem.props}/>
{/if}
</div>
</div> </div>
<NewComponent {isCreatingNewComponent}/>
<style> <style>
.root { .root {
display: grid; display: grid;
grid-template-columns: [uiNav] 300px [preview] auto; grid-template-columns: [uiNav] 250px [preview] auto [properties] 250px;
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
@ -66,19 +95,54 @@ import getIcon from "../common/icon";
grid-column-start: middle; grid-column-start: middle;
} }
.properties-pane {
grid-column-start: properties;
background-color: var(--primary10);
height: 100%;
}
.pages-list-container { .pages-list-container {
padding-top: 20px; padding-top: 20px;
} }
.nav-group-header {
h5 {
font-size: 10pt; font-size: 10pt;
padding-left: 10px; padding-left: 10px;
} }
.nav-title-inner { .nav-items-container {
padding-top: 10px;
}
.nav-group-header {
display:grid;
grid-template-columns: [icon] auto [title] 1fr [button] auto;
padding: 10px 2px 0px 7px;
}
.nav-group-header>div:nth-child(1) {
padding:0px 7px 0px 0px;
vertical-align: bottom;
grid-column-start: icon;
margin-right: 5px;
}
.nav-group-header>span:nth-child(2) {
margin-left:5px; margin-left:5px;
vertical-align: bottom; vertical-align: bottom;
grid-column-start: title;
margin-top:auto;
} }
.nav-group-header>div:nth-child(3) {
vertical-align: bottom;
grid-column-start: button;
cursor: pointer;
color: var(--slate);
}
.nav-group-header>div:nth-child(3):hover {
color: var(--primary75);
}
</style> </style>

View File

@ -5,7 +5,8 @@ import {
keys, keys,
uniq, uniq,
some, some,
keyBy filter,
reduce
} from "lodash/fp"; } from "lodash/fp";
import { types } from "./types"; import { types } from "./types";
import { assign } from "lodash"; import { assign } from "lodash";
@ -31,7 +32,8 @@ export const createPropDefinitionForDerived = (allComponents, componentName) =>
keys, keys,
filter(k => !hasDerivedProp(k)), filter(k => !hasDerivedProp(k)),
reduce((obj, k) => { reduce((obj, k) => {
obj[k] = propDef[k] obj[k] = propDef[k];
return obj;
}, {}) }, {})
]) ])
} }

View File

@ -83,17 +83,17 @@ describe("getAncestorProps", () => {
it("should return props of all ancestors and current component, in order", () => { it("should return props of all ancestors and current component, in order", () => {
const components = components(); const allComponents = components();
const result = getAncestorProps( const result = getAncestorProps(
components, allComponents,
"common/PasswordBox" "common/PasswordBox"
); );
expect(result).toEqual([ expect(result).toEqual([
root[0].props, allComponents[0].props,
{_component: "budibase-components/TextBox", ...components[2].props}, {_component: "budibase-components/TextBox", ...allComponents[2].props},
{_component: "common/SmallTextbox", ...components[3].props} {_component: "common/SmallTextbox", ...allComponents[3].props}
]); ]);
}); });

View File

@ -4,8 +4,20 @@
"name": "Textbox", "name": "Textbox",
"description": "A text input, with a label", "description": "A text input, with a label",
"props": { "props": {
"label": "string" "label": "string",
"content": "component"
}, },
"tags": ["textboxt", "input", "text"] "tags": ["textbox", "input", "text"]
} },
"button" : {
"path": "./button",
"name": "Button",
"description": "a button",
"props": {
"contentText": "string",
"contentComponent": "component",
"class": "string"
},
"tags": ["button"]
}
} }

View File

@ -1,32 +1,31 @@
main.svelte-j8mzr7{height:100%;width:100%;font-family:"Lato", Helvetica, Arial, sans-serif} main.svelte-j8mzr7{height:100%;width:100%;font-family:"Lato", Helvetica, Arial, sans-serif}
.root.svelte-1rxbdcd{height:100%}.content.svelte-1rxbdcd{position:fixed;height:100%;background-color:var(--white);margin:0} .root.svelte-e4n7zy{position:fixed;margin:0 auto;text-align:center;top:20%;width:100%}.inner.svelte-e4n7zy{display:inline-block;margin:auto}.logo.svelte-e4n7zy{width:300px;margin-bottom:40px}.root.svelte-e4n7zy .option{width:250px}.app-link.svelte-e4n7zy{margin-top:10px;display:block}
.root.svelte-jymnqv{position:fixed;margin:0 auto;text-align:center;top:20%;width:100%}.inner.svelte-jymnqv{display:inline-block;margin:auto}.logo.svelte-jymnqv{width:300px;margin-bottom:40px}.root.svelte-jymnqv .option{width:250px}.app-link.svelte-jymnqv{margin-top:10px;display:block} .root.svelte-i0dstr{height:100%}.content.svelte-i0dstr{position:fixed;height:100%;background-color:var(--white);margin:0}
.nav.svelte-n1ql72{height:100%;position:fixed;left:0px;background-color:var(--secondary100);color:var(--darkslate)}.nav.svelte-n1ql72>img.svelte-n1ql72{width:100%;margin-bottom:30px;margin-top:5px;margin-left:0px}
.root.svelte-z7gm0t{display:flex;height:100%;position:relative}.hierarchy.svelte-z7gm0t{flex:0 1 auto;background-color:var(--primary10);overflow-y:auto;height:100%}.node-container.svelte-z7gm0t{flex:1 1 auto;display:flex;flex-direction:column}.actions-header.svelte-z7gm0t{flex:0 1 auto}.node-view.svelte-z7gm0t{overflow-y:auto;flex:1 1 auto}.hierarchy-title-row.svelte-z7gm0t{padding:15px 7px;font-size:11pt;display:flex;font-weight:bold}.hierarchy-title.svelte-z7gm0t{flex:auto 1 1}
.root.svelte-1y6dy5x{padding:10px}
h4.svelte-o0id5a{margin-top:20px} h4.svelte-o0id5a{margin-top:20px}
.root.svelte-5zgcq9{display:grid;grid-template-columns:[uiNav] 300px [preview] auto;height:100%;width:100%}.ui-nav.svelte-5zgcq9{grid-column-start:uiNav;background-color:var(--primary10);height:100%}.component-preview.svelte-5zgcq9{display:grid;grid-template-rows:[top] 1fr [middle] auto [bottom] 1fr;grid-template-columns:[left] 1fr [middle] auto [right] 1fr;grid-column-start:preview}.component-container.svelte-5zgcq9{grid-row-start:middle;grid-column-start:middle}.pages-list-container.svelte-5zgcq9{padding-top:20px}h5.svelte-5zgcq9{font-size:10pt;padding-left:10px}.nav-title-inner.svelte-5zgcq9{margin-left:5px;vertical-align:bottom}
.border-normal.svelte-7rfkdx{border-radius:var(--borderradiusall)}.border-left.svelte-7rfkdx{border-radius:var(--borderradius) 0 0 var(--borderradius)}.border-right.svelte-7rfkdx{border-radius:0 var(--borderradius) var(--borderradius) 0}.border-middle.svelte-7rfkdx{border-radius:0}button.svelte-7rfkdx{border-style:solid;padding:7px 15px;cursor:pointer}.primary.svelte-7rfkdx{background-color:var(--primary100);border-color:var(--primary100);color:var(--white)}.primary.svelte-7rfkdx:hover{background-color:var(--primary75);border-color:var(--primary75)}.primary.svelte-7rfkdx:active{background-color:var(--primarydark);border-color:var(--primarydark)}.primary-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--primary100);color:var(--primary100)}.primary-outline.svelte-7rfkdx:hover{background-color:var(--primary10)}.primary-outline.svelte-7rfkdx:pressed{background-color:var(--primary25)}.secondary.svelte-7rfkdx{background-color:var(--secondary100);border-color:var(--secondary100);color:var(--white)}.secondary.svelte-7rfkdx:hover{background-color:var(--secondary75);border-color:var(--secondary75)}.secondary.svelte-7rfkdx:pressed{background-color:var(--secondarydark);border-color:var(--secondarydark)}.secondary-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--secondary100);color:var(--secondary100)}.secondary-outline.svelte-7rfkdx:hover{background-color:var(--secondary10)}.secondary-outline.svelte-7rfkdx:pressed{background-color:var(--secondary25)}.success.svelte-7rfkdx{background-color:var(--success100);border-color:var(--success100);color:var(--white)}.success.svelte-7rfkdx:hover{background-color:var(--success75);border-color:var(--success75)}.success.svelte-7rfkdx:pressed{background-color:var(--successdark);border-color:var(--successdark)}.success-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--success100);color:var(--success100)}.success-outline.svelte-7rfkdx:hover{background-color:var(--success10)}.success-outline.svelte-7rfkdx:pressed{background-color:var(--success25)}.deletion.svelte-7rfkdx{background-color:var(--deletion100);border-color:var(--deletion100);color:var(--white)}.deletion.svelte-7rfkdx:hover{background-color:var(--deletion75);border-color:var(--deletion75)}.deletion.svelte-7rfkdx:pressed{background-color:var(--deletiondark);border-color:var(--deletiondark)}.deletion-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--deletion100);color:var(--deletion100)}.deletion-outline.svelte-7rfkdx:hover{background-color:var(--deletion10)}.deletion-outline.svelte-7rfkdx:pressed{background-color:var(--deletion25)} .border-normal.svelte-7rfkdx{border-radius:var(--borderradiusall)}.border-left.svelte-7rfkdx{border-radius:var(--borderradius) 0 0 var(--borderradius)}.border-right.svelte-7rfkdx{border-radius:0 var(--borderradius) var(--borderradius) 0}.border-middle.svelte-7rfkdx{border-radius:0}button.svelte-7rfkdx{border-style:solid;padding:7px 15px;cursor:pointer}.primary.svelte-7rfkdx{background-color:var(--primary100);border-color:var(--primary100);color:var(--white)}.primary.svelte-7rfkdx:hover{background-color:var(--primary75);border-color:var(--primary75)}.primary.svelte-7rfkdx:active{background-color:var(--primarydark);border-color:var(--primarydark)}.primary-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--primary100);color:var(--primary100)}.primary-outline.svelte-7rfkdx:hover{background-color:var(--primary10)}.primary-outline.svelte-7rfkdx:pressed{background-color:var(--primary25)}.secondary.svelte-7rfkdx{background-color:var(--secondary100);border-color:var(--secondary100);color:var(--white)}.secondary.svelte-7rfkdx:hover{background-color:var(--secondary75);border-color:var(--secondary75)}.secondary.svelte-7rfkdx:pressed{background-color:var(--secondarydark);border-color:var(--secondarydark)}.secondary-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--secondary100);color:var(--secondary100)}.secondary-outline.svelte-7rfkdx:hover{background-color:var(--secondary10)}.secondary-outline.svelte-7rfkdx:pressed{background-color:var(--secondary25)}.success.svelte-7rfkdx{background-color:var(--success100);border-color:var(--success100);color:var(--white)}.success.svelte-7rfkdx:hover{background-color:var(--success75);border-color:var(--success75)}.success.svelte-7rfkdx:pressed{background-color:var(--successdark);border-color:var(--successdark)}.success-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--success100);color:var(--success100)}.success-outline.svelte-7rfkdx:hover{background-color:var(--success10)}.success-outline.svelte-7rfkdx:pressed{background-color:var(--success25)}.deletion.svelte-7rfkdx{background-color:var(--deletion100);border-color:var(--deletion100);color:var(--white)}.deletion.svelte-7rfkdx:hover{background-color:var(--deletion75);border-color:var(--deletion75)}.deletion.svelte-7rfkdx:pressed{background-color:var(--deletiondark);border-color:var(--deletiondark)}.deletion-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--deletion100);color:var(--deletion100)}.deletion-outline.svelte-7rfkdx:hover{background-color:var(--deletion10)}.deletion-outline.svelte-7rfkdx:pressed{background-color:var(--deletion25)}
.root.svelte-1be865r{padding:10px}.edit-button.svelte-1be865r{cursor:pointer;color:var(--white)}tr.svelte-1be865r:hover .edit-button.svelte-1be865r{color:var(--secondary75)} .nav.svelte-lgepe1{height:100%;position:fixed;left:0px;background-color:var(--secondary100);color:var(--darkslate)}.nav.svelte-lgepe1>img.svelte-lgepe1{width:100%;margin-bottom:30px;margin-top:5px;margin-left:0px}
.nav-item.svelte-td9xyr{padding:0px 5px;display:block;padding:10px;color:var(--slate);cursor:pointer}.inner.svelte-td9xyr{padding:0px 20px 10px 0px;display:inline-block;width:100%}.nav-item.svelte-td9xyr:hover{background-color:var(--primary25)}.icon.svelte-td9xyr{font-size:0.9em;display:inline-block;position:relative;top:5px;margin-right:5px;width:100%}.active.svelte-td9xyr>div.svelte-td9xyr{background-color:var(--primary10);color:var(--secondary100)}.active.svelte-td9xyr>div.svelte-td9xyr:hover{background-color:var(--slate);color:var(--secondary100)}.active.svelte-td9xyr{background-color:white} .root.svelte-ui57a{display:flex;height:100%;position:relative}.hierarchy.svelte-ui57a{flex:0 1 auto;background-color:var(--primary10);overflow-y:auto;height:100%}.node-container.svelte-ui57a{flex:1 1 auto;display:flex;flex-direction:column}.actions-header.svelte-ui57a{flex:0 1 auto}.node-view.svelte-ui57a{overflow-y:auto;flex:1 1 auto}.hierarchy-title-row.svelte-ui57a{padding:15px 7px;font-size:11pt;display:flex;font-weight:bold}.hierarchy-title.svelte-ui57a{flex:auto 1 1}
.root.svelte-1rctf7f{display:block;font-size:13pt;width:100%;cursor:pointer}.title.svelte-1rctf7f{font:var(--bodytext);padding-top:10px;padding-right:5px;padding-bottom:10px;color:var(--secondary100)}.title.svelte-1rctf7f:hover{background-color:var(--secondary10)} .root.svelte-zzs4qg{padding:10px}
.root.svelte-gq7l8x{height:100%;padding:15px}.fields-table.svelte-gq7l8x{margin:10px;border-collapse:collapse}.add-field-button.svelte-gq7l8x{margin-left:15px;cursor:pointer}.edit-button.svelte-gq7l8x{cursor:pointer;color:var(--white)}.edit-button.svelte-gq7l8x:hover{color:var(--secondary75)}th.svelte-gq7l8x{text-align:left}td.svelte-gq7l8x{padding:5px 30px 5px 0px;margin:0}thead.svelte-gq7l8x>tr.svelte-gq7l8x{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--secondary75);margin-bottom:20px}tbody.svelte-gq7l8x>tr.svelte-gq7l8x{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--primary10)}tbody.svelte-gq7l8x>tr.svelte-gq7l8x:hover{background-color:var(--primary10)}tbody.svelte-gq7l8x>tr:hover .edit-button.svelte-gq7l8x{color:var(--secondary75)}.index-container.svelte-gq7l8x{border-style:solid;border-width:0 0 1px 0;border-color:var(--secondary25);padding:10px;margin-bottom:5px}.index-label.svelte-gq7l8x{color:var(--slate)}.index-name.svelte-gq7l8x{font-weight:bold;color:var(--primary100)}.index-container.svelte-gq7l8x code.svelte-gq7l8x{margin:0;display:inline;background-color:var(--primary10);color:var(--secondary100);padding:3px}.index-field-row.svelte-gq7l8x{margin-top:7px} .root.svelte-179wat4{display:grid;grid-template-columns:[uiNav] 250px [preview] auto [properties] 250px;height:100%;width:100%}.ui-nav.svelte-179wat4{grid-column-start:uiNav;background-color:var(--primary10);height:100%}.component-preview.svelte-179wat4{display:grid;grid-template-rows:[top] 1fr [middle] auto [bottom] 1fr;grid-template-columns:[left] 1fr [middle] auto [right] 1fr;grid-column-start:preview}.component-container.svelte-179wat4{grid-row-start:middle;grid-column-start:middle}.properties-pane.svelte-179wat4{grid-column-start:properties;background-color:var(--primary10);height:100%}.pages-list-container.svelte-179wat4{padding-top:20px}.nav-group-header.svelte-179wat4{font-size:10pt;padding-left:10px}.nav-items-container.svelte-179wat4{padding-top:10px}.nav-group-header.svelte-179wat4{display:grid;grid-template-columns:[icon] auto [title] 1fr [button] auto;padding:10px 2px 0px 7px}.nav-group-header.svelte-179wat4>div.svelte-179wat4:nth-child(1){padding:0px 7px 0px 0px;vertical-align:bottom;grid-column-start:icon;margin-right:5px}.nav-group-header.svelte-179wat4>span.svelte-179wat4:nth-child(2){margin-left:5px;vertical-align:bottom;grid-column-start:title;margin-top:auto}.nav-group-header.svelte-179wat4>div.svelte-179wat4:nth-child(3){vertical-align:bottom;grid-column-start:button;cursor:pointer;color:var(--slate)}.nav-group-header.svelte-179wat4>div.svelte-179wat4:nth-child(3):hover{color:var(--primary75)}
.root.svelte-1fkfoam{height:100%;padding:15px}.allowed-records.svelte-1fkfoam{margin:20px 0px}.allowed-records.svelte-1fkfoam>span.svelte-1fkfoam{margin-right:30px} .root.svelte-1qmjs65{padding:10px}.edit-button.svelte-1qmjs65{cursor:pointer;color:var(--white)}tr.svelte-1qmjs65:hover .edit-button.svelte-1qmjs65{color:var(--secondary75)}
.root.svelte-d6wwkb{display:flex}.root.svelte-d6wwkb:last-child{border-radius:0 var(--borderradius) var(--borderradius) 0}.root.svelte-d6wwkb:first-child{border-radius:var(--borderradius) 0 0 var(--borderradius)}.root.svelte-d6wwkb:not(:first-child):not(:last-child){border-radius:0} .root.svelte-1q40nqm{display:block;font-size:13pt;width:100%;cursor:pointer}.title.svelte-1q40nqm{font:var(--bodytext);padding-top:10px;padding-right:5px;padding-bottom:10px;color:var(--secondary100)}.title.svelte-1q40nqm:hover{background-color:var(--secondary10)}
.root.svelte-160njkp{padding:5px;top:0;width:100%} .root.svelte-kswv5p{height:100%;padding:15px}.fields-table.svelte-kswv5p{margin:10px;border-collapse:collapse}.add-field-button.svelte-kswv5p{margin-left:15px;cursor:pointer}.edit-button.svelte-kswv5p{cursor:pointer;color:var(--white)}.edit-button.svelte-kswv5p:hover{color:var(--secondary75)}th.svelte-kswv5p{text-align:left}td.svelte-kswv5p{padding:5px 30px 5px 0px;margin:0}thead.svelte-kswv5p>tr.svelte-kswv5p{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--secondary75);margin-bottom:20px}tbody.svelte-kswv5p>tr.svelte-kswv5p{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--primary10)}tbody.svelte-kswv5p>tr.svelte-kswv5p:hover{background-color:var(--primary10)}tbody.svelte-kswv5p>tr:hover .edit-button.svelte-kswv5p{color:var(--secondary75)}.index-container.svelte-kswv5p{border-style:solid;border-width:0 0 1px 0;border-color:var(--secondary25);padding:10px;margin-bottom:5px}.index-label.svelte-kswv5p{color:var(--slate)}.index-name.svelte-kswv5p{font-weight:bold;color:var(--primary100)}.index-container.svelte-kswv5p code.svelte-kswv5p{margin:0;display:inline;background-color:var(--primary10);color:var(--secondary100);padding:3px}.index-field-row.svelte-kswv5p{margin-top:7px}
.edit-button.svelte-1le5bpl{cursor:pointer;color:var(--white)}tr.svelte-1le5bpl:hover .edit-button.svelte-1le5bpl{color:var(--secondary75)} .nav-item.svelte-5cf6ht{padding:0px 5px;display:block;padding:10px;color:var(--slate);cursor:pointer}.inner.svelte-5cf6ht{padding:0px 20px 10px 0px;display:inline-block;width:100%}.nav-item.svelte-5cf6ht:hover{background-color:var(--primary25)}.icon.svelte-5cf6ht{font-size:0.9em;display:inline-block;position:relative;top:5px;margin-right:5px;width:100%}.active.svelte-5cf6ht>div.svelte-5cf6ht{background-color:var(--primary10);color:var(--secondary100)}.active.svelte-5cf6ht>div.svelte-5cf6ht:hover{background-color:var(--slate);color:var(--secondary100)}.active.svelte-5cf6ht{background-color:white}
.root.svelte-1tilbnf{padding:5px;top:0;width:100%}
.dropdown-background.svelte-179p8ge{position:fixed;top:0;left:0;width:100vw;height:100vh}.root.svelte-179p8ge{cursor:pointer;z-index:1}.dropdown-content.svelte-179p8ge{position:absolute;background-color:var(--white);min-width:160px;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);z-index:1;font-weight:normal;border-style:solid;border-width:1px;border-color:var(--secondary10)}.dropdown-content.svelte-179p8ge:not(:focus){display:none}.action-row.svelte-179p8ge{padding:7px 10px;cursor:pointer}.action-row.svelte-179p8ge:hover{background-color:var(--primary100);color:var(--white)} .dropdown-background.svelte-179p8ge{position:fixed;top:0;left:0;width:100vw;height:100vh}.root.svelte-179p8ge{cursor:pointer;z-index:1}.dropdown-content.svelte-179p8ge{position:absolute;background-color:var(--white);min-width:160px;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);z-index:1;font-weight:normal;border-style:solid;border-width:1px;border-color:var(--secondary10)}.dropdown-content.svelte-179p8ge:not(:focus){display:none}.action-row.svelte-179p8ge{padding:7px 10px;cursor:pointer}.action-row.svelte-179p8ge:hover{background-color:var(--primary100);color:var(--white)}
.root.svelte-1ba51k0{color:var(--secondary50)}.hierarchy-item.svelte-1ba51k0{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-1ba51k0:hover{color:var(--secondary75)}.component.svelte-1ba51k0{margin-left:5px}.currentfolder.svelte-1ba51k0{color:var(--secondary100)}.selected.svelte-1ba51k0{color:var(--primary100)}.title.svelte-1ba51k0{margin-left:10px} .root.svelte-d6wwkb{display:flex}.root.svelte-d6wwkb:last-child{border-radius:0 var(--borderradius) var(--borderradius) 0}.root.svelte-d6wwkb:first-child{border-radius:var(--borderradius) 0 0 var(--borderradius)}.root.svelte-d6wwkb:not(:first-child):not(:last-child){border-radius:0}
.edit-button.svelte-12jzg4k{cursor:pointer;color:var(--white)}tr.svelte-12jzg4k:hover .edit-button.svelte-12jzg4k{color:var(--secondary75)} .root.svelte-pq2tmv{height:100%;padding:15px}.allowed-records.svelte-pq2tmv{margin:20px 0px}.allowed-records.svelte-pq2tmv>span.svelte-pq2tmv{margin-right:30px}
.root.svelte-6ej2ac{padding-left:20px;padding-bottom:20px;color:var(--secondary50)}.hierarchy-item.svelte-6ej2ac{cursor:pointer}.hierarchy-item.svelte-6ej2ac:hover{color:var(--secondary75)}.component.svelte-6ej2ac{margin-left:5px}.selected.svelte-6ej2ac{color:var(--primary100)}.title.svelte-6ej2ac{margin-left:10px} .edit-button.svelte-neetem{cursor:pointer;color:var(--white)}tr.svelte-neetem:hover .edit-button.svelte-neetem{color:var(--secondary75)}
textarea.svelte-1ooq0hh{padding:3px;background:var(--darkslate);color:var(--white);font-family:'Courier New', Courier, monospace;width:95%;height:100px} .edit-button.svelte-9z4fqi{cursor:pointer;color:var(--white)}tr.svelte-9z4fqi:hover .edit-button.svelte-9z4fqi{color:var(--secondary75)}
.container.svelte-umifqh{display:grid;grid-template-columns:[label] 100px [control] auto;margin:20px 0px}.label.svelte-umifqh{grid-column-start:label;align-self:center}.control.svelte-umifqh{grid-column-start:control;align-self:center;margin:0}input.svelte-umifqh{width:300px} button.svelte-6dbfug{border-style:none;background-color:rgba(0,0,0,0);cursor:pointer}
.root.svelte-1hxxti1{padding:10px;font-size:10pt}.title.svelte-1hxxti1{font:var(--smallheavybodytext)}.prop-row.svelte-1hxxti1{padding:7px 3px}.component-description.svelte-1hxxti1{font:var(--lightbodytext)}
.root.svelte-ffb307{padding-bottom:10px;padding-left:10px;font-size:16px;color:var(--secondary50)}.hierarchy-item.svelte-ffb307{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-ffb307:hover{color:var(--secondary75)}.component.svelte-ffb307{margin-left:5px}.selected.svelte-ffb307{color:var(--primary100)}.title.svelte-ffb307{margin-left:10px}
.root.svelte-1cnqtw{color:var(--secondary50)}.hierarchy-item.svelte-1cnqtw{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-1cnqtw:hover{color:var(--secondary75)}.component.svelte-1cnqtw{margin-left:5px}.currentfolder.svelte-1cnqtw{color:var(--secondary100)}.selected.svelte-1cnqtw{color:var(--primary100)}.title.svelte-1cnqtw{margin-left:10px}
.error-container.svelte-jwy920{padding:10px;border-style:solid;border-color:var(--deletion100);border-radius:var(--borderradiusall);background:var(--deletion75)}.error-row.svelte-jwy920{padding:5px 0px} .error-container.svelte-jwy920{padding:10px;border-style:solid;border-color:var(--deletion100);border-radius:var(--borderradiusall);background:var(--deletion75)}.error-row.svelte-jwy920{padding:5px 0px}
.container.svelte-bm0783{display:grid;grid-template-columns:[label] 100px [control] auto;margin:20px 0px}.label.svelte-bm0783{grid-column-start:label;align-self:center}.control.svelte-bm0783{grid-column-start:control;align-self:center;margin:0}select.svelte-bm0783{width:300px} textarea.svelte-1ooq0hh{padding:3px;background:var(--darkslate);color:var(--white);font-family:'Courier New', Courier, monospace;width:95%;height:100px}
.root.svelte-bv289q{padding:10px}.option-container.svelte-bv289q{border-style:dotted;border-width:1px;border-color:var(--primary75);padding:3px;margin-right:5px}
input.svelte-66516k{margin-right:7px} input.svelte-66516k{margin-right:7px}
.root.svelte-emcy8y{padding:10px}.option-container.svelte-emcy8y{border-style:dotted;border-width:1px;border-color:var(--primary75);padding:3px;margin-right:5px} .component.svelte-13tuzj8{padding:5px;border-style:solid;border-width:0 0 1px 0;border-color:var(--lightslate);cursor:pointer}.component.svelte-13tuzj8:hover{background-color:var(--primary10)}.component.svelte-13tuzj8>.title.svelte-13tuzj8{font-size:13pt;color:var(--secondary100)}.component.svelte-13tuzj8>.description.svelte-13tuzj8{font-size:10pt;color:var(--primary75);font-style:italic}
.container.svelte-1pf9x5k{display:grid;grid-template-columns:[label] 100px [control] auto;margin:20px 0px}.label.svelte-1pf9x5k{grid-column-start:label;align-self:center}.control.svelte-1pf9x5k{grid-column-start:control;align-self:center;margin:0}input.svelte-1pf9x5k{width:300px} textarea.svelte-1wfv4cc{width:300px;height:200px}
.container.svelte-umifqh{display:grid;grid-template-columns:[label] 100px [control] auto;margin:20px 0px}.label.svelte-umifqh{grid-column-start:label;align-self:center}.control.svelte-umifqh{grid-column-start:control;align-self:center;margin:0}input.svelte-umifqh{width:300px}
.container.svelte-85b8gk{display:grid;grid-template-columns:[label] 100px [control] auto;margin:20px 0px}.label.svelte-85b8gk{grid-column-start:label;align-self:center}.control.svelte-85b8gk{grid-column-start:control;align-self:center;margin:0}textarea.svelte-85b8gk{width:300px;height:200px}
/*# sourceMappingURL=bundle.css.map */ /*# sourceMappingURL=bundle.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -32,6 +32,7 @@
--white: #FFFFFF; --white: #FFFFFF;
--darkslate: #5C6B82; --darkslate: #5C6B82;
--slate: #8B95A6; --slate: #8B95A6;
--lightslate: rgb(203, 212, 228);
--borderradius: 2px; --borderradius: 2px;
--borderradiusall: 2px 2px 2px 2px; --borderradiusall: 2px 2px 2px 2px;
@ -44,11 +45,10 @@
--bodytext: var(--fontnormal) "regular" var(--secondary100) 16pt; --bodytext: var(--fontnormal) "regular" var(--secondary100) 16pt;
--bigbodytext: var(--fontnormal) "regular" var(--secondary100) 20pt; --bigbodytext: var(--fontnormal) "regular" var(--secondary100) 20pt;
--smallbodytext: var(--fontnormal) "regular" var(--secondary100) 12pt; --smallbodytext: var(--fontnormal) "regular" var(--secondary100) 12pt;
--lightbodytext: var(--fontnormal) "regular" var(--darkslate) 16pt; --lightbodytext: "regular" "normal" 16pt var(--fontnormal);
--heavybodytext: var(--fontbold) "regular" var(--secondary100) 16pt; --heavybodytext: var(--fontbold) "regular" var(--secondary100) 16pt;
--quotation: var(--fontnormal) "italics" var(--darkslate) 16pt; --quotation: var(--fontnormal) "italics" var(--darkslate) 16pt;
--smallheavybodytext: var(--fontbold) "regular" var(--secondary100) 14pt; --smallheavybodytext: var(--fontbold) "regular" var(--secondary100) 14pt;
} }
html, body { html, body {

File diff suppressed because one or more lines are too long

View File

@ -183,6 +183,9 @@ const fetchDerivedComponents = async (appPath, relativePath = "") => {
.substring(0, itemRelativePath.length - 5) .substring(0, itemRelativePath.length - 5)
.replace(/\\/g, "/"); .replace(/\\/g, "/");
component.props = component.props || {};
component.props._component = component.name;
components.push(component); components.push(component);
} else { } else {
const childComponents = await fetchDerivedComponents( const childComponents = await fetchDerivedComponents(