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"
import { filter, map, reduce, toPairs } from "lodash/fp"
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_if_number = suffix => s => {
try {
if (isNaN(s) || isNaN(parseFloat(s))) return s
} catch (_) {
return s
export const generate_screen_css = component_arr => {
let styles = ""
for (const { _styles, _id, _children, _component } of component_arr) {
let [componentName] = _component.match(/[a-z]*$/)
Object.keys(_styles).forEach(selector => {
const cssString = generate_css(_styles[selector])
if (cssString) {
styles += apply_class(_id, componentName, cssString, selector)
}
return s + suffix
}
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)
})
if (_children && _children.length) {
styles += generate_screen_css(_children) + "\n"
}
return acc.concat([[name, value]])
}
return styles.trim()
}
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 => {
// let cssString = pipe(style, object_to_css_string)
let cssString = Object.entries(style).reduce((str, [key, value]) => {
//TODO Handle arrays and objects here also
if (typeof value === "string") {
@ -130,23 +32,12 @@ export const generate_css = style => {
return (cssString || "").trim()
}
const apply_class = (id, name, styles) => `.${name}-${id} {\n${styles}\n}`
//USED IN MULTIPLE PLACES IN THE BUILDER STORE
export const generate_screen_css = component_array => {
let styles = ""
let emptyStyles = { normal: {}, hover: {}, active: {}, selected: {} }
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)
const apply_class = (id, name = "element", styles, selector) => {
if (selector === "normal") {
return `.${name}-${id} {\n${styles}\n}`
} else {
let sel = selector === "selected" ? "::selection" : `:${selector}`
return `.${name}-${id}${sel} {\n${styles}\n}`
}
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) => {
api
.post(`/_builder/api/${s.appId}/pages/${s.currentPageName}/screen`, screen)
.then(() => _savePage(s))
@ -427,8 +426,7 @@ const setComponentStyle = store => (type, name, value) => {
if (!state.currentComponentInfo._styles) {
state.currentComponentInfo._styles = {}
}
// state.currentComponentInfo._styles[type][name] = value
state.currentComponentInfo._styles[name] = value
state.currentComponentInfo._styles[type][name] = value
state.currentPreviewItem._css = generate_screen_css([
state.currentPreviewItem.props,

View File

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

View File

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

View File

@ -1,6 +1,7 @@
export default ({
styles,
stylesheetLinks,
selectedComponentType,
selectedComponentId,
frontendDefinition,
currentPageFunctions,
@ -11,7 +12,7 @@ export default ({
<style>
${styles || ""}
.element-${selectedComponentId} {
.${selectedComponentType}-${selectedComponentId} {
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
const handlevalueKey = value =>
props.valueKey ? { [props.valueKey]: value } : { value }
props.valueKey ? { [props.valueKey]: safeValue() } : { value: safeValue() }
</script>
<div class="property-control">

View File

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

View File

@ -1,7 +1,7 @@
import Input from "../common/Input.svelte"
import OptionSelect from "./OptionSelect.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
*/
@ -74,15 +74,16 @@ export const typography = [
label: "Font",
key: "font-family",
control: OptionSelect,
defaultValue: "initial",
options: [
{ label: "initial" },
{ label: "Times New Roman" },
{ label: "Georgia" },
{ label: "Arial" },
{ label: "Arial Black" },
{ label: "Comic Sans MS" },
{ label: "Impact" },
{ label: "Lucida Sans Unicode" },
"initial",
"Times New Roman",
"Georgia",
"Arial",
"Arial Black",
"Comic Sans MS",
"Impact",
"Lucida Sans Unicode",
],
styleBindingProperty: "font-family",
},
@ -97,12 +98,13 @@ export const typography = [
{ 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: "Color",
key: "color",
control: Colorpicker,
control: OptionSelect,
options: ["black", "white", "red", "blue", "green"],
},
{
label: "align",
@ -118,7 +120,8 @@ export const background = [
{
label: "Background",
key: "background",
control: Colorpicker,
control: OptionSelect,
options: ["black", "white", "red", "blue", "green"],
},
{ label: "Image", key: "image", control: Input }, //custom
]
@ -126,7 +129,10 @@ export const background = [
export const border = [
{ label: "Radius", key: "border-radius", control: Input },
{ 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 },
]

View File

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

View File

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