48 builder frontend 2 (#70)
* Implement collapsing component hierarchy. * Save screen when adding new components. * Allow creation of nested child components. * Fix level-based indentation of hierarchy. * Rename updateComponentProps to setComponentProps * Save layout information to the disk. * Cleanup: switch to autosubscriptions to prevent memory leaks, remove unused imports. * Remove unused css. * Fix incorrect subscription.
This commit is contained in:
parent
6cb523478d
commit
6aa6c4d433
|
@ -4,7 +4,7 @@ import {
|
||||||
import {
|
import {
|
||||||
filter, cloneDeep, sortBy,
|
filter, cloneDeep, sortBy,
|
||||||
map, last, keys, concat, keyBy,
|
map, last, keys, concat, keyBy,
|
||||||
find, isEmpty, reduce, values
|
find, isEmpty, reduce, values, isEqual
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import {
|
import {
|
||||||
pipe, getNode, validate,
|
pipe, getNode, validate,
|
||||||
|
@ -93,8 +93,8 @@ export const getStore = () => {
|
||||||
store.createGeneratedComponents = createGeneratedComponents(store);
|
store.createGeneratedComponents = createGeneratedComponents(store);
|
||||||
store.addChildComponent = addChildComponent(store);
|
store.addChildComponent = addChildComponent(store);
|
||||||
store.selectComponent = selectComponent(store);
|
store.selectComponent = selectComponent(store);
|
||||||
store.updateComponentProp = updateComponentProp(store);
|
store.setComponentProp = setComponentProp(store);
|
||||||
|
store.setComponentStyle = setComponentStyle(store);
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,6 +456,10 @@ const _saveScreen = (store, s, screen) => {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _save = (appname, screen, store, s) =>
|
||||||
|
api.post(`/_builder/api/${appname}/screen`, screen)
|
||||||
|
.then(() => savePackage(store, s));
|
||||||
|
|
||||||
const createScreen = store => (screenName, layoutComponentName) => {
|
const createScreen = store => (screenName, layoutComponentName) => {
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
const newComponentInfo = getNewComponentInfo(
|
const newComponentInfo = getNewComponentInfo(
|
||||||
|
@ -597,8 +601,6 @@ const addComponentLibrary = store => async lib => {
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeComponentLibrary = store => lib => {
|
const removeComponentLibrary = store => lib => {
|
||||||
|
@ -701,17 +703,31 @@ const addChildComponent = store => component => {
|
||||||
const newComponent = getNewComponentInfo(
|
const newComponent = getNewComponentInfo(
|
||||||
s.components, component);
|
s.components, component);
|
||||||
|
|
||||||
const children = s.currentFrontEndItem.props._children;
|
let children = s.currentComponentInfo.component ?
|
||||||
|
s.currentComponentInfo.component.props._children :
|
||||||
|
s.currentComponentInfo._children;
|
||||||
|
|
||||||
const component_definition = Object.assign(
|
const component_definition = Object.assign(
|
||||||
cloneDeep(newComponent.fullProps), {
|
cloneDeep(newComponent.fullProps), {
|
||||||
_component: component,
|
_component: component,
|
||||||
|
_layout: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
s.currentFrontEndItem.props._children =
|
if (children) {
|
||||||
children ?
|
if (s.currentComponentInfo.component) {
|
||||||
children.concat(component_definition) :
|
s.currentComponentInfo.component.props._children = children.concat(component_definition);
|
||||||
[component_definition];
|
} else {
|
||||||
|
s.currentComponentInfo._children = children.concat(component_definition)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (s.currentComponentInfo.component) {
|
||||||
|
s.currentComponentInfo.component.props._children = [component_definition];
|
||||||
|
} else {
|
||||||
|
s.currentComponentInfo._children = [component_definition]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_saveScreen(store, s, s.currentFrontEndItem);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
})
|
})
|
||||||
|
@ -725,7 +741,7 @@ const selectComponent = store => component => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateComponentProp = store => (name, value) => {
|
const setComponentProp = store => (name, value) => {
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
const current_component = s.currentComponentInfo;
|
const current_component = s.currentComponentInfo;
|
||||||
s.currentComponentInfo[name] = value;
|
s.currentComponentInfo[name] = value;
|
||||||
|
@ -733,5 +749,18 @@ const updateComponentProp = store => (name, value) => {
|
||||||
s.currentComponentInfo = current_component;
|
s.currentComponentInfo = current_component;
|
||||||
return s;
|
return s;
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const setComponentStyle = store => (name, value) => {
|
||||||
|
store.update(s => {
|
||||||
|
if (!s.currentComponentInfo._layout) {
|
||||||
|
s.currentComponentInfo._layout = {};
|
||||||
|
}
|
||||||
|
s.currentComponentInfo._layout[name] = value;
|
||||||
|
|
||||||
|
// save without messing with the store
|
||||||
|
_save(s.appname, s.currentFrontEndItem, store, s)
|
||||||
|
|
||||||
|
return s;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<path fill="none" d="M0 0h24v24H0z"/>
|
||||||
|
<path fill="currentColor" d="M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 228 B |
|
@ -3,3 +3,4 @@ export { default as PaintIcon } from './Paint.svelte';
|
||||||
export { default as TerminalIcon } from './Terminal.svelte';
|
export { default as TerminalIcon } from './Terminal.svelte';
|
||||||
export { default as InputIcon } from './Input.svelte';
|
export { default as InputIcon } from './Input.svelte';
|
||||||
export { default as ImageIcon } from './Image.svelte';
|
export { default as ImageIcon } from './Image.svelte';
|
||||||
|
export { default as ArrowDownIcon } from './ArrowDown.svelte';
|
||||||
|
|
|
@ -2,11 +2,19 @@
|
||||||
export let meta = [];
|
export let meta = [];
|
||||||
export let size = '';
|
export let size = '';
|
||||||
export let values = [];
|
export let values = [];
|
||||||
|
export let onStyleChanged = () => {};
|
||||||
|
|
||||||
|
let _values = values.map(v => v);
|
||||||
|
|
||||||
|
$: onStyleChanged(_values);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="inputs {size}">
|
<div class="inputs {size}">
|
||||||
{#each meta as { placeholder }, i}
|
{#each meta as { placeholder }, i}
|
||||||
<input type="number" placeholder="{placeholder}" bind:value={values[i]}/>
|
<input type="number"
|
||||||
|
placeholder="{placeholder}"
|
||||||
|
value={values[i]}
|
||||||
|
on:input={(e) => _values[i] = e.target.value} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,58 +1,22 @@
|
||||||
<script>
|
<script>
|
||||||
|
import PropsView from "./PropsView.svelte";
|
||||||
|
import { store } from "../builderStore";
|
||||||
|
import IconButton from "../common/IconButton.svelte";
|
||||||
|
import { LayoutIcon, PaintIcon, TerminalIcon } from '../common/Icons/';
|
||||||
|
import CodeEditor from './CodeEditor.svelte';
|
||||||
|
import LayoutEditor from './LayoutEditor.svelte';
|
||||||
|
|
||||||
import PropsView from "./PropsView.svelte";
|
let current_view = 'props';
|
||||||
import { store } from "../builderStore";
|
|
||||||
import { isRootComponent } from "./pagesParsing/searchComponents";
|
|
||||||
import IconButton from "../common/IconButton.svelte";
|
|
||||||
import Textbox from "../common/Textbox.svelte";
|
|
||||||
import { pipe } from "../common/core";
|
|
||||||
import {
|
|
||||||
getScreenInfo
|
|
||||||
} from "./pagesParsing/createProps";
|
|
||||||
import { LayoutIcon, PaintIcon, TerminalIcon } from '../common/Icons/';
|
|
||||||
import CodeEditor from './CodeEditor.svelte';
|
|
||||||
import LayoutEditor from './LayoutEditor.svelte';
|
|
||||||
|
|
||||||
import {
|
$: component = $store.currentComponentInfo;
|
||||||
cloneDeep,
|
$: originalName = component.name;
|
||||||
join,
|
$: name = component.name;
|
||||||
split,
|
$: description = component.description;
|
||||||
map,
|
$: componentInfo = $store.currentComponentInfo;
|
||||||
keys,
|
$: components = $store.components;
|
||||||
isUndefined,
|
|
||||||
last
|
|
||||||
} from "lodash/fp";
|
|
||||||
import { assign } from "lodash";
|
|
||||||
|
|
||||||
let component;
|
const onPropChanged = store.setComponentProp;
|
||||||
let name = "";
|
const onStyleChanged = store.setComponentStyle;
|
||||||
let description = "";
|
|
||||||
let tagsString = "";
|
|
||||||
let nameInvalid = "";
|
|
||||||
let componentInfo = {};
|
|
||||||
let modalElement
|
|
||||||
let propsValidationErrors = [];
|
|
||||||
let originalName="";
|
|
||||||
let components;
|
|
||||||
let ignoreStore = false;
|
|
||||||
|
|
||||||
// $: shortName = last(name.split("/"));
|
|
||||||
|
|
||||||
store.subscribe(s => {
|
|
||||||
if(ignoreStore) return;
|
|
||||||
component = s.currentComponentInfo;
|
|
||||||
if(!component) return;
|
|
||||||
originalName = component.name;
|
|
||||||
name = component.name;
|
|
||||||
description = component.description;
|
|
||||||
tagsString = join(", ")(component.tags);
|
|
||||||
componentInfo = s.currentComponentInfo;
|
|
||||||
components = s.components;
|
|
||||||
});
|
|
||||||
|
|
||||||
const onPropsChanged = store.updateComponentProp;
|
|
||||||
|
|
||||||
let current_view = 'props';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -78,9 +42,9 @@ let current_view = 'props';
|
||||||
<div class="component-props-container">
|
<div class="component-props-container">
|
||||||
|
|
||||||
{#if current_view === 'props'}
|
{#if current_view === 'props'}
|
||||||
<PropsView {componentInfo} {components} {onPropsChanged} />
|
<PropsView {componentInfo} {components} {onPropChanged} />
|
||||||
{:else if current_view === 'layout'}
|
{:else if current_view === 'layout'}
|
||||||
<LayoutEditor />
|
<LayoutEditor {onStyleChanged} {componentInfo}/>
|
||||||
{:else}
|
{:else}
|
||||||
<CodeEditor />
|
<CodeEditor />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,22 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { searchAllComponents } from "./pagesParsing/searchComponents";
|
import { searchAllComponents } from "./pagesParsing/searchComponents";
|
||||||
import { store } from "../builderStore";
|
import { store } from "../builderStore";
|
||||||
|
|
||||||
export let onComponentChosen = () => {};
|
export let onComponentChosen = () => {};
|
||||||
|
|
||||||
let components = [];
|
let phrase = "";
|
||||||
let phrase = "";
|
|
||||||
|
|
||||||
store.subscribe(s => {
|
components = $store.components;
|
||||||
components = s.components;
|
|
||||||
});
|
|
||||||
|
|
||||||
$: filteredComponents =
|
|
||||||
!phrase
|
|
||||||
? []
|
|
||||||
: searchAllComponents(components, phrase);
|
|
||||||
|
|
||||||
|
$: filteredComponents =
|
||||||
|
!phrase
|
||||||
|
? []
|
||||||
|
: searchAllComponents(components, phrase);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
|
|
@ -1,74 +1,66 @@
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
isRootComponent
|
isRootComponent
|
||||||
} from "./pagesParsing/searchComponents"
|
} from "./pagesParsing/searchComponents"
|
||||||
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
||||||
import { store } from "../builderStore";
|
import { store } from "../builderStore";
|
||||||
import {
|
import { find, sortBy } from "lodash/fp";
|
||||||
groupBy, keys, find, sortBy
|
|
||||||
} from "lodash/fp";
|
|
||||||
import { pipe } from "../common/core";
|
|
||||||
|
|
||||||
export let onComponentChosen;
|
export let onComponentChosen;
|
||||||
export let onGeneratorChosen;
|
export let onGeneratorChosen;
|
||||||
export let allowGenerators;
|
export let allowGenerators;
|
||||||
|
|
||||||
let screens=[];
|
let screens = [];
|
||||||
let componentLibraries=[];
|
let componentLibraries=[];
|
||||||
|
|
||||||
const addRootComponent = (c, all, isGenerator) => {
|
const addRootComponent = (c, all, isGenerator) => {
|
||||||
const { libName } = splitName(c.name);
|
const { libName } = splitName(c.name);
|
||||||
let group = find(r => r.libName === libName)(all);
|
let group = find(r => r.libName === libName)(all);
|
||||||
|
|
||||||
if(!group) {
|
if(!group) {
|
||||||
group = {
|
group = {
|
||||||
libName,
|
libName,
|
||||||
components: [],
|
components: [],
|
||||||
generators: []
|
generators: []
|
||||||
};
|
};
|
||||||
|
|
||||||
all.push(group);
|
all.push(group);
|
||||||
}
|
|
||||||
|
|
||||||
if(isGenerator) {
|
|
||||||
group.generators.push(c)
|
|
||||||
} else {
|
|
||||||
group.components.push(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
store.subscribe(s => {
|
|
||||||
|
|
||||||
const newComponentLibraries = [];
|
|
||||||
const newscreens = [];
|
|
||||||
|
|
||||||
for(let comp of sortBy(["name"])(s.components)) {
|
|
||||||
if(isRootComponent(comp)) {
|
|
||||||
addRootComponent(
|
|
||||||
comp,
|
|
||||||
newComponentLibraries,
|
|
||||||
false);
|
|
||||||
} else {
|
|
||||||
newscreens.push(comp);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for(let generator of s.generators) {
|
if(isGenerator) {
|
||||||
addRootComponent(
|
group.generators.push(c)
|
||||||
generator,
|
} else {
|
||||||
newComponentLibraries,
|
group.components.push(c)
|
||||||
true);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
screens = sortBy(["name"])(newscreens);
|
};
|
||||||
componentLibraries = newComponentLibraries;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
$: {
|
||||||
|
|
||||||
|
const newComponentLibraries = [];
|
||||||
|
const newscreens = [];
|
||||||
|
|
||||||
|
for(let comp of sortBy(["name"])($store.components)) {
|
||||||
|
if(isRootComponent(comp)) {
|
||||||
|
addRootComponent(
|
||||||
|
comp,
|
||||||
|
newComponentLibraries,
|
||||||
|
false);
|
||||||
|
} else {
|
||||||
|
newscreens.push(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let generator of $store.generators) {
|
||||||
|
addRootComponent(
|
||||||
|
generator,
|
||||||
|
newComponentLibraries,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
screens = sortBy(["name"])(newscreens);
|
||||||
|
componentLibraries = newComponentLibraries;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each componentLibraries as lib}
|
{#each componentLibraries as lib}
|
||||||
|
|
|
@ -1,90 +1,79 @@
|
||||||
<script>
|
<script>
|
||||||
import ComponentsHierarchyChildren from './ComponentsHierarchyChildren.svelte';
|
import ComponentsHierarchyChildren from './ComponentsHierarchyChildren.svelte';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
last,
|
last,
|
||||||
sortBy,
|
sortBy,
|
||||||
filter,
|
map,
|
||||||
map,
|
trimCharsStart,
|
||||||
uniqWith,
|
trimChars,
|
||||||
isEqual,
|
join,
|
||||||
trimCharsStart,
|
} from "lodash/fp";
|
||||||
trimChars,
|
|
||||||
join,
|
|
||||||
includes
|
|
||||||
} from "lodash/fp";
|
|
||||||
|
|
||||||
import { pipe } from "../common/core";
|
import { pipe } from "../common/core";
|
||||||
import getIcon from "../common/icon";
|
import { store } from "../builderStore";
|
||||||
import { store } from "../builderStore";
|
import { ArrowDownIcon } from '../common/Icons/'
|
||||||
|
|
||||||
export let components = []
|
export let components = []
|
||||||
|
|
||||||
const joinPath = join("/");
|
const joinPath = join("/");
|
||||||
|
|
||||||
const normalizedName = name => pipe(name, [
|
const normalizedName = name => pipe(name, [
|
||||||
trimCharsStart("./"),
|
trimCharsStart("./"),
|
||||||
trimCharsStart("~/"),
|
trimCharsStart("~/"),
|
||||||
trimCharsStart("../"),
|
trimCharsStart("../"),
|
||||||
trimChars(" ")
|
trimChars(" ")
|
||||||
]);
|
|
||||||
|
|
||||||
const lastPartOfName = (c) =>
|
|
||||||
last(c.name ? c.name.split("/") : c._component.split("/"))
|
|
||||||
|
|
||||||
const expandFolder = folder => {
|
|
||||||
const expandedFolder = {...folder};
|
|
||||||
if(expandedFolder.isExpanded) {
|
|
||||||
expandedFolder.isExpanded = false;
|
|
||||||
expandedFolders = filter(f => f.name !== folder.name)(expandedFolders);
|
|
||||||
} else {
|
|
||||||
expandedFolder.isExpanded = true;
|
|
||||||
expandedFolders.push(folder.name);
|
|
||||||
}
|
|
||||||
const newFolders = [...subfolders];
|
|
||||||
newFolders.splice(
|
|
||||||
newFolders.indexOf(folder),
|
|
||||||
1,
|
|
||||||
expandedFolder);
|
|
||||||
subfolders = newFolders;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const isComponentSelected = (type, current,c) =>
|
|
||||||
type==="screen"
|
|
||||||
&& current
|
|
||||||
&& current.name === c.name
|
|
||||||
|
|
||||||
const isFolderSelected = (current, folder) =>
|
|
||||||
isInSubfolder(current, folder)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$: _components =
|
|
||||||
pipe(components, [
|
|
||||||
map(c => ({component: c, title:lastPartOfName(c)})),
|
|
||||||
sortBy("title")
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function select_component(screen, component) {
|
const lastPartOfName = (c) =>
|
||||||
store.setCurrentScreen(screen);
|
last(c.name ? c.name.split("/") : c._component.split("/"))
|
||||||
store.selectComponent(component);
|
|
||||||
}
|
const isComponentSelected = (current, comp) =>
|
||||||
|
current &&
|
||||||
|
current.component &&
|
||||||
|
comp.component &&
|
||||||
|
current.component.name === comp.component.name
|
||||||
|
|
||||||
|
const isFolderSelected = (current, folder) =>
|
||||||
|
isInSubfolder(current, folder)
|
||||||
|
|
||||||
|
$: _components =
|
||||||
|
pipe(components, [
|
||||||
|
map(c => ({component: c, title:lastPartOfName(c)})),
|
||||||
|
sortBy("title")
|
||||||
|
]);
|
||||||
|
|
||||||
|
function select_component(screen, component) {
|
||||||
|
store.setCurrentScreen(screen);
|
||||||
|
store.selectComponent(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isScreenSelected = component =>
|
||||||
|
component.component &&
|
||||||
|
$store.currentFrontEndItem &&
|
||||||
|
component.component.name === $store.currentFrontEndItem.name;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
|
||||||
|
|
||||||
{#each _components as component}
|
{#each _components as component}
|
||||||
<div class="hierarchy-item component"
|
<div class="hierarchy-item component"
|
||||||
class:selected={isComponentSelected($store.currentFrontEndType, $store.currentFrontEndItem, component.component)}
|
class:selected={isComponentSelected($store.currentComponentInfo, component)}
|
||||||
on:click|stopPropagation={() => store.setCurrentScreen(component.component.name)}>
|
on:click|stopPropagation={() => store.setCurrentScreen(component.component.name)}>
|
||||||
|
|
||||||
<span class="title">{component.title}</span>
|
<span class="icon" style="transform: rotate({isScreenSelected(component) ? 0 : -90}deg);">
|
||||||
</div>
|
{#if component.component.props && component.component.props._children}
|
||||||
{#if component.component.props && component.component.props._children}
|
<ArrowDownIcon />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="title">{component.title}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if isScreenSelected(component) && component.component.props && component.component.props._children}
|
||||||
<ComponentsHierarchyChildren components={component.component.props._children}
|
<ComponentsHierarchyChildren components={component.component.props._children}
|
||||||
|
currentComponent={$store.currentComponentInfo}
|
||||||
onSelect={child => select_component(component.component.name, child)} />
|
onSelect={child => select_component(component.component.name, child)} />
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -102,9 +91,10 @@ function select_component(screen, component) {
|
||||||
.hierarchy-item {
|
.hierarchy-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 11px 7px;
|
padding: 11px 7px;
|
||||||
|
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hierarchy-item:hover {
|
.hierarchy-item:hover {
|
||||||
|
@ -112,12 +102,6 @@ function select_component(screen, component) {
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.currentfolder {
|
|
||||||
color: var(--secondary100);
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
color: var(--button-text);
|
color: var(--button-text);
|
||||||
background: var(--background-button)!important;
|
background: var(--background-button)!important;
|
||||||
|
@ -127,5 +111,10 @@ function select_component(screen, component) {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
transition: 0.2s;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,22 +3,55 @@
|
||||||
import { pipe } from "../common/core";
|
import { pipe } from "../common/core";
|
||||||
|
|
||||||
export let components = [];
|
export let components = [];
|
||||||
|
export let currentComponent;
|
||||||
export let onSelect = () => {};
|
export let onSelect = () => {};
|
||||||
|
export let level = 0;
|
||||||
|
|
||||||
|
|
||||||
const capitalise = s => s.substring(0,1).toUpperCase() + s.substring(1);
|
const capitalise = s => s.substring(0,1).toUpperCase() + s.substring(1);
|
||||||
const get_name = s => last(s.split('/'));
|
const get_name = s => last(s.split('/'));
|
||||||
const get_capitalised_name = name => pipe(name, [get_name,capitalise]);
|
const get_capitalised_name = name => pipe(name, [get_name,capitalise]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each components as component}
|
<ul>
|
||||||
<ul>
|
{#each components as component}
|
||||||
<li on:click|stopPropagation={() => onSelect(component)}>
|
<li on:click|stopPropagation={() => onSelect(component)}>
|
||||||
{get_capitalised_name(component._component)}
|
<span class="item"
|
||||||
|
class:selected={currentComponent === component}
|
||||||
|
style="padding-left: {level * 20 + 67}px">
|
||||||
|
{get_capitalised_name(component._component)}
|
||||||
|
</span>
|
||||||
|
|
||||||
{#if component._children}
|
{#if component._children}
|
||||||
<svelte:self components={component._children}/>
|
<svelte:self components={component._children}
|
||||||
|
{currentComponent}
|
||||||
|
{onSelect}
|
||||||
|
level={level + 1}/>
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
|
||||||
</ul>
|
<style>
|
||||||
{/each}
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: block;
|
||||||
|
padding: 11px 67px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:hover {
|
||||||
|
background: #fafafa;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
color: var(--button-text);
|
||||||
|
background: var(--background-button)!important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,52 +1,43 @@
|
||||||
<script>
|
<script>
|
||||||
import {
|
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
||||||
isRootComponent
|
import { store } from "../builderStore";
|
||||||
} from "./pagesParsing/searchComponents"
|
import { find, sortBy } from "lodash/fp";
|
||||||
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
import { ImageIcon, InputIcon, LayoutIcon } from '../common/Icons/';
|
||||||
import { store } from "../builderStore";
|
|
||||||
import {
|
|
||||||
groupBy, keys, find, sortBy
|
|
||||||
} from "lodash/fp";
|
|
||||||
import { pipe } from "../common/core";
|
|
||||||
import { ImageIcon, InputIcon, LayoutIcon } from '../common/Icons/';
|
|
||||||
|
|
||||||
let componentLibraries=[];
|
let componentLibraries = [];
|
||||||
|
let current_view = 'text';
|
||||||
|
|
||||||
const addRootComponent = (c, all) => {
|
const addRootComponent = (c, all) => {
|
||||||
const { libName } = splitName(c.name);
|
const { libName } = splitName(c.name);
|
||||||
let group = find(r => r.libName === libName)(all);
|
let group = find(r => r.libName === libName)(all);
|
||||||
|
|
||||||
if(!group) {
|
if(!group) {
|
||||||
group = {
|
group = {
|
||||||
libName,
|
libName,
|
||||||
components: [],
|
components: [],
|
||||||
generators: []
|
generators: []
|
||||||
};
|
};
|
||||||
|
|
||||||
all.push(group);
|
all.push(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
group.components.push(c)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const onComponentChosen = store.addChildComponent;
|
||||||
|
|
||||||
|
$: {
|
||||||
|
const newComponentLibraries = [];
|
||||||
|
|
||||||
|
for(let comp of sortBy(["name"])($store.components)) {
|
||||||
|
addRootComponent(
|
||||||
|
comp,
|
||||||
|
newComponentLibraries);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentLibraries = newComponentLibraries;
|
||||||
}
|
}
|
||||||
|
|
||||||
group.components.push(c)
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const onComponentChosen = store.addChildComponent;
|
|
||||||
|
|
||||||
store.subscribe(s => {
|
|
||||||
|
|
||||||
const newComponentLibraries = [];
|
|
||||||
|
|
||||||
for(let comp of sortBy(["name"])(s.components)) {
|
|
||||||
addRootComponent(
|
|
||||||
comp,
|
|
||||||
newComponentLibraries);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentLibraries = newComponentLibraries;
|
|
||||||
});
|
|
||||||
|
|
||||||
let current_view = 'text';
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -115,13 +106,6 @@ let current_view = 'text';
|
||||||
min-height: 0px;
|
min-height: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inner-header {
|
|
||||||
font-size: 0.9em;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 7px;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.component {
|
.component {
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -147,13 +131,6 @@ let current_view = 'text';
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.component > .description {
|
|
||||||
font-size: 0.8em;
|
|
||||||
color: var(--secondary75);
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
<script>
|
<script>
|
||||||
import ComponentPanel from "./ComponentPanel.svelte";
|
import ComponentPanel from "./ComponentPanel.svelte";
|
||||||
import ComponentsList from "./ComponentsList.svelte";
|
import ComponentsList from "./ComponentsList.svelte";
|
||||||
|
|
||||||
let selected="properties";
|
let selected="properties";
|
||||||
|
|
||||||
const isSelected = tab =>
|
|
||||||
selected === tab;
|
|
||||||
|
|
||||||
const selectTab = tab =>
|
|
||||||
selected = tab;
|
|
||||||
|
|
||||||
|
const isSelected = tab =>
|
||||||
|
selected === tab;
|
||||||
|
|
||||||
|
const selectTab = tab =>
|
||||||
|
selected = tab;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
|
|
@ -1,41 +1,25 @@
|
||||||
<script>
|
<script>
|
||||||
import { store } from "../builderStore";
|
import { store } from "../builderStore";
|
||||||
import { makeLibraryUrl } from "../builderStore/loadComponentLibraries";
|
import { map, join } from "lodash/fp";
|
||||||
import {
|
import { pipe } from "../common/core";
|
||||||
last, split, map, join
|
import { buildPropsHierarchy } from "./pagesParsing/buildPropsHierarchy";
|
||||||
} from "lodash/fp";
|
|
||||||
import { pipe } from "../common/core";
|
|
||||||
import { splitName } from "./pagesParsing/splitRootComponentName"
|
|
||||||
import { afterUpdate } from 'svelte';
|
|
||||||
import { getRootComponent } from "./pagesParsing/getRootComponent";
|
|
||||||
import { buildPropsHierarchy } from "./pagesParsing/buildPropsHierarchy";
|
|
||||||
|
|
||||||
|
$: hasComponent = !!$store.currentFrontEndItem;
|
||||||
|
|
||||||
let hasComponent=false;
|
$: stylesheetLinks = pipe($store.pages.stylesheets, [
|
||||||
let stylesheetLinks = "";
|
|
||||||
let appDefinition = {};
|
|
||||||
|
|
||||||
store.subscribe(s => {
|
|
||||||
hasComponent = !!s.currentFrontEndItem;
|
|
||||||
|
|
||||||
stylesheetLinks = pipe(s.pages.stylesheets, [
|
|
||||||
map(s => `<link rel="stylesheet" href="${s}"/>`),
|
map(s => `<link rel="stylesheet" href="${s}"/>`),
|
||||||
join("\n")
|
join("\n")
|
||||||
]);
|
]);
|
||||||
appDefinition = {
|
|
||||||
componentLibraries: s.loadLibraryUrls(),
|
$: appDefinition = {
|
||||||
|
componentLibraries: $store.loadLibraryUrls(),
|
||||||
props: buildPropsHierarchy(
|
props: buildPropsHierarchy(
|
||||||
s.components,
|
$store.components,
|
||||||
s.screens,
|
$store.screens,
|
||||||
s.currentFrontEndItem),
|
$store.currentFrontEndItem),
|
||||||
hierarchy: s.hierarchy,
|
hierarchy: $store.hierarchy,
|
||||||
appRootPath: ""
|
appRootPath: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +36,6 @@ store.subscribe(s => {
|
||||||
window["##BUDIBASE_APPDEFINITION##"] = ${JSON.stringify(appDefinition)};
|
window["##BUDIBASE_APPDEFINITION##"] = ${JSON.stringify(appDefinition)};
|
||||||
import('/_builder/budibase-client.esm.mjs')
|
import('/_builder/budibase-client.esm.mjs')
|
||||||
.then(module => {
|
.then(module => {
|
||||||
console.log(module, window);
|
|
||||||
module.loadBudibase({ window, localStorage });
|
module.loadBudibase({ window, localStorage });
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -73,23 +56,21 @@ store.subscribe(s => {
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.component-container {
|
||||||
|
grid-row-start: middle;
|
||||||
|
grid-column-start: middle;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: 56.25%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.component-container {
|
.component-container iframe {
|
||||||
grid-row-start: middle;
|
border: 0;
|
||||||
grid-column-start: middle;
|
height: 100%;
|
||||||
position: relative;
|
left: 0;
|
||||||
overflow: hidden;
|
position: absolute;
|
||||||
padding-top: 56.25%;
|
top: 0;
|
||||||
margin: auto;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.component-container iframe {
|
|
||||||
border: 0;
|
|
||||||
height: 100%;
|
|
||||||
left: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,68 +1,31 @@
|
||||||
<script>
|
<script>
|
||||||
|
import PropsView from "./PropsView.svelte";
|
||||||
|
import { store } from "../builderStore";
|
||||||
|
import IconButton from "../common/IconButton.svelte";
|
||||||
|
import Textbox from "../common/Textbox.svelte";
|
||||||
|
import Button from "../common/Button.svelte";
|
||||||
|
import { LayoutIcon, PaintIcon, TerminalIcon } from '../common/Icons/';
|
||||||
|
|
||||||
import PropsView from "./PropsView.svelte";
|
import {
|
||||||
import { store } from "../builderStore";
|
cloneDeep,
|
||||||
import { isRootComponent } from "./pagesParsing/searchComponents";
|
join,
|
||||||
import IconButton from "../common/IconButton.svelte";
|
split,
|
||||||
import Textbox from "../common/Textbox.svelte";
|
last
|
||||||
import UIkit from "uikit";
|
} from "lodash/fp";
|
||||||
import { pipe } from "../common/core";
|
import { assign } from "lodash";
|
||||||
import {
|
|
||||||
getScreenInfo
|
|
||||||
} from "./pagesParsing/createProps";
|
|
||||||
import Button from "../common/Button.svelte";
|
|
||||||
import ButtonGroup from "../common/ButtonGroup.svelte";
|
|
||||||
import { LayoutIcon, PaintIcon, TerminalIcon } from '../common/Icons/';
|
|
||||||
|
|
||||||
import {
|
$: component = $store.currentFrontEndItem;
|
||||||
cloneDeep,
|
$: componentInfo = $store.currentComponentInfo;
|
||||||
join,
|
$: components = $store.components;
|
||||||
split,
|
|
||||||
map,
|
|
||||||
keys,
|
|
||||||
isUndefined,
|
|
||||||
last
|
|
||||||
} from "lodash/fp";
|
|
||||||
import { assign } from "lodash";
|
|
||||||
|
|
||||||
let component;
|
|
||||||
let name = "";
|
|
||||||
let description = "";
|
|
||||||
let tagsString = "";
|
|
||||||
let nameInvalid = "";
|
|
||||||
let componentInfo;
|
|
||||||
let modalElement
|
|
||||||
let propsValidationErrors = [];
|
|
||||||
let originalName="";
|
|
||||||
let components;
|
|
||||||
let ignoreStore = false;
|
|
||||||
|
|
||||||
$: shortName = last(name.split("/"));
|
const updateComponent = doChange =>
|
||||||
|
doChange(cloneDeep(component));
|
||||||
store.subscribe(s => {
|
|
||||||
if(ignoreStore) return;
|
|
||||||
component = s.currentFrontEndItem;
|
|
||||||
if(!component) return;
|
|
||||||
originalName = component.name;
|
|
||||||
name = component.name;
|
|
||||||
description = component.description;
|
|
||||||
tagsString = join(", ")(component.tags);
|
|
||||||
componentInfo = s.currentComponentInfo;
|
|
||||||
components = s.components;
|
|
||||||
});
|
|
||||||
|
|
||||||
const updateComponent = doChange => {
|
|
||||||
const newComponent = cloneDeep(component);
|
|
||||||
doChange(newComponent);
|
|
||||||
component = newComponent;
|
|
||||||
componentInfo = getScreenInfo(components, newComponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
const onPropsChanged = newProps => {
|
|
||||||
updateComponent(newComponent =>
|
|
||||||
assign(newComponent.props, newProps));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const onPropsChanged = newProps => {
|
||||||
|
updateComponent(newComponent =>
|
||||||
|
assign(newComponent.props, newProps));
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -74,74 +37,54 @@ const onPropsChanged = newProps => {
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="component-props-container">
|
<div class="component-props-container">
|
||||||
|
|
||||||
|
|
||||||
<PropsView
|
<PropsView
|
||||||
{componentInfo}
|
{componentInfo}
|
||||||
{onPropsChanged} />
|
{onPropsChanged} />
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.root {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.root {
|
}
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
}
|
.title > div:nth-child(1) {
|
||||||
|
grid-column-start: name;
|
||||||
|
color: var(--secondary100);
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title > div:nth-child(2) {
|
||||||
padding: 1rem;
|
grid-column-start: actions;
|
||||||
display: grid;
|
}
|
||||||
grid-template-columns: [name] 1fr [actions] auto;
|
|
||||||
color: var(--secondary100);
|
|
||||||
font-size: .9rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title > div:nth-child(1) {
|
.component-props-container {
|
||||||
grid-column-start: name;
|
flex: 1 1 auto;
|
||||||
color: var(--secondary100);
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title > div:nth-child(2) {
|
ul {
|
||||||
grid-column-start: actions;
|
list-style: none;
|
||||||
}
|
display: flex;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.component-props-container {
|
li {
|
||||||
flex: 1 1 auto;
|
margin-right: 20px;
|
||||||
overflow-y: auto;
|
background: none;
|
||||||
}
|
border-radius: 5px;
|
||||||
|
width: 45px;
|
||||||
ul {
|
height: 45px;
|
||||||
list-style: none;
|
}
|
||||||
display: flex;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
margin-right: 20px;
|
|
||||||
background: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
width: 45px;
|
|
||||||
height: 45px;
|
|
||||||
}
|
|
||||||
|
|
||||||
li button {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected {
|
|
||||||
background: lightblue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
li button {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,45 +1,39 @@
|
||||||
<script>
|
<script>
|
||||||
import IconButton from "../common/IconButton.svelte";
|
import IconButton from "../common/IconButton.svelte";
|
||||||
import EventSelector from "./EventSelector.svelte";
|
import EventSelector from "./EventSelector.svelte";
|
||||||
import {
|
import {
|
||||||
filter
|
filter
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import {EVENT_TYPE_MEMBER_NAME} from "../common/eventHandlers";
|
import {EVENT_TYPE_MEMBER_NAME} from "../common/eventHandlers";
|
||||||
|
|
||||||
export let parentProps;
|
export let parentProps;
|
||||||
export let propDef;
|
export let propDef;
|
||||||
export let onValueChanged;
|
export let onValueChanged;
|
||||||
export let onValidate = () => {};
|
|
||||||
|
|
||||||
let events = [];
|
$: events = parentProps[propDef.____name];
|
||||||
let elementErrors = {};
|
|
||||||
|
|
||||||
$: {
|
const addHandler = () => {
|
||||||
events = parentProps[propDef.____name];
|
const newHandler = {parameters:{}};
|
||||||
}
|
newHandler[EVENT_TYPE_MEMBER_NAME] = "";
|
||||||
|
events = [...events, newHandler];
|
||||||
|
onValueChanged(events);
|
||||||
|
}
|
||||||
|
|
||||||
const addHandler = () => {
|
const onEventHandlerChanged = (oldEvent) => (newEvent) => {
|
||||||
const newHandler = {parameters:{}};
|
const indexOfOldEvent = events.indexOf(oldEvent);
|
||||||
newHandler[EVENT_TYPE_MEMBER_NAME] = "";
|
const newEvents = [...events];
|
||||||
events = [...events, newHandler];
|
newEvents.splice(
|
||||||
onValueChanged(events);
|
events.indexOf(oldEvent),
|
||||||
}
|
1,
|
||||||
|
newEvent);
|
||||||
|
events = newEvents;
|
||||||
|
onValueChanged(events);
|
||||||
|
}
|
||||||
|
|
||||||
const onEventHandlerChanged = (oldEvent) => (newEvent) => {
|
const removeHandler = (index) => () => {
|
||||||
const indexOfOldEvent = events.indexOf(oldEvent);
|
events = filter(e => e !== events[index])(events);
|
||||||
const newEvents = [...events];
|
onValueChanged(events);
|
||||||
newEvents.splice(
|
}
|
||||||
events.indexOf(oldEvent),
|
|
||||||
1,
|
|
||||||
newEvent);
|
|
||||||
events = newEvents;
|
|
||||||
onValueChanged(events);
|
|
||||||
}
|
|
||||||
|
|
||||||
const removeHandler = (index) => () => {
|
|
||||||
events = filter(e => e !== events[index])(events);
|
|
||||||
onValueChanged(events);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -67,32 +61,28 @@ const removeHandler = (index) => () => {
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.addelement-container {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 3px 0px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.addelement-container {
|
.addelement-container:hover {
|
||||||
cursor: pointer;
|
background-color: var(--primary25);
|
||||||
padding: 3px 0px;
|
margin-top: 5px;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
.control-container {
|
||||||
|
padding-left: 3px;
|
||||||
|
background: var(--secondary10);
|
||||||
|
}
|
||||||
|
|
||||||
.addelement-container:hover {
|
.separator {
|
||||||
background-color: var(--primary25);
|
width: 60%;
|
||||||
margin-top: 5px;
|
margin: 10px auto;
|
||||||
}
|
border-style:solid;
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
border-color: var(--primary25);
|
||||||
.control-container {
|
}
|
||||||
padding-left: 3px;
|
|
||||||
background: var(--secondary10);
|
|
||||||
}
|
|
||||||
|
|
||||||
.separator {
|
|
||||||
width: 60%;
|
|
||||||
margin: 10px auto;
|
|
||||||
border-style:solid;
|
|
||||||
border-width: 1px 0 0 0;
|
|
||||||
border-color: var(--primary25);
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,71 +1,67 @@
|
||||||
<script>
|
<script>
|
||||||
import IconButton from "../common/IconButton.svelte";
|
import IconButton from "../common/IconButton.svelte";
|
||||||
import StateBindingControl from "./StateBindingControl.svelte";
|
import StateBindingControl from "./StateBindingControl.svelte";
|
||||||
import {
|
import {
|
||||||
find, map, keys, reduce, keyBy
|
find, map, keys, reduce, keyBy
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import { pipe, userWithFullAccess } from "../common/core";
|
import { pipe, userWithFullAccess } from "../common/core";
|
||||||
import { EVENT_TYPE_MEMBER_NAME, allHandlers } from "../common/eventHandlers";
|
import { EVENT_TYPE_MEMBER_NAME, allHandlers } from "../common/eventHandlers";
|
||||||
import { store } from "../builderStore";
|
import { store } from "../builderStore";
|
||||||
|
|
||||||
export let event;
|
export let event;
|
||||||
export let onChanged;
|
export let onChanged;
|
||||||
export let onRemoved;
|
export let onRemoved;
|
||||||
|
|
||||||
let events;
|
let eventType;
|
||||||
let eventType;
|
let parameters = [];
|
||||||
let parameters = [];
|
|
||||||
|
|
||||||
store.subscribe(s => {
|
|
||||||
events = allHandlers(
|
$: events = allHandlers(
|
||||||
{hierarchy: s.hierarchy},
|
{hierarchy: $store.hierarchy},
|
||||||
userWithFullAccess({
|
userWithFullAccess({
|
||||||
hierarchy: s.hierarchy,
|
hierarchy: s.hierarchy,
|
||||||
actions: keyBy("name")(s.actions)
|
actions: keyBy("name")($store.actions)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
$: {
|
$: if(event) {
|
||||||
if(event) {
|
eventType = event[EVENT_TYPE_MEMBER_NAME];
|
||||||
eventType = event[EVENT_TYPE_MEMBER_NAME];
|
parameters = pipe(event.parameters, [
|
||||||
parameters = pipe(event.parameters, [
|
keys,
|
||||||
keys,
|
map(k => ({name:k, value:event.parameters[k]}))
|
||||||
map(k => ({name:k, value:event.parameters[k]}))
|
]);
|
||||||
]);
|
} else {
|
||||||
} else {
|
eventType = "";
|
||||||
eventType = "";
|
parameters = [];
|
||||||
parameters = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventChanged = (type, parameters) => {
|
|
||||||
const paramsAsObject = reduce(
|
|
||||||
(obj, p) => {
|
|
||||||
obj[p.name] = p.value;
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
, {}
|
|
||||||
)(parameters)
|
|
||||||
|
|
||||||
const ev = {};
|
const eventChanged = (type, parameters) => {
|
||||||
ev[EVENT_TYPE_MEMBER_NAME]=type;
|
const paramsAsObject = reduce(
|
||||||
ev.parameters = paramsAsObject;
|
(obj, p) => {
|
||||||
|
obj[p.name] = p.value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
, {}
|
||||||
|
)(parameters)
|
||||||
|
|
||||||
onChanged(ev);
|
const ev = {};
|
||||||
}
|
ev[EVENT_TYPE_MEMBER_NAME]=type;
|
||||||
|
ev.parameters = paramsAsObject;
|
||||||
|
|
||||||
const eventTypeChanged = (ev) => {
|
onChanged(ev);
|
||||||
const eType = find(e => e.name === ev.target.value)(events);
|
}
|
||||||
const emptyParameters = map(p => ({name:p, value:""}))(eType.parameters);
|
|
||||||
eventChanged(eType.name, emptyParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
const onParameterChanged = index => val => {
|
const eventTypeChanged = (ev) => {
|
||||||
const newparameters = [...parameters];
|
const eType = find(e => e.name === ev.target.value)(events);
|
||||||
newparameters[index].value = val;
|
const emptyParameters = map(p => ({name:p, value:""}))(eType.parameters);
|
||||||
eventChanged(eventType, newparameters);
|
eventChanged(eType.name, emptyParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onParameterChanged = index => val => {
|
||||||
|
const newparameters = [...parameters];
|
||||||
|
newparameters[index].value = val;
|
||||||
|
eventChanged(eventType, newparameters);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -84,28 +80,26 @@ const onParameterChanged = index => val => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if parameters}
|
{#if parameters}
|
||||||
{#each parameters as p, index}
|
{#each parameters as p, index}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{p.name}
|
{p.name}
|
||||||
</div>
|
</div>
|
||||||
<StateBindingControl onChanged={onParameterChanged(index)}
|
<StateBindingControl onChanged={onParameterChanged(index)}
|
||||||
value={p.value} />
|
value={p.value} />
|
||||||
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.type-selector-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.type-selector-container {
|
.type-selector {
|
||||||
display: flex;
|
border-color: var(--primary50);
|
||||||
}
|
border-radius: 2px;
|
||||||
|
width: 50px;
|
||||||
.type-selector {
|
flex: 1 0 auto;
|
||||||
border-color: var(--primary50);
|
}
|
||||||
border-radius: 2px;
|
|
||||||
width: 50px;
|
|
||||||
flex: 1 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -1,13 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import InputGroup from '../common/Inputs/InputGroup.svelte';
|
import InputGroup from '../common/Inputs/InputGroup.svelte';
|
||||||
|
|
||||||
let grid_values = ['', '', '', ''];
|
export let onStyleChanged = () => {};
|
||||||
let column_values = ['', ''];
|
export let componentInfo;
|
||||||
let row_values = ['', ''];
|
|
||||||
let gap_values = [''];
|
|
||||||
let margin_values = ['', '', '', ''];
|
|
||||||
let padding_values = ['', '', '', ''];
|
|
||||||
let zindex_values = [''];
|
|
||||||
|
|
||||||
const tbrl = [
|
const tbrl = [
|
||||||
{ placeholder: 'T' },
|
{ placeholder: 'T' },
|
||||||
|
@ -22,6 +17,27 @@
|
||||||
]
|
]
|
||||||
|
|
||||||
const single = [{ placeholder: '' }];
|
const single = [{ placeholder: '' }];
|
||||||
|
|
||||||
|
|
||||||
|
$: layout = componentInfo._layout;
|
||||||
|
|
||||||
|
$: positions = {
|
||||||
|
gridarea: ['Grid Area', tbrl, 'small'],
|
||||||
|
column: ['Column', se],
|
||||||
|
row: ['Row', se],
|
||||||
|
gap: ['Gap', single],
|
||||||
|
};
|
||||||
|
|
||||||
|
$: spacing = {
|
||||||
|
margin: ['Margin', tbrl, 'small'],
|
||||||
|
padding: ['Padding', tbrl, 'small']
|
||||||
|
};
|
||||||
|
|
||||||
|
$: zindex = {
|
||||||
|
zindex: ['Z-Index', single]
|
||||||
|
}
|
||||||
|
|
||||||
|
const newValue = n => Array(n).fill('');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,48 +46,41 @@
|
||||||
<h4>Positioning</h4>
|
<h4>Positioning</h4>
|
||||||
|
|
||||||
<div class="layout-pos">
|
<div class="layout-pos">
|
||||||
<div class="grid">
|
{#each Object.entries(positions) as [key, [name, meta, size]]}
|
||||||
<h5>Grid Area:</h5>
|
<div class="grid">
|
||||||
<InputGroup meta={tbrl} bind:values={grid_values} size="small"/>
|
<h5>Grid Area:</h5>
|
||||||
</div>
|
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
||||||
|
values={layout[key] || newValue(meta.length)}
|
||||||
<div class="grid">
|
{meta}
|
||||||
<h5>Column:</h5>
|
{size} />
|
||||||
<InputGroup meta={se} bind:values={column_values} />
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
|
|
||||||
<div class="grid">
|
|
||||||
<h5>Row:</h5>
|
|
||||||
<InputGroup meta={se} bind:values={row_values} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid">
|
|
||||||
<h5>Gap:</h5>
|
|
||||||
<InputGroup meta={single} bind:values={gap_values} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4>Spacing</h4>
|
<h4>Spacing</h4>
|
||||||
|
|
||||||
<div class="layout-spacing">
|
<div class="layout-spacing">
|
||||||
<div class="grid">
|
{#each Object.entries(spacing) as [key, [name, meta, size]]}
|
||||||
<h5>Margin:</h5>
|
<div class="grid">
|
||||||
<InputGroup meta={tbrl} bind:values={margin_values} size="small"/>
|
<h5>Grid Area:</h5>
|
||||||
</div>
|
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
||||||
|
values={layout[key] || newValue(meta.length)}
|
||||||
<div class="grid">
|
{meta}
|
||||||
<h5>Padding:</h5>
|
{size} />
|
||||||
<InputGroup meta={tbrl} bind:values={padding_values} size="small"/>
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4>Z-Index</h4>
|
<h4>Z-Index</h4>
|
||||||
|
|
||||||
<div class="layout-layer">
|
<div class="layout-layer">
|
||||||
<div class="grid">
|
{#each Object.entries(zindex) as [key, [name, meta, size]]}
|
||||||
<h5>Z-Index:</h5>
|
<div class="grid">
|
||||||
<InputGroup meta={single} bind:values={zindex_values}/>
|
<h5>Grid Area:</h5>
|
||||||
</div>
|
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
||||||
|
values={layout[key] || newValue(meta.length)}
|
||||||
|
{meta}
|
||||||
|
{size} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -112,5 +121,4 @@
|
||||||
.grid {
|
.grid {
|
||||||
grid-template-columns: 70px 1fr;
|
grid-template-columns: 70px 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,65 +1,64 @@
|
||||||
<script>
|
<script>
|
||||||
|
import ComponentSelector from "./ComponentSelector.svelte";
|
||||||
|
import { store } from "../builderStore";
|
||||||
|
import PropsView from "./PropsView.svelte";
|
||||||
|
import Textbox from "../common/Textbox.svelte";
|
||||||
|
import Button from "../common/Button.svelte";
|
||||||
|
import ButtonGroup from "../common/ButtonGroup.svelte";
|
||||||
|
import { pipe } from "../common/core";
|
||||||
|
import UIkit from "uikit";
|
||||||
|
import { isRootComponent } from "./pagesParsing/searchComponents";
|
||||||
|
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
||||||
|
|
||||||
import ComponentSelector from "./ComponentSelector.svelte";
|
import {
|
||||||
import { store } from "../builderStore";
|
find, filter, some, map, includes
|
||||||
import PropsView from "./PropsView.svelte";
|
} from "lodash/fp";
|
||||||
import Textbox from "../common/Textbox.svelte";
|
import { assign } from "lodash";
|
||||||
import Button from "../common/Button.svelte";
|
|
||||||
import ButtonGroup from "../common/ButtonGroup.svelte";
|
|
||||||
import { pipe } from "../common/core";
|
|
||||||
import UIkit from "uikit";
|
|
||||||
import { isRootComponent } from "./pagesParsing/searchComponents";
|
|
||||||
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
|
||||||
|
|
||||||
import {
|
|
||||||
find, filter, some, map, includes
|
|
||||||
} from "lodash/fp";
|
|
||||||
import { assign } from "lodash";
|
|
||||||
|
|
||||||
|
|
||||||
export const show = () => {
|
export const show = () => {
|
||||||
UIkit.modal(componentSelectorModal).show();
|
UIkit.modal(componentSelectorModal).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
let componentSelectorModal;
|
let componentSelectorModal;
|
||||||
let layoutComponents;
|
let layoutComponents;
|
||||||
let layoutComponent;
|
let layoutComponent;
|
||||||
let screens;
|
let screens;
|
||||||
let name="";
|
let name="";
|
||||||
let saveAttempted=false;
|
let saveAttempted=false;
|
||||||
|
|
||||||
store.subscribe(s => {
|
store.subscribe(s => {
|
||||||
layoutComponents = pipe(s.components, [
|
layoutComponents = pipe(s.components, [
|
||||||
filter(c => c.container),
|
filter(c => c.container),
|
||||||
map(c => ({name:c.name, ...splitName(c.name)}))
|
map(c => ({name:c.name, ...splitName(c.name)}))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
layoutComponent = layoutComponent
|
layoutComponent = layoutComponent
|
||||||
? find(c => c.name === layoutComponent.name)(layoutComponents)
|
? find(c => c.name === layoutComponent.name)(layoutComponents)
|
||||||
: layoutComponents[0];
|
: layoutComponents[0];
|
||||||
|
|
||||||
screens = s.screens;
|
screens = s.screens;
|
||||||
});
|
});
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
saveAttempted = true;
|
saveAttempted = true;
|
||||||
|
|
||||||
const isValid = name.length > 0
|
const isValid = name.length > 0
|
||||||
&& !screenNameExists(name)
|
&& !screenNameExists(name)
|
||||||
&& layoutComponent;
|
&& layoutComponent;
|
||||||
|
|
||||||
if(!isValid) return;
|
if(!isValid) return;
|
||||||
|
|
||||||
store.createScreen(name, layoutComponent.name);
|
store.createScreen(name, layoutComponent.name);
|
||||||
UIkit.modal(componentSelectorModal).hide();
|
UIkit.modal(componentSelectorModal).hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
UIkit.modal(componentSelectorModal).hide();
|
UIkit.modal(componentSelectorModal).hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
const screenNameExists = (name) =>
|
const screenNameExists = (name) =>
|
||||||
some(s => s.name.toLowerCase() === name.toLowerCase())(screens)
|
some(s => s.name.toLowerCase() === name.toLowerCase())(screens)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -106,27 +105,7 @@ const screenNameExists = (name) =>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h1 {
|
h1 {
|
||||||
font-size:1.2em;
|
font-size:1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.component-option {
|
|
||||||
border-style: solid;
|
|
||||||
border-color: var(--slate);
|
|
||||||
border-width: 0 0 1px 0;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.component-option:hover {
|
|
||||||
background-color: var(--lightslate);
|
|
||||||
}
|
|
||||||
|
|
||||||
.component-name {
|
|
||||||
font-size: 11pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lib-name {
|
|
||||||
font-size: 9pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,44 +1,36 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import Textbox from "../common/Textbox.svelte";
|
import Textbox from "../common/Textbox.svelte";
|
||||||
import Dropdown from "../common/Dropdown.svelte";
|
import Dropdown from "../common/Dropdown.svelte";
|
||||||
import Button from "../common/Button.svelte";
|
import Button from "../common/Button.svelte";
|
||||||
import { store } from "../builderStore";
|
import { store } from "../builderStore";
|
||||||
import { isRootComponent } from "./pagesParsing/searchComponents";
|
import { isRootComponent } from "./pagesParsing/searchComponents";
|
||||||
import { pipe } from "../common/core";
|
import { pipe } from "../common/core";
|
||||||
import {
|
import {
|
||||||
filter, find, concat
|
filter, find, concat
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
|
|
||||||
let entryComponent;
|
const notSeletedComponent = {name:"(none selected)"};
|
||||||
let title = "";
|
|
||||||
let components = [];
|
|
||||||
let page={};
|
|
||||||
const notSeletedComponent = {name:"(none selected)"};
|
|
||||||
|
|
||||||
store.subscribe(s => {
|
$: page = $store.pages[$store.currentPageName];
|
||||||
page = s.pages[s.currentPageName];
|
$: title = page.index.title;
|
||||||
if(!page) return;
|
$: components = pipe($store.components, [
|
||||||
title = page.index.title;
|
filter(store => !isRootComponent($store)),
|
||||||
components = pipe(s.components, [
|
|
||||||
filter(s => !isRootComponent(s)),
|
|
||||||
concat([notSeletedComponent])
|
concat([notSeletedComponent])
|
||||||
]);
|
]);
|
||||||
entryComponent = find(c => c.name === page.appBody)(components);
|
$: entryComponent = find(c => c.name === page.appBody)(components) || notSeletedComponent;
|
||||||
if(!entryComponent) entryComponent = notSeletedComponent;
|
|
||||||
});
|
|
||||||
|
|
||||||
const save = () => {
|
|
||||||
if(!title || !entryComponent || entryComponent === notSeletedComponent) return;
|
const save = () => {
|
||||||
const page = {
|
if(!title || !entryComponent || entryComponent === notSeletedComponent) return;
|
||||||
index: {
|
const page = {
|
||||||
title
|
index: {
|
||||||
},
|
title
|
||||||
appBody: entryComponent.name,
|
},
|
||||||
|
appBody: entryComponent.name,
|
||||||
|
}
|
||||||
|
store.savePage(page);
|
||||||
}
|
}
|
||||||
store.savePage(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -61,11 +53,11 @@ const save = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.root {
|
.root {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
.help-text {
|
.help-text {
|
||||||
color: var(--slate);
|
color: var(--slate);
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,22 +1,21 @@
|
||||||
<script>
|
<script>
|
||||||
import { store } from "../builderStore";
|
import { store } from "../builderStore";
|
||||||
import getIcon from "../common/icon";
|
import getIcon from "../common/icon";
|
||||||
|
|
||||||
const getPage = (s, name) => {
|
const getPage = (s, name) => {
|
||||||
const props = s.pages[name];
|
const props = s.pages[name];
|
||||||
return ({name, props});
|
return ({name, props});
|
||||||
}
|
}
|
||||||
|
|
||||||
const pages = [{
|
const pages = [{
|
||||||
title: 'Main',
|
title: 'Main',
|
||||||
id: 'main'
|
id: 'main'
|
||||||
}, {
|
}, {
|
||||||
title: 'Login',
|
title: 'Login',
|
||||||
id: 'unauthenticated'
|
id: 'unauthenticated'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
store.setCurrentPage('main')
|
|
||||||
|
|
||||||
|
store.setCurrentPage('main')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -31,46 +30,44 @@ store.setCurrentPage('main')
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.root {
|
||||||
.root {
|
padding-bottom: 10px;
|
||||||
padding-bottom: 10px;
|
font-size: .9rem;
|
||||||
font-size: .9rem;
|
color: var(--secondary50);
|
||||||
color: var(--secondary50);
|
font-weight: bold;
|
||||||
font-weight: bold;
|
position: relative;
|
||||||
position: relative;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #444;
|
color: #444;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
padding: 1em 2.6em 0.9em 1.4em;
|
padding: 1em 2.6em 0.9em 1.4em;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: .5em;
|
border-radius: .5em;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.arrow {
|
|
||||||
position: absolute;
|
|
||||||
right: 10px;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
pointer-events: none;
|
|
||||||
color: var(--primary100);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
margin: auto;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
pointer-events: none;
|
||||||
|
color: var(--primary100);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,37 +1,25 @@
|
||||||
<script>
|
<script>
|
||||||
|
import Checkbox from "../common/Checkbox.svelte";
|
||||||
|
import Textbox from "../common/Textbox.svelte";
|
||||||
|
import Dropdown from "../common/Dropdown.svelte";
|
||||||
|
import StateBindingControl from "./StateBindingControl.svelte";
|
||||||
|
|
||||||
import Checkbox from "../common/Checkbox.svelte";
|
export let setProp = () => {};
|
||||||
import Textbox from "../common/Textbox.svelte";
|
export let index;
|
||||||
import Dropdown from "../common/Dropdown.svelte";
|
export let prop_name;
|
||||||
import EventListSelector from "./EventListSelector.svelte";
|
export let prop_value;
|
||||||
import StateBindingControl from "./StateBindingControl.svelte";
|
export let prop_type = {};
|
||||||
|
|
||||||
export let setProp = () => {};
|
$: isOdd = (index % 2 !== 0);
|
||||||
export let disabled;
|
|
||||||
export let index;
|
|
||||||
export let prop_name;
|
|
||||||
export let prop_value;
|
|
||||||
export let prop_type = {};
|
|
||||||
|
|
||||||
$: isOdd = (index % 2 !== 0);
|
|
||||||
|
|
||||||
const setComponentProp = (props) => {
|
|
||||||
setProp(propDef.____name, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const setComponentProp = (props) => {
|
||||||
|
setProp(propDef.____name, props);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div class="root" >
|
<div class="root" >
|
||||||
|
{#if prop_type !== "event" }
|
||||||
{#if prop_type === "event"}
|
|
||||||
|
|
||||||
<!-- <h5>{prop_name}</h5>
|
|
||||||
<EventListSelector parentProps={props}
|
|
||||||
{propDef}
|
|
||||||
onValueChanged={setComponentProp} /> -->
|
|
||||||
|
|
||||||
{:else }
|
|
||||||
|
|
||||||
<h5>{prop_name}</h5>
|
<h5>{prop_name}</h5>
|
||||||
<StateBindingControl value={prop_value}
|
<StateBindingControl value={prop_value}
|
||||||
|
@ -40,27 +28,24 @@ const setComponentProp = (props) => {
|
||||||
onChanged={v => setProp(prop_name, v)}/>
|
onChanged={v => setProp(prop_name, v)}/>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.root {
|
||||||
|
height: 40px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
grid-template-columns: 70px 1fr;
|
||||||
|
grid-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.root {
|
h5 {
|
||||||
height: 40px;
|
font-size: 12px;
|
||||||
margin-bottom: 15px;
|
font-weight: 700;
|
||||||
display: grid;
|
color: #163057;
|
||||||
grid-template-rows: 1fr;
|
opacity: 0.6;
|
||||||
grid-template-columns: 70px 1fr;
|
padding-top: 12px;
|
||||||
grid-gap: 10px;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #163057;
|
|
||||||
opacity: 0.6;
|
|
||||||
padding-top: 12px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,44 +1,32 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { some, includes, filter } from "lodash/fp";
|
||||||
|
import Textbox from "../common/Textbox.svelte";
|
||||||
|
import Dropdown from "../common/Dropdown.svelte";
|
||||||
|
import PropControl from "./PropControl.svelte";
|
||||||
|
import IconButton from "../common/IconButton.svelte";
|
||||||
|
|
||||||
import {
|
export let componentInfo;
|
||||||
keys, map, some, includes,
|
export let onPropChanged = () => {};
|
||||||
cloneDeep, isEqual, sortBy,
|
export let components;
|
||||||
filter, difference
|
|
||||||
} from "lodash/fp";
|
|
||||||
import { pipe } from "../common/core";
|
|
||||||
import { getInstanceProps } from "./pagesParsing/createProps";
|
|
||||||
import Checkbox from "../common/Checkbox.svelte";
|
|
||||||
import Textbox from "../common/Textbox.svelte";
|
|
||||||
import Dropdown from "../common/Dropdown.svelte";
|
|
||||||
import PropControl from "./PropControl.svelte";
|
|
||||||
import IconButton from "../common/IconButton.svelte";
|
|
||||||
|
|
||||||
export let componentInfo;
|
let errors = [];
|
||||||
export let instanceProps = null;
|
let props = {};
|
||||||
export let onPropsChanged = () => {};
|
|
||||||
export let components;
|
|
||||||
|
|
||||||
let errors = [];
|
const props_to_ignore = ['_component','_children', '_layout'];
|
||||||
let props = {};
|
|
||||||
let propsDefinitions = [];
|
|
||||||
let isInstance = false;
|
|
||||||
|
|
||||||
const props_to_ignore = ['_component','_children', '_layout'];
|
$: propDefs = componentInfo && Object.entries(componentInfo).filter(([name])=> !props_to_ignore.includes(name));
|
||||||
|
|
||||||
$: propDefs = componentInfo && Object.entries(componentInfo).filter(([name])=> !props_to_ignore.includes(name));
|
function find_type(prop_name) {
|
||||||
|
if(!componentInfo._component) return;
|
||||||
|
return components.find(({name}) => name === componentInfo._component).props[prop_name];
|
||||||
|
}
|
||||||
|
|
||||||
function find_type(prop_name) {
|
let setProp = (name, value) => {
|
||||||
if(!componentInfo._component) return;
|
onPropChanged(name, value);
|
||||||
return components.find(({name}) => name === componentInfo._component).props[prop_name];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let setProp = (name, value) => {
|
|
||||||
onPropsChanged(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const fieldHasError = (propName) =>
|
|
||||||
some(e => e.propName === propName)(errors);
|
|
||||||
|
|
||||||
|
const fieldHasError = (propName) =>
|
||||||
|
some(e => e.propName === propName)(errors);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -65,20 +53,18 @@ const fieldHasError = (propName) =>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.root {
|
||||||
|
font-size:10pt;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.root {
|
.form-root {
|
||||||
font-size:10pt;
|
display: flex;
|
||||||
width: 100%;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-root {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prop-container {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-width: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.prop-container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 250px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,52 +1,46 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { store } from "../builderStore";
|
||||||
|
import Textbox from "../common/Textbox.svelte";
|
||||||
|
import Button from "../common/Button.svelte";
|
||||||
|
import IconButton from "../common/IconButton.svelte";
|
||||||
|
import { libraryDependencies } from "./pagesParsing/findDependencies";
|
||||||
|
import UIkit from "uikit";
|
||||||
|
|
||||||
import { store } from "../builderStore";
|
let addNewLib = "";
|
||||||
import Textbox from "../common/Textbox.svelte";
|
let addNewStylesheet = "";
|
||||||
import Button from "../common/Button.svelte";
|
let modalElement;
|
||||||
import IconButton from "../common/IconButton.svelte";
|
|
||||||
import { libraryDependencies } from "./pagesParsing/findDependencies";
|
|
||||||
import UIkit from "uikit";
|
|
||||||
|
|
||||||
let addNewLib = "";
|
$: components = $store.components;
|
||||||
let addNewStylesheet = "";
|
|
||||||
let addComponentError = "";
|
|
||||||
let modalElement;
|
|
||||||
let components;
|
|
||||||
|
|
||||||
store.subscribe(s => {
|
const removeLibrary = lib => {
|
||||||
components = s.components;
|
const dependencies = libraryDependencies(components, lib);
|
||||||
})
|
if(dependencies.length > 0) return;
|
||||||
|
store.removeComponentLibrary(lib);
|
||||||
|
}
|
||||||
|
|
||||||
const removeLibrary = lib => {
|
const addLib = () => {
|
||||||
const dependencies = libraryDependencies(components, lib);
|
store.addComponentLibrary(addNewLib)
|
||||||
if(dependencies.length > 0) return;
|
.then(() => {
|
||||||
store.removeComponentLibrary(lib);
|
addNewLib = "";
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const addLib = () => {
|
const removeStylesheet = stylesheet => {
|
||||||
store.addComponentLibrary(addNewLib)
|
store.removeStylesheet(stylesheet);
|
||||||
.then(() => {
|
}
|
||||||
addNewLib = "";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const removeStylesheet = stylesheet => {
|
const addStylesheet = () => {
|
||||||
store.removeStylesheet(stylesheet);
|
if(addNewStylesheet)
|
||||||
}
|
store.addStylesheet(addNewStylesheet);
|
||||||
|
}
|
||||||
|
|
||||||
const addStylesheet = () => {
|
export const close = () => {
|
||||||
if(addNewStylesheet)
|
UIkit.modal(modalElement).hide();
|
||||||
store.addStylesheet(addNewStylesheet);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export const close = () => {
|
|
||||||
UIkit.modal(modalElement).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
export const show = () => {
|
|
||||||
UIkit.modal(modalElement).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
export const show = () => {
|
||||||
|
UIkit.modal(modalElement).show();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={modalElement} id="new-component-modal" uk-modal>
|
<div bind:this={modalElement} id="new-component-modal" uk-modal>
|
||||||
|
@ -103,43 +97,41 @@ export const show = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.section-container {
|
||||||
|
padding: 15px;
|
||||||
|
border-style: dotted;
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--lightslate);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.section-container {
|
.section-container:nth-child(1) {
|
||||||
padding: 15px;
|
margin-bottom: 15px;
|
||||||
border-style: dotted;
|
}
|
||||||
border-width: 1px;
|
|
||||||
border-color: var(--lightslate);
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-container:nth-child(1) {
|
.row-text {
|
||||||
margin-bottom: 15px;
|
margin-right: 15px;
|
||||||
}
|
color: var(--primary100);
|
||||||
|
}
|
||||||
|
|
||||||
.row-text {
|
input {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
color: var(--primary100);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
p > span {
|
||||||
margin-right: 15px;
|
margin-left: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
p > span {
|
.header {
|
||||||
margin-left: 30px;
|
display: grid;
|
||||||
}
|
grid-template-columns: [title] 1fr [icon] auto;
|
||||||
|
}
|
||||||
|
|
||||||
.header {
|
.header > div:nth-child(1) {
|
||||||
display: grid;
|
grid-column-start: title;
|
||||||
grid-template-columns: [title] 1fr [icon] auto;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.header > div:nth-child(1) {
|
|
||||||
grid-column-start: title;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header > div:nth-child(2) {
|
|
||||||
grid-column-start: icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.header > div:nth-child(2) {
|
||||||
|
grid-column-start: icon;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,145 +1,130 @@
|
||||||
<script>
|
<script>
|
||||||
import {
|
import IconButton from "../common/IconButton.svelte";
|
||||||
isString
|
import {
|
||||||
} from "lodash/fp";
|
isBinding, getBinding, setBinding
|
||||||
import IconButton from "../common/IconButton.svelte";
|
} from "../common/binding";
|
||||||
import {
|
|
||||||
isBinding, getBinding, setBinding
|
|
||||||
} from "../common/binding";
|
|
||||||
|
|
||||||
export let value="";
|
export let value="";
|
||||||
export let onChanged= () => {};
|
export let onChanged= () => {};
|
||||||
export let type="";
|
export let type="";
|
||||||
export let options=[];
|
export let options=[];
|
||||||
|
|
||||||
let isBound=false;
|
let isBound=false;
|
||||||
let bindingPath="";
|
let bindingPath="";
|
||||||
let bindingFallbackValue="";
|
let bindingFallbackValue="";
|
||||||
let bindingSource="store";
|
let bindingSource="store";
|
||||||
let isExpanded = false;
|
let isExpanded = false;
|
||||||
let forceIsBound = false;
|
let forceIsBound = false;
|
||||||
let canOnlyBind = false;
|
let canOnlyBind = false;
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
canOnlyBind = type === "state";
|
canOnlyBind = type === "state";
|
||||||
if(!forceIsBound && canOnlyBind)
|
if(!forceIsBound && canOnlyBind)
|
||||||
forceIsBound = true;
|
forceIsBound = true;
|
||||||
|
|
||||||
isBound= forceIsBound || isBinding(value);
|
isBound= forceIsBound || isBinding(value);
|
||||||
|
|
||||||
if(isBound) {
|
if(isBound) {
|
||||||
const binding = getBinding(value);
|
const binding = getBinding(value);
|
||||||
bindingPath= binding.path;
|
bindingPath= binding.path;
|
||||||
bindingFallbackValue= binding.fallback;
|
bindingFallbackValue= binding.fallback;
|
||||||
bindingSource = binding.source || "store";
|
bindingSource = binding.source || "store";
|
||||||
} else {
|
} else {
|
||||||
bindingPath="";
|
bindingPath="";
|
||||||
bindingFallbackValue="";
|
bindingFallbackValue="";
|
||||||
bindingSource="store";
|
bindingSource="store";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const clearBinding = () => {
|
const clearBinding = () => {
|
||||||
forceIsBound = false;
|
forceIsBound = false;
|
||||||
onChanged("");
|
onChanged("");
|
||||||
}
|
|
||||||
|
|
||||||
const bind = (path, fallback, source) => {
|
|
||||||
if(!path) {
|
|
||||||
clearBinding("");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const binding = setBinding({path, fallback, source});
|
|
||||||
onChanged(binding);
|
|
||||||
}
|
|
||||||
|
|
||||||
const setBindingPath = ev => {
|
const bind = (path, fallback, source) => {
|
||||||
forceIsBound = canOnlyBind;
|
if(!path) {
|
||||||
bind(ev.target.value, bindingFallbackValue, bindingSource)
|
clearBinding("");
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
const binding = setBinding({path, fallback, source});
|
||||||
|
onChanged(binding);
|
||||||
|
}
|
||||||
|
|
||||||
const setBindingFallback = ev => {
|
const setBindingPath = ev => {
|
||||||
bind(bindingPath, ev.target.value, bindingSource);
|
forceIsBound = canOnlyBind;
|
||||||
}
|
bind(ev.target.value, bindingFallbackValue, bindingSource)
|
||||||
|
}
|
||||||
|
|
||||||
const setBindingSource = ev => {
|
const setBindingFallback = ev => {
|
||||||
bind(bindingPath, bindingFallbackValue, ev.target.value);
|
bind(bindingPath, ev.target.value, bindingSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
// const makeBinding = () => {
|
const setBindingSource = ev => {
|
||||||
// forceIsBound=true;
|
bind(bindingPath, bindingFallbackValue, ev.target.value);
|
||||||
// isExpanded=true;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if isBound}
|
{#if isBound}
|
||||||
<div>
|
<div>
|
||||||
<div class="bound-header">
|
<div class="bound-header">
|
||||||
<div>{isExpanded ? "" : bindingPath}</div>
|
<div>{isExpanded ? "" : bindingPath}</div>
|
||||||
<IconButton icon={isExpanded ? "chevron-up" : "chevron-down"}
|
<IconButton icon={isExpanded ? "chevron-up" : "chevron-down"}
|
||||||
size="12"
|
size="12"
|
||||||
on:click={() => isExpanded=!isExpanded}/>
|
on:click={() => isExpanded=!isExpanded}/>
|
||||||
{#if !canOnlyBind}
|
{#if !canOnlyBind}
|
||||||
<IconButton icon="trash"
|
<IconButton icon="trash"
|
||||||
size="12"
|
size="12"
|
||||||
on:click={clearBinding}/>
|
on:click={clearBinding}/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{#if isExpanded}
|
||||||
|
<div>
|
||||||
|
<div class="binding-prop-label">Binding Path</div>
|
||||||
|
<input class="uk-input uk-form-small"
|
||||||
|
value={bindingPath}
|
||||||
|
on:change={setBindingPath} >
|
||||||
|
<div class="binding-prop-label">Fallback Value</div>
|
||||||
|
<input class="uk-input uk-form-small"
|
||||||
|
value={bindingFallbackValue}
|
||||||
|
on:change={setBindingFallback} >
|
||||||
|
<div class="binding-prop-label">Binding Source</div>
|
||||||
|
<select class="uk-select uk-form-small"
|
||||||
|
value={bindingSource}
|
||||||
|
on:change={setBindingSource}>
|
||||||
|
|
||||||
|
<option>store</option>
|
||||||
|
<option>context</option>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{#if isExpanded}
|
|
||||||
<div>
|
|
||||||
<div class="binding-prop-label">Binding Path</div>
|
|
||||||
<input class="uk-input uk-form-small"
|
|
||||||
value={bindingPath}
|
|
||||||
on:change={setBindingPath} >
|
|
||||||
<div class="binding-prop-label">Fallback Value</div>
|
|
||||||
<input class="uk-input uk-form-small"
|
|
||||||
value={bindingFallbackValue}
|
|
||||||
on:change={setBindingFallback} >
|
|
||||||
<div class="binding-prop-label">Binding Source</div>
|
|
||||||
<select class="uk-select uk-form-small"
|
|
||||||
value={bindingSource}
|
|
||||||
on:change={setBindingSource}>
|
|
||||||
|
|
||||||
<option>store</option>
|
|
||||||
<option>context</option>
|
|
||||||
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{:else}
|
{:else}
|
||||||
<div class="unbound-container">
|
<div class="unbound-container">
|
||||||
|
|
||||||
{#if type === "bool"}
|
{#if type === "bool"}
|
||||||
|
<div>
|
||||||
|
<IconButton icon={value == true ? "check-square" : "square"}
|
||||||
|
size="19"
|
||||||
|
on:click={() => onChanged(!value)} />
|
||||||
|
</div>
|
||||||
|
{:else if type === "options"}
|
||||||
|
<select class="uk-select uk-form-small"
|
||||||
|
value={value}
|
||||||
|
on:change={ev => onChanged(ev.target.value)}>
|
||||||
|
{#each options as option}
|
||||||
|
<option value={option}>{option}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
{:else}
|
||||||
|
<input on:change={ev => onChanged(ev.target.value)}
|
||||||
|
bind:value={value}
|
||||||
|
style="flex: 1 0 auto;" />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div>
|
|
||||||
<IconButton icon={value == true ? "check-square" : "square"}
|
|
||||||
size="19"
|
|
||||||
on:click={() => onChanged(!value)} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{:else if type === "options"}
|
|
||||||
|
|
||||||
<select class="uk-select uk-form-small"
|
|
||||||
value={value}
|
|
||||||
on:change={ev => onChanged(ev.target.value)}>
|
|
||||||
{#each options as option}
|
|
||||||
<option value={option}>{option}</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
{:else}
|
|
||||||
|
|
||||||
<input on:change={ev => onChanged(ev.target.value)}
|
|
||||||
bind:value={value}
|
|
||||||
style="flex: 1 0 auto;" />
|
|
||||||
|
|
||||||
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
<script>
|
<script>
|
||||||
|
import ComponentsHierarchy from "./ComponentsHierarchy.svelte";
|
||||||
|
import PagesList from "./PagesList.svelte"
|
||||||
|
import { store } from "../builderStore";
|
||||||
|
import IconButton from "../common/IconButton.svelte";
|
||||||
|
import Modal from "../common/Modal.svelte";
|
||||||
|
import NewComponent from "./NewComponent.svelte";
|
||||||
|
import CurrentItemPreview from "./CurrentItemPreview.svelte";
|
||||||
|
import SettingsView from "./SettingsView.svelte";
|
||||||
|
import PageView from "./PageView.svelte";
|
||||||
|
import ComponentsPaneSwitcher from "./ComponentsPaneSwitcher.svelte";
|
||||||
|
|
||||||
import ComponentsHierarchy from "./ComponentsHierarchy.svelte";
|
let newComponentPicker;
|
||||||
import PagesList from "./PagesList.svelte"
|
|
||||||
import { store } from "../builderStore";
|
|
||||||
import getIcon from "../common/icon";
|
|
||||||
import { isComponent } from "./pagesParsing/searchComponents";
|
|
||||||
import IconButton from "../common/IconButton.svelte";
|
|
||||||
import Modal from "../common/Modal.svelte";
|
|
||||||
import NewComponent from "./NewComponent.svelte";
|
|
||||||
import CurrentItemPreview from "./CurrentItemPreview.svelte";
|
|
||||||
import SettingsView from "./SettingsView.svelte";
|
|
||||||
import PageView from "./PageView.svelte";
|
|
||||||
import ComponentsPaneSwitcher from "./ComponentsPaneSwitcher.svelte";
|
|
||||||
|
|
||||||
let newComponentPicker;
|
const newComponent = () => {
|
||||||
const newComponent = () => {
|
newComponentPicker.show();
|
||||||
newComponentPicker.show();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let settingsView;
|
|
||||||
const settings = () => {
|
|
||||||
settingsView.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let settingsView;
|
||||||
|
const settings = () => {
|
||||||
|
settingsView.show();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -44,11 +41,6 @@ const settings = () => {
|
||||||
|
|
||||||
<span class="components-nav-header">Screens</span>
|
<span class="components-nav-header">Screens</span>
|
||||||
<div>
|
<div>
|
||||||
<!-- <IconButton icon="settings"
|
|
||||||
size="14px"
|
|
||||||
on:click={settings}/> -->
|
|
||||||
<!-- <IconButton icon="plus"
|
|
||||||
on:click={newComponent}/> -->
|
|
||||||
<button on:click={newComponent}>+</button>
|
<button on:click={newComponent}>+</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -61,16 +53,16 @@ const settings = () => {
|
||||||
|
|
||||||
<div class="preview-pane">
|
<div class="preview-pane">
|
||||||
{#if $store.currentFrontEndType === "screen"}
|
{#if $store.currentFrontEndType === "screen"}
|
||||||
<CurrentItemPreview />
|
<CurrentItemPreview />
|
||||||
{:else if $store.currentFrontEndType === "page"}
|
{:else if $store.currentFrontEndType === "page"}
|
||||||
<PageView />
|
<PageView />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if $store.currentFrontEndType === "screen"}
|
{#if $store.currentFrontEndType === "screen"}
|
||||||
<div class="components-pane">
|
<div class="components-pane">
|
||||||
<ComponentsPaneSwitcher />
|
<ComponentsPaneSwitcher />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -81,109 +73,108 @@ const settings = () => {
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
button {
|
button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: var(--background-button);
|
background: var(--background-button);
|
||||||
|
|
||||||
width: 1.8rem;
|
width: 1.8rem;
|
||||||
height: 1.8rem;
|
height: 1.8rem;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--button-text);
|
color: var(--button-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 290px 1fr 300px;
|
grid-template-columns: 290px 1fr 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-nav {
|
.ui-nav {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
background-color: var(--secondary5);
|
background-color: var(--secondary5);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0 1.5rem 0rem 1.5rem
|
padding: 0 1.5rem 0rem 1.5rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-pane {
|
.preview-pane {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
margin: 80px 60px;
|
margin: 80px 60px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow: 0 0px 6px rgba(0,0,0,0.05)
|
box-shadow: 0 0px 6px rgba(0,0,0,0.05)
|
||||||
}
|
}
|
||||||
|
|
||||||
.components-pane {
|
.components-pane {
|
||||||
grid-column: 3;
|
grid-column: 3;
|
||||||
background-color: var(--secondary5);
|
background-color: var(--secondary5);
|
||||||
min-height: 0px;
|
min-height: 0px;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.components-nav-header {
|
.components-nav-header {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
color: #999;
|
color: #999;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header {
|
.nav-group-header {
|
||||||
font-size: .9rem;
|
font-size: .9rem;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-items-container {
|
.nav-items-container {
|
||||||
padding: 1rem 0rem 0rem 0rem;
|
padding: 1rem 0rem 0rem 0rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header {
|
.nav-group-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 2rem 0 0 0;
|
padding: 2rem 0 0 0;
|
||||||
font-size: .9rem;
|
font-size: .9rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header>div:nth-child(1) {
|
.nav-group-header>div:nth-child(1) {
|
||||||
padding: 0rem .5rem 0rem 0rem;
|
padding: 0rem .5rem 0rem 0rem;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
grid-column-start: icon;
|
grid-column-start: icon;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header>span:nth-child(2) {
|
.nav-group-header>span:nth-child(2) {
|
||||||
margin-left:5px;
|
margin-left:5px;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
grid-column-start: title;
|
grid-column-start: title;
|
||||||
margin-top:auto;
|
margin-top:auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header>div:nth-child(3) {
|
.nav-group-header>div:nth-child(3) {
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
grid-column-start: button;
|
grid-column-start: button;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: var(--primary75);
|
color: var(--primary75);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header>div:nth-child(3):hover {
|
.nav-group-header>div:nth-child(3):hover {
|
||||||
color: var(--primary75);
|
color: var(--primary75);
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigator-title {
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.navigator-title {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue