Completed CSS Selector Styling

This commit is contained in:
Conor_Mack 2020-05-25 15:23:56 +01:00
parent dd14dd6de2
commit d250d61c62
10 changed files with 65 additions and 154 deletions

View File

@ -1,119 +1,21 @@
import { pipe } from "components/common/core" export const generate_screen_css = component_arr => {
import { filter, map, reduce, toPairs } from "lodash/fp" let styles = ""
for (const { _styles, _id, _children, _component } of component_arr) {
const self = n => n let [componentName] = _component.match(/[a-z]*$/)
const join_with = delimiter => a => a.join(delimiter) Object.keys(_styles).forEach(selector => {
const empty_string_to_unset = s => (s.length ? s : "0") const cssString = generate_css(_styles[selector])
const add_suffix_if_number = suffix => s => { if (cssString) {
try { styles += apply_class(_id, componentName, cssString, selector)
if (isNaN(s) || isNaN(parseFloat(s))) return s }
} catch (_) { })
return s if (_children && _children.length) {
styles += generate_screen_css(_children) + "\n"
}
} }
return s + suffix return styles.trim()
} }
export const make_margin = values =>
pipe(values, [
map(empty_string_to_unset),
map(add_suffix_if_number("px")),
join_with(" "),
])
const css_map = {
templaterows: {
name: "grid-template-rows",
generate: self,
},
templatecolumns: {
name: "grid-template-columns",
generate: self,
},
align: {
name: "align-items",
generate: self,
},
justify: {
name: "justify-content",
generate: self,
},
direction: {
name: "flex-direction",
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,
},
height: {
name: "height",
generate: self,
},
width: {
name: "width",
generate: self,
},
}
//Only used here
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"),
]
//USED BY generate_screen_css
export const generate_css = style => { export const generate_css = style => {
// let cssString = pipe(style, object_to_css_string)
let cssString = Object.entries(style).reduce((str, [key, value]) => { let cssString = Object.entries(style).reduce((str, [key, value]) => {
//TODO Handle arrays and objects here also //TODO Handle arrays and objects here also
if (typeof value === "string") { if (typeof value === "string") {
@ -130,23 +32,12 @@ export const generate_css = style => {
return (cssString || "").trim() return (cssString || "").trim()
} }
const apply_class = (id, name, styles) => `.${name}-${id} {\n${styles}\n}` const apply_class = (id, name = "element", styles, selector) => {
if (selector === "normal") {
//USED IN MULTIPLE PLACES IN THE BUILDER STORE return `.${name}-${id} {\n${styles}\n}`
export const generate_screen_css = component_array => { } else {
let styles = "" let sel = selector === "selected" ? "::selection" : `:${selector}`
let emptyStyles = { normal: {}, hover: {}, active: {}, selected: {} } return `.${name}-${id}${sel} {\n${styles}\n}`
for (let i = 0; i < component_array.length; i += 1) {
const { _styles, _id, _children, _component } = component_array[i]
// let [componentName] = _component.match(/[a-z]*$/)
debugger
const cssString = generate_css(_styles || emptyStyles) || ""
if (cssString) {
styles += apply_class(_id, "element", cssString)
}
if (_children && _children.length) {
styles += generate_screen_css(_children) + "\n"
}
} }
return styles.trim()
} }

View File

@ -141,7 +141,6 @@ const _saveScreen = async (store, s, screen) => {
} }
const _saveScreenApi = (screen, s) => { const _saveScreenApi = (screen, s) => {
api api
.post(`/_builder/api/${s.appId}/pages/${s.currentPageName}/screen`, screen) .post(`/_builder/api/${s.appId}/pages/${s.currentPageName}/screen`, screen)
.then(() => _savePage(s)) .then(() => _savePage(s))
@ -427,8 +426,7 @@ const setComponentStyle = store => (type, name, value) => {
if (!state.currentComponentInfo._styles) { if (!state.currentComponentInfo._styles) {
state.currentComponentInfo._styles = {} state.currentComponentInfo._styles = {}
} }
// state.currentComponentInfo._styles[type][name] = value state.currentComponentInfo._styles[type][name] = value
state.currentComponentInfo._styles[name] = value
state.currentPreviewItem._css = generate_screen_css([ state.currentPreviewItem._css = generate_screen_css([
state.currentPreviewItem.props, state.currentPreviewItem.props,

View File

@ -21,7 +21,7 @@
<input <input
{type} {type}
placeholder={placeholder || ''} placeholder={placeholder || ''}
value={value[i] === 0 ? '' : value[i]} value={!value || value[i] === 0 ? '' : value[i]}
on:change={e => handleChange(e.target.value || 0, i)} /> on:change={e => handleChange(e.target.value || 0, i)} />
{/each} {/each}
</div> </div>

View File

@ -16,6 +16,11 @@
return props return props
} }
const getComponentTypeName = component => {
let [componentName] = component._component.match(/[a-z]*$/)
return componentName || "element"
}
$: iframe && $: iframe &&
console.log( console.log(
iframe.contentDocument.head.insertAdjacentHTML( iframe.contentDocument.head.insertAdjacentHTML(
@ -93,6 +98,8 @@
appRootPath: "", appRootPath: "",
} }
$: selectedComponentType = getComponentTypeName($store.currentComponentInfo)
$: selectedComponentId = $store.currentComponentInfo $: selectedComponentId = $store.currentComponentInfo
? $store.currentComponentInfo._id ? $store.currentComponentInfo._id
: "" : ""
@ -107,6 +114,7 @@
srcdoc={iframeTemplate({ srcdoc={iframeTemplate({
styles, styles,
stylesheetLinks, stylesheetLinks,
selectedComponentType,
selectedComponentId, selectedComponentId,
frontendDefinition: JSON.stringify(frontendDefinition), frontendDefinition: JSON.stringify(frontendDefinition),
currentPageFunctions: $store.currentPageFunctions, currentPageFunctions: $store.currentPageFunctions,

View File

@ -1,6 +1,7 @@
export default ({ export default ({
styles, styles,
stylesheetLinks, stylesheetLinks,
selectedComponentType,
selectedComponentId, selectedComponentId,
frontendDefinition, frontendDefinition,
currentPageFunctions, currentPageFunctions,
@ -11,7 +12,7 @@ export default ({
<style> <style>
${styles || ""} ${styles || ""}
.element-${selectedComponentId} { .${selectedComponentType}-${selectedComponentId} {
border: 2px solid #0055ff; border: 2px solid #0055ff;
} }

View File

@ -17,9 +17,15 @@
} }
} }
const safeValue = () => {
return value === undefined && props.defaultValue !== undefined
? props.defaultValue
: value
}
//Incase the component has a different value key name //Incase the component has a different value key name
const handlevalueKey = value => const handlevalueKey = value =>
props.valueKey ? { [props.valueKey]: value } : { value } props.valueKey ? { [props.valueKey]: safeValue() } : { value: safeValue() }
</script> </script>
<div class="property-control"> <div class="property-control">

View File

@ -13,6 +13,7 @@
const capitalize = name => name[0].toUpperCase() + name.slice(1) const capitalize = name => name[0].toUpperCase() + name.slice(1)
$: icon = show ? "ri-arrow-down-s-fill" : "ri-arrow-right-s-fill" $: icon = show ? "ri-arrow-down-s-fill" : "ri-arrow-right-s-fill"
$: style = componentInstance["_styles"][styleCategory] || {}
</script> </script>
<div class="property-group-container"> <div class="property-group-container">
@ -29,8 +30,8 @@
label={props.label} label={props.label}
control={props.control} control={props.control}
key={props.key} key={props.key}
value={componentInstance['_styles'][props.key]} value={style[props.key]}
onChange={(key, value) => onStyleChanged(name, key, value)} onChange={(key, value) => onStyleChanged(styleCategory, key, value)}
props={{ ...excludeProps(props, ['control', 'label']) }} /> props={{ ...excludeProps(props, ['control', 'label']) }} />
{/each} {/each}
</div> </div>

View File

@ -1,7 +1,7 @@
import Input from "../common/Input.svelte" import Input from "../common/Input.svelte"
import OptionSelect from "./OptionSelect.svelte" import OptionSelect from "./OptionSelect.svelte"
import InputGroup from "../common/Inputs/InputGroup.svelte" import InputGroup from "../common/Inputs/InputGroup.svelte"
import Colorpicker from "../common/Colorpicker.svelte" // import Colorpicker from "../common/Colorpicker.svelte"
/* /*
TODO: Allow for default values for all properties TODO: Allow for default values for all properties
*/ */
@ -74,15 +74,16 @@ export const typography = [
label: "Font", label: "Font",
key: "font-family", key: "font-family",
control: OptionSelect, control: OptionSelect,
defaultValue: "initial",
options: [ options: [
{ label: "initial" }, "initial",
{ label: "Times New Roman" }, "Times New Roman",
{ label: "Georgia" }, "Georgia",
{ label: "Arial" }, "Arial",
{ label: "Arial Black" }, "Arial Black",
{ label: "Comic Sans MS" }, "Comic Sans MS",
{ label: "Impact" }, "Impact",
{ label: "Lucida Sans Unicode" }, "Lucida Sans Unicode",
], ],
styleBindingProperty: "font-family", styleBindingProperty: "font-family",
}, },
@ -97,12 +98,13 @@ export const typography = [
{ label: "lighter" }, { label: "lighter" },
], ],
}, },
{ label: "size", key: "font-size", control: Input }, { label: "size", key: "font-size", defaultValue: "", control: Input },
{ label: "Line H", key: "line-height", control: Input }, { label: "Line H", key: "line-height", control: Input },
{ {
label: "Color", label: "Color",
key: "color", key: "color",
control: Colorpicker, control: OptionSelect,
options: ["black", "white", "red", "blue", "green"],
}, },
{ {
label: "align", label: "align",
@ -118,7 +120,8 @@ export const background = [
{ {
label: "Background", label: "Background",
key: "background", key: "background",
control: Colorpicker, control: OptionSelect,
options: ["black", "white", "red", "blue", "green"],
}, },
{ label: "Image", key: "image", control: Input }, //custom { label: "Image", key: "image", control: Input }, //custom
] ]
@ -126,7 +129,10 @@ export const background = [
export const border = [ export const border = [
{ label: "Radius", key: "border-radius", control: Input }, { label: "Radius", key: "border-radius", control: Input },
{ label: "Width", key: "border-width", control: Input }, //custom { label: "Width", key: "border-width", control: Input }, //custom
{ label: "Color", key: "border-color", control: Colorpicker }, {
label: "Color", key: "border-color", control: OptionSelect,
options: ["black", "white", "red", "blue", "green"]
},
{ label: "Style", key: "border-style", control: Input }, { label: "Style", key: "border-style", control: Input },
] ]

View File

@ -15,7 +15,6 @@
<link rel='stylesheet' href='/_builder/bundle.css'> <link rel='stylesheet' href='/_builder/bundle.css'>
<link rel='stylesheet' href='/_builder/fonts.css'> <link rel='stylesheet' href='/_builder/fonts.css'>
<link rel='stylesheet' href="/_builder/uikit.min.css"> <link rel='stylesheet' href="/_builder/uikit.min.css">
<link rel='stylesheet' href="/_builder/nano.min.css">
</head> </head>
<body id="app"> <body id="app">

View File

@ -35,8 +35,9 @@ export const prepareRenderComponent = ({
thisNode.rootElement = thisNode.rootElement =
htmlElement.children[htmlElement.children.length - 1] htmlElement.children[htmlElement.children.length - 1]
let [componentName] = props._component.match(/[a-z]*$/)
if (props._id && thisNode.rootElement) { if (props._id && thisNode.rootElement) {
thisNode.rootElement.classList.add(`element-${props._id}`) thisNode.rootElement.classList.add(`${componentName}-${props._id}`)
} }
} }
} }