48 builder frontend 2 (#76)
* Implement collapsing component hierarchy. * Save screen when adding new components. * Allow creation of nested child components. * Rename updateComponentProps to setComponentProps * Compile layout and position properties to css strings. * Correct ordering errors. * Compile the css for an entire screen. * Add unique id for each component. * Ignore _id props. * Update client to add correct class names to component elements. * Add grid-template fields to layout styling panel. * Inject css into iframe. Minor tweaks. * Fix unset margins. * Update failing tests.
This commit is contained in:
parent
3fedde9ad0
commit
5aa44a88a4
|
@ -6,6 +6,7 @@
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"start": "rollup -c -w",
|
"start": "rollup -c -w",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watchAll",
|
||||||
"dev:builder": "rollup -c -w"
|
"dev:builder": "rollup -c -w"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
|
|
|
@ -12,11 +12,11 @@ import proxy from "http-proxy-middleware";
|
||||||
|
|
||||||
const target = 'http://localhost:4001';
|
const target = 'http://localhost:4001';
|
||||||
const _builderProxy = proxy('/_builder', {
|
const _builderProxy = proxy('/_builder', {
|
||||||
target:"http://localhost:3000",
|
target: "http://localhost:3000",
|
||||||
pathRewrite: {'^/_builder' : ''}
|
pathRewrite: { '^/_builder': '' }
|
||||||
});
|
});
|
||||||
|
|
||||||
const apiProxy = proxy(['/_builder/api/**', '/_builder/**/componentlibrary', '/_builder/**/componentlibraryGenerators'] , {
|
const apiProxy = proxy(['/_builder/api/**', '/_builder/**/componentlibrary', '/_builder/**/componentlibraryGenerators'], {
|
||||||
target,
|
target,
|
||||||
logLevel: "debug",
|
logLevel: "debug",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
@ -26,19 +26,19 @@ const apiProxy = proxy(['/_builder/api/**', '/_builder/**/componentlibrary', '/
|
||||||
proxyReq.setHeader("origin", target)
|
proxyReq.setHeader("origin", target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const production = !process.env.ROLLUP_WATCH;
|
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", "isInteger", "isNumber", "isString", "isBoolean", "isDate", "isArray", "isObject", "clone", "values", "keyBy", "isNaN",
|
"take", "first", "intersection", "mapValues", "isNull", "has", "isInteger", "isNumber", "isString", "isBoolean", "isDate", "isArray", "isObject", "clone", "values", "keyBy", "isNaN",
|
||||||
"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", "isObjectLike", "flattenDeep", "indexOf", "isPlainObject",
|
"differenceBy", "intersectionBy", "isEqual", "max", "sortBy", "assign", "uniq", "trimChars", "trimCharsStart", "isObjectLike", "flattenDeep", "indexOf", "isPlainObject",
|
||||||
"toNumber", "takeRight"];
|
"toNumber", "takeRight", "toPairs"];
|
||||||
|
|
||||||
const lodash_exports = ["flow", "join", "replace", "trim", "dropRight", "takeRight", "head", "reduce",
|
const lodash_exports = ["flow", "join", "replace", "trim", "dropRight", "takeRight", "head", "reduce",
|
||||||
"tail", "startsWith", "findIndex", "merge",
|
"tail", "startsWith", "findIndex", "merge",
|
||||||
"assign", "each", "find", "orderBy", "union"];
|
"assign", "each", "find", "orderBy", "union"];
|
||||||
|
|
||||||
const outputpath = "../server/builder";
|
const outputpath = "../server/builder";
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ export default {
|
||||||
commonjs({
|
commonjs({
|
||||||
namedExports: {
|
namedExports: {
|
||||||
"lodash/fp": lodash_fp_exports,
|
"lodash/fp": lodash_fp_exports,
|
||||||
"lodash":lodash_exports,
|
"lodash": lodash_exports,
|
||||||
"shortid": ["generate"]
|
"shortid": ["generate"]
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -113,7 +113,7 @@ export default {
|
||||||
!production && livereload(outputpath),
|
!production && livereload(outputpath),
|
||||||
!production && browsersync({
|
!production && browsersync({
|
||||||
server: outputpath,
|
server: outputpath,
|
||||||
middleware: [apiProxy,_builderProxy]
|
middleware: [apiProxy, _builderProxy]
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// If we're building for production (npm run build
|
// If we're building for production (npm run build
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
import { filter, map, reduce, toPairs } from "lodash/fp";
|
||||||
|
import { pipe } from "../common/core";
|
||||||
|
|
||||||
|
const self = n => n;
|
||||||
|
const join_with = delimiter => a => a.join(delimiter);
|
||||||
|
const empty_string_to_unset = s => s.length ? s : "0";
|
||||||
|
const add_suffix = suffix => s => s + suffix;
|
||||||
|
|
||||||
|
export const make_margin = (values) => pipe(values, [
|
||||||
|
map(empty_string_to_unset),
|
||||||
|
map(add_suffix('px')),
|
||||||
|
join_with(' ')
|
||||||
|
]);
|
||||||
|
|
||||||
|
const tap = message => x => {
|
||||||
|
console.log(x);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
const css_map = {
|
||||||
|
templaterows: {
|
||||||
|
name: 'grid-template-columns',
|
||||||
|
generate: self
|
||||||
|
},
|
||||||
|
templatecolumns: {
|
||||||
|
name: 'grid-template-rows',
|
||||||
|
generate: self
|
||||||
|
},
|
||||||
|
gridarea: {
|
||||||
|
name: 'grid-area',
|
||||||
|
generate: make_margin
|
||||||
|
},
|
||||||
|
gap: {
|
||||||
|
name: 'grid-gap',
|
||||||
|
generate: n => `${n}px`
|
||||||
|
},
|
||||||
|
columnstart: {
|
||||||
|
name: 'grid-column-start',
|
||||||
|
generate: self
|
||||||
|
},
|
||||||
|
columnend: {
|
||||||
|
name: 'grid-column-end',
|
||||||
|
generate: self
|
||||||
|
},
|
||||||
|
rowstart: {
|
||||||
|
name: 'grid-row-start',
|
||||||
|
generate: self
|
||||||
|
},
|
||||||
|
rowend: {
|
||||||
|
name: 'grid-row-end',
|
||||||
|
generate: self
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
name: 'padding',
|
||||||
|
generate: make_margin
|
||||||
|
},
|
||||||
|
margin: {
|
||||||
|
name: 'margin',
|
||||||
|
generate: make_margin
|
||||||
|
},
|
||||||
|
zindex: {
|
||||||
|
name: 'z-index',
|
||||||
|
generate: self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generate_rule = ([name, values]) =>
|
||||||
|
`${css_map[name].name}: ${css_map[name].generate(values)};`
|
||||||
|
|
||||||
|
const handle_grid = (acc, [name, value]) => {
|
||||||
|
let tmp = [];
|
||||||
|
|
||||||
|
if (name === 'row' || name === 'column') {
|
||||||
|
if (value[0]) tmp.push([`${name}start`, value[0]]);
|
||||||
|
if (value[1]) tmp.push([`${name}end`, value[1]]);
|
||||||
|
return acc.concat(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc.concat([[name, value]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const object_to_css_string = [
|
||||||
|
toPairs,
|
||||||
|
reduce(handle_grid, []),
|
||||||
|
filter(v => Array.isArray(v[1]) ? v[1].some(s => s.length) : v[1].length),
|
||||||
|
map(generate_rule),
|
||||||
|
join_with('\n'),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const generate_css = ({ layout, position }) => {
|
||||||
|
let _layout = pipe(layout, object_to_css_string);
|
||||||
|
_layout = _layout.length ? _layout + "\ndisplay: grid;" : _layout;
|
||||||
|
|
||||||
|
return {
|
||||||
|
layout: _layout,
|
||||||
|
position: pipe(position, object_to_css_string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const apply_class = (id, name, styles) => `.${name}-${id} {\n${styles}\n}`;
|
||||||
|
|
||||||
|
export const generate_screen_css = (component_array) => {
|
||||||
|
let styles = "";
|
||||||
|
|
||||||
|
for (let i = 0; i < component_array.length; i += 1) {
|
||||||
|
const { _styles, _id, _children } = component_array[i];
|
||||||
|
const { layout, position } = generate_css(_styles);
|
||||||
|
|
||||||
|
styles += apply_class(_id, 'pos', position) + "\n";
|
||||||
|
styles += apply_class(_id, 'lay', layout) + "\n";
|
||||||
|
|
||||||
|
if (_children && _children.length) {
|
||||||
|
styles += generate_screen_css(_children) + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return styles.trim();
|
||||||
|
}
|
|
@ -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, isEqual
|
find, isEmpty, values,
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import {
|
import {
|
||||||
pipe, getNode, validate,
|
pipe, getNode, validate,
|
||||||
|
@ -17,11 +17,13 @@ import api from "./api";
|
||||||
import { isRootComponent, getExactComponent } from "../userInterface/pagesParsing/searchComponents";
|
import { isRootComponent, getExactComponent } from "../userInterface/pagesParsing/searchComponents";
|
||||||
import { rename } from "../userInterface/pagesParsing/renameScreen";
|
import { rename } from "../userInterface/pagesParsing/renameScreen";
|
||||||
import {
|
import {
|
||||||
getNewComponentInfo, getScreenInfo, getComponentInfo
|
getNewComponentInfo, getScreenInfo,
|
||||||
} from "../userInterface/pagesParsing/createProps";
|
} from "../userInterface/pagesParsing/createProps";
|
||||||
import {
|
import {
|
||||||
loadLibs, loadLibUrls, loadGeneratorLibs
|
loadLibs, loadLibUrls, loadGeneratorLibs
|
||||||
} from "./loadComponentLibraries";
|
} from "./loadComponentLibraries";
|
||||||
|
import { uuid } from './uuid';
|
||||||
|
import { generate_screen_css } from './generate_css';
|
||||||
|
|
||||||
let appname = "";
|
let appname = "";
|
||||||
|
|
||||||
|
@ -710,7 +712,8 @@ const addChildComponent = store => component => {
|
||||||
const component_definition = Object.assign(
|
const component_definition = Object.assign(
|
||||||
cloneDeep(newComponent.fullProps), {
|
cloneDeep(newComponent.fullProps), {
|
||||||
_component: component,
|
_component: component,
|
||||||
_layout: {}
|
_styles: { position: {}, layout: {} },
|
||||||
|
_id: uuid()
|
||||||
})
|
})
|
||||||
|
|
||||||
if (children) {
|
if (children) {
|
||||||
|
@ -729,6 +732,8 @@ const addChildComponent = store => component => {
|
||||||
|
|
||||||
_saveScreen(store, s, s.currentFrontEndItem);
|
_saveScreen(store, s, s.currentFrontEndItem);
|
||||||
|
|
||||||
|
_saveScreen(store, s, s.currentFrontEndItem);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -751,12 +756,13 @@ const setComponentProp = store => (name, value) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const setComponentStyle = store => (name, value) => {
|
const setComponentStyle = store => (type, name, value) => {
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
if (!s.currentComponentInfo._layout) {
|
if (!s.currentComponentInfo._styles) {
|
||||||
s.currentComponentInfo._layout = {};
|
s.currentComponentInfo._styles = {};
|
||||||
}
|
}
|
||||||
s.currentComponentInfo._layout[name] = value;
|
s.currentComponentInfo._styles[type][name] = value;
|
||||||
|
s.currentFrontEndItem._css = generate_screen_css(s.currentFrontEndItem.props._children)
|
||||||
|
|
||||||
// save without messing with the store
|
// save without messing with the store
|
||||||
_save(s.appname, s.currentFrontEndItem, store, s)
|
_save(s.appname, s.currentFrontEndItem, store, s)
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
export function uuid() {
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||||
|
const r = (Math.random() * 16) | 0,
|
||||||
|
v = c == 'x' ? r : (r & 0x3) | 0x8;
|
||||||
|
return v.toString(16);
|
||||||
|
});
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
export let meta = [];
|
export let meta = [];
|
||||||
export let size = '';
|
export let size = '';
|
||||||
export let values = [];
|
export let values = [];
|
||||||
|
export let type = "number";
|
||||||
export let onStyleChanged = () => {};
|
export let onStyleChanged = () => {};
|
||||||
|
|
||||||
let _values = values.map(v => v);
|
let _values = values.map(v => v);
|
||||||
|
@ -11,7 +12,7 @@
|
||||||
|
|
||||||
<div class="inputs {size}">
|
<div class="inputs {size}">
|
||||||
{#each meta as { placeholder }, i}
|
{#each meta as { placeholder }, i}
|
||||||
<input type="number"
|
<input {type}
|
||||||
placeholder="{placeholder}"
|
placeholder="{placeholder}"
|
||||||
value={values[i]}
|
value={values[i]}
|
||||||
on:input={(e) => _values[i] = e.target.value} />
|
on:input={(e) => _values[i] = e.target.value} />
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { last } from "lodash/fp";
|
import { last } from "lodash/fp";
|
||||||
import { pipe } from "../common/core";
|
import { pipe } from "../common/core";
|
||||||
|
|
||||||
export let components = [];
|
export let components = [];
|
||||||
export let currentComponent;
|
export let currentComponent;
|
||||||
export let onSelect = () => {};
|
export let onSelect = () => {};
|
||||||
export let level = 0;
|
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]);
|
||||||
|
@ -38,18 +35,15 @@
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 11px 67px;
|
padding: 11px 67px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item:hover {
|
.item:hover {
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
color: var(--button-text);
|
color: var(--button-text);
|
||||||
background: var(--background-button)!important;
|
background: var(--background-button)!important;
|
||||||
|
|
|
@ -4,7 +4,11 @@
|
||||||
import { pipe } from "../common/core";
|
import { pipe } from "../common/core";
|
||||||
import { buildPropsHierarchy } from "./pagesParsing/buildPropsHierarchy";
|
import { buildPropsHierarchy } from "./pagesParsing/buildPropsHierarchy";
|
||||||
|
|
||||||
|
let iframe;
|
||||||
|
|
||||||
|
$: iframe && console.log(iframe.contentDocument.head.insertAdjacentHTML('beforeend', '<style></style>'))
|
||||||
$: hasComponent = !!$store.currentFrontEndItem;
|
$: hasComponent = !!$store.currentFrontEndItem;
|
||||||
|
$: styles = hasComponent ? $store.currentFrontEndItem._css : '';
|
||||||
|
|
||||||
$: stylesheetLinks = pipe($store.pages.stylesheets, [
|
$: stylesheetLinks = pipe($store.pages.stylesheets, [
|
||||||
map(s => `<link rel="stylesheet" href="${s}"/>`),
|
map(s => `<link rel="stylesheet" href="${s}"/>`),
|
||||||
|
@ -27,6 +31,7 @@
|
||||||
{#if hasComponent}
|
{#if hasComponent}
|
||||||
<iframe style="height: 100%; width: 100%"
|
<iframe style="height: 100%; width: 100%"
|
||||||
title="componentPreview"
|
title="componentPreview"
|
||||||
|
bind:this={iframe}
|
||||||
srcdoc={
|
srcdoc={
|
||||||
`<html>
|
`<html>
|
||||||
|
|
||||||
|
@ -45,6 +50,7 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
${styles}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -19,13 +19,16 @@
|
||||||
const single = [{ placeholder: '' }];
|
const single = [{ placeholder: '' }];
|
||||||
|
|
||||||
|
|
||||||
$: layout = componentInfo._layout;
|
$: layout = { ...componentInfo._styles.position, ...componentInfo._styles.layout };
|
||||||
|
|
||||||
|
$: layouts = {
|
||||||
|
templaterows: ['Grid Rows', single],
|
||||||
|
templatecolumns: ['Grid Columns', single],
|
||||||
|
};
|
||||||
|
|
||||||
$: positions = {
|
$: positions = {
|
||||||
gridarea: ['Grid Area', tbrl, 'small'],
|
|
||||||
column: ['Column', se],
|
column: ['Column', se],
|
||||||
row: ['Row', se],
|
row: ['Row', se],
|
||||||
gap: ['Gap', single],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$: spacing = {
|
$: spacing = {
|
||||||
|
@ -41,15 +44,28 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<h3>Layout</h3>
|
<h3>Styles</h3>
|
||||||
|
|
||||||
<h4>Positioning</h4>
|
<h4>Positioning</h4>
|
||||||
|
<div class="layout-pos">
|
||||||
|
{#each Object.entries(layouts) as [key, [name, meta, size]]}
|
||||||
|
<div class="grid">
|
||||||
|
<h5>{name}:</h5>
|
||||||
|
<InputGroup onStyleChanged={_value => onStyleChanged('layout',key, _value)}
|
||||||
|
values={layout[key] || newValue(meta.length)}
|
||||||
|
{meta}
|
||||||
|
{size}
|
||||||
|
type="text"/>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4>Positioning</h4>
|
||||||
<div class="layout-pos">
|
<div class="layout-pos">
|
||||||
{#each Object.entries(positions) as [key, [name, meta, size]]}
|
{#each Object.entries(positions) as [key, [name, meta, size]]}
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<h5>Grid Area:</h5>
|
<h5>{name}:</h5>
|
||||||
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
<InputGroup onStyleChanged={_value => onStyleChanged('position',key, _value)}
|
||||||
values={layout[key] || newValue(meta.length)}
|
values={layout[key] || newValue(meta.length)}
|
||||||
{meta}
|
{meta}
|
||||||
{size} />
|
{size} />
|
||||||
|
@ -61,8 +77,8 @@
|
||||||
<div class="layout-spacing">
|
<div class="layout-spacing">
|
||||||
{#each Object.entries(spacing) as [key, [name, meta, size]]}
|
{#each Object.entries(spacing) as [key, [name, meta, size]]}
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<h5>Grid Area:</h5>
|
<h5>{name}:</h5>
|
||||||
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
<InputGroup onStyleChanged={_value => onStyleChanged('position', key, _value)}
|
||||||
values={layout[key] || newValue(meta.length)}
|
values={layout[key] || newValue(meta.length)}
|
||||||
{meta}
|
{meta}
|
||||||
{size} />
|
{size} />
|
||||||
|
@ -74,8 +90,8 @@
|
||||||
<div class="layout-layer">
|
<div class="layout-layer">
|
||||||
{#each Object.entries(zindex) as [key, [name, meta, size]]}
|
{#each Object.entries(zindex) as [key, [name, meta, size]]}
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<h5>Grid Area:</h5>
|
<h5>{name}:</h5>
|
||||||
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
<InputGroup onStyleChanged={_value => onStyleChanged('position', key, _value)}
|
||||||
values={layout[key] || newValue(meta.length)}
|
values={layout[key] || newValue(meta.length)}
|
||||||
{meta}
|
{meta}
|
||||||
{size} />
|
{size} />
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
let errors = [];
|
let errors = [];
|
||||||
let props = {};
|
let props = {};
|
||||||
|
|
||||||
const props_to_ignore = ['_component','_children', '_layout'];
|
const props_to_ignore = ['_component','_children', '_styles', '_id'];
|
||||||
|
|
||||||
$: propDefs = componentInfo && Object.entries(componentInfo).filter(([name])=> !props_to_ignore.includes(name));
|
$: propDefs = componentInfo && Object.entries(componentInfo).filter(([name])=> !props_to_ignore.includes(name));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,337 @@
|
||||||
|
import { generate_css, make_margin, generate_screen_css } from '../src/builderStore/generate_css.js';
|
||||||
|
|
||||||
|
describe('make_margin', () => {
|
||||||
|
test('it should generate a valid rule', () => {
|
||||||
|
expect(make_margin(["1", "1", "1", "1"])).toEqual('1px 1px 1px 1px')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('empty values should output 0', () => {
|
||||||
|
expect(make_margin(["1", "1", "", ""])).toEqual('1px 1px 0px 0px')
|
||||||
|
expect(make_margin(["1", "", "", "1"])).toEqual('1px 0px 0px 1px')
|
||||||
|
expect(make_margin(["", "", "", ""])).toEqual('0px 0px 0px 0px')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('generate_css', () => {
|
||||||
|
test('it should generate a valid css rule: grid-area', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ layout: { gridarea: ["", "", "", ""] } })
|
||||||
|
).toEqual({
|
||||||
|
layout: '',
|
||||||
|
position: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: grid-gap', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ layout: { gap: "10" } })
|
||||||
|
).toEqual({
|
||||||
|
layout: 'grid-gap: 10px;\ndisplay: grid;',
|
||||||
|
position: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: column 1', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { column: ["", ""] } }
|
||||||
|
)).toEqual({ layout: '', position: '' });
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: column 2', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { column: ["1", ""] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'grid-column-start: 1;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: column 3', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { column: ["", "1"] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'grid-column-end: 1;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: column 4', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { column: ["1", "1"] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'grid-column-start: 1;\ngrid-column-end: 1;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: row 1', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { row: ["", ""] } })
|
||||||
|
).toEqual({ layout: '', position: '' });
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: row 2', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { row: ["1", ""] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'grid-row-start: 1;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: row 3', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { row: ["", "1"] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'grid-row-end: 1;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: row 4', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { row: ["1", "1"] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'grid-row-start: 1;\ngrid-row-end: 1;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: padding 1', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { padding: ["1", "1", "1", "1"] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'padding: 1px 1px 1px 1px;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: padding 2', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { padding: ["1", "", "", "1"] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'padding: 1px 0px 0px 1px;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: margin 1', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { margin: ["1", "1", "1", "1"] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'margin: 1px 1px 1px 1px;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: margin 2', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { margin: ["1", "", "", "1"] } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'margin: 1px 0px 0px 1px;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: z-index 1', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { zindex: "" } })
|
||||||
|
).toEqual({
|
||||||
|
position: '',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should generate a valid css rule: z-index 2', () => {
|
||||||
|
expect(
|
||||||
|
generate_css({ position: { zindex: "1" } })
|
||||||
|
).toEqual({
|
||||||
|
position: 'z-index: 1;',
|
||||||
|
layout: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('generate_screen_css', () => {
|
||||||
|
test('it should compile the css for a list of components', () => {
|
||||||
|
const components = [
|
||||||
|
{
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 2
|
||||||
|
}, {
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 3
|
||||||
|
}
|
||||||
|
, {
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const compiled = `.pos-1 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-1 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-2 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-2 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-3 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-3 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-4 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-4 {
|
||||||
|
|
||||||
|
}`
|
||||||
|
|
||||||
|
expect(generate_screen_css(components)).toEqual(compiled)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it should compile the css for a list of components', () => {
|
||||||
|
const components = [
|
||||||
|
{
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 1,
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 2,
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 3,
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 4,
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 5,
|
||||||
|
_children: [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 6
|
||||||
|
}, {
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 7
|
||||||
|
}
|
||||||
|
, {
|
||||||
|
_styles: {
|
||||||
|
layout: { gridarea: ["", "", "", ""] },
|
||||||
|
position: { margin: ["1", "1", "1", "1"] }
|
||||||
|
},
|
||||||
|
_id: 8
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const compiled = `.pos-1 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-1 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-2 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-2 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-3 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-3 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-4 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-4 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-5 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-5 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-6 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-6 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-7 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-7 {
|
||||||
|
|
||||||
|
}
|
||||||
|
.pos-8 {
|
||||||
|
margin: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.lay-8 {
|
||||||
|
|
||||||
|
}`
|
||||||
|
|
||||||
|
expect(generate_screen_css(components)).toEqual(compiled)
|
||||||
|
})
|
||||||
|
})
|
|
@ -28,6 +28,8 @@ export const _initialiseChildren = (initialiseOpts) =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
htmlElement.classList.add(`lay-${treeNode.props._id}`)
|
||||||
|
|
||||||
const renderedComponents = [];
|
const renderedComponents = [];
|
||||||
for(let childProps of childrenProps) {
|
for(let childProps of childrenProps) {
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ export const renderComponent = ({
|
||||||
const thisNode = createTreeNode();
|
const thisNode = createTreeNode();
|
||||||
thisNode.context = componentContext;
|
thisNode.context = componentContext;
|
||||||
thisNode.parentNode = parentNode;
|
thisNode.parentNode = parentNode;
|
||||||
|
thisNode.props = props;
|
||||||
|
|
||||||
parentNode.children.push(thisNode);
|
parentNode.children.push(thisNode);
|
||||||
renderedNodes.push(thisNode);
|
renderedNodes.push(thisNode);
|
||||||
|
@ -38,6 +39,10 @@ export const renderComponent = ({
|
||||||
|
|
||||||
thisNode.rootElement = htmlElement.children[
|
thisNode.rootElement = htmlElement.children[
|
||||||
htmlElement.children.length - 1];
|
htmlElement.children.length - 1];
|
||||||
|
|
||||||
|
if (initialProps._id) {
|
||||||
|
thisNode.rootElement.classList.add(`pos-${initialProps._id}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(func) {
|
if(func) {
|
||||||
|
@ -51,6 +56,7 @@ export const renderComponent = ({
|
||||||
|
|
||||||
export const createTreeNode = () => ({
|
export const createTreeNode = () => ({
|
||||||
context: {},
|
context: {},
|
||||||
|
props: {},
|
||||||
rootElement: null,
|
rootElement: null,
|
||||||
parentNode: null,
|
parentNode: null,
|
||||||
children: [],
|
children: [],
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue