Merge pull request #286 from Budibase/property-panel/components-from-design

Property panel components upgrade
This commit is contained in:
Conor_Mack 2020-06-02 11:22:52 +01:00 committed by GitHub
commit b977cbd9aa
18 changed files with 600 additions and 192 deletions

View File

@ -1,5 +1,3 @@
import { toNumber } from "lodash/fp"
export const generate_screen_css = component_arr => {
let styles = ""
for (const { _styles, _id, _children, _component } of component_arr) {
@ -19,16 +17,13 @@ export const generate_screen_css = component_arr => {
export const generate_css = style => {
let cssString = Object.entries(style).reduce((str, [key, value]) => {
//TODO Handle arrays and objects here also
if (typeof value === "string") {
if (value) {
return (str += `${key}: ${value};\n`)
}
} else if (Array.isArray(value)) {
if (value.length > 0 && !value.every(v => v === "")) {
return (str += `${key}: ${value
.map(generate_array_styles)
.join(" ")};\n`)
return (str += `${key}: ${value.join(" ")};\n`)
}
}
}, "")
@ -36,16 +31,6 @@ export const generate_css = style => {
return (cssString || "").trim()
}
export const generate_array_styles = item => {
let safeItem = item === "" ? 0 : item
let hasPx = new RegExp("px$")
if (!hasPx.test(safeItem) && !isNaN(toNumber(safeItem))) {
return `${safeItem}px`
} else {
return safeItem
}
}
export const apply_class = (id, name = "element", styles, selector) => {
if (selector === "normal") {
return `.${name}-${id} {\n${styles}\n}`

View File

@ -364,6 +364,7 @@ const addChildComponent = store => (componentToAdd, presetName) => {
/**
* @param {string} props - props to add, as child of current component
*/
const addTemplatedComponent = store => props => {
store.update(state => {
walkProps(props, p => {

View File

@ -1,29 +1,42 @@
<script>
import {onMount} from "svelte"
import { buildStyle } from "../../helpers.js"
export let value = ""
export let width = ""
export let textAlign = "left"
export let width = "160px"
export let placeholder = ""
let centerPlaceholder = textAlign === "center"
let style = { width }
let style = buildStyle({ width, textAlign })
</script>
<input type="text" style={`width: ${width};`} on:change bind:value />
<input class:centerPlaceholder type="text" {placeholder} {style} on:change bind:value />
<style>
input {
display: block;
font-size: 14px;
font-weight: 500;
color: var(--ink);
line-height: 1.3;
padding: 12px;
width: 164px;
max-width: 100%;
box-sizing: border-box;
margin: 0;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
background: #fff;
border: 1px solid var(--grey-dark);
/* width: 32px; */
height: 32px;
font-size: 12px;
font-weight: 700;
margin: 0px 0px 0px 1px;
color: var(--ink);
opacity: 0.7;
padding: 0px 4px;
line-height: 1.3;
/* padding: 12px; */
width: 164px;
box-sizing: border-box;
border: 1px solid var(--grey);
border-radius: 2px;
outline: none;
}
input::placeholder {
text-align: left;
}
.centerPlaceholder::placeholder {
text-align: center;
}
</style>

View File

@ -1,27 +1,35 @@
<script>
import { onMount } from "svelte"
import Input from "../Input.svelte"
export let meta = []
export let label = ""
export let value = [0, 0, 0, 0]
export let type = "text"
export let value = ["0", "0", "0", "0"]
export let suffix = ""
export let onChange = () => {}
function handleChange(val, idx) {
value.splice(idx, 1, val)
value.splice(idx, 1, suffix ? val + suffix : val)
value = value
onChange(value)
let _value = value.map(v => (!v.endsWith(suffix) ? v + suffix : v))
onChange(_value)
}
$: displayValues = value
? value.map(v => v.replace(new RegExp(`${suffix}$`), ""))
: []
</script>
<div class="input-container">
<div class="label">{label}</div>
<div class="inputs">
{#each meta as { placeholder }, i}
<input
{type}
placeholder={placeholder || ''}
value={!value || value[i] === 0 ? '' : value[i]}
<div class="inputs-group">
{#each meta as m, i}
<Input
width="32px"
textAlign="center"
placeholder={m.placeholder || ''}
value={!displayValues || displayValues[i] === '0' ? '' : displayValues[i]}
on:change={e => handleChange(e.target.value || 0, i)} />
{/each}
</div>
@ -32,39 +40,8 @@
flex: 0;
}
.inputs {
.inputs-group {
flex: 1;
}
input {
width: 40px;
height: 32px;
font-size: 12px;
font-weight: 700;
margin: 0px 0px 0px 1px;
text-align: center;
color: var(--ink);
opacity: 0.7;
padding: 0px 4px;
box-sizing: border-box;
border: 1px solid var(--grey);
border-radius: 2px;
outline: none;
}
input[type="text"]::-webkit-inner-spin-button,
input[type="text"]::-webkit-outer-spin-button {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
margin: 0;
}
input[type="text"] {
-moz-appearance: textfield;
}
input::placeholder {
text-align: center;
}
</style>

View File

@ -106,10 +106,12 @@
height: 100%;
display: flex;
flex-direction: column;
/* Merge Check */
overflow-x: hidden;
overflow-y: hidden;
padding: 20px;
box-sizing: border-box;
/* Merge Check */
}
.title > div:nth-child(1) {

View File

@ -54,7 +54,7 @@
height: 100%;
display: flex;
flex-direction: column;
padding: 20px 20px;
padding: 20px 5px 20px 10px;
border-left: solid 1px var(--grey);
}
@ -78,4 +78,8 @@
.switcher > .selected {
color: var(--ink);
}
.panel {
height: 100%;
}
</style>

View File

@ -55,6 +55,7 @@
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.design-view-state-categories {
@ -63,6 +64,9 @@
.design-view-property-groups {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
max-height: 500px;
}
.no-design {

View File

@ -1,21 +1,26 @@
<script>
import {buildStyle} from "../../helpers.js"
export let value = ""
export let text = ""
export let icon = ""
export let padding = "8px 5px;"
export let onClick = value => {}
export let selected = false
export let fontWeight = ""
$: style = buildStyle({padding, fontWeight})
$: useIcon = !!icon
</script>
<div class="flatbutton" class:selected on:click={() => onClick(value || text)}>
<div class="flatbutton" {style} class:selected on:click={() => onClick(value || text)}>
{#if useIcon}
<i class={icon} />
{:else}
<span>{text}</span>
<span>{@html text}</span>
{/if}
</div>
<style>
.flatbutton {
cursor: pointer;
@ -28,6 +33,7 @@
font-size: 14px;
font-weight: 400;
transition: all 0.3s;
margin-left: 5px;
text-rendering: optimizeLegibility;
}
@ -35,4 +41,8 @@
background: var(--ink-light);
color: #ffffff;
}
i{
font-size: 20px;
}
</style>

View File

@ -27,13 +27,18 @@
}
onChange(val)
}
const checkSelected = val =>
isMultiSelect ? value.includes(val) : value === val
</script>
<div class="flatbutton-group">
{#each buttonProps as props}
<div class="button-container">
<FlatButton
selected={value.includes(props.value)}
selected={isMultiSelect ? value.includes(props.value) : value === props.value}
onClick={onButtonClicked}
{...props} />
</div>

View File

@ -1,36 +1,223 @@
<script>
import { onMount } from "svelte"
export let value = ""
export let onChange = value => {}
import { onMount, beforeUpdate } from "svelte"
import {buildStyle} from "../../helpers.js"
export let options = []
export let initialValue = ""
export let styleBindingProperty = ""
export let value = ""
export let styleBindingProperty
export let onChange = value => {}
let open = null
let rotate = ""
let select
let selectMenu
let icon
let selectYPosition = null
let availableSpace = 0
let positionSide = "top"
let maxHeight = null
let menuHeight
const handleStyleBind = value =>
!!styleBindingProperty ? { style: `${styleBindingProperty}: ${value}` } : {}
$: isOptionsObject = options.every(o => typeof o === "object")
onMount(() => {
if (!value && !!initialValue) {
value = initialValue
if (select) {
select.addEventListener("keydown", addSelectKeyEvents)
}
return () => {
select.removeEventListener("keydown", addSelectKeyEvents)
}
})
function checkPosition() {
const { bottom, top: spaceAbove } = select.getBoundingClientRect()
const spaceBelow = window.innerHeight - bottom
if (spaceAbove > spaceBelow) {
positionSide = "bottom"
maxHeight = `${spaceAbove.toFixed(0) - 20}px`
} else {
positionSide = "top"
maxHeight = `${spaceBelow.toFixed(0) - 20}px`
}
}
function addSelectKeyEvents(e) {
if (e.key === "Enter") {
if (!open) {
toggleSelect(true)
}
} else if (e.key === "Escape") {
if (open) {
toggleSelect(false)
}
}
}
function toggleSelect(isOpen) {
checkPosition()
if (isOpen) {
icon.style.transform = "rotate(180deg)"
} else {
icon.style.transform = "rotate(0deg)"
}
open = isOpen
}
function handleClick(val) {
value = val
onChange(value)
}
$: menuStyle = buildStyle({
"max-height": maxHeight,
"transform-origin": `center ${positionSide}`,
[positionSide]: "32px",
})
$: isOptionsObject = options.every(o => typeof o === "object")
$: selectedOption = isOptionsObject
? options.find(o => o.value === value)
: {}
$: displayLabel =
selectedOption && selectedOption.label ? selectedOption.label : value || ""
</script>
<select
class="uk-select uk-form-small"
{value}
on:change={ev => onChange(ev.target.value)}>
{#if isOptionsObject}
{#each options as { value, label }}
<option {...handleStyleBind(value || label)} value={value || label}>
{label}
</option>
{/each}
{:else}
{#each options as value}
<option {...handleStyleBind(value)} {value}>{value}</option>
{/each}
{/if}
</select>
<div
tabindex="0"
bind:this={select}
class="bb-select-container"
on:click={() => toggleSelect(!open)}>
<div class="bb-select-anchor selected">
<span>{displayLabel}</span>
<i bind:this={icon} class="ri-arrow-down-s-fill" />
</div>
<div
bind:this={selectMenu}
style={menuStyle}
class="bb-select-menu"
class:open>
<ul>
{#if isOptionsObject}
{#each options as { value: v, label }}
<li
{...handleStyleBind(v)}
on:click|self={handleClick(v)}
class:selected={value === v}>
{label}
</li>
{/each}
{:else}
{#each options as v}
<li
{...handleStyleBind(v)}
on:click|self={handleClick(v)}
class:selected={value === v}>
{v}
</li>
{/each}
{/if}
</ul>
</div>
</div>
{#if open}
<div on:click|self={() => toggleSelect(false)} class="overlay" />
{/if}
<style>
.overlay {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: 1;
}
.bb-select-container {
position: relative;
outline: none;
width: 160px;
height: 32px;
cursor: pointer;
font-size: 12px;
}
.bb-select-anchor {
cursor: pointer;
display: flex;
padding: 5px 10px;
background-color: #f2f2f2;
border-radius: 2px;
border: 1px solid var(--grey-dark);
align-items: center;
}
.bb-select-anchor > span {
color: #565a66;
font-weight: 500;
width: 140px;
overflow-x: hidden;
}
.bb-select-anchor > i {
transition: transform 0.13s ease;
transform-origin: center;
width: 20px;
height: 20px;
text-align: center;
}
.selected {
color: #565a66;
font-weight: 500;
}
.bb-select-menu {
position: absolute;
display: flex;
box-sizing: border-box;
flex-direction: column;
opacity: 0;
width: 160px;
z-index: 2;
color: #808192;
font-weight: 500;
height: fit-content !important;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
border-right: 1px solid var(--grey-dark);
border-left: 1px solid var(--grey-dark);
border-bottom: 1px solid var(--grey-dark);
background-color: #f2f2f2;
transform: scale(0);
transition: opacity 0.13s linear, transform 0.12s cubic-bezier(0, 0, 0.2, 1);
overflow-y: auto;
}
.open {
transform: scale(1);
opacity: 1;
}
ul {
list-style-type: none;
margin: 0;
padding: 5px 0px;
}
li {
height: auto;
padding: 5px 0px;
cursor: pointer;
padding-left: 10px
}
li:hover {
background-color:#e6e6e6
}
</style>

View File

@ -0,0 +1,33 @@
<script>
import { onMount } from "svelte"
export let value = ""
export let onChange = value => {}
export let options = []
export let initialValue = ""
export let styleBindingProperty = ""
const handleStyleBind = value =>
!!styleBindingProperty ? { style: `${styleBindingProperty}: ${value}` } : {}
$: isOptionsObject = options.every(o => typeof o === "object")
onMount(() => {
if (!value && !!initialValue) {
value = initialValue
}
})
</script>
<select {value} on:change={ev => onChange(ev.target.value)}>
{#if isOptionsObject}
{#each options as { value, label }}
<option {...handleStyleBind(value || label)} value={value || label}>
{label}
</option>
{/each}
{:else}
{#each options as value}
<option {...handleStyleBind(value)} {value}>{value}</option>
{/each}
{/if}
</select>

View File

@ -50,6 +50,9 @@
.label {
flex: 0 0 50px;
display: flex;
align-items: center;
padding: 0px 5px;
font-size: 12px;
font-weight: 400;
text-align: left;
@ -60,6 +63,7 @@
.control {
flex: 1;
display: flex;
padding-left: 2px;
max-width: 164px;
}

View File

@ -71,12 +71,16 @@
}
.property-panel {
height: 0px;
overflow: hidden;
/* height: 0px;
overflow: hidden; */
display: none;
}
.show {
overflow: auto;
height: auto;
/* overflow: auto;
height: auto; */
display: flex;
flex-direction: column;
flex: 1;
}
</style>

View File

@ -123,8 +123,7 @@
.components-pane {
grid-column: 3;
background-color: var(--white);
height: 100vh;
overflow-y: scroll;
height: calc(100vh - 49px);
}
.components-nav-page {

View File

@ -1,6 +1,7 @@
import Input from "../common/Input.svelte"
import OptionSelect from "./OptionSelect.svelte"
import InputGroup from "../common/Inputs/InputGroup.svelte"
import FlatButtonGroup from "./FlatButtonGroup.svelte"
// import Colorpicker from "../common/Colorpicker.svelte"
/*
TODO: Allow for default values for all properties
@ -11,9 +12,8 @@ export const layout = [
label: "Display",
key: "display",
control: OptionSelect,
initialValue: "Select Option",
initialValue: "Flex",
options: [
{ label: "Select Option", value: "" },
{ label: "Flex", value: "flex" },
{ label: "Inline Flex", value: "inline-flex" },
],
@ -21,23 +21,24 @@ export const layout = [
{
label: "Direction",
key: "flex-direction",
control: OptionSelect,
initialValue: "Select Option",
options: [
{ label: "Select Option", value: "" },
{ label: "Row", value: "row" },
{ label: "Row Reverse", value: "rowReverse" },
{ label: "Column", value: "column" },
{ label: "Column Reverse", value: "columnReverse" },
control: FlatButtonGroup,
buttonProps: [
{ icon: "ri-arrow-right-line", padding: "0px 5px", value: "row" },
{ icon: "ri-arrow-left-line", padding: "0px 5px", value: "rowReverse" },
{ icon: "ri-arrow-down-line", padding: "0px 5px", value: "column" },
{
icon: "ri-arrow-up-line",
padding: "0px 5px",
value: "columnReverse",
},
],
},
{
label: "Justify",
key: "justify-content",
control: OptionSelect,
initialValue: "Select Option",
initialValue: "Flex Start",
options: [
{ label: "Select Option", value: "" },
{ label: "Flex Start", value: "flex-start" },
{ label: "Flex End", value: "flex-end" },
{ label: "Center", value: "center" },
@ -50,9 +51,8 @@ export const layout = [
label: "Align",
key: "align-items",
control: OptionSelect,
initialValue: "Select Option",
initialValue: "Flex Start",
options: [
{ label: "Select Option", value: "" },
{ label: "Flex Start", value: "flex-start" },
{ label: "Flex End", value: "flex-end" },
{ label: "Center", value: "center" },
@ -64,12 +64,9 @@ export const layout = [
label: "Wrap",
key: "flex-wrap",
control: OptionSelect,
initialValue: "Select Option",
options: [
{ label: "Select Option", value: "" },
{ label: "No Wrap", value: "nowrap" },
{ label: "Wrap", value: "wrap" },
{ label: "Wrap Reverse", value: "wrap-reverse" },
{ label: "wrap", value: "wrap" },
{ label: "no wrap", value: "noWrap" },
],
},
]
@ -82,22 +79,73 @@ const spacingMeta = [
]
export const spacing = [
{ label: "Margin", key: "margin", control: InputGroup, meta: spacingMeta },
{
label: "Margin",
key: "margin",
control: InputGroup,
meta: spacingMeta,
suffix: "px",
defaultValue: ["0", "0", "0", "0"],
},
{
label: "Padding",
key: "padding",
control: InputGroup,
meta: spacingMeta,
suffix: "px",
defaultValue: ["0", "0", "0", "0"],
},
]
export const size = [
{ label: "Width", key: "width", control: Input },
{ label: "Height", key: "height", control: Input },
{ label: "Min W", key: "min-width", control: Input },
{ label: "Min H", key: "min-height", control: Input },
{ label: "Max W", key: "max-width", control: Input },
{ label: "Max H", key: "max-height", control: Input },
{
label: "Width",
key: "width",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Height",
key: "height",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Min W",
key: "min-width",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Min H",
key: "min-height",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Max W",
key: "max-width",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Max H",
key: "max-height",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
]
export const position = [
@ -118,26 +166,41 @@ export const position = [
label: "Top",
key: "top",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Right",
key: "right",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Bottom",
key: "bottom",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Left",
key: "left",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Z-index",
key: "z-index",
control: Input,
placeholder: "num",
width: "48px",
textAlign: "center",
},
]
@ -171,47 +234,59 @@ export const typography = [
label: "Weight",
key: "font-weight",
control: OptionSelect,
options: [
{ label: "100", value: "100" },
{ label: "200", value: "200" },
{ label: "300", value: "300" },
{ label: "400", value: "400" },
{ label: "500", value: "500" },
{ label: "600", value: "600" },
{ label: "700", value: "700" },
{ label: "800", value: "800" },
{ label: "900", value: "900" },
],
options: ["normal", "bold", "bolder", "lighter"],
},
{
label: "size",
key: "font-size",
defaultValue: "",
control: Input,
placeholder: "px",
width: "48px",
textAlign: "center",
},
{
label: "Line H",
key: "line-height",
control: Input,
placeholder: "lh",
width: "48px",
textAlign: "center",
},
{ label: "size", key: "font-size", defaultValue: "", control: Input },
{ label: "Line H", key: "line-height", control: Input },
{
label: "Color",
key: "color",
control: Input,
placeholder: "hex",
},
{
label: "align",
key: "text-align",
control: OptionSelect,
options: ["initial", "left", "right", "center", "justify"],
}, //custom
{
label: "Decoration",
key: "text-decoration-line",
control: OptionSelect,
defaultValue: "None",
options: [
{ label: "None", value: "none" },
{ label: "Underline", value: "underline" },
{ label: "Overline", value: "overline" },
{ label: "Line-through", value: "line-through" },
{ label: "Under Over", value: "underline overline" },
control: FlatButtonGroup,
buttonProps: [
{ icon: "ri-align-left", padding: "0px 5px", value: "left" },
{ icon: "ri-align-center", padding: "0px 5px", value: "center" },
{ icon: "ri-align-right", padding: "0px 5px", value: "right" },
{ icon: "ri-align-justify", padding: "0px 5px", value: "justify" },
],
},
{ label: "transform", key: "text-transform", control: Input }, //custom
{ label: "style", key: "font-style", control: Input }, //custom
{
label: "transform",
key: "text-transform",
control: FlatButtonGroup,
buttonProps: [
{ text: "BB", padding: "0px 5px", fontWeight: 500, value: "uppercase" },
{ text: "Bb", padding: "0px 5px", fontWeight: 500, value: "capitalize" },
{ text: "bb", padding: "0px 5px", fontWeight: 500, value: "lowercase" },
{
text: "&times;",
padding: "0px 5px",
fontWeight: 500,
value: "none",
},
],
},
{ label: "style", key: "font-style", control: Input },
]
export const background = [
@ -220,12 +295,31 @@ export const background = [
key: "background",
control: Input,
},
{ label: "Image", key: "image", control: Input }, //custom
{
label: "Image",
key: "background-image",
control: Input,
placeholder: "src",
},
]
export const border = [
{ label: "Radius", key: "border-radius", control: Input },
{ label: "Width", key: "border-width", control: Input }, //custom
{
label: "Radius",
key: "border-radius",
control: Input,
width: "48px",
placeholder: "px",
textAlign: "center",
},
{
label: "Width",
key: "border-width",
control: Input,
width: "48px",
placeholder: "px",
textAlign: "center",
}, //custom
{
label: "Color",
key: "border-color",
@ -251,30 +345,65 @@ export const border = [
]
export const effects = [
{ label: "Opacity", key: "opacity", control: Input },
{
label: "Opacity",
key: "opacity",
control: Input,
width: "48px",
textAlign: "center",
placeholder: "%",
},
{
label: "Rotate",
key: "transform",
control: OptionSelect,
options: [
{ label: "None", value: "rotate(0deg)" },
{ label: "45 degrees", value: "rotate(45deg)" },
{ label: "90 degrees", value: "rotate(90deg)" },
{ label: "135 degrees", value: "rotate(135deg)" },
{ label: "180 degrees", value: "rotate(180deg)" },
{ label: "225 degrees", value: "rotate(225deg)" },
{ label: "270 degrees", value: "rotate(270deg)" },
{ label: "315 degrees", value: "rotate(315deg)" },
{ label: "360 degrees", value: "rotate(360deg)" },
],
control: Input,
width: "48px",
textAlign: "center",
placeholder: "deg",
}, //needs special control
{ label: "Shadow", key: "box-shadow", control: Input },
{
label: "Shadow",
key: "box-shadow",
control: InputGroup,
meta: [{ placeholder: "X" }, { placeholder: "Y" }, { placeholder: "B" }],
},
]
export const transitions = [
{ label: "Property", key: "transition-property", control: Input },
{ label: "Duration", key: "transition-timing-function", control: Input },
{ label: "Ease", key: "transition-ease", control: Input },
{
label: "Property",
key: "transition-property",
control: OptionSelect,
options: [
"None",
"All",
"Background Color",
"Color",
"Font Size",
"Font Weight",
"Height",
"Margin",
"Opacity",
"Padding",
"Rotate",
"Shadow",
"Width",
],
},
{
label: "Duration",
key: "transition-timing-function",
control: Input,
width: "48px",
textAlign: "center",
placeholder: "sec",
},
{
label: "Ease",
key: "transition-ease",
control: OptionSelect,
options: ["linear", "ease", "ease-in", "ease-out", "ease-in-out"],
},
]
export const all = {

View File

@ -0,0 +1,14 @@
export const buildStyle = styles => {
let str = ""
for (let s in styles) {
if (styles[s]) {
let key = convertCamel(s)
str += `${key}: ${styles[s]}; `
}
}
return str
}
export const convertCamel = str => {
return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)
}

View File

@ -84,7 +84,7 @@
.ui-nav {
grid-column: 1;
background-color: var(--white);
height: calc(100vh - 49px);
height: calc(100vh - 69px);
padding: 0;
display: flex;
flex-direction: column;
@ -101,6 +101,47 @@
.components-pane {
grid-column: 3;
background-color: var(--white);
min-height: 0px;
height: calc(100vh - 69px);
overflow-y: hidden;
}
.components-nav-page {
font-size: 13px;
color: var(--ink);
padding-left: 20px;
margin-top: 20px;
font-weight: 600;
opacity: 0.4;
letter-spacing: 1px;
}
.components-nav-header {
font-size: 13px;
color: var(--ink);
margin-top: 20px;
font-weight: 600;
opacity: 0.4;
letter-spacing: 1px;
}
.nav-header {
display: flex;
flex-direction: column;
margin-top: 20px;
}
.nav-items-container {
padding: 1rem 0rem 0rem 0rem;
}
.nav-group-header {
display: flex;
padding: 0px 20px 0px 20px;
font-size: 0.9rem;
font-weight: bold;
justify-content: space-between;
align-items: center;
min-height: 0;
}

View File

@ -1,14 +1,10 @@
import {
generate_css,
generate_screen_css,
generate_array_styles
} from "../src/builderStore/generate_css.js"
describe("generate_css", () => {
test("Check how partially empty arrays are handled", () => {
expect(["", "5", "", ""].map(generate_array_styles)).toEqual(["0px", "5px", "0px", "0px"])
})
test("Check how array styles are output", () => {
expect(generate_css({ margin: ["0", "10", "0", "15"] })).toBe("margin: 0px 10px 0px 15px;")