backup
This commit is contained in:
parent
21224b119b
commit
fb9f4f6158
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Chrome against localhost",
|
||||||
|
"url": "http://localhost:3000",
|
||||||
|
"webRoot": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ const production = !process.env.ROLLUP_WATCH;
|
||||||
const lodash_fp_exports = ["union", "reduce", "isUndefined", "cloneDeep", "split", "some", "map", "filter", "isEmpty", "countBy", "includes", "last", "find", "constant",
|
const lodash_fp_exports = ["union", "reduce", "isUndefined", "cloneDeep", "split", "some", "map", "filter", "isEmpty", "countBy", "includes", "last", "find", "constant",
|
||||||
"take", "first", "intersection", "mapValues", "isNull", "has", "isNumber", "isString", "isBoolean", "isDate", "isArray", "isObject", "clone", "values", "keyBy",
|
"take", "first", "intersection", "mapValues", "isNull", "has", "isNumber", "isString", "isBoolean", "isDate", "isArray", "isObject", "clone", "values", "keyBy",
|
||||||
"keys", "orderBy", "concat", "reverse", "difference", "merge", "flatten", "each", "pull", "join", "defaultCase", "uniqBy", "every", "uniqWith", "isFunction", "groupBy",
|
"keys", "orderBy", "concat", "reverse", "difference", "merge", "flatten", "each", "pull", "join", "defaultCase", "uniqBy", "every", "uniqWith", "isFunction", "groupBy",
|
||||||
"differenceBy", "intersectionBy", "isEqual", "max", "sortBy", "assign", "uniq", "trimChars", "trimCharsStart", "isObjectLike"];
|
"differenceBy", "intersectionBy", "isEqual", "max", "sortBy", "assign", "uniq", "trimChars", "trimCharsStart", "isObjectLike", "flattenDeep", "indexOf"];
|
||||||
|
|
||||||
const lodash_exports = ["toNumber", "flow", "isArray", "join", "replace", "trim", "dropRight", "takeRight", "head", "isUndefined", "isNull", "isNaN", "reduce", "isEmpty",
|
const lodash_exports = ["toNumber", "flow", "isArray", "join", "replace", "trim", "dropRight", "takeRight", "head", "isUndefined", "isNull", "isNaN", "reduce", "isEmpty",
|
||||||
"constant", "tail", "includes", "startsWith", "findIndex", "isInteger", "isDate", "isString", "split", "clone", "keys", "isFunction", "merge", "has", "isBoolean", "isNumber",
|
"constant", "tail", "includes", "startsWith", "findIndex", "isInteger", "isDate", "isString", "split", "clone", "keys", "isFunction", "merge", "has", "isBoolean", "isNumber",
|
||||||
|
|
|
@ -14,7 +14,7 @@ $: borderClass = grouped
|
||||||
|
|
||||||
<button class="{color} {className} {borderClass} {grouped ? "grouped" : ""}"
|
<button class="{color} {className} {borderClass} {grouped ? "grouped" : ""}"
|
||||||
style="{style}"
|
style="{style}"
|
||||||
on:click>
|
on:click >
|
||||||
<slot/>
|
<slot/>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,43 @@ export let icon = "";
|
||||||
export let style = "";
|
export let style = "";
|
||||||
export let color = "";
|
export let color = "";
|
||||||
export let hoverColor = "";
|
export let hoverColor = "";
|
||||||
|
export let attributes = {};
|
||||||
|
|
||||||
$: borderClass = grouped
|
$: borderClass = grouped
|
||||||
? ""
|
? ""
|
||||||
: "border-normal";
|
: "border-normal";
|
||||||
|
|
||||||
|
let currentAttributes = [];
|
||||||
|
const addAttributes = (node, attributes) => {
|
||||||
|
|
||||||
|
const add = (_attributes) => {
|
||||||
|
const attrs = [];
|
||||||
|
for(let attr in _attributes) {
|
||||||
|
node.setAttribute(attr, _attributes[attr]);
|
||||||
|
attrs.push("uk-toggle")
|
||||||
|
}
|
||||||
|
currentAttributes = attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(attributes);
|
||||||
|
|
||||||
|
return {
|
||||||
|
// should implement update method
|
||||||
|
update(attributes) {
|
||||||
|
for(let attr of currentAttributes) {
|
||||||
|
node.removeAttribute(attr)
|
||||||
|
}
|
||||||
|
add(attributes);
|
||||||
|
},
|
||||||
|
destroy() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button style="{style} color:{color}"
|
<button style="{style} color:{color}"
|
||||||
on:click>
|
on:click
|
||||||
|
use:addAttributes={attributes}>
|
||||||
{@html getIcon(icon, size)}
|
{@html getIcon(icon, size)}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,30 @@ export let text = "";
|
||||||
export let label = "";
|
export let label = "";
|
||||||
export let width = "medium";
|
export let width = "medium";
|
||||||
export let size = "small";
|
export let size = "small";
|
||||||
|
export let margin = true;
|
||||||
|
export let infoText = "";
|
||||||
|
export let hasError = false;
|
||||||
|
export let disabled = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="uk-margin">
|
<div class:uk-margin={margin}>
|
||||||
<label class="uk-form-label">{label}</label>
|
<label class="uk-form-label">{label}</label>
|
||||||
<div class="uk-form-controls">
|
<div class="uk-form-controls">
|
||||||
<input class="uk-input uk-form-width-{width} uk-form-{size}" bind:value={text} >
|
<input class="uk-input uk-form-width-{width} uk-form-{size}"
|
||||||
|
class:uk-form-danger={hasError}
|
||||||
|
on:change
|
||||||
|
bind:value={text}
|
||||||
|
{disabled}>
|
||||||
</div>
|
</div>
|
||||||
|
{#if infoText}
|
||||||
|
<div class="info-text">{infoText}</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.info-text {
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: var(--slate);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,14 @@ $: filteredComponents =
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
|
||||||
<input class="uk-input" bind:value={phrase}>
|
<form class="uk-search uk-search-large">
|
||||||
|
<span uk-search-icon></span>
|
||||||
|
<input class="uk-search-input"
|
||||||
|
type="search"
|
||||||
|
placeholder="Based on component..."
|
||||||
|
bind:value={phrase}>
|
||||||
|
</form>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{#each filteredComponents as component}
|
{#each filteredComponents as component}
|
||||||
<div class="component" on:click={() => onComponentChosen(component)}>
|
<div class="component" on:click={() => onComponentChosen(component)}>
|
||||||
|
|
|
@ -3,39 +3,152 @@
|
||||||
import ComponentSearch from "./ComponentSearch.svelte";
|
import ComponentSearch from "./ComponentSearch.svelte";
|
||||||
import { store } from "../builderStore";
|
import { store } from "../builderStore";
|
||||||
import PropsView from "./PropsView.svelte";
|
import PropsView from "./PropsView.svelte";
|
||||||
import Modal from "../common/Modal.svelte";
|
|
||||||
import Textbox from "../common/Textbox.svelte";
|
import Textbox from "../common/Textbox.svelte";
|
||||||
|
import Button from "../common/Button.svelte";
|
||||||
|
import ButtonGroup from "../common/ButtonGroup.svelte";
|
||||||
|
import { pipe } from "../common/core";
|
||||||
|
import UIkit from "uikit";
|
||||||
|
import {
|
||||||
|
getNewComponentInfo
|
||||||
|
} from "./pagesParsing/createProps";
|
||||||
|
import { isRootComponent } from "./pagesParsing/searchComponents";
|
||||||
|
|
||||||
export let isCreatingNewComponent;
|
import {
|
||||||
let basedOnComponent;
|
cloneDeep,
|
||||||
|
join,
|
||||||
|
split,
|
||||||
|
map,
|
||||||
|
keys,
|
||||||
|
isUndefined
|
||||||
|
} from "lodash/fp";
|
||||||
|
import { assign } from "lodash";
|
||||||
|
|
||||||
const onBasedOnChosen = component => {
|
let component;
|
||||||
basedOnComponent = component;
|
let modalElement;
|
||||||
|
let errors = {};
|
||||||
|
let componentInfo;
|
||||||
|
|
||||||
|
let name = "";
|
||||||
|
let description = "";
|
||||||
|
let tagsString = "";
|
||||||
|
let propsValidationErrors = [];
|
||||||
|
let inheritedProps;
|
||||||
|
let nameInvalid = "";
|
||||||
|
let propsDefinition;
|
||||||
|
|
||||||
|
const onBasedOnChosen = (allComponents) => (c) => {
|
||||||
|
componentInfo = getNewComponentInfo(allComponents, c.name);
|
||||||
|
tagsString = join(", ")(componentInfo.component.tags);
|
||||||
|
inheritedProps = componentInfo.inheritedProps;
|
||||||
|
propsDefinition = componentInfo.propsDefinition;
|
||||||
|
component = componentInfo.component;
|
||||||
|
}
|
||||||
|
|
||||||
|
const createComponent = () => {
|
||||||
|
|
||||||
|
if(!validate()) return;
|
||||||
|
|
||||||
|
component.props._component = name;
|
||||||
|
component.name = name;
|
||||||
|
component.description = description;
|
||||||
|
component.tags = pipe(tagsString, [
|
||||||
|
split(","),
|
||||||
|
map(s => s.trim())
|
||||||
|
]);
|
||||||
|
|
||||||
|
store.saveDerivedComponent(component);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
component = null;
|
||||||
|
componentInfo = null;
|
||||||
|
UIkit.modal(modalElement).hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPropsValidate = result => {
|
||||||
|
propsValidationErrors = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPropsChanged = props => {
|
||||||
|
assign(component.props, [props]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const validate = () => {
|
||||||
|
const fieldInvalid = (field, err) =>
|
||||||
|
errors[field] = err;
|
||||||
|
const fieldValid = field =>
|
||||||
|
errors[field] && delete errors[field];
|
||||||
|
|
||||||
|
if(!name) nameInvalid = "component name i not supplied";
|
||||||
|
else nameInvalid = "";
|
||||||
|
|
||||||
|
return (!nameInvalid && propsValidationErrors.length === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal bind:isOpen={isCreatingNewComponent} id="search-component-modal">
|
<div bind:this={modalElement} id="new-component-modal" uk-modal>
|
||||||
<div class="uk-margin">
|
<div class="uk-modal-dialog">
|
||||||
<form class="uk-form-horizontal">
|
|
||||||
{#if basedOnComponent}
|
<div class="uk-modal-header">
|
||||||
|
<h1>New Component</h1>
|
||||||
<Textbox label="name"/>
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-modal-body">
|
||||||
{:else}
|
<form class="uk-form-horizontal">
|
||||||
|
{#if componentInfo}
|
||||||
<label class="uk-form-label" for="form-stacked-text">Based On</label>
|
|
||||||
<div class="uk-form-controls">
|
<Textbox label="Name"
|
||||||
|
infoText="use forward slash to store in subfolders"
|
||||||
|
bind:text={name}
|
||||||
|
hasError={!!nameInvalid}/>
|
||||||
|
<div class="info-text"></div>
|
||||||
|
<Textbox label="Description"
|
||||||
|
bind:text={description}/>
|
||||||
|
<Textbox label="Tags"
|
||||||
|
infoText="comma separated"
|
||||||
|
bind:text={tagsString}/>
|
||||||
|
<p class="uk-heading-line props-header"><span>Properties</span></p>
|
||||||
|
<PropsView allComponents={$store.allComponents}
|
||||||
|
onValidate={onPropsValidate}
|
||||||
|
showTitle={false}
|
||||||
|
{componentInfo}
|
||||||
|
{onPropsChanged} />
|
||||||
|
|
||||||
|
|
||||||
|
{:else}
|
||||||
|
|
||||||
|
|
||||||
<ComponentSearch allComponents={$store.allComponents}
|
<ComponentSearch allComponents={$store.allComponents}
|
||||||
onComponentChosen={onBasedOnChosen} />
|
onComponentChosen={onBasedOnChosen($store.allComponents)} />
|
||||||
</div>
|
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
{#if component}
|
||||||
|
<div class="uk-modal-footer">
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button grouped
|
||||||
|
on:click={close}
|
||||||
|
color="secondary" >Cancel</Button>
|
||||||
|
<Button grouped
|
||||||
|
on:click={createComponent}>Create Component</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
h1 {
|
||||||
|
font-size:1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.props-header {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -3,57 +3,113 @@
|
||||||
import {
|
import {
|
||||||
keys,
|
keys,
|
||||||
map,
|
map,
|
||||||
|
some,
|
||||||
|
includes,
|
||||||
|
cloneDeep,
|
||||||
|
isEqual
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import {
|
import { pipe } from "../common/core";
|
||||||
pipe
|
import { getComponentInfo } from "./pagesParsing/createProps";
|
||||||
} from "../common/core";
|
import { getExactComponent } from "./pagesParsing/searchComponents";
|
||||||
import {
|
|
||||||
createPropDefinitionForDerived
|
|
||||||
} from "./pagesParsing/createProps";
|
|
||||||
import {
|
|
||||||
getExactComponent
|
|
||||||
} from "./pagesParsing/searchComponents";
|
|
||||||
import Checkbox from "../common/Checkbox.svelte";
|
import Checkbox from "../common/Checkbox.svelte";
|
||||||
import Textbox from "../common/Textbox.svelte";
|
import Textbox from "../common/Textbox.svelte";
|
||||||
import Dropdown from "../common/Dropdown.svelte";
|
import Dropdown from "../common/Dropdown.svelte";
|
||||||
|
import { validateProps } from "./pagesParsing/validateProps";
|
||||||
|
|
||||||
export let props;
|
|
||||||
export let allComponents;
|
export let allComponents;
|
||||||
|
export let shouldValidate = true;
|
||||||
|
export let onValidate = () => {};
|
||||||
|
export let showTitle = true;
|
||||||
|
export let componentInfo;
|
||||||
|
export let component;
|
||||||
|
export let onPropsChanged = () => {};
|
||||||
|
|
||||||
let propsDefinition = createPropDefinitionForDerived(allComponents, props._component);
|
let errors = [];
|
||||||
|
let fields = [];
|
||||||
|
let props = {};
|
||||||
|
let propsDefinitionArray = [];
|
||||||
|
|
||||||
let fields = pipe(propsDefinition,[
|
$: {
|
||||||
keys,
|
if(componentInfo || component)
|
||||||
map(k => propsDefinition[k])
|
{
|
||||||
]);
|
if(!componentInfo || (component &&
|
||||||
|
component.name !== componentInfo.component.name)) {
|
||||||
|
componentInfo = getComponentInfo(allComponents, component.name);
|
||||||
|
}
|
||||||
|
|
||||||
let component = getExactComponent(allComponents, props._component);
|
props = cloneDeep(componentInfo.fullProps);
|
||||||
|
|
||||||
let setProp = (name) => (ev) =>
|
propsDefinitionArray = pipe(componentInfo.propsDefinition, [
|
||||||
props[name] = ev.target.checked !== undefined
|
keys,
|
||||||
? ev.target.checked
|
map(k => ({...componentInfo.propsDefinition[k], ____name:k}))
|
||||||
: ev.target.value;
|
]);
|
||||||
|
|
||||||
|
fields = pipe(componentInfo.propsDefinition,[
|
||||||
|
keys,
|
||||||
|
map(k => componentInfo.propsDefinition[k])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isPropInherited = name =>
|
||||||
|
includes(name)(componentInfo.inheritedProps);
|
||||||
|
|
||||||
|
let setProp = (name) => (ev, targetValue="value") => {
|
||||||
|
const newProps = cloneDeep(props);
|
||||||
|
newProps[name] = ev.target[targetValue];
|
||||||
|
|
||||||
|
|
||||||
|
const finalProps = {_component:props._component};
|
||||||
|
|
||||||
|
for(let p of componentInfo.unsetProps) {
|
||||||
|
if(!isEqual(newProps[p])(componentInfo.rootDefaultProps[p])) {
|
||||||
|
finalProps[p] = newProps[p];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
props = newProps;
|
||||||
|
if(validate(finalProps))
|
||||||
|
onPropsChanged(finalProps);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const validate = (finalProps) => {
|
||||||
|
errors = validateProps(componentInfo.propsDefinition, finalProps, [], false);
|
||||||
|
onValidate(errors);
|
||||||
|
return errors.length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldHasError = (propName) =>
|
||||||
|
some(e => e.propName === propName)(errors);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
|
||||||
<div class="title">{component.name}</div>
|
{#if showTitle=true}
|
||||||
<div class="component-description">{component.description || ""}</div>
|
<div class="title">{componentInfo.component.name}</div>
|
||||||
{#each propsDefinition as propDef}
|
<div class="component-description">{componentInfo.component.description || ""}</div>
|
||||||
<form class="uk-form-horizontal prop-row ">
|
{/if}
|
||||||
|
{#each propsDefinitionArray as propDef}
|
||||||
|
<form class="uk-form-stacked prop-row ">
|
||||||
{#if propDef.type === "bool"}
|
{#if propDef.type === "bool"}
|
||||||
<Checkbox label={propDef.name}
|
<Checkbox label={propDef.____name}
|
||||||
checked={props[propDef.name]}
|
checked={props[propDef.____name]}
|
||||||
on:change={setProp(propDef.name)} />
|
on:change={setProp(propDef.____name, "checked")}
|
||||||
|
hasError={fieldHasError(propDef.____name)} />
|
||||||
{:else if propDef.type === "options"}
|
{:else if propDef.type === "options"}
|
||||||
<Dropdown label={propDef.name}
|
<Dropdown label={propDef.____name}
|
||||||
selected={props[propDef.name]}
|
selected={props[propDef.____name]}
|
||||||
options={propDef.options}
|
options={propDef.options}
|
||||||
on:change={setProp(propDef.name)}/>
|
on:change={setProp(propDef.____name)}
|
||||||
|
hasError={fieldHasError(propDef.____name)}/>
|
||||||
{:else}
|
{:else}
|
||||||
<Textbox label={propDef.name}
|
<Textbox label={propDef.____name}
|
||||||
bind:text={props[propDef.name]} />
|
text={props[propDef.____name]}
|
||||||
|
on:change={setProp(propDef.____name)}
|
||||||
|
margin={false}
|
||||||
|
hasError={fieldHasError(propDef.____name)}
|
||||||
|
disabled={isPropInherited(propDef.____name)} />
|
||||||
{/if}
|
{/if}
|
||||||
</form>
|
</form>
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -65,12 +121,12 @@ let setProp = (name) => (ev) =>
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
padding: 10px;
|
|
||||||
font-size:10pt;
|
font-size:10pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font: var(--smallheavybodytext);
|
font-size: 1.2em;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prop-row {
|
.prop-row {
|
||||||
|
@ -78,7 +134,9 @@ let setProp = (name) => (ev) =>
|
||||||
}
|
}
|
||||||
|
|
||||||
.component-description {
|
.component-description {
|
||||||
font: var(--lightbodytext);
|
font-size: 0.9em;
|
||||||
|
color: var(--slate);
|
||||||
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -27,7 +27,8 @@ const newComponent = () => {
|
||||||
<span>COMPONENTS</span>
|
<span>COMPONENTS</span>
|
||||||
<div>
|
<div>
|
||||||
<IconButton icon="plus"
|
<IconButton icon="plus"
|
||||||
on:click={newComponent} />
|
on:click={newComponent}
|
||||||
|
attributes={{"uk-toggle" : "target: #new-component-modal" }}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-items-container">
|
<div class="nav-items-container">
|
||||||
|
@ -58,14 +59,14 @@ const newComponent = () => {
|
||||||
<div class="properties-pane">
|
<div class="properties-pane">
|
||||||
{#if $store.currentFrontEndItem && !isRootComponent($store.currentFrontEndItem)}
|
{#if $store.currentFrontEndItem && !isRootComponent($store.currentFrontEndItem)}
|
||||||
<PropsView allComponents={$store.allComponents}
|
<PropsView allComponents={$store.allComponents}
|
||||||
props={$store.currentFrontEndItem.props}/>
|
component={$store.currentFrontEndItem}/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<NewComponent {isCreatingNewComponent}/>
|
<NewComponent bind:isCreatingNewComponent={isCreatingNewComponent}/>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -99,6 +100,7 @@ const newComponent = () => {
|
||||||
grid-column-start: properties;
|
grid-column-start: properties;
|
||||||
background-color: var(--primary10);
|
background-color: var(--primary10);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pages-list-container {
|
.pages-list-container {
|
||||||
|
|
|
@ -6,21 +6,19 @@ import {
|
||||||
uniq,
|
uniq,
|
||||||
some,
|
some,
|
||||||
filter,
|
filter,
|
||||||
reduce
|
reduce,
|
||||||
|
cloneDeep,
|
||||||
|
includes
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import { types } from "./types";
|
import { types, expandPropsDefinition } from "./types";
|
||||||
import { assign } from "lodash";
|
import { assign } from "lodash";
|
||||||
import { pipe } from "../../common/core";
|
import { pipe } from "../../common/core";
|
||||||
import { isRootComponent } from "./searchComponents";
|
import { isRootComponent } from "./searchComponents";
|
||||||
|
|
||||||
export const createPropDefinitionForDerived = (allComponents, componentName) => {
|
export const createPropDefinitionForDerived = (allComponents, componentName) => {
|
||||||
const traverseForProps = (cname, derivedProps=[]) => {
|
|
||||||
const component = find(c => c.name === cname)(allComponents);
|
|
||||||
if(isRootComponent(component)) return ({propDef:component.props, derivedProps});
|
|
||||||
return traverseForProps(component.inherits, [component.props, ...derivedProps]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const {propDef, derivedProps} = traverseForProps(componentName);
|
const {propDef, derivedProps} = getComponentInfo(allComponents, componentName);
|
||||||
|
|
||||||
const hasDerivedProp = k => pipe(derivedProps, [
|
const hasDerivedProp = k => pipe(derivedProps, [
|
||||||
keys,
|
keys,
|
||||||
|
@ -34,10 +32,81 @@ export const createPropDefinitionForDerived = (allComponents, componentName) =>
|
||||||
reduce((obj, k) => {
|
reduce((obj, k) => {
|
||||||
obj[k] = propDef[k];
|
obj[k] = propDef[k];
|
||||||
return obj;
|
return obj;
|
||||||
}, {})
|
}, {}),
|
||||||
|
expandPropsDefinition
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const traverseForProps = getComponentInfo;
|
||||||
|
|
||||||
|
export const getFinalProps = (componentInfo, props) => {
|
||||||
|
const finalProps = cloneDeep(componentInfo.fullProps);
|
||||||
|
|
||||||
|
for(let p in props) {
|
||||||
|
finalProps[p] = props[p];
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getNewComponentInfo = (allComponents, inherits) => {
|
||||||
|
const parentcomponent = find(c => c.name === inherits)(allComponents);
|
||||||
|
const component = {
|
||||||
|
name:"",
|
||||||
|
description:"",
|
||||||
|
inherits,
|
||||||
|
props:{_component:inherits},
|
||||||
|
tags:parentcomponent.tags
|
||||||
|
};
|
||||||
|
return getComponentInfo(
|
||||||
|
allComponents,
|
||||||
|
inherits,
|
||||||
|
[component],
|
||||||
|
{});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const getComponentInfo = (allComponents, cname, stack=[], subComponentProps=null) => {
|
||||||
|
const component = find(c => c.name === cname)(allComponents);
|
||||||
|
if(isRootComponent(component)) {
|
||||||
|
subComponentProps = subComponentProps||{};
|
||||||
|
const p = createProps(cname, component.props, subComponentProps);
|
||||||
|
const inheritedProps = [];
|
||||||
|
if(stack.length > 0) {
|
||||||
|
const targetComponent = stack[0];
|
||||||
|
p.props._component = targetComponent.name;
|
||||||
|
for(let prop in subComponentProps) {
|
||||||
|
if(prop === "_component") continue;
|
||||||
|
const hasProp = pipe(targetComponent.props, [
|
||||||
|
keys,
|
||||||
|
includes(prop)]);
|
||||||
|
|
||||||
|
if(!hasProp)
|
||||||
|
inheritedProps.push(prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const unsetProps = pipe(p.props, [
|
||||||
|
keys,
|
||||||
|
filter(k => k !== "_component" && !includes(k)(keys(subComponentProps)))
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ({
|
||||||
|
propsDefinition:component.props,
|
||||||
|
inheritedProps,
|
||||||
|
rootDefaultProps: p.props,
|
||||||
|
unsetProps,
|
||||||
|
fullProps: p.props,
|
||||||
|
errors: p.errors,
|
||||||
|
component: stack.length > 0 ? stack[0] : component
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return getComponentInfo(
|
||||||
|
allComponents,
|
||||||
|
component.inherits,
|
||||||
|
[...stack, component],
|
||||||
|
{...component.props, ...subComponentProps});
|
||||||
|
}
|
||||||
|
|
||||||
export const createProps = (componentName, propsDefinition, derivedFromProps) => {
|
export const createProps = (componentName, propsDefinition, derivedFromProps) => {
|
||||||
|
|
||||||
const error = (propName, error) =>
|
const error = (propName, error) =>
|
||||||
|
@ -61,7 +130,7 @@ export const createProps = (componentName, propsDefinition, derivedFromProps) =>
|
||||||
}
|
}
|
||||||
|
|
||||||
if(derivedFromProps) {
|
if(derivedFromProps) {
|
||||||
assign(props, ...derivedFromProps);
|
assign(props, derivedFromProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ({
|
return ({
|
||||||
|
|
|
@ -57,4 +57,4 @@ export const getAncestorProps = (allComponents, name, found=[]) => {
|
||||||
[{_component:thisComponent.inherits, ...thisComponent.props},
|
[{_component:thisComponent.inherits, ...thisComponent.props},
|
||||||
...found]);
|
...found]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
const defaultDef = typeName => () => ({
|
const defaultDef = typeName => () => ({
|
||||||
type: typeName,
|
type: typeName,
|
||||||
required:false,
|
required:false,
|
||||||
default:types[typeName].default,
|
default:types[typeName].default(),
|
||||||
options: typeName === "options" ? [] : undefined,
|
options: typeName === "options" ? [] : undefined,
|
||||||
elementDefinition: typeName === "array" ? {} : undefined
|
elementDefinition: typeName === "array" ? {} : undefined
|
||||||
});
|
});
|
||||||
|
@ -18,21 +18,33 @@ const propType = (defaultValue, isOfType, defaultDefinition) => ({
|
||||||
isOfType, default:defaultValue, defaultDefinition
|
isOfType, default:defaultValue, defaultDefinition
|
||||||
});
|
});
|
||||||
|
|
||||||
/*export const expandPropDef = propDef => {
|
const expandSingleProp = propDef => {
|
||||||
const p = isString(propDef)
|
const p = isString(propDef)
|
||||||
? types[propDef].defaultDefinition()
|
? types[propDef].defaultDefinition()
|
||||||
: propDef;
|
: propDef;
|
||||||
|
|
||||||
if(!isString(propDef)) {
|
if(!isString(propDef)) {
|
||||||
const def = types[propDef.type].defaultDefinition();
|
const def = types[propDef.type].defaultDefinition();
|
||||||
assign(propDef, def);
|
for(let p in def) {
|
||||||
|
if(propDef[p] === undefined) {
|
||||||
|
propDef[p] = def[p];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p.type === "array" && isString(p.elementDefinition)) {
|
if(p.type === "array") {
|
||||||
p.elementDefinition = types[p.elementDefinition].defaultDefinition()
|
p.elementDefinition = expandPropsDefinition(p.elementDefinition);
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
export const expandPropsDefinition = propsDefinition => {
|
||||||
|
const expandedProps = {};
|
||||||
|
for(let p in propsDefinition) {
|
||||||
|
expandedProps[p] = expandSingleProp(propsDefinition[p]);
|
||||||
|
}
|
||||||
|
return expandedProps;
|
||||||
|
}
|
||||||
|
|
||||||
const isComponent = isObjectLike;
|
const isComponent = isObjectLike;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@ import {
|
||||||
flatten,
|
flatten,
|
||||||
flattenDeep,
|
flattenDeep,
|
||||||
each,
|
each,
|
||||||
indexOf } from "lodash/fp";
|
indexOf
|
||||||
|
} from "lodash/fp";
|
||||||
import { common } from "../../../../core/src";
|
import { common } from "../../../../core/src";
|
||||||
|
|
||||||
const pipe = common.$;
|
const pipe = common.$;
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { createProps } from "../src/userInterface/pagesParsing/createProps";
|
import {
|
||||||
|
createProps,
|
||||||
|
createPropsAndDefinition
|
||||||
|
} from "../src/userInterface/pagesParsing/createProps";
|
||||||
import {
|
import {
|
||||||
keys, some
|
keys, some
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
|
import { allComponents } from "./testData";
|
||||||
|
|
||||||
describe("createDefaultProps", () => {
|
describe("createDefaultProps", () => {
|
||||||
|
|
||||||
|
@ -162,7 +166,7 @@ describe("createDefaultProps", () => {
|
||||||
fieldName: "surname"
|
fieldName: "surname"
|
||||||
};
|
};
|
||||||
|
|
||||||
const { props, errors } = createProps("some_component",propDef, [derivedFrom]);
|
const { props, errors } = createProps("some_component",propDef, derivedFrom);
|
||||||
|
|
||||||
expect(errors.length).toBe(0);
|
expect(errors.length).toBe(0);
|
||||||
expect(props.fieldName).toBe("surname");
|
expect(props.fieldName).toBe("surname");
|
||||||
|
@ -170,35 +174,4 @@ describe("createDefaultProps", () => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should merge in derived props, last in list taking priority", () => {
|
})
|
||||||
const propDef = {
|
|
||||||
fieldName: "string",
|
|
||||||
fieldLength: { type: "number", default: 500},
|
|
||||||
header: "component",
|
|
||||||
content: {
|
|
||||||
type: "component",
|
|
||||||
default: { _component: "childcomponent", wdith: 500 }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const derivedFrom1 = {
|
|
||||||
_component:"root",
|
|
||||||
fieldName: "surname",
|
|
||||||
fieldLength: 200
|
|
||||||
};
|
|
||||||
|
|
||||||
const derivedFrom2 = {
|
|
||||||
_component:"child",
|
|
||||||
fieldName: "forename"
|
|
||||||
};
|
|
||||||
|
|
||||||
const { props, errors } = createProps("some_component",propDef, [derivedFrom1, derivedFrom2]);
|
|
||||||
|
|
||||||
expect(errors.length).toBe(0);
|
|
||||||
expect(props.fieldName).toBe("forename");
|
|
||||||
expect(props.fieldLength).toBe(200);
|
|
||||||
expect(props._component).toBe("child");
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { expandPropsDefinition } from "../src/userInterface/pagesParsing/types";
|
||||||
|
|
||||||
|
const propDef = {
|
||||||
|
label: "string",
|
||||||
|
width: {type:"number"},
|
||||||
|
color: {type:"string", required:true},
|
||||||
|
child: "component",
|
||||||
|
navitems: {
|
||||||
|
type: "array",
|
||||||
|
elementDefinition: {
|
||||||
|
name: {type:"string"},
|
||||||
|
height: "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("expandPropDefintion", () => {
|
||||||
|
|
||||||
|
it("should expand property defined as string, into default for that type", () => {
|
||||||
|
|
||||||
|
const result = expandPropsDefinition(propDef);
|
||||||
|
|
||||||
|
expect(result.label.type).toBe("string");
|
||||||
|
expect(result.label.required).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should add members to property defined as object, when members do not exist", () => {
|
||||||
|
|
||||||
|
const result = expandPropsDefinition(propDef);
|
||||||
|
expect(result.width.required).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not override existing memebers", () => {
|
||||||
|
|
||||||
|
const result = expandPropsDefinition(propDef);
|
||||||
|
expect(result.color.required).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should also expand out elementdefinition of array", () => {
|
||||||
|
const result = expandPropsDefinition(propDef);
|
||||||
|
expect(result.navitems.elementDefinition.height.type).toBe("number");
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
|
@ -0,0 +1,103 @@
|
||||||
|
import {
|
||||||
|
getFinalProps,
|
||||||
|
getComponentInfo
|
||||||
|
} from "../src/userInterface/pagesParsing/createProps";
|
||||||
|
import {
|
||||||
|
keys, some
|
||||||
|
} from "lodash/fp";
|
||||||
|
import { allComponents } from "./testData";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
describe("getComponentInfo", () => {
|
||||||
|
|
||||||
|
it("should return default props for root component", () => {
|
||||||
|
const result = getComponentInfo(
|
||||||
|
allComponents(),
|
||||||
|
"budibase-components/TextBox");
|
||||||
|
|
||||||
|
expect(result.errors).toEqual([]);
|
||||||
|
expect(result.fullProps).toEqual({
|
||||||
|
_component: "budibase-components/TextBox",
|
||||||
|
size: "",
|
||||||
|
isPassword: false,
|
||||||
|
placeholder: "",
|
||||||
|
label:""
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return no inherited for root component", () => {
|
||||||
|
const result = getComponentInfo(
|
||||||
|
allComponents(),
|
||||||
|
"budibase-components/TextBox");
|
||||||
|
|
||||||
|
expect(result.inheritedProps).toEqual([]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("getFinalProps should set supplied props on top of default props", () => {
|
||||||
|
const result = getFinalProps(
|
||||||
|
getComponentInfo(
|
||||||
|
allComponents(),
|
||||||
|
"budibase-components/TextBox"),
|
||||||
|
{size:"small"});
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
_component: "budibase-components/TextBox",
|
||||||
|
size: "small",
|
||||||
|
isPassword: false,
|
||||||
|
placeholder: "",
|
||||||
|
label:""
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return correct props for derived component", () => {
|
||||||
|
const result = getComponentInfo(
|
||||||
|
allComponents(),
|
||||||
|
"common/SmallTextbox");
|
||||||
|
|
||||||
|
expect(result.errors).toEqual([]);
|
||||||
|
expect(result.fullProps).toEqual({
|
||||||
|
_component: "common/SmallTextbox",
|
||||||
|
size: "small",
|
||||||
|
isPassword: false,
|
||||||
|
placeholder: "",
|
||||||
|
label:""
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return correct props for twice derived component", () => {
|
||||||
|
const result = getComponentInfo(
|
||||||
|
allComponents(),
|
||||||
|
"common/PasswordBox");
|
||||||
|
|
||||||
|
expect(result.errors).toEqual([]);
|
||||||
|
expect(result.fullProps).toEqual({
|
||||||
|
_component: "common/PasswordBox",
|
||||||
|
size: "small",
|
||||||
|
isPassword: true,
|
||||||
|
placeholder: "",
|
||||||
|
label:""
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should list inheirted props as those that are defined in ancestor, derived components", () => {
|
||||||
|
const result = getComponentInfo(
|
||||||
|
allComponents(),
|
||||||
|
"common/PasswordBox");
|
||||||
|
|
||||||
|
// size is inherited from SmallTextbox
|
||||||
|
expect(result.inheritedProps).toEqual(["size"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should list unset props as those that are only defined in root", () => {
|
||||||
|
const result = getComponentInfo(
|
||||||
|
allComponents(),
|
||||||
|
"common/PasswordBox");
|
||||||
|
|
||||||
|
expect(result.unsetProps).toEqual([
|
||||||
|
"placeholder", "label"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
|
@ -3,14 +3,14 @@ import {
|
||||||
getExactComponent,
|
getExactComponent,
|
||||||
getAncestorProps
|
getAncestorProps
|
||||||
} from "../src/userInterface/pagesParsing/searchComponents";
|
} from "../src/userInterface/pagesParsing/searchComponents";
|
||||||
|
import { allComponents } from "./testData";
|
||||||
|
|
||||||
describe("searchAllComponents", () => {
|
describe("searchAllComponents", () => {
|
||||||
|
|
||||||
it("should match derived component by name", () => {
|
it("should match derived component by name", () => {
|
||||||
|
|
||||||
const results = searchAllComponents(
|
const results = searchAllComponents(
|
||||||
components(),
|
allComponents(),
|
||||||
"password"
|
"password"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ describe("searchAllComponents", () => {
|
||||||
it("should match derived component by tag", () => {
|
it("should match derived component by tag", () => {
|
||||||
|
|
||||||
const results = searchAllComponents(
|
const results = searchAllComponents(
|
||||||
components(),
|
allComponents(),
|
||||||
"mask"
|
"mask"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ describe("searchAllComponents", () => {
|
||||||
it("should match component if ancestor matches", () => {
|
it("should match component if ancestor matches", () => {
|
||||||
|
|
||||||
const results = searchAllComponents(
|
const results = searchAllComponents(
|
||||||
components(),
|
allComponents(),
|
||||||
"smalltext"
|
"smalltext"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ describe("searchAllComponents", () => {
|
||||||
describe("getExactComponent", () => {
|
describe("getExactComponent", () => {
|
||||||
it("should get component by name", () => {
|
it("should get component by name", () => {
|
||||||
const result = getExactComponent(
|
const result = getExactComponent(
|
||||||
components(),
|
allComponents(),
|
||||||
"common/SmallTextbox"
|
"common/SmallTextbox"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ describe("getExactComponent", () => {
|
||||||
|
|
||||||
it("should return nothing when no result (should not fail)", () => {
|
it("should return nothing when no result (should not fail)", () => {
|
||||||
const result = getExactComponent(
|
const result = getExactComponent(
|
||||||
components(),
|
allComponents(),
|
||||||
"bla/bla/bla"
|
"bla/bla/bla"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -71,75 +71,33 @@ describe("getAncestorProps", () => {
|
||||||
it("should return props of root component", () => {
|
it("should return props of root component", () => {
|
||||||
|
|
||||||
const result = getAncestorProps(
|
const result = getAncestorProps(
|
||||||
components(),
|
allComponents(),
|
||||||
"budibase-components/TextBox"
|
"budibase-components/TextBox"
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
components()[0].props
|
allComponents()[0].props
|
||||||
]);
|
]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return props of all ancestors and current component, in order", () => {
|
it("should return props of all ancestors and current component, in order", () => {
|
||||||
|
|
||||||
const allComponents = components();
|
const components = allComponents();
|
||||||
|
|
||||||
const result = getAncestorProps(
|
const result = getAncestorProps(
|
||||||
allComponents,
|
components,
|
||||||
"common/PasswordBox"
|
"common/PasswordBox"
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
allComponents[0].props,
|
components[0].props,
|
||||||
{_component: "budibase-components/TextBox", ...allComponents[2].props},
|
{_component: "budibase-components/TextBox", ...components[2].props},
|
||||||
{_component: "common/SmallTextbox", ...allComponents[3].props}
|
{_component: "common/SmallTextbox", ...components[3].props}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const components = () => ([
|
|
||||||
{
|
|
||||||
name: "budibase-components/TextBox",
|
|
||||||
tags: ["Text", "input"],
|
|
||||||
props: {
|
|
||||||
size: {type:"options", options:["small", "medium", "large"]},
|
|
||||||
isPassword: "boolean",
|
|
||||||
placeholder: "string",
|
|
||||||
label:"string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "budibase-components/Button",
|
|
||||||
tags: ["input"],
|
|
||||||
props: {
|
|
||||||
size: {type:"options", options:["small", "medium", "large"]},
|
|
||||||
css: "string",
|
|
||||||
content: "component"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inherits:"budibase-components/TextBox",
|
|
||||||
name: "common/SmallTextbox",
|
|
||||||
props: {
|
|
||||||
size: "small"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inherits:"common/SmallTextbox",
|
|
||||||
name: "common/PasswordBox",
|
|
||||||
tags: ["mask"],
|
|
||||||
props: {
|
|
||||||
isPassword: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inherits:"budibase-components/Button",
|
|
||||||
name:"PrimaryButton",
|
|
||||||
props: {
|
|
||||||
css:"btn-primary"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
export const allComponents = () => ([
|
||||||
|
{
|
||||||
|
name: "budibase-components/TextBox",
|
||||||
|
tags: ["Text", "input"],
|
||||||
|
props: {
|
||||||
|
size: {type:"options", options:["small", "medium", "large"]},
|
||||||
|
isPassword: "bool",
|
||||||
|
placeholder: "string",
|
||||||
|
label:"string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "budibase-components/Button",
|
||||||
|
tags: ["input"],
|
||||||
|
props: {
|
||||||
|
size: {type:"options", options:["small", "medium", "large"]},
|
||||||
|
css: "string",
|
||||||
|
content: "component"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inherits:"budibase-components/TextBox",
|
||||||
|
name: "common/SmallTextbox",
|
||||||
|
props: {
|
||||||
|
size: "small"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inherits:"common/SmallTextbox",
|
||||||
|
name: "common/PasswordBox",
|
||||||
|
tags: ["mask"],
|
||||||
|
props: {
|
||||||
|
isPassword: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inherits:"budibase-components/Button",
|
||||||
|
name:"PrimaryButton",
|
||||||
|
props: {
|
||||||
|
css:"btn-primary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
Loading…
Reference in New Issue