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
77fa60dae2
commit
aa4c7fa1c1
|
@ -6,6 +6,7 @@
|
|||
"build": "rollup -c",
|
||||
"start": "rollup -c -w",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watchAll",
|
||||
"dev:builder": "rollup -c -w"
|
||||
},
|
||||
"jest": {
|
||||
|
|
|
@ -11,34 +11,34 @@ import browsersync from "rollup-plugin-browsersync";
|
|||
import proxy from "http-proxy-middleware";
|
||||
|
||||
const target = 'http://localhost:4001';
|
||||
const _builderProxy = proxy('/_builder', {
|
||||
target:"http://localhost:3000",
|
||||
pathRewrite: {'^/_builder' : ''}
|
||||
const _builderProxy = proxy('/_builder', {
|
||||
target: "http://localhost:3000",
|
||||
pathRewrite: { '^/_builder': '' }
|
||||
});
|
||||
|
||||
const apiProxy = proxy(['/_builder/api/**', '/_builder/**/componentlibrary', '/_builder/**/componentlibraryGenerators'] , {
|
||||
const apiProxy = proxy(['/_builder/api/**', '/_builder/**/componentlibrary', '/_builder/**/componentlibraryGenerators'], {
|
||||
target,
|
||||
logLevel: "debug",
|
||||
changeOrigin: true,
|
||||
cookieDomainRewrite: true,
|
||||
onProxyReq(proxyReq) {
|
||||
if (proxyReq.getHeader("origin")) {
|
||||
proxyReq.setHeader("origin", target)
|
||||
}
|
||||
if (proxyReq.getHeader("origin")) {
|
||||
proxyReq.setHeader("origin", target)
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
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",
|
||||
"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",
|
||||
"toNumber", "takeRight"];
|
||||
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",
|
||||
"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",
|
||||
"toNumber", "takeRight", "toPairs"];
|
||||
|
||||
const lodash_exports = ["flow", "join", "replace", "trim", "dropRight", "takeRight", "head", "reduce",
|
||||
"tail", "startsWith", "findIndex", "merge",
|
||||
"assign", "each", "find", "orderBy", "union"];
|
||||
const lodash_exports = ["flow", "join", "replace", "trim", "dropRight", "takeRight", "head", "reduce",
|
||||
"tail", "startsWith", "findIndex", "merge",
|
||||
"assign", "each", "find", "orderBy", "union"];
|
||||
|
||||
const outputpath = "../server/builder";
|
||||
|
||||
|
@ -63,7 +63,7 @@ export default {
|
|||
{ src: 'src/favicon.png', dest: outputpath },
|
||||
{ src: 'src/assets', dest: outputpath },
|
||||
{ src: 'node_modules/@budibase/client/dist/budibase-client.esm.mjs', dest: outputpath },
|
||||
]
|
||||
]
|
||||
}),
|
||||
|
||||
svelte({
|
||||
|
@ -80,28 +80,28 @@ export default {
|
|||
resolve({
|
||||
browser: true,
|
||||
dedupe: importee => {
|
||||
return importee === 'svelte'
|
||||
|| importee.startsWith('svelte/')
|
||||
|| coreExternal.includes(importee);
|
||||
return importee === 'svelte'
|
||||
|| importee.startsWith('svelte/')
|
||||
|| coreExternal.includes(importee);
|
||||
}
|
||||
|
||||
|
||||
}),
|
||||
commonjs({
|
||||
namedExports: {
|
||||
"lodash/fp": lodash_fp_exports,
|
||||
"lodash":lodash_exports,
|
||||
"lodash": lodash_exports,
|
||||
"shortid": ["generate"]
|
||||
}
|
||||
}),
|
||||
url({
|
||||
limit: 0,
|
||||
include: ["**/*.woff2", "**/*.png"],
|
||||
limit: 0,
|
||||
include: ["**/*.woff2", "**/*.png"],
|
||||
fileName: "[dirname][name][extname]",
|
||||
emitFiles: true
|
||||
}),
|
||||
url({
|
||||
limit: 0,
|
||||
include: ["**/*.css"],
|
||||
limit: 0,
|
||||
include: ["**/*.css"],
|
||||
fileName: "[name][extname]",
|
||||
emitFiles: true
|
||||
}),
|
||||
|
@ -113,7 +113,7 @@ export default {
|
|||
!production && livereload(outputpath),
|
||||
!production && browsersync({
|
||||
server: outputpath,
|
||||
middleware: [apiProxy,_builderProxy]
|
||||
middleware: [apiProxy, _builderProxy]
|
||||
}),
|
||||
|
||||
// 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 {
|
||||
filter, cloneDeep, sortBy,
|
||||
map, last, keys, concat, keyBy,
|
||||
find, isEmpty, reduce, values, isEqual
|
||||
find, isEmpty, values,
|
||||
} from "lodash/fp";
|
||||
import {
|
||||
pipe, getNode, validate,
|
||||
|
@ -17,11 +17,13 @@ import api from "./api";
|
|||
import { isRootComponent, getExactComponent } from "../userInterface/pagesParsing/searchComponents";
|
||||
import { rename } from "../userInterface/pagesParsing/renameScreen";
|
||||
import {
|
||||
getNewComponentInfo, getScreenInfo, getComponentInfo
|
||||
getNewComponentInfo, getScreenInfo,
|
||||
} from "../userInterface/pagesParsing/createProps";
|
||||
import {
|
||||
loadLibs, loadLibUrls, loadGeneratorLibs
|
||||
} from "./loadComponentLibraries";
|
||||
import { uuid } from './uuid';
|
||||
import { generate_screen_css } from './generate_css';
|
||||
|
||||
let appname = "";
|
||||
|
||||
|
@ -710,7 +712,8 @@ const addChildComponent = store => component => {
|
|||
const component_definition = Object.assign(
|
||||
cloneDeep(newComponent.fullProps), {
|
||||
_component: component,
|
||||
_layout: {}
|
||||
_styles: { position: {}, layout: {} },
|
||||
_id: uuid()
|
||||
})
|
||||
|
||||
if (children) {
|
||||
|
@ -729,6 +732,8 @@ const addChildComponent = store => component => {
|
|||
|
||||
_saveScreen(store, s, s.currentFrontEndItem);
|
||||
|
||||
_saveScreen(store, s, s.currentFrontEndItem);
|
||||
|
||||
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 => {
|
||||
if (!s.currentComponentInfo._layout) {
|
||||
s.currentComponentInfo._layout = {};
|
||||
if (!s.currentComponentInfo._styles) {
|
||||
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(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 size = '';
|
||||
export let values = [];
|
||||
export let type = "number";
|
||||
export let onStyleChanged = () => {};
|
||||
|
||||
let _values = values.map(v => v);
|
||||
|
@ -11,7 +12,7 @@
|
|||
|
||||
<div class="inputs {size}">
|
||||
{#each meta as { placeholder }, i}
|
||||
<input type="number"
|
||||
<input {type}
|
||||
placeholder="{placeholder}"
|
||||
value={values[i]}
|
||||
on:input={(e) => _values[i] = e.target.value} />
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
<script>
|
||||
import { last } from "lodash/fp";
|
||||
import { pipe } from "../common/core";
|
||||
|
||||
export let components = [];
|
||||
export let currentComponent;
|
||||
export let onSelect = () => {};
|
||||
export let level = 0;
|
||||
|
||||
|
||||
const capitalise = s => s.substring(0,1).toUpperCase() + s.substring(1);
|
||||
const get_name = s => last(s.split('/'));
|
||||
const get_capitalised_name = name => pipe(name, [get_name,capitalise]);
|
||||
|
@ -38,18 +35,15 @@
|
|||
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;
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
import { pipe } from "../common/core";
|
||||
import { buildPropsHierarchy } from "./pagesParsing/buildPropsHierarchy";
|
||||
|
||||
let iframe;
|
||||
|
||||
$: iframe && console.log(iframe.contentDocument.head.insertAdjacentHTML('beforeend', '<style></style>'))
|
||||
$: hasComponent = !!$store.currentFrontEndItem;
|
||||
$: styles = hasComponent ? $store.currentFrontEndItem._css : '';
|
||||
|
||||
$: stylesheetLinks = pipe($store.pages.stylesheets, [
|
||||
map(s => `<link rel="stylesheet" href="${s}"/>`),
|
||||
|
@ -27,6 +31,7 @@
|
|||
{#if hasComponent}
|
||||
<iframe style="height: 100%; width: 100%"
|
||||
title="componentPreview"
|
||||
bind:this={iframe}
|
||||
srcdoc={
|
||||
`<html>
|
||||
|
||||
|
@ -45,6 +50,7 @@
|
|||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
}
|
||||
${styles}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -19,13 +19,16 @@
|
|||
const single = [{ placeholder: '' }];
|
||||
|
||||
|
||||
$: layout = componentInfo._layout;
|
||||
$: layout = { ...componentInfo._styles.position, ...componentInfo._styles.layout };
|
||||
|
||||
$: layouts = {
|
||||
templaterows: ['Grid Rows', single],
|
||||
templatecolumns: ['Grid Columns', single],
|
||||
};
|
||||
|
||||
$: positions = {
|
||||
gridarea: ['Grid Area', tbrl, 'small'],
|
||||
column: ['Column', se],
|
||||
row: ['Row', se],
|
||||
gap: ['Gap', single],
|
||||
};
|
||||
|
||||
$: spacing = {
|
||||
|
@ -41,15 +44,28 @@
|
|||
</script>
|
||||
|
||||
|
||||
<h3>Layout</h3>
|
||||
<h3>Styles</h3>
|
||||
|
||||
<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">
|
||||
{#each Object.entries(positions) as [key, [name, meta, size]]}
|
||||
<div class="grid">
|
||||
<h5>Grid Area:</h5>
|
||||
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
||||
<h5>{name}:</h5>
|
||||
<InputGroup onStyleChanged={_value => onStyleChanged('position',key, _value)}
|
||||
values={layout[key] || newValue(meta.length)}
|
||||
{meta}
|
||||
{size} />
|
||||
|
@ -61,8 +77,8 @@
|
|||
<div class="layout-spacing">
|
||||
{#each Object.entries(spacing) as [key, [name, meta, size]]}
|
||||
<div class="grid">
|
||||
<h5>Grid Area:</h5>
|
||||
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
||||
<h5>{name}:</h5>
|
||||
<InputGroup onStyleChanged={_value => onStyleChanged('position', key, _value)}
|
||||
values={layout[key] || newValue(meta.length)}
|
||||
{meta}
|
||||
{size} />
|
||||
|
@ -74,8 +90,8 @@
|
|||
<div class="layout-layer">
|
||||
{#each Object.entries(zindex) as [key, [name, meta, size]]}
|
||||
<div class="grid">
|
||||
<h5>Grid Area:</h5>
|
||||
<InputGroup onStyleChanged={_value => onStyleChanged(key, _value)}
|
||||
<h5>{name}:</h5>
|
||||
<InputGroup onStyleChanged={_value => onStyleChanged('position', key, _value)}
|
||||
values={layout[key] || newValue(meta.length)}
|
||||
{meta}
|
||||
{size} />
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
let errors = [];
|
||||
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));
|
||||
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
|
@ -27,6 +27,8 @@ export const _initialiseChildren = (initialiseOpts) =>
|
|||
htmlElement.removeChild(htmlElement.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
htmlElement.classList.add(`lay-${treeNode.props._id}`)
|
||||
|
||||
const renderedComponents = [];
|
||||
for(let childProps of childrenProps) {
|
||||
|
|
|
@ -23,6 +23,7 @@ export const renderComponent = ({
|
|||
const thisNode = createTreeNode();
|
||||
thisNode.context = componentContext;
|
||||
thisNode.parentNode = parentNode;
|
||||
thisNode.props = props;
|
||||
|
||||
parentNode.children.push(thisNode);
|
||||
renderedNodes.push(thisNode);
|
||||
|
@ -38,6 +39,10 @@ export const renderComponent = ({
|
|||
|
||||
thisNode.rootElement = htmlElement.children[
|
||||
htmlElement.children.length - 1];
|
||||
|
||||
if (initialProps._id) {
|
||||
thisNode.rootElement.classList.add(`pos-${initialProps._id}`)
|
||||
}
|
||||
}
|
||||
|
||||
if(func) {
|
||||
|
@ -51,6 +56,7 @@ export const renderComponent = ({
|
|||
|
||||
export const createTreeNode = () => ({
|
||||
context: {},
|
||||
props: {},
|
||||
rootElement: null,
|
||||
parentNode: null,
|
||||
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