This commit is contained in:
michael shanks 2019-08-14 22:11:59 +01:00
parent 21224b119b
commit fb9f4f6158
18 changed files with 621 additions and 176 deletions

15
packages/builder/.vscode/launch.json vendored Normal file
View File

@ -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}"
}
]
}

View File

@ -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",
"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",
"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",
"constant", "tail", "includes", "startsWith", "findIndex", "isInteger", "isDate", "isString", "split", "clone", "keys", "isFunction", "merge", "has", "isBoolean", "isNumber",

View File

@ -14,7 +14,7 @@ $: borderClass = grouped
<button class="{color} {className} {borderClass} {grouped ? "grouped" : ""}"
style="{style}"
on:click>
on:click >
<slot/>
</button>

View File

@ -6,15 +6,43 @@ export let icon = "";
export let style = "";
export let color = "";
export let hoverColor = "";
export let attributes = {};
$: borderClass = grouped
? ""
: "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>
<button style="{style} color:{color}"
on:click>
on:click
use:addAttributes={attributes}>
{@html getIcon(icon, size)}
</button>

View File

@ -3,12 +3,30 @@ export let text = "";
export let label = "";
export let width = "medium";
export let size = "small";
export let margin = true;
export let infoText = "";
export let hasError = false;
export let disabled = false;
</script>
<div class="uk-margin">
<div class:uk-margin={margin}>
<label class="uk-form-label">{label}</label>
<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>
{#if infoText}
<div class="info-text">{infoText}</div>
{/if}
</div>
<style>
.info-text {
font-size: 0.8em;
color: var(--slate);
}
</style>

View File

@ -16,7 +16,14 @@ $: filteredComponents =
<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>
{#each filteredComponents as component}
<div class="component" on:click={() => onComponentChosen(component)}>

View File

@ -3,39 +3,152 @@
import ComponentSearch from "./ComponentSearch.svelte";
import { store } from "../builderStore";
import PropsView from "./PropsView.svelte";
import Modal from "../common/Modal.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;
let basedOnComponent;
import {
cloneDeep,
join,
split,
map,
keys,
isUndefined
} from "lodash/fp";
import { assign } from "lodash";
const onBasedOnChosen = component => {
basedOnComponent = component;
let 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>
<Modal bind:isOpen={isCreatingNewComponent} id="search-component-modal">
<div class="uk-margin">
<form class="uk-form-horizontal">
{#if basedOnComponent}
<Textbox label="name"/>
{:else}
<label class="uk-form-label" for="form-stacked-text">Based On</label>
<div class="uk-form-controls">
<div bind:this={modalElement} id="new-component-modal" uk-modal>
<div class="uk-modal-dialog">
<div class="uk-modal-header">
<h1>New Component</h1>
</div>
<div class="uk-modal-body">
<form class="uk-form-horizontal">
{#if componentInfo}
<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}
onComponentChosen={onBasedOnChosen} />
</div>
{/if}
</form>
onComponentChosen={onBasedOnChosen($store.allComponents)} />
{/if}
</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>
</Modal>
</div>
<style>
h1 {
font-size:1.2em;
}
.props-header {
font-style: italic;
}
</style>

View File

@ -3,57 +3,113 @@
import {
keys,
map,
some,
includes,
cloneDeep,
isEqual
} from "lodash/fp";
import {
pipe
} from "../common/core";
import {
createPropDefinitionForDerived
} from "./pagesParsing/createProps";
import {
getExactComponent
} from "./pagesParsing/searchComponents";
import { pipe } from "../common/core";
import { getComponentInfo } from "./pagesParsing/createProps";
import { getExactComponent } from "./pagesParsing/searchComponents";
import Checkbox from "../common/Checkbox.svelte";
import Textbox from "../common/Textbox.svelte";
import Dropdown from "../common/Dropdown.svelte";
import { validateProps } from "./pagesParsing/validateProps";
export let props;
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,
map(k => propsDefinition[k])
]);
$: {
if(componentInfo || component)
{
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) =>
props[name] = ev.target.checked !== undefined
? ev.target.checked
: ev.target.value;
propsDefinitionArray = pipe(componentInfo.propsDefinition, [
keys,
map(k => ({...componentInfo.propsDefinition[k], ____name:k}))
]);
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>
<div class="root">
<div class="title">{component.name}</div>
<div class="component-description">{component.description || ""}</div>
{#each propsDefinition as propDef}
<form class="uk-form-horizontal prop-row ">
{#if showTitle=true}
<div class="title">{componentInfo.component.name}</div>
<div class="component-description">{componentInfo.component.description || ""}</div>
{/if}
{#each propsDefinitionArray as propDef}
<form class="uk-form-stacked prop-row ">
{#if propDef.type === "bool"}
<Checkbox label={propDef.name}
checked={props[propDef.name]}
on:change={setProp(propDef.name)} />
<Checkbox label={propDef.____name}
checked={props[propDef.____name]}
on:change={setProp(propDef.____name, "checked")}
hasError={fieldHasError(propDef.____name)} />
{:else if propDef.type === "options"}
<Dropdown label={propDef.name}
selected={props[propDef.name]}
options={propDef.options}
on:change={setProp(propDef.name)}/>
<Dropdown label={propDef.____name}
selected={props[propDef.____name]}
options={propDef.options}
on:change={setProp(propDef.____name)}
hasError={fieldHasError(propDef.____name)}/>
{:else}
<Textbox label={propDef.name}
bind:text={props[propDef.name]} />
<Textbox label={propDef.____name}
text={props[propDef.____name]}
on:change={setProp(propDef.____name)}
margin={false}
hasError={fieldHasError(propDef.____name)}
disabled={isPropInherited(propDef.____name)} />
{/if}
</form>
{/each}
@ -65,12 +121,12 @@ let setProp = (name) => (ev) =>
<style>
.root {
padding: 10px;
font-size:10pt;
}
.title {
font: var(--smallheavybodytext);
font-size: 1.2em;
font-weight: bold;
}
.prop-row {
@ -78,7 +134,9 @@ let setProp = (name) => (ev) =>
}
.component-description {
font: var(--lightbodytext);
font-size: 0.9em;
color: var(--slate);
margin-bottom: 10px;
}
</style>

View File

@ -27,7 +27,8 @@ const newComponent = () => {
<span>COMPONENTS</span>
<div>
<IconButton icon="plus"
on:click={newComponent} />
on:click={newComponent}
attributes={{"uk-toggle" : "target: #new-component-modal" }}/>
</div>
</div>
<div class="nav-items-container">
@ -58,14 +59,14 @@ const newComponent = () => {
<div class="properties-pane">
{#if $store.currentFrontEndItem && !isRootComponent($store.currentFrontEndItem)}
<PropsView allComponents={$store.allComponents}
props={$store.currentFrontEndItem.props}/>
component={$store.currentFrontEndItem}/>
{/if}
</div>
</div>
<NewComponent {isCreatingNewComponent}/>
<NewComponent bind:isCreatingNewComponent={isCreatingNewComponent}/>
<style>
@ -99,6 +100,7 @@ const newComponent = () => {
grid-column-start: properties;
background-color: var(--primary10);
height: 100%;
padding: 10px;
}
.pages-list-container {

View File

@ -6,21 +6,19 @@ import {
uniq,
some,
filter,
reduce
reduce,
cloneDeep,
includes
} from "lodash/fp";
import { types } from "./types";
import { types, expandPropsDefinition } from "./types";
import { assign } from "lodash";
import { pipe } from "../../common/core";
import { isRootComponent } from "./searchComponents";
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, [
keys,
@ -34,10 +32,81 @@ export const createPropDefinitionForDerived = (allComponents, componentName) =>
reduce((obj, k) => {
obj[k] = propDef[k];
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) => {
const error = (propName, error) =>
@ -61,7 +130,7 @@ export const createProps = (componentName, propsDefinition, derivedFromProps) =>
}
if(derivedFromProps) {
assign(props, ...derivedFromProps);
assign(props, derivedFromProps);
}
return ({

View File

@ -57,4 +57,4 @@ export const getAncestorProps = (allComponents, name, found=[]) => {
[{_component:thisComponent.inherits, ...thisComponent.props},
...found]);
}
}

View File

@ -9,7 +9,7 @@ import {
const defaultDef = typeName => () => ({
type: typeName,
required:false,
default:types[typeName].default,
default:types[typeName].default(),
options: typeName === "options" ? [] : undefined,
elementDefinition: typeName === "array" ? {} : undefined
});
@ -18,21 +18,33 @@ const propType = (defaultValue, isOfType, defaultDefinition) => ({
isOfType, default:defaultValue, defaultDefinition
});
/*export const expandPropDef = propDef => {
const expandSingleProp = propDef => {
const p = isString(propDef)
? types[propDef].defaultDefinition()
: propDef;
if(!isString(propDef)) {
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)) {
p.elementDefinition = types[p.elementDefinition].defaultDefinition()
if(p.type === "array") {
p.elementDefinition = expandPropsDefinition(p.elementDefinition);
}
return p;
}*/
}
export const expandPropsDefinition = propsDefinition => {
const expandedProps = {};
for(let p in propsDefinition) {
expandedProps[p] = expandSingleProp(propsDefinition[p]);
}
return expandedProps;
}
const isComponent = isObjectLike;

View File

@ -9,7 +9,8 @@ import {
flatten,
flattenDeep,
each,
indexOf } from "lodash/fp";
indexOf
} from "lodash/fp";
import { common } from "../../../../core/src";
const pipe = common.$;

View File

@ -1,7 +1,11 @@
import { createProps } from "../src/userInterface/pagesParsing/createProps";
import {
createProps,
createPropsAndDefinition
} from "../src/userInterface/pagesParsing/createProps";
import {
keys, some
} from "lodash/fp";
import { allComponents } from "./testData";
describe("createDefaultProps", () => {
@ -162,7 +166,7 @@ describe("createDefaultProps", () => {
fieldName: "surname"
};
const { props, errors } = createProps("some_component",propDef, [derivedFrom]);
const { props, errors } = createProps("some_component",propDef, derivedFrom);
expect(errors.length).toBe(0);
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");
});
})
})

View File

@ -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");
})
})

View File

@ -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"]);
});
})

View File

@ -3,14 +3,14 @@ import {
getExactComponent,
getAncestorProps
} from "../src/userInterface/pagesParsing/searchComponents";
import { allComponents } from "./testData";
describe("searchAllComponents", () => {
it("should match derived component by name", () => {
const results = searchAllComponents(
components(),
allComponents(),
"password"
);
@ -22,7 +22,7 @@ describe("searchAllComponents", () => {
it("should match derived component by tag", () => {
const results = searchAllComponents(
components(),
allComponents(),
"mask"
);
@ -34,7 +34,7 @@ describe("searchAllComponents", () => {
it("should match component if ancestor matches", () => {
const results = searchAllComponents(
components(),
allComponents(),
"smalltext"
);
@ -47,7 +47,7 @@ describe("searchAllComponents", () => {
describe("getExactComponent", () => {
it("should get component by name", () => {
const result = getExactComponent(
components(),
allComponents(),
"common/SmallTextbox"
)
@ -57,7 +57,7 @@ describe("getExactComponent", () => {
it("should return nothing when no result (should not fail)", () => {
const result = getExactComponent(
components(),
allComponents(),
"bla/bla/bla"
)
@ -71,75 +71,33 @@ describe("getAncestorProps", () => {
it("should return props of root component", () => {
const result = getAncestorProps(
components(),
allComponents(),
"budibase-components/TextBox"
);
expect(result).toEqual([
components()[0].props
allComponents()[0].props
]);
});
it("should return props of all ancestors and current component, in order", () => {
const allComponents = components();
const components = allComponents();
const result = getAncestorProps(
allComponents,
components,
"common/PasswordBox"
);
expect(result).toEqual([
allComponents[0].props,
{_component: "budibase-components/TextBox", ...allComponents[2].props},
{_component: "common/SmallTextbox", ...allComponents[3].props}
components[0].props,
{_component: "budibase-components/TextBox", ...components[2].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"
}
}
])

View File

@ -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"
}
}
])