Completed CSS Selector Styling
This commit is contained in:
parent
0a745edfe4
commit
deab1adc31
|
@ -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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue