Building components settings and refactoring

This commit is contained in:
Conor_Mack 2020-05-19 17:00:53 +01:00
parent 983a1c3718
commit 3cd48773d1
15 changed files with 227 additions and 408 deletions

View File

@ -87,6 +87,7 @@ const css_map = {
},
}
//Only used here
export const generate_rule = ([name, values]) =>
`${css_map[name].name}: ${css_map[name].generate(values)};`
@ -110,6 +111,7 @@ const object_to_css_string = [
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]) => {
@ -128,6 +130,7 @@ export const generate_css = style => {
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 = {}

View File

@ -46,9 +46,6 @@
? getProps($store.currentPreviewItem, ["name", "favicon"])
: getProps($store.currentPreviewItem, ["name", "description", "route"])
// const onStyleChanged = store.setComponentStyle
// const onStyleChanged = store.onStyleChanged
const onStyleChanged = store.setComponentStyle
const onPropChanged = store.setComponentProp
@ -87,14 +84,11 @@
<div class="component-props-container">
{#if selectedCategory.value === 'design'}
<DesignView
{panelDefinition}
{componentInstance}
{componentDefinition}
{onStyleChanged} />
<DesignView {panelDefinition} {componentInstance} {onStyleChanged} />
{:else if selectedCategory.value === 'settings'}
<SettingsView
{componentInstance}
{componentDefinition}
{panelDefinition}
onChange={onPropChanged} />
{/if}

View File

@ -16,12 +16,15 @@
const joinPath = join("/")
const normalizedName = name =>
pipe(name, [
trimCharsStart("./"),
trimCharsStart("~/"),
trimCharsStart("../"),
trimChars(" "),
])
pipe(
name,
[
trimCharsStart("./"),
trimCharsStart("~/"),
trimCharsStart("../"),
trimChars(" "),
]
)
const lastPartOfName = c => {
if (!c) return ""
@ -31,10 +34,10 @@
const isComponentSelected = (current, comp) => current === comp
$: _screens = pipe(screens, [
map(c => ({ component: c, title: lastPartOfName(c) })),
sortBy("title"),
])
$: _screens = pipe(
screens,
[map(c => ({ component: c, title: lastPartOfName(c) })), sortBy("title")]
)
const confirmDeleteComponent = component => {
componentToDelete = component
@ -42,6 +45,7 @@
}
const changeScreen = screen => {
debugger
store.setCurrentScreen(screen.title)
$goto(`./:page/${screen.title}`)
}

View File

@ -22,7 +22,11 @@
const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
const get_name = s => (!s ? "" : last(s.split("/")))
const get_capitalised_name = name => pipe(name, [get_name, capitalise])
const get_capitalised_name = name =>
pipe(
name,
[get_name, capitalise]
)
const moveDownComponent = component => {
const c = component
@ -33,6 +37,7 @@
const selectComponent = component => {
// Set current component
debugger
store.selectComponent(component)
// Get ID path

View File

@ -6,7 +6,10 @@
export let initialValue = ""
export let styleBindingProperty = ""
$: bindOptionToStyle = !!styleBindingProperty
const handleStyleBind = value =>
!!styleBindingProperty ? { style: `${styleBindingProperty}: ${value}` } : {}
$: isOptionsObject = options.every(o => typeof o === "object")
onMount(() => {
if (!value && !!initialValue) {
@ -19,15 +22,15 @@
class="uk-select uk-form-small"
{value}
on:change={ev => onChange(ev.target.value)}>
{#each options as { value, label }}
{#if bindOptionToStyle}
<option
style={`${styleBindingProperty}: ${value || label};`}
value={value || label}>
{#if isOptionsObject}
{#each options as { value, label }}
<option {...handleStyleBind(value || label)} value={value || label}>
{label}
</option>
{:else}
<option value={value || label}>{label}</option>
{/if}
{/each}
{/each}
{:else}
{#each options as value}
<option {...handleStyleBind(value)} {value}>{value}</option>
{/each}
{/if}
</select>

View File

@ -3,9 +3,20 @@
export let label = ""
export let control = null
export let key = ""
export let value = ""
export let valueType = ""
export let props = {}
export let onChange = () => {}
function handleChange(key, v) {
!!v.target
? onChange(name, key, valueType ? v.target[valueType] : v.target.value)
: onChange(name, key, v)
}
const handleValueType = value =>
valueType ? { [valueType]: value } : { value }
</script>
<div class="property-control">
@ -13,9 +24,9 @@
<div class="control">
<svelte:component
this={control}
{value}
on:change={onChange}
{onChange}
{...handleValueType(value)}
on:change={val => handleChange(key, val)}
onChange={val => handleChange(key, val)}
{...props} />
</div>
</div>

View File

@ -5,37 +5,21 @@
export let name = ""
export let properties = []
export let componentInstance = {}
export let componentDefinition = {}
export let onStyleChanged = () => {}
export let show = false
let showComponentGroup = false
const propExistsOnComponentDef = prop => prop in componentDefinition.props
const capitalize = name => name[0].toUpperCase() + name.slice(1)
function onChange(key, v) {
console.log("PROPERTY GROUP ON CHANGE")
!!v.target
? onStyleChanged(name, key, v.target.value)
: onStyleChanged(name, key, v)
}
$: {
let res = false
let componentProps = Object.keys(componentDefinition.props)
for (let prop in properties) {
if (componentProps.includes(prop)) {
showComponentGroup = true
}
if (showComponentGroup) break
}
}
$: icon = show ? "ri-arrow-down-s-fill" : "ri-arrow-right-s-fill"
</script>
<!-- {#if showComponentGroup} -->
<div class="property-group-container">
<div class="property-group-name" on:click={() => (show = !show)}>
<div class="icon">
@ -46,18 +30,16 @@
<div class="property-panel" class:show>
{#each properties as props}
<!-- {#if propExistsOnComponentDef(key)} -->
<PropertyControl
label={props.label}
control={props.control}
value={componentInstance[props.cssKey]}
onChange={value => onChange(props.cssKey, value)}
key={props.cssKey}
value={componentInstance['_styles'][props.cssKey]}
onChange={onStyleChanged}
props={{ ...excludeProps(props, ['control']) }} />
<!-- {/if} -->
{/each}
</div>
</div>
<!-- {/if} -->
<style>
.property-group-container {

View File

@ -3,33 +3,26 @@
import InputGroup from "../common/Inputs/InputGroup.svelte"
import { excludeProps } from "./propertyCategories.js"
export let panelDefinition = {}
export let panelDefinition = []
export let componentDefinition = {}
export let componentInstance = {}
export let onChange = () => {}
const propExistsOnComponentDef = prop => prop in componentDefinition.props
function handleChange(key, data) {
data.target ? onChange(key, data.target.value) : onChange(key, data)
}
const meta = [
{ placeholder: "T" },
{ placeholder: "R" },
{ placeholder: "B" },
{ placeholder: "L" },
]
$: settingsControls = !!panelDefinition ? Object.entries(panelDefinition) : []
</script>
<h4>Settings Panel</h4>
<InputGroup label="Testing" {meta} />
{#each settingsControls as [key, definition]}
<PropertyControl
control={definition.control}
label={key}
value={componentInstance[key]}
onChange={value => handleChange(key, value)}
props={{ ...excludeProps(definition, ['control']) }} />
{#each panelDefinition as definition}
{#if propExistsOnComponentDef(definition.key)}
<PropertyControl
control={definition.control}
label={definition.label}
key={definition.key}
value={componentInstance[definition.key]}
{onChange}
props={{ ...excludeProps(definition, ['control']) }} />
{/if}
{/each}

View File

@ -102,25 +102,13 @@ export const typography = [
label: "Color",
cssKey: "color",
control: OptionSelect,
options: [
{ label: "black" },
{ label: "red" },
{ label: "white" },
{ label: "blue" },
{ label: "green" },
],
options: ["black", "red", "white", "blue", "green"],
},
{
label: "align",
cssKey: "text-align",
control: OptionSelect,
options: [
{ label: "initial" },
{ label: "left" },
{ label: "right" },
{ label: "center" },
{ label: "justify" },
],
options: ["initial", "left", "right", "center", "justify"],
}, //custom
{ label: "transform", cssKey: "text-transform", control: Input }, //custom
{ label: "style", cssKey: "font-style", control: Input }, //custom

View File

@ -1,4 +1,6 @@
import Input from "../common/Input.svelte"
import OptionSelect from "./OptionSelect.svelte"
import Checkbox from "../common/Checkbox.svelte"
import { all } from "./propertyCategories.js"
@ -24,7 +26,31 @@ export default {
icon: "ri-layout-row-fill",
commonProps: {},
children: [],
properties: { design: { ...all } },
properties: {
design: { ...all },
settings: [
{
key: "type",
label: "Type",
control: OptionSelect,
options: [
{ label: "article" },
{ label: "aside" },
{ label: "details" },
{ label: "div" },
{ label: "figure" },
{ label: "figcaption" },
{ label: "footer" },
{ label: "header" },
{ label: "main" },
{ label: "mark" },
{ label: "nav" },
{ label: "paragraph" },
{ label: "summary" },
],
},
],
},
},
{
name: "Text",
@ -39,11 +65,19 @@ export default {
icon: "ri-heading",
properties: {
design: { ...all },
settings: {
text: {
settings: [
{
key: "text",
label: "Text",
control: Input,
},
},
{
key: "type",
label: "Type",
control: OptionSelect,
options: ["h1", "h2", "h3", "h4", "h5", "h6"],
},
],
},
},
{
@ -53,11 +87,31 @@ export default {
icon: "ri-paragraph",
properties: {
design: { ...all },
settings: {
text: {
settings: [
{
label: "Text",
key: "text",
control: Input,
},
},
{
label: "Type",
key: "type",
control: OptionSelect,
options: [
"none",
"bold",
"strong",
"italic",
"emphasis",
"mark",
"small",
"del",
"ins",
"sub",
"sup",
],
},
],
},
},
],
@ -74,21 +128,38 @@ export default {
description:
"A textfield component that allows the user to input text.",
icon: "ri-edit-box-line",
properties: { design: { ...all } },
properties: {
design: { ...all },
settings: [
{ label: "Label", key: "label", control: Input },
{
label: "Type",
key: "type",
control: OptionSelect,
options: ["text", "password"],
},
],
},
},
{
_component: "@budibase/standard-components/checkbox",
name: "Checkbox",
description: "A selectable checkbox component",
icon: "ri-checkbox-line",
properties: { design: { ...all } },
properties: {
design: { ...all },
settings: [{ label: "Label", key: "label", control: Input }],
},
},
{
_component: "@budibase/standard-components/radiobutton",
name: "Radiobutton",
description: "A selectable radiobutton component",
icon: "ri-radio-button-line",
properties: { design: { ...all } },
properties: {
design: { ...all },
settings: [{ label: "Label", key: "label", control: Input }],
},
},
{
_component: "@budibase/standard-components/select",
@ -96,7 +167,10 @@ export default {
description:
"A select component for choosing from different options",
icon: "ri-file-list-line",
properties: { design: { ...all } },
properties: {
design: { ...all },
settings: []
},
},
],
},
@ -106,7 +180,20 @@ export default {
description: "A basic html button that is ready for styling",
icon: "ri-radio-button-fill",
children: [],
properties: { design: { ...all } },
properties: {
design: {
...all
},
settings: [
{ label: "Text", key: "text", control: Input },
{
label: "Disabled",
key: "disabled",
valueType: "checked",
control: Checkbox,
},
]
},
},
{
_component: "@budibase/standard-components/icon",

View File

@ -23,35 +23,10 @@
"name": "Button",
"description": "an html <button />",
"props": {
"contentText": {
"type": "string",
"default": "Button"
},
"text": "string",
"className": "string",
"disabled": "bool",
"onClick": "event",
"background": "string",
"color": "string",
"border": "string",
"padding": "string",
"hoverColor": "string",
"hoverBackground": "string",
"hoverBorder": "string",
"fontFamily": {
"type": "options",
"default": "initial",
"styleBindingProperty": "font-family",
"options": [
"initial",
"Times New Roman",
"Georgia",
"Arial",
"Arial Black",
"Comic Sans MS",
"Impact",
"Lucida Sans Unicode"
]
}
"onClick": "event"
},
"tags": [
"layout"
@ -167,58 +142,7 @@
"children": false,
"props": {
"text": "string",
"color": "string",
"fontFamily": {
"type": "options",
"default": "initial",
"styleBindingProperty": "font-family",
"options": [
"initial",
"Times New Roman",
"Georgia",
"Arial",
"Arial Black",
"Comic Sans MS",
"Impact",
"Lucida Sans Unicode"
]
},
"fontSize": "string",
"textAlign": {
"type": "options",
"default": "inline",
"options": [
"left",
"center",
"right"
]
},
"verticalAlign": {
"type": "options",
"default": "inline",
"options": [
"top",
"middle",
"bottom"
]
},
"formattingTag": {
"type": "options",
"default": "none",
"options": [
"none",
"<b> - bold",
"<strong> - important",
"<i> - italic",
"<em> - emphasized",
"<mark> - marked text",
"<small> - small",
"<del> - deleted",
"<ins> - inserted",
"<sub> - subscript",
"<sup> - superscript"
]
}
"type": {"type": "string", "default": "none"}
},
"tags": [
"div",
@ -230,6 +154,7 @@
"description": "A component that allows the user to input text.",
"props": {
"label": "string",
"type": "string",
"value": "string",
"onchange": "event"
}
@ -383,27 +308,6 @@
"summary"
],
"default": "div"
},
"backgroundColor": "string",
"color": "string",
"height": "string",
"width": "string",
"borderWidth": "string",
"borderColor": "string",
"borderStyle": {
"type": "options",
"options": [
"none",
"solid",
"dotted",
"dashed",
"double",
"groove",
"ridge",
"inset",
"outset"
],
"default": "none"
}
},
"container": true,
@ -430,21 +334,6 @@
"h5",
"h6"
]
},
"fontFamily": {
"type": "options",
"default": "initial",
"styleBindingProperty": "font-family",
"options": [
"initial",
"Times New Roman",
"Georgia",
"Arial",
"Arial Black",
"Comic Sans MS",
"Impact",
"Lucida Sans Unicode"
]
}
},
"tags": []

View File

@ -1,58 +1,15 @@
<script>
import { cssVars, createClasses } from "./cssVars"
import { buildStyle } from "./buildStyle"
export let className = "default"
export let disabled = false
export let text
export let onClick
export let background
export let color
export let border
export let padding
export let hoverColor
export let hoverBackground
export let hoverBorder
export let fontFamily
export let _bb
let theButton
let cssVariables
let buttonStyles
let customHoverColorClass
let customHoverBorderClass
let customHoverBackClass
let customClasses = ""
$: if (_bb.props._children && _bb.props._children.length > 0)
theButton && _bb.attachChildren(theButton)
$: {
cssVariables = {
hoverColor,
hoverBorder,
hoverBackground,
background,
color,
border,
}
buttonStyles = buildStyle({
padding,
"font-family": fontFamily,
})
customClasses = createClasses({
hoverColor,
hoverBorder,
hoverBackground,
background,
border,
color,
})
}
const clickHandler = () => {
_bb.call(onClick)
}
@ -60,13 +17,12 @@
<button
bind:this={theButton}
use:cssVars={cssVariables}
class="{className}
{customClasses}"
disabled={disabled || false}
on:click={clickHandler}
style={buttonStyles}>
{#if !_bb.props._children || _bb.props._children.length === 0}{text}{/if}
on:click={clickHandler}>
{#if !_bb.props._children || _bb.props._children.length === 0}
{text}
{/if}
</button>
<style>

View File

@ -4,30 +4,12 @@
export let className = ""
export let onLoad
export let type = "div"
export let backgroundColor
export let color
export let width
export let height
export let borderWidth
export let borderColor
export let borderStyle
export let _bb
let containerElement
let hasLoaded
let currentChildren
$: cssVariables = {
backgroundColor,
color,
height,
width,
borderWidth,
borderColor,
borderStyle,
}
$: classes = `${createClasses(cssVariables)} ${className}`
$: {
if (containerElement) {
_bb.attachChildren(containerElement)
@ -40,95 +22,29 @@
</script>
{#if type === 'div'}
<div
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<div bind:this={containerElement} />
{:else if type === 'header'}
<header
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<header bind:this={containerElement} />
{:else if type === 'main'}
<main
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<main bind:this={containerElement} />
{:else if type === 'footer'}
<footer
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<footer bind:this={containerElement} />
{:else if type === 'aside'}
<aside
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<aside bind:this={containerElement} />
{:else if type === 'summary'}
<summary
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<summary bind:this={containerElement} />
{:else if type === 'details'}
<details
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<details bind:this={containerElement} />
{:else if type === 'article'}
<article
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<article bind:this={containerElement} />
{:else if type === 'nav'}
<nav
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<nav bind:this={containerElement} />
{:else if type === 'mark'}
<mark
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<mark bind:this={containerElement} />
{:else if type === 'figure'}
<figure
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<figure bind:this={containerElement} />
{:else if type === 'figcaption'}
<figcaption
class={classes}
bind:this={containerElement}
use:cssVars={cssVariables} />
<figcaption bind:this={containerElement} />
{:else if type === 'paragraph'}
<p class={classes} bind:this={containerElement} use:cssVars={cssVariables} />
<p bind:this={containerElement} />
{/if}
<style>
.backgroundColor {
background-color: var(--backgroundColor);
}
.color {
color: var(--color);
}
.height {
height: var(--height);
}
.width {
width: var(--width);
}
.borderColor {
border-color: var(--borderColor);
}
.borderWidth {
border-width: var(--borderWidth);
}
.borderStyle {
border-style: var(--borderStyle);
}
</style>

View File

@ -2,27 +2,25 @@
import { buildStyle } from "./buildStyle.js"
export let className = ""
export let type
export let _bb
export let text = ""
export let fontFamily = ""
export let color = ""
export let _bb
let containerElement
$: containerElement && !text && _bb.attachChildren(containerElement)
$: style = buildStyle({ "font-family": fontFamily, color })
</script>
{#if type === 'h1'}
<h1 class={className} {style} bind:this={containerElement}>{text}</h1>
<h1 class={className} bind:this={containerElement}>{text}</h1>
{:else if type === 'h2'}
<h2 class={className} {style} bind:this={containerElement}>{text}</h2>
<h2 class={className} bind:this={containerElement}>{text}</h2>
{:else if type === 'h3'}
<h3 class={className} {style} bind:this={containerElement}>{text}</h3>
<h3 class={className} bind:this={containerElement}>{text}</h3>
{:else if type === 'h4'}
<h4 class={className} {style} bind:this={containerElement}>{text}</h4>
<h4 class={className} bind:this={containerElement}>{text}</h4>
{:else if type === 'h5'}
<h5 class={className} {style} bind:this={containerElement}>{text}</h5>
<h5 class={className} bind:this={containerElement}>{text}</h5>
{:else if type === 'h6'}
<h6 class={className} {style} bind:this={containerElement}>{text}</h6>
<h6 class={className} bind:this={containerElement}>{text}</h6>
{/if}

View File

@ -4,45 +4,35 @@
export let text = ""
export let className = ""
export let formattingTag = ""
export let fontFamily = ""
export let fontSize = "1em"
export let textAlign = ""
export let verticalAlign = ""
export let color = ""
export let type = ""
export let _bb
const isTag = tag => (formattingTag || "").indexOf(tag) > -1
$: style = buildStyle({
"font-size": fontSize,
"font-family": fontFamily,
color,
})
const isTag = tag => type === tag
</script>
{#if isTag('none')}
<span {style}>{text}</span>
{:else if isTag('<b>')}
<b class={className} {style}>{text}</b>
{:else if isTag('<strong>')}
<strong class={className} {style}>{text}</strong>
{:else if isTag('<i>')}
<i class={className} {style}>{text}</i>
{:else if isTag('<em>')}
<em class={className} {style}>{text}</em>
{:else if isTag('<mark>')}
<mark class={className} {style}>{text}</mark>
{:else if isTag('<small>')}
<small class={className} {style}>{text}</small>
{:else if isTag('<del>')}
<del class={className} {style}>{text}</del>
{:else if isTag('<ins>')}
<ins class={className} {style}>{text}</ins>
{:else if isTag('<sub>')}
<sub class={className} {style}>{text}</sub>
{:else if isTag('<sup>')}
<sup class={className} {style}>{text}</sup>
{:else}{text}{/if}
<span>{text}</span>
{:else if isTag('bold')}
<b class={className}>{text}</b>
{:else if isTag('strong')}
<strong class={className}>{text}</strong>
{:else if isTag('italic')}
<i class={className}>{text}</i>
{:else if isTag('emphasis')}
<em class={className}>{text}</em>
{:else if isTag('mark')}
<mark class={className}>{text}</mark>
{:else if isTag('small')}
<small class={className}>{text}</small>
{:else if isTag('del')}
<del class={className}>{text}</del>
{:else if isTag('ins')}
<ins class={className}>{text}</ins>
{:else if isTag('sub')}
<sub class={className}>{text}</sub>
{:else if isTag('sup')}
<sup class={className}>{text}</sup>
{:else}
<span>{text}</span>
{/if}