Merge pull request #214 from Budibase/simplified-component-panel
New components panel
This commit is contained in:
commit
974576de1d
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,7 @@
|
||||||
"name": "root",
|
"name": "root",
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-json": "^4.0.2",
|
||||||
"babel-eslint": "^10.0.3",
|
"babel-eslint": "^10.0.3",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-plugin-prettier": "^3.1.2",
|
"eslint-plugin-prettier": "^3.1.2",
|
||||||
|
@ -17,7 +18,7 @@
|
||||||
"build": "lerna run build",
|
"build": "lerna run build",
|
||||||
"initialise": "lerna run initialise",
|
"initialise": "lerna run initialise",
|
||||||
"publishdev": "lerna run publishdev",
|
"publishdev": "lerna run publishdev",
|
||||||
"publishnpm":"yarn build && lerna publish",
|
"publishnpm": "yarn build && lerna publish",
|
||||||
"clean": "lerna clean",
|
"clean": "lerna clean",
|
||||||
"dev": "lerna run --parallel --stream dev:builder",
|
"dev": "lerna run --parallel --stream dev:builder",
|
||||||
"test": "lerna run test",
|
"test": "lerna run test",
|
||||||
|
|
|
@ -9,6 +9,8 @@ import builtins from "rollup-plugin-node-builtins"
|
||||||
import nodeglobals from "rollup-plugin-node-globals"
|
import nodeglobals from "rollup-plugin-node-globals"
|
||||||
import copy from "rollup-plugin-copy"
|
import copy from "rollup-plugin-copy"
|
||||||
import replace from "rollup-plugin-replace"
|
import replace from "rollup-plugin-replace"
|
||||||
|
import json from '@rollup/plugin-json';
|
||||||
|
|
||||||
|
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
||||||
|
@ -133,10 +135,16 @@ export default {
|
||||||
plugins: [
|
plugins: [
|
||||||
alias({
|
alias({
|
||||||
entries: [
|
entries: [
|
||||||
{ find: "components", replacement: path.resolve(projectRootDir, 'src/components') },
|
{
|
||||||
{ find: "builderStore", replacement: path.resolve(projectRootDir, 'src/builderStore') }
|
find: "components",
|
||||||
|
replacement: path.resolve(projectRootDir, "src/components"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "builderStore",
|
||||||
|
replacement: path.resolve(projectRootDir, "src/builderStore"),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
customResolver
|
customResolver,
|
||||||
}),
|
}),
|
||||||
copy({
|
copy({
|
||||||
targets: [
|
targets: [
|
||||||
|
@ -206,5 +214,6 @@ export default {
|
||||||
// If we're building for production (npm run build
|
// If we're building for production (npm run build
|
||||||
// instead of npm run dev), minify
|
// instead of npm run dev), minify
|
||||||
production && terser(),
|
production && terser(),
|
||||||
|
json(),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,7 @@
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
padding: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
||||||
import { store } from "builderStore"
|
import components from "./temporaryPanelStructure.js"
|
||||||
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
import {
|
import {
|
||||||
find,
|
find,
|
||||||
sortBy,
|
sortBy,
|
||||||
|
@ -11,10 +12,7 @@
|
||||||
uniqBy,
|
uniqBy,
|
||||||
flatten,
|
flatten,
|
||||||
} from "lodash/fp"
|
} from "lodash/fp"
|
||||||
import { ImageIcon, InputIcon, LayoutIcon } from "components/common/Icons/"
|
|
||||||
import Select from "components/common/Select.svelte"
|
|
||||||
import Button from "components/common/PlusButton.svelte"
|
|
||||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
|
||||||
import {
|
import {
|
||||||
getRecordNodes,
|
getRecordNodes,
|
||||||
getIndexNodes,
|
getIndexNodes,
|
||||||
|
@ -22,15 +20,54 @@
|
||||||
pipe,
|
pipe,
|
||||||
} from "components/common/core"
|
} from "components/common/core"
|
||||||
|
|
||||||
|
import Tab from "./ItemTab/Tab.svelte"
|
||||||
|
import { store } from "builderStore"
|
||||||
|
|
||||||
export let toggleTab
|
export let toggleTab
|
||||||
|
|
||||||
let componentLibraries = []
|
|
||||||
let current_view = "text"
|
|
||||||
let selectedComponent = null
|
|
||||||
let selectedLib
|
|
||||||
let selectTemplateDialog
|
let selectTemplateDialog
|
||||||
let templateInstances = []
|
|
||||||
let selectedTemplateInstance
|
let selectedTemplateInstance
|
||||||
|
let templateInstances = []
|
||||||
|
|
||||||
|
let selectedComponent = null
|
||||||
|
|
||||||
|
const categories = components.categories
|
||||||
|
let selectedCategory = categories[0]
|
||||||
|
|
||||||
|
const onTemplateChosen = template => {
|
||||||
|
selectedComponent = null
|
||||||
|
const { componentName, libName } = splitName(template.name)
|
||||||
|
const templateOptions = {
|
||||||
|
records: getRecordNodes(hierarchy),
|
||||||
|
indexes: getIndexNodes(hierarchy),
|
||||||
|
helpers: {
|
||||||
|
indexSchema: getIndexSchema(hierarchy),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
templateInstances = libraryModules[libName][componentName](templateOptions)
|
||||||
|
if (!templateInstances || templateInstances.length === 0) return
|
||||||
|
selectedTemplateInstance = templateInstances[0].name
|
||||||
|
selectTemplateDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onComponentChosen = component => {
|
||||||
|
if (component.template) {
|
||||||
|
onTemplateChosen(component.template)
|
||||||
|
} else {
|
||||||
|
store.addChildComponent(component._component)
|
||||||
|
toggleTab()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onTemplateInstanceChosen = () => {
|
||||||
|
selectedComponent = null
|
||||||
|
const instance = templateInstances.find(
|
||||||
|
i => i.name === selectedTemplateInstance
|
||||||
|
)
|
||||||
|
store.addTemplatedComponent(instance.props)
|
||||||
|
toggleTab()
|
||||||
|
}
|
||||||
|
|
||||||
$: templatesByComponent = groupBy(t => t.component)($store.templates)
|
$: templatesByComponent = groupBy(t => t.component)($store.templates)
|
||||||
$: hierarchy = $store.hierarchy
|
$: hierarchy = $store.hierarchy
|
||||||
|
@ -45,157 +82,25 @@
|
||||||
uniqBy(t => t.name),
|
uniqBy(t => t.name),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
const addRootComponent = (component, allComponents) => {
|
|
||||||
const { libName } = splitName(component.name)
|
|
||||||
let group = find(r => r.libName === libName)(allComponents)
|
|
||||||
|
|
||||||
if (!group) {
|
|
||||||
group = {
|
|
||||||
libName,
|
|
||||||
components: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
allComponents.push(group)
|
|
||||||
}
|
|
||||||
|
|
||||||
group.components.push(component)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onComponentChosen = component => {
|
|
||||||
if (component.template) {
|
|
||||||
onTemplateChosen(component.template)
|
|
||||||
} else {
|
|
||||||
store.addChildComponent(component.name)
|
|
||||||
toggleTab()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onTemplateChosen = template => {
|
|
||||||
selectedComponent = null
|
|
||||||
const { componentName, libName } = splitName(template.name)
|
|
||||||
const templateOptions = {
|
|
||||||
records: getRecordNodes(hierarchy),
|
|
||||||
indexes: getIndexNodes(hierarchy),
|
|
||||||
helpers: {
|
|
||||||
indexSchema: getIndexSchema(hierarchy),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
templateInstances = libraryModules[libName][componentName](templateOptions)
|
|
||||||
if (!templateInstances || templateInstances.length === 0) return
|
|
||||||
selectedTemplateInstance = templateInstances[0].name
|
|
||||||
selectTemplateDialog.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
const onTemplateInstanceChosen = () => {
|
|
||||||
selectedComponent = null
|
|
||||||
const instance = templateInstances.find(
|
|
||||||
i => i.name === selectedTemplateInstance
|
|
||||||
)
|
|
||||||
store.addTemplatedComponent(instance.props)
|
|
||||||
toggleTab()
|
|
||||||
}
|
|
||||||
|
|
||||||
function generate_components_list(components) {
|
|
||||||
return ($store.currentFrontEndType === "page"
|
|
||||||
? $store.builtins.concat(components)
|
|
||||||
: components
|
|
||||||
).concat(standaloneTemplates)
|
|
||||||
}
|
|
||||||
|
|
||||||
$: {
|
|
||||||
const newComponentLibraries = []
|
|
||||||
|
|
||||||
for (let comp of sortBy(["name"])($store.components)) {
|
|
||||||
addRootComponent(comp, newComponentLibraries)
|
|
||||||
}
|
|
||||||
|
|
||||||
componentLibraries = newComponentLibraries
|
|
||||||
if (!selectedLib) selectedLib = newComponentLibraries[0].libName
|
|
||||||
}
|
|
||||||
|
|
||||||
$: componentLibrary = componentLibraries.find(l => l.libName === selectedLib)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<Select on:change={e => (selectedLib = e.target.value)}>
|
<ul class="tabs">
|
||||||
{#each componentLibraries as lib}
|
{#each categories as category}
|
||||||
<option value={lib.libName}>{lib.libName}</option>
|
<li
|
||||||
|
on:click={() => (selectedCategory = category)}
|
||||||
|
class:active={selectedCategory === category}>
|
||||||
|
{category.name}
|
||||||
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</ul>
|
||||||
|
<div class="panel">
|
||||||
<div class="library-container">
|
<Tab
|
||||||
<!-- <ul>
|
list={selectedCategory}
|
||||||
<li>
|
on:selectItem={e => onComponentChosen(e.detail)}
|
||||||
<button
|
{onTemplateChosen}
|
||||||
class:selected={current_view === 'text'}
|
{toggleTab} />
|
||||||
on:click={() => (current_view = 'text')}>
|
|
||||||
<InputIcon />
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
class:selected={current_view === 'layout'}
|
|
||||||
on:click={() => (current_view = 'layout')}>
|
|
||||||
<LayoutIcon />
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
class:selected={current_view === 'media'}
|
|
||||||
on:click={() => (current_view = 'media')}>
|
|
||||||
<ImageIcon />
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul> -->
|
|
||||||
|
|
||||||
{#if componentLibrary}
|
|
||||||
{#each generate_components_list(componentLibrary.components) as component}
|
|
||||||
<div class="component-container">
|
|
||||||
<div class="component" on:click={() => onComponentChosen(component)}>
|
|
||||||
<div class="name">{splitName(component.name).componentName}</div>
|
|
||||||
{#if (component.presets || templatesByComponent[component.name]) && component.name === selectedComponent}
|
|
||||||
<ul class="preset-menu">
|
|
||||||
{#if component.presets}
|
|
||||||
<span>{splitName(component.name).componentName} Presets</span>
|
|
||||||
{#each Object.keys(component.presets) as preset}
|
|
||||||
<li
|
|
||||||
on:click|stopPropagation={() => onComponentChosen(component, preset)}>
|
|
||||||
{preset}
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
{#if templatesByComponent[component.name]}
|
|
||||||
<span>
|
|
||||||
{splitName(component.name).componentName} Templates
|
|
||||||
</span>
|
|
||||||
{#each templatesByComponent[component.name] as template}
|
|
||||||
<li
|
|
||||||
on:click|stopPropagation={() => onTemplateChosen(template)}>
|
|
||||||
{template.description}
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
</ul>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{#if component.presets || templatesByComponent[component.name]}
|
|
||||||
<Button
|
|
||||||
on:click={() => {
|
|
||||||
selectedComponent = selectedComponent ? null : component.name
|
|
||||||
}}>
|
|
||||||
<span
|
|
||||||
class="open-presets"
|
|
||||||
class:open={selectedComponent === component.name}>
|
|
||||||
...
|
|
||||||
</span>
|
|
||||||
</Button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
|
@ -218,111 +123,32 @@
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.root {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
justify-content: center;
|
||||||
}
|
|
||||||
|
|
||||||
.library-container {
|
|
||||||
padding: 0 0 10px 0;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 0px;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.component-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.component {
|
|
||||||
position: relative;
|
|
||||||
padding: 0 15px;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid #d8d8d8;
|
|
||||||
border-radius: 2px;
|
|
||||||
margin: 5px 0;
|
|
||||||
height: 40px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: #000333;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex: 1;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.component:hover {
|
|
||||||
background-color: var(--lightslate);
|
|
||||||
}
|
|
||||||
|
|
||||||
.component > .name {
|
|
||||||
color: #000333;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 13px;
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
display: flex;
|
margin: 0 auto;
|
||||||
padding: 0;
|
padding: 0 30px;
|
||||||
}
|
border-bottom: 1px solid #d8d8d8;
|
||||||
|
|
||||||
.preset-menu {
|
|
||||||
flex-direction: column;
|
|
||||||
position: absolute;
|
|
||||||
top: 25px;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1;
|
|
||||||
background: #fafafa;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 2px;
|
|
||||||
color: var(--secondary80);
|
|
||||||
}
|
|
||||||
|
|
||||||
.preset-menu > span {
|
|
||||||
font-size: 13px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preset-menu li {
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-top: 13px;
|
font-weight: 500;
|
||||||
}
|
letter-spacing: 0.14px;
|
||||||
|
|
||||||
.preset-menu li:hover {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
margin-right: 20px;
|
color: #808192;
|
||||||
background: none;
|
margin: 0 5px;
|
||||||
border-radius: 5px;
|
padding: 0 8px;
|
||||||
}
|
|
||||||
|
|
||||||
/* li button {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 13px;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
} */
|
|
||||||
|
|
||||||
/* .selected {
|
|
||||||
color: var(--button-text);
|
|
||||||
background: var(--background-button) !important;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.open {
|
|
||||||
color: rgba(0, 85, 255, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.template-instance-label {
|
.panel {
|
||||||
margin-left: 20px;
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
border-bottom: solid 3px #0055ff;
|
||||||
|
color: #393c44;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -60,9 +60,7 @@
|
||||||
.switcher {
|
.switcher {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 20px;
|
margin: 20px;
|
||||||
padding: 0 20px 20px;
|
|
||||||
border-bottom: 1px solid #d8d8d8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.switcher > button {
|
.switcher > button {
|
||||||
|
@ -85,11 +83,4 @@
|
||||||
color: var(--secondary100);
|
color: var(--secondary100);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
height: 0px;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 0 20px 40px 20px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<script>
|
||||||
|
export let item
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="item-item" on:click>
|
||||||
|
<div class="item-icon">
|
||||||
|
<i class={item.icon} />
|
||||||
|
</div>
|
||||||
|
<div class="item-text">
|
||||||
|
<div class="item-name">{item.name}</div>
|
||||||
|
<div class="item-description">
|
||||||
|
<p>{item.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.item-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 10px 0px 8px 10px;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-item:hover {
|
||||||
|
background: #fbfbfb;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-icon {
|
||||||
|
flex: 0 0 40px;
|
||||||
|
background: #f1f4fc;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 5px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-text {
|
||||||
|
display: flex;
|
||||||
|
padding-left: 16px;
|
||||||
|
padding-top: 8px;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-description {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #808192;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
line-height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #808192;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script>
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
import Item from "./Item.svelte"
|
||||||
|
import { store } from "builderStore"
|
||||||
|
export let list
|
||||||
|
|
||||||
|
let category = list
|
||||||
|
|
||||||
|
const handleClick = item => {
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
list = item
|
||||||
|
} else {
|
||||||
|
dispatch("selectItem", item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
list = category
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !list.isCategory}
|
||||||
|
<button class="back-button" on:click={() => (list = category)}>Back</button>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#each list.children as item}
|
||||||
|
<Item {item} on:click={() => handleClick(item)} />
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.back-button {
|
||||||
|
font-size: 16px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: solid 1px #e8e8ef;
|
||||||
|
background: white;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,335 @@
|
||||||
|
<script>
|
||||||
|
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
||||||
|
import { store } from "builderStore"
|
||||||
|
import {
|
||||||
|
find,
|
||||||
|
sortBy,
|
||||||
|
groupBy,
|
||||||
|
values,
|
||||||
|
filter,
|
||||||
|
map,
|
||||||
|
uniqBy,
|
||||||
|
flatten,
|
||||||
|
} from "lodash/fp"
|
||||||
|
import { ImageIcon, InputIcon, LayoutIcon } from "components/common/Icons/"
|
||||||
|
import Select from "components/common/Select.svelte"
|
||||||
|
import Button from "components/common/PlusButton.svelte"
|
||||||
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
|
import {
|
||||||
|
getRecordNodes,
|
||||||
|
getIndexNodes,
|
||||||
|
getIndexSchema,
|
||||||
|
pipe,
|
||||||
|
} from "components/common/core"
|
||||||
|
|
||||||
|
export let toggleTab
|
||||||
|
|
||||||
|
let componentLibraries = []
|
||||||
|
let current_view = "text"
|
||||||
|
let selectedComponent = null
|
||||||
|
let selectedLib
|
||||||
|
let selectTemplateDialog
|
||||||
|
let templateInstances = []
|
||||||
|
let selectedTemplateInstance
|
||||||
|
|
||||||
|
//Info: Components seem to be generated from individual templates. Will this be the same going forward
|
||||||
|
$: templatesByComponent = groupBy(t => t.component)($store.templates)
|
||||||
|
$: hierarchy = $store.hierarchy
|
||||||
|
$: libraryModules = $store.libraries
|
||||||
|
$: standaloneTemplates = pipe(
|
||||||
|
templatesByComponent,
|
||||||
|
[
|
||||||
|
values,
|
||||||
|
flatten,
|
||||||
|
filter(t => !$store.components.some(c => c.name === t.component)),
|
||||||
|
map(t => ({ name: splitName(t.component).componentName, template: t })),
|
||||||
|
uniqBy(t => t.name),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
const addRootComponent = (component, allComponents) => {
|
||||||
|
const { libName } = splitName(component.name)
|
||||||
|
let group = find(r => r.libName === libName)(allComponents)
|
||||||
|
|
||||||
|
if (!group) {
|
||||||
|
group = {
|
||||||
|
libName,
|
||||||
|
components: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
allComponents.push(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
group.components.push(component)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onComponentChosen = component => {
|
||||||
|
if (component.template) {
|
||||||
|
onTemplateChosen(component.template)
|
||||||
|
} else {
|
||||||
|
store.addChildComponent(component.name)
|
||||||
|
toggleTab()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Info: Called from menu beside components with presets and templates
|
||||||
|
const onTemplateChosen = template => {
|
||||||
|
selectedComponent = null
|
||||||
|
const { componentName, libName } = splitName(template.name)
|
||||||
|
//Info: how will DB changes effect this?
|
||||||
|
const templateOptions = {
|
||||||
|
records: getRecordNodes(hierarchy),
|
||||||
|
indexes: getIndexNodes(hierarchy),
|
||||||
|
helpers: {
|
||||||
|
indexSchema: getIndexSchema(hierarchy),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
//Info: go off and get template instances by library and component name
|
||||||
|
//libraryModules and hierarchies (used above) come from builderStore
|
||||||
|
templateInstances = libraryModules[libName][componentName](templateOptions)
|
||||||
|
if (!templateInstances || templateInstances.length === 0) return
|
||||||
|
selectedTemplateInstance = templateInstances[0].name
|
||||||
|
selectTemplateDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onTemplateInstanceChosen = () => {
|
||||||
|
selectedComponent = null
|
||||||
|
const instance = templateInstances.find(
|
||||||
|
i => i.name === selectedTemplateInstance
|
||||||
|
)
|
||||||
|
debugger
|
||||||
|
store.addTemplatedComponent(instance.props)
|
||||||
|
toggleTab()
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate_components_list(components) {
|
||||||
|
debugger
|
||||||
|
return ($store.currentFrontEndType === "page"
|
||||||
|
? $store.builtins.concat(components)
|
||||||
|
: components
|
||||||
|
).concat(standaloneTemplates)
|
||||||
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
const newComponentLibraries = []
|
||||||
|
|
||||||
|
for (let comp of sortBy(["name"])($store.components)) {
|
||||||
|
addRootComponent(comp, newComponentLibraries)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentLibraries = newComponentLibraries
|
||||||
|
if (!selectedLib) selectedLib = newComponentLibraries[0].libName
|
||||||
|
}
|
||||||
|
|
||||||
|
$: componentLibrary = componentLibraries.find(l => l.libName === selectedLib)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="root">
|
||||||
|
<Select on:change={e => (selectedLib = e.target.value)}>
|
||||||
|
{#each componentLibraries as lib}
|
||||||
|
<option value={lib.libName}>{lib.libName}</option>
|
||||||
|
{/each}
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<div class="library-container">
|
||||||
|
<!-- <ul>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
class:selected={current_view === 'text'}
|
||||||
|
on:click={() => (current_view = 'text')}>
|
||||||
|
<InputIcon />
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
class:selected={current_view === 'layout'}
|
||||||
|
on:click={() => (current_view = 'layout')}>
|
||||||
|
<LayoutIcon />
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
class:selected={current_view === 'media'}
|
||||||
|
on:click={() => (current_view = 'media')}>
|
||||||
|
<ImageIcon />
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul> -->
|
||||||
|
|
||||||
|
{#if componentLibrary}
|
||||||
|
{#each generate_components_list(componentLibrary.components) as component}
|
||||||
|
<div class="component-container">
|
||||||
|
<div class="component" on:click={() => onComponentChosen(component)}>
|
||||||
|
<div class="name">{splitName(component.name).componentName}</div>
|
||||||
|
{#if (component.presets || templatesByComponent[component.name]) && component.name === selectedComponent}
|
||||||
|
<ul class="preset-menu">
|
||||||
|
{#if component.presets}
|
||||||
|
<span>{splitName(component.name).componentName} Presets</span>
|
||||||
|
{#each Object.keys(component.presets) as preset}
|
||||||
|
<li
|
||||||
|
on:click|stopPropagation={() => onComponentChosen(component, preset)}>
|
||||||
|
{preset}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{#if templatesByComponent[component.name]}
|
||||||
|
<span>
|
||||||
|
{splitName(component.name).componentName} Templates
|
||||||
|
</span>
|
||||||
|
{#each templatesByComponent[component.name] as template}
|
||||||
|
<li
|
||||||
|
on:click|stopPropagation={() => onTemplateChosen(template)}>
|
||||||
|
{template.description}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</ul>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{#if component.presets || templatesByComponent[component.name]}
|
||||||
|
<Button
|
||||||
|
on:click={() => {
|
||||||
|
selectedComponent = selectedComponent ? null : component.name
|
||||||
|
}}>
|
||||||
|
<span
|
||||||
|
class="open-presets"
|
||||||
|
class:open={selectedComponent === component.name}>
|
||||||
|
...
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
bind:this={selectTemplateDialog}
|
||||||
|
title="Choose Template"
|
||||||
|
onCancel={() => (selectedComponent = null)}
|
||||||
|
onOk={onTemplateInstanceChosen}>
|
||||||
|
{#each templateInstances.map(i => i.name) as instance}
|
||||||
|
<div class="uk-margin uk-grid-small uk-child-width-auto uk-grid">
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
class="uk-radio"
|
||||||
|
type="radio"
|
||||||
|
bind:group={selectedTemplateInstance}
|
||||||
|
value={instance} />
|
||||||
|
<span class="template-instance-label">{instance}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.root {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.library-container {
|
||||||
|
padding: 0 0 10px 0;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component {
|
||||||
|
position: relative;
|
||||||
|
padding: 0 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #d8d8d8;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin: 5px 0;
|
||||||
|
height: 40px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #000333;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component:hover {
|
||||||
|
background-color: var(--lightslate);
|
||||||
|
}
|
||||||
|
|
||||||
|
.component > .name {
|
||||||
|
color: #000333;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 13px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preset-menu {
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
top: 25px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1;
|
||||||
|
background: #fafafa;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 2px;
|
||||||
|
color: var(--secondary80);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preset-menu > span {
|
||||||
|
font-size: 13px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preset-menu li {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preset-menu li:hover {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-right: 20px;
|
||||||
|
background: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* li button {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 13px;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* .selected {
|
||||||
|
color: var(--button-text);
|
||||||
|
background: var(--background-button) !important;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.open {
|
||||||
|
color: rgba(0, 85, 255, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-instance-label {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,162 @@
|
||||||
|
export default {
|
||||||
|
categories: [
|
||||||
|
{
|
||||||
|
name: 'Basic',
|
||||||
|
isCategory: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/container",
|
||||||
|
name: 'Container',
|
||||||
|
description: 'This component contains things within itself',
|
||||||
|
icon: 'ri-layout-row-fill',
|
||||||
|
commonProps: {},
|
||||||
|
children: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Text',
|
||||||
|
description: 'This is a simple text component',
|
||||||
|
icon: 'ri-t-box-fill',
|
||||||
|
commonProps: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
_component: '@budibase/standard-components/heading',
|
||||||
|
name: 'Headline',
|
||||||
|
description: "A component for displaying heading text",
|
||||||
|
icon: "ri-heading",
|
||||||
|
props: {
|
||||||
|
type: {
|
||||||
|
type: "options",
|
||||||
|
options: ["h1", "h2", "h3", "h4", "h5", "h6"],
|
||||||
|
default: "h1",
|
||||||
|
},
|
||||||
|
text: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_component: '@budibase/standard-components/text',
|
||||||
|
name: 'Paragraph',
|
||||||
|
description: "A component for displaying paragraph text.",
|
||||||
|
icon: 'ri-paragraph',
|
||||||
|
props: {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Input',
|
||||||
|
description: "These components handle user input.",
|
||||||
|
icon: 'ri-edit-box-line',
|
||||||
|
commonProps: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/textfield",
|
||||||
|
name: "Textfield",
|
||||||
|
description: "A textfield component that allows the user to input text.",
|
||||||
|
icon: 'ri-edit-box-line',
|
||||||
|
props: {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/checkbox",
|
||||||
|
name: "Checkbox",
|
||||||
|
description: "A selectable checkbox component",
|
||||||
|
icon: 'ri-checkbox-line',
|
||||||
|
props: {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/radiobutton",
|
||||||
|
name: "Radiobutton",
|
||||||
|
description: "A selectable radiobutton component",
|
||||||
|
icon: 'ri-radio-button-line',
|
||||||
|
props: {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/select",
|
||||||
|
name: "Select",
|
||||||
|
description: "A select component for choosing from different options",
|
||||||
|
icon: 'ri-file-list-line',
|
||||||
|
props: {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/button",
|
||||||
|
name: 'Button',
|
||||||
|
description: 'A basic html button that is ready for styling',
|
||||||
|
icon: 'ri-radio-button-fill',
|
||||||
|
commonProps: {},
|
||||||
|
children: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/icon",
|
||||||
|
name: 'Icon',
|
||||||
|
description: 'A basic component for displaying icons',
|
||||||
|
icon: 'ri-sun-fill',
|
||||||
|
commonProps: {},
|
||||||
|
children: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/link",
|
||||||
|
name: 'Link',
|
||||||
|
description: 'A basic link component for internal and external links',
|
||||||
|
icon: 'ri-link',
|
||||||
|
commonProps: {},
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Blocks',
|
||||||
|
isCategory: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
_component: "@budibase/materialdesign-components/BasicCard",
|
||||||
|
name: 'Card',
|
||||||
|
description: 'A basic card component that can contain content and actions.',
|
||||||
|
icon: 'ri-layout-bottom-line',
|
||||||
|
commonProps: {},
|
||||||
|
children: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Login',
|
||||||
|
description: 'A component that automatically generates a login screen for your app.',
|
||||||
|
icon: 'ri-login-box-fill',
|
||||||
|
commonProps: {},
|
||||||
|
children: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Navigation Bar",
|
||||||
|
_component: "@budibase/standard-components/Navigation",
|
||||||
|
description: "A component for handling the navigation within your app.",
|
||||||
|
icon: "ri-navigation-fill",
|
||||||
|
commonProps: {},
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Data',
|
||||||
|
isCategory: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'Table',
|
||||||
|
description: 'A component that generates a table from your data.',
|
||||||
|
icon: 'ri-archive-drawer-fill',
|
||||||
|
commonProps: {},
|
||||||
|
children: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Form',
|
||||||
|
description: 'A component that generates a form from your data.',
|
||||||
|
icon: 'ri-file-edit-fill',
|
||||||
|
commonProps: {},
|
||||||
|
component: "@budibase/materialdesign-components/Form",
|
||||||
|
template: {
|
||||||
|
component: "@budibase/materialdesign-components/Form",
|
||||||
|
description: "Form for saving a record",
|
||||||
|
name: "@budibase/materialdesign-components/recordForm",
|
||||||
|
},
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
{
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Basic",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"component": "Container",
|
||||||
|
"description": "This component contains things within itself",
|
||||||
|
"icon": "ri-layout-row-fill",
|
||||||
|
"commonProps": {},
|
||||||
|
"type": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"component": "Text",
|
||||||
|
"description": "This is a simple text component",
|
||||||
|
"icon": "ri-t-box-fill",
|
||||||
|
"commonProps": {
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
{
|
||||||
|
"_component": "@budibase/standard-components/header",
|
||||||
|
"name": "Headline",
|
||||||
|
"icon": "headline",
|
||||||
|
"props": {
|
||||||
|
"type": {
|
||||||
|
"type": "options",
|
||||||
|
"options": [
|
||||||
|
"h1",
|
||||||
|
"h2"
|
||||||
|
],
|
||||||
|
"default": "h1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_component": "@budibase/standard-components/text",
|
||||||
|
"name": "Paragraph",
|
||||||
|
"icon": "paragraph",
|
||||||
|
"props": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"component": "Button",
|
||||||
|
"description": "A basic html button that is ready for styling",
|
||||||
|
"icon": "ri-radio-button-fill",
|
||||||
|
"commonProps": {},
|
||||||
|
"type": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"component": "Icon",
|
||||||
|
"description": "A basic component for displaying icons",
|
||||||
|
"icon": "ri-sun-fill",
|
||||||
|
"commonProps": {},
|
||||||
|
"type": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"component": "Avatar",
|
||||||
|
"description": "A basic component for rendering an avatar",
|
||||||
|
"icon": "ri-user-smile-fill",
|
||||||
|
"commonProps": {},
|
||||||
|
"type": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"component": "Link",
|
||||||
|
"description": "A basic link component for internal and external links",
|
||||||
|
"icon": "ri-link",
|
||||||
|
"commonProps": {},
|
||||||
|
"type": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -115,6 +115,21 @@
|
||||||
},
|
},
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
|
"BasicCard": {
|
||||||
|
"name": "BasicCard",
|
||||||
|
"description": "This is a basic card",
|
||||||
|
"props": {
|
||||||
|
"heading": "string",
|
||||||
|
"subheading": "string",
|
||||||
|
"content": "string",
|
||||||
|
"imageUrl": "string",
|
||||||
|
"button1Text": "string",
|
||||||
|
"button2Text": "string",
|
||||||
|
"cardClick": "event",
|
||||||
|
"button1Click": "event",
|
||||||
|
"button2Click": "event"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Card": {
|
"Card": {
|
||||||
"name": "Card",
|
"name": "Card",
|
||||||
"description": "A Material Card container. Accepts CardHeader, CardBody and CardFooter as possible children",
|
"description": "A Material Card container. Accepts CardHeader, CardBody and CardFooter as possible children",
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
<script>
|
||||||
|
export let heading = ""
|
||||||
|
export let subheading = ""
|
||||||
|
export let content = ""
|
||||||
|
export let imageUrl = ""
|
||||||
|
export let button1Text = ""
|
||||||
|
export let button2Text = ""
|
||||||
|
export let cardClick = () => {}
|
||||||
|
export let button1Click = () => {}
|
||||||
|
export let button2Click = () => {}
|
||||||
|
|
||||||
|
$: showImage = !!imageUrl
|
||||||
|
$: showButton1 = !!button1Text
|
||||||
|
$: showButton2 = !!button2Text
|
||||||
|
$: showButtons = !!showButton1 && !!showButton2
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mdc-card" on:click={cardClick}>
|
||||||
|
<div class="mdc-card__primary-action demo-card__primary-action" tabindex="0">
|
||||||
|
{#if showImage}
|
||||||
|
<div
|
||||||
|
class="mdc-card__media mdc-card__media--16-9 demo-card__media"
|
||||||
|
style="background-image: url("{imageUrl}");" />
|
||||||
|
{/if}
|
||||||
|
<div class="pad">
|
||||||
|
<div class="demo-card__primary">
|
||||||
|
<h2 class="demo-card__title mdc-typography mdc-typography--headline6">
|
||||||
|
{heading}
|
||||||
|
</h2>
|
||||||
|
<h3
|
||||||
|
class="demo-card__subtitle mdc-typography mdc-typography--subtitle2">
|
||||||
|
{subheading}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="demo-card__secondary mdc-typography mdc-typography--body2">
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#if showButtons}
|
||||||
|
<div class="mdc-card__actions">
|
||||||
|
<div class="mdc-card__action-buttons">
|
||||||
|
{#if showButton1}
|
||||||
|
<button class="mdc-button mdc-card__action mdc-card__action--button">
|
||||||
|
<span class="mdc-button__ripple" on:click={button1Click} />
|
||||||
|
{button1Text}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if showButton2}
|
||||||
|
<button
|
||||||
|
class="mdc-button mdc-card__action mdc-card__action--button"
|
||||||
|
on:click={button2Click}>
|
||||||
|
<span class="mdc-button__ripple" />
|
||||||
|
{button2Text}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.pad {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,5 +1,6 @@
|
||||||
import "./_styles.scss"
|
import "./_styles.scss"
|
||||||
export { default as Card } from "./Card.svelte"
|
export { default as Card } from "./Card.svelte"
|
||||||
|
export { default as BasicCard } from "./BasicCard.svelte"
|
||||||
export { default as CardBody } from "./CardBody.svelte"
|
export { default as CardBody } from "./CardBody.svelte"
|
||||||
export { default as CardFooter } from "./CardFooter.svelte"
|
export { default as CardFooter } from "./CardFooter.svelte"
|
||||||
export { default as CardHeader } from "./CardHeader.svelte"
|
export { default as CardHeader } from "./CardHeader.svelte"
|
||||||
|
|
|
@ -22,7 +22,7 @@ export { Menu } from "./Menu"
|
||||||
export { Select } from "./Select"
|
export { Select } from "./Select"
|
||||||
export { DatePicker } from "./DatePicker"
|
export { DatePicker } from "./DatePicker"
|
||||||
export { IconButton } from "./IconButton"
|
export { IconButton } from "./IconButton"
|
||||||
export { Card, CardHeader, CardImage, CardBody, CardFooter } from "./Card"
|
export { Card, CardHeader, CardImage, CardBody, CardFooter, BasicCard } from "./Card"
|
||||||
export { Dialog, DialogHeader, DialogContent, DialogActions } from "./Dialog"
|
export { Dialog, DialogHeader, DialogContent, DialogActions } from "./Dialog"
|
||||||
export { Switch } from "./Switch"
|
export { Switch } from "./Switch"
|
||||||
export { Slider } from "./Slider"
|
export { Slider } from "./Slider"
|
||||||
|
|
|
@ -1,16 +1,32 @@
|
||||||
{
|
{
|
||||||
"_lib": "./dist/index.js",
|
"_lib": "./dist/index.js",
|
||||||
"_templates" : {
|
"_templates": {
|
||||||
"saveRecordButton" : {
|
"saveRecordButton": {
|
||||||
"description": "Save record button",
|
"description": "Save record button",
|
||||||
"component": "button"
|
"component": "button"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"button" : {
|
"Navigation": {
|
||||||
|
"name": "Navigation",
|
||||||
|
"description": "A basic header navigation component",
|
||||||
|
"props": {
|
||||||
|
"logoUrl": "string",
|
||||||
|
"title": "string",
|
||||||
|
"backgroundColor": "string",
|
||||||
|
"color": "string",
|
||||||
|
"borderWidth": "string",
|
||||||
|
"borderColor": "string",
|
||||||
|
"borderStyle": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"button": {
|
||||||
"name": "Button",
|
"name": "Button",
|
||||||
"description": "an html <button />",
|
"description": "an html <button />",
|
||||||
"props": {
|
"props": {
|
||||||
"contentText": { "type": "string", "default": "Button" },
|
"contentText": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "Button"
|
||||||
|
},
|
||||||
"className": "string",
|
"className": "string",
|
||||||
"disabled": "bool",
|
"disabled": "bool",
|
||||||
"onClick": "event",
|
"onClick": "event",
|
||||||
|
@ -22,76 +38,110 @@
|
||||||
"hoverBackground": "string",
|
"hoverBackground": "string",
|
||||||
"hoverBorder": "string"
|
"hoverBorder": "string"
|
||||||
},
|
},
|
||||||
"tags": ["layout"],
|
"tags": [
|
||||||
|
"layout"
|
||||||
|
],
|
||||||
"presets": {
|
"presets": {
|
||||||
"primary": {
|
"primary": {
|
||||||
"contentText": "Primary Button Preset",
|
"contentText": "Primary Button Preset",
|
||||||
"color": "papayawhip",
|
"color": "papayawhip",
|
||||||
"padding": "20px",
|
"padding": "20px",
|
||||||
"background": "blue"
|
"background": "blue"
|
||||||
},
|
},
|
||||||
"secondary": {
|
"secondary": {
|
||||||
"contentText": "Secondary Button Preset",
|
"contentText": "Secondary Button Preset",
|
||||||
"color": "rebeccapurple",
|
"color": "rebeccapurple",
|
||||||
"padding": "10px",
|
"padding": "10px",
|
||||||
"background": "#fff",
|
"background": "#fff",
|
||||||
"border": "1px solid red"
|
"border": "1px solid red"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"contentText": "ERROR",
|
"contentText": "ERROR",
|
||||||
"color": "red",
|
"color": "red",
|
||||||
"padding": "10px",
|
"padding": "10px",
|
||||||
"border": "1px solid red"
|
"border": "1px solid red"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login" : {
|
"login": {
|
||||||
"name": "Login Control",
|
"name": "Login Control",
|
||||||
"description": "A control that accepts username, password an also handles password resets",
|
"description": "A control that accepts username, password an also handles password resets",
|
||||||
"props" : {
|
"props": {
|
||||||
"logo": "asset",
|
"logo": "asset",
|
||||||
"loginRedirect": "string",
|
"loginRedirect": "string",
|
||||||
"usernameLabel": {"type":"string", "default": "Username"},
|
"usernameLabel": {
|
||||||
"passwordLabel": {"type":"string", "default": "Password"},
|
"type": "string",
|
||||||
"loginButtonLabel": {"type":"string", "default": "Login"},
|
"default": "Username"
|
||||||
|
},
|
||||||
|
"passwordLabel": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "Password"
|
||||||
|
},
|
||||||
|
"loginButtonLabel": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "Login"
|
||||||
|
},
|
||||||
"buttonClass": "string",
|
"buttonClass": "string",
|
||||||
"inputClass": "string"
|
"inputClass": "string"
|
||||||
},
|
},
|
||||||
"tags": ["login", "credentials", "password", "logon"]
|
"tags": [
|
||||||
|
"login",
|
||||||
|
"credentials",
|
||||||
|
"password",
|
||||||
|
"logon"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"input" : {
|
"input": {
|
||||||
"name": "Input",
|
"name": "Input",
|
||||||
"description": "An HTML input",
|
"description": "An HTML input",
|
||||||
"props" : {
|
"props": {
|
||||||
"value": "string",
|
"value": "string",
|
||||||
"type": {
|
"type": {
|
||||||
"type":"options",
|
"type": "options",
|
||||||
"options":[
|
"options": [
|
||||||
"text", "password", "checkbox", "color",
|
"text",
|
||||||
"date", "datetime-local", "email",
|
"password",
|
||||||
"file", "hidden", "image", "month", "number",
|
"checkbox",
|
||||||
"radio", "range", "reset", "search", "submit",
|
"color",
|
||||||
"tel", "time", "week"],
|
"date",
|
||||||
"default":"text"
|
"datetime-local",
|
||||||
|
"email",
|
||||||
|
"file",
|
||||||
|
"hidden",
|
||||||
|
"image",
|
||||||
|
"month",
|
||||||
|
"number",
|
||||||
|
"radio",
|
||||||
|
"range",
|
||||||
|
"reset",
|
||||||
|
"search",
|
||||||
|
"submit",
|
||||||
|
"tel",
|
||||||
|
"time",
|
||||||
|
"week"
|
||||||
|
],
|
||||||
|
"default": "text"
|
||||||
},
|
},
|
||||||
"onChange": "event",
|
"onChange": "event",
|
||||||
"className": "string"
|
"className": "string"
|
||||||
},
|
},
|
||||||
"tags": ["form"]
|
"tags": [
|
||||||
|
"form"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"select" : {
|
"select": {
|
||||||
"name": "Select",
|
"name": "Select",
|
||||||
"description": "An HTML <select> (dropdown)",
|
"description": "An HTML <select> (dropdown)",
|
||||||
"props" : {
|
"props": {
|
||||||
"value": "string",
|
"value": "string",
|
||||||
"className": "string"
|
"className": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"option" : {
|
"option": {
|
||||||
"name": "Option",
|
"name": "Option",
|
||||||
"description": "An HTML <option>, to be used with <select>",
|
"description": "An HTML <option>, to be used with <select>",
|
||||||
"children": false,
|
"children": false,
|
||||||
"props" : {
|
"props": {
|
||||||
"value": "string",
|
"value": "string",
|
||||||
"text": "string"
|
"text": "string"
|
||||||
}
|
}
|
||||||
|
@ -100,27 +150,32 @@
|
||||||
"name": "Text",
|
"name": "Text",
|
||||||
"description": "stylable block of text",
|
"description": "stylable block of text",
|
||||||
"children": false,
|
"children": false,
|
||||||
"props" : {
|
"props": {
|
||||||
"text": "string",
|
"text": "string",
|
||||||
"font": "string",
|
"font": "string",
|
||||||
|
"fontSize": "string",
|
||||||
"color": "string",
|
"color": "string",
|
||||||
"textAlign": {
|
"textAlign": {
|
||||||
"type": "options",
|
"type": "options",
|
||||||
"default":"inline",
|
"default": "inline",
|
||||||
"options": [
|
"options": [
|
||||||
"left", "center", "right"
|
"left",
|
||||||
|
"center",
|
||||||
|
"right"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"verticalAlign": {
|
"verticalAlign": {
|
||||||
"type": "options",
|
"type": "options",
|
||||||
"default":"inline",
|
"default": "inline",
|
||||||
"options": [
|
"options": [
|
||||||
"top", "middle", "bottom"
|
"top",
|
||||||
|
"middle",
|
||||||
|
"bottom"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"formattingTag": {
|
"formattingTag": {
|
||||||
"type": "options",
|
"type": "options",
|
||||||
"default":"none",
|
"default": "none",
|
||||||
"options": [
|
"options": [
|
||||||
"none",
|
"none",
|
||||||
"<b> - bold",
|
"<b> - bold",
|
||||||
|
@ -136,7 +191,46 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tags": ["div", "container"]
|
"tags": [
|
||||||
|
"div",
|
||||||
|
"container"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"textfield": {
|
||||||
|
"name": "Textfield",
|
||||||
|
"description": "A component that allows the user to input text.",
|
||||||
|
"props": {
|
||||||
|
"label": "string",
|
||||||
|
"value": "string",
|
||||||
|
"onchange": "event"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"checkbox": {
|
||||||
|
"name": "Checkbox",
|
||||||
|
"description": "A selectable checkbox component",
|
||||||
|
"props": {
|
||||||
|
"label": "string",
|
||||||
|
"checked": "bool",
|
||||||
|
"value": "string",
|
||||||
|
"onchange": "event"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"radiobutton": {
|
||||||
|
"name": "Radiobutton",
|
||||||
|
"description": "A selectable radiobutton component",
|
||||||
|
"props": {
|
||||||
|
"label": "string",
|
||||||
|
"checked": "bool",
|
||||||
|
"value": "string",
|
||||||
|
"onchange": "event"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"description": "A HTML icon tag",
|
||||||
|
"props": {
|
||||||
|
"icon": "string",
|
||||||
|
"fontSize": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"link": {
|
"link": {
|
||||||
"description": "an HTML anchor <a> tag",
|
"description": "an HTML anchor <a> tag",
|
||||||
|
@ -163,11 +257,11 @@
|
||||||
"container": {
|
"container": {
|
||||||
"name": "Container",
|
"name": "Container",
|
||||||
"description": "An element that contains and lays out other elements. e.g. <div>, <header> etc",
|
"description": "An element that contains and lays out other elements. e.g. <div>, <header> etc",
|
||||||
"props" : {
|
"props": {
|
||||||
"className":"string",
|
"className": "string",
|
||||||
"onLoad": "event",
|
"onLoad": "event",
|
||||||
"type": {
|
"type": {
|
||||||
"type": "options",
|
"type": "options",
|
||||||
"options": [
|
"options": [
|
||||||
"article",
|
"article",
|
||||||
"aside",
|
"aside",
|
||||||
|
@ -190,7 +284,7 @@
|
||||||
"borderWidth": "string",
|
"borderWidth": "string",
|
||||||
"borderColor": "string",
|
"borderColor": "string",
|
||||||
"borderStyle": {
|
"borderStyle": {
|
||||||
"type":"options",
|
"type": "options",
|
||||||
"options": [
|
"options": [
|
||||||
"none",
|
"none",
|
||||||
"solid",
|
"solid",
|
||||||
|
@ -204,20 +298,31 @@
|
||||||
],
|
],
|
||||||
"default": "none"
|
"default": "none"
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
"container": true,
|
"container": true,
|
||||||
"tags": ["div", "container", "layout"]
|
"tags": [
|
||||||
|
"div",
|
||||||
|
"container",
|
||||||
|
"layout"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"heading": {
|
"heading": {
|
||||||
"name": "Heading",
|
"name": "Heading",
|
||||||
"description": "An HTML H1 - H6 tag",
|
"description": "An HTML H1 - H6 tag",
|
||||||
"props" : {
|
"props": {
|
||||||
"className":"string",
|
"className": "string",
|
||||||
|
"text": "string",
|
||||||
"type": {
|
"type": {
|
||||||
"type": "options",
|
"type": "options",
|
||||||
"default": "h1",
|
"default": "h1",
|
||||||
"options": ["h1","h2","h3","h4","h5","h6"]
|
"options": [
|
||||||
|
"h1",
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"h4",
|
||||||
|
"h5",
|
||||||
|
"h6"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tags": []
|
"tags": []
|
||||||
|
@ -225,15 +330,15 @@
|
||||||
"thead": {
|
"thead": {
|
||||||
"name": "TableHead",
|
"name": "TableHead",
|
||||||
"description": "an HTML <thead> tab",
|
"description": "an HTML <thead> tab",
|
||||||
"props" : {
|
"props": {
|
||||||
"className":"string"
|
"className": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tbody": {
|
"tbody": {
|
||||||
"name": "TableBody",
|
"name": "TableBody",
|
||||||
"description": "an HTML <tbody> tab",
|
"description": "an HTML <tbody> tab",
|
||||||
"props" : {
|
"props": {
|
||||||
"className":"string"
|
"className": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script>
|
||||||
|
import Input from "./Input.svelte"
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
export let label = ""
|
||||||
|
export let checked = false
|
||||||
|
export let value = ""
|
||||||
|
export let onchange = () => {}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Input type="checkbox" {_bb} {checked} {label} {value} {onchange} />
|
|
@ -2,22 +2,22 @@
|
||||||
export let className = ""
|
export let className = ""
|
||||||
export let type
|
export let type
|
||||||
export let _bb
|
export let _bb
|
||||||
|
export let text = ""
|
||||||
let containerElement
|
let containerElement
|
||||||
|
|
||||||
$: containerElement && _bb.attachChildren(containerElement)
|
$: containerElement && !text && _bb.attachChildren(containerElement)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if type === 'h1'}
|
{#if type === 'h1'}
|
||||||
<h1 class={className} bind:this={containerElement} />
|
<h1 class={className} bind:this={containerElement}>{text}</h1>
|
||||||
{:else if type === 'h2'}
|
{:else if type === 'h2'}
|
||||||
<h2 class={className} bind:this={containerElement} />
|
<h2 class={className} bind:this={containerElement}>{text}</h2>
|
||||||
{:else if type === 'h3'}
|
{:else if type === 'h3'}
|
||||||
<h3 class={className} bind:this={containerElement} />
|
<h3 class={className} bind:this={containerElement}>{text}</h3>
|
||||||
{:else if type === 'h4'}
|
{:else if type === 'h4'}
|
||||||
<h4 class={className} bind:this={containerElement} />
|
<h4 class={className} bind:this={containerElement}>{text}</h4>
|
||||||
{:else if type === 'h5'}
|
{:else if type === 'h5'}
|
||||||
<h5 class={className} bind:this={containerElement} />
|
<h5 class={className} bind:this={containerElement}>{text}</h5>
|
||||||
{:else if type === 'h6'}
|
{:else if type === 'h6'}
|
||||||
<h6 class={className} bind:this={containerElement} />
|
<h6 class={className} bind:this={containerElement}>{text}</h6>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<script>
|
||||||
|
export let icon = ""
|
||||||
|
export let fontSize = "1em"
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
$: style = { fontSize }
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<i class={icon} {style} />
|
|
@ -1,7 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
|
export let id = ""
|
||||||
export let value = ""
|
export let value = ""
|
||||||
export let className = ""
|
export let className = ""
|
||||||
export let type = "text"
|
export let type = "text"
|
||||||
|
export let label = ""
|
||||||
|
export let checked = false
|
||||||
|
|
||||||
export let _bb
|
export let _bb
|
||||||
|
|
||||||
|
@ -14,4 +17,5 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<input class={className} {type} {value} on:change={onchange} />
|
<label for={id}>{label}</label>
|
||||||
|
<input {id} class={className} {type} {value} {checked} on:change={onchange} />
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
<script>
|
||||||
|
import { cssVars, createClasses } from "./cssVars"
|
||||||
|
|
||||||
|
export let className = ""
|
||||||
|
export let onLoad
|
||||||
|
export let backgroundColor
|
||||||
|
export let color
|
||||||
|
export let borderWidth
|
||||||
|
export let borderColor
|
||||||
|
export let borderStyle
|
||||||
|
export let logoUrl
|
||||||
|
export let title
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
let itemContainer
|
||||||
|
let hasLoaded
|
||||||
|
let currentChildren
|
||||||
|
|
||||||
|
$: cssVariables = {
|
||||||
|
backgroundColor,
|
||||||
|
color,
|
||||||
|
borderWidth,
|
||||||
|
borderColor,
|
||||||
|
borderStyle,
|
||||||
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (itemContainer) {
|
||||||
|
_bb.attachChildren(itemContainer)
|
||||||
|
if (!hasLoaded) {
|
||||||
|
_bb.call(onLoad)
|
||||||
|
hasLoaded = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav use:cssVars={cssVariables}>
|
||||||
|
<a href="/">
|
||||||
|
<img class="logo" alt="logo" src={logoUrl} height="30" />
|
||||||
|
<span>{title}</span>
|
||||||
|
</a>
|
||||||
|
<div class="menu-items" bind:this={itemContainer} />
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
nav {
|
||||||
|
color: var(--color);
|
||||||
|
background-color: var(--backgroundColor);
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
font-weight: bold;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20px 0 20px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav > a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1.5em;
|
||||||
|
color: var(--color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a img {
|
||||||
|
border-radius: 15px;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
.menu-items {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.menu-items > :global(*) {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script>
|
||||||
|
import Input from "./Input.svelte"
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
export let label = ""
|
||||||
|
export let checked = false
|
||||||
|
export let value = ""
|
||||||
|
export let onchange = () => {}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Input type="radio" {_bb} {checked} {label} {value} {onchange} />
|
|
@ -7,29 +7,26 @@
|
||||||
export let formattingTag = ""
|
export let formattingTag = ""
|
||||||
|
|
||||||
export let font = ""
|
export let font = ""
|
||||||
|
export let fontSize = "1em"
|
||||||
export let textAlign = ""
|
export let textAlign = ""
|
||||||
export let verticalAlign = ""
|
export let verticalAlign = ""
|
||||||
export let color = ""
|
export let color = ""
|
||||||
|
|
||||||
export let _bb
|
export let _bb
|
||||||
|
|
||||||
let style = ""
|
|
||||||
|
|
||||||
const isTag = tag => (formattingTag || "").indexOf(tag) > -1
|
const isTag = tag => (formattingTag || "").indexOf(tag) > -1
|
||||||
|
|
||||||
$: {
|
$: style = buildStyle({
|
||||||
style = buildStyle({
|
font: `${fontSize} ${font}`,
|
||||||
font,
|
verticalAlign,
|
||||||
verticalAlign,
|
color,
|
||||||
color,
|
"text-align": textAlign,
|
||||||
"text-align": textAlign,
|
"vertical-align": verticalAlign,
|
||||||
"vertical-align": verticalAlign,
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if isTag('none')}
|
{#if isTag('none')}
|
||||||
<span>{text}</span>
|
<span {style}>{text}</span>
|
||||||
{:else if isTag('<b>')}
|
{:else if isTag('<b>')}
|
||||||
<b class={className} {style}>{text}</b>
|
<b class={className} {style}>{text}</b>
|
||||||
{:else if isTag('<strong>')}
|
{:else if isTag('<strong>')}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<script>
|
||||||
|
import Input from "./Input.svelte"
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
export let label = ""
|
||||||
|
export let value = ""
|
||||||
|
export let onchange = () => {}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Input type="text" {_bb} {label} {value} {onchange} />
|
|
@ -3,9 +3,14 @@ export { default as text } from "./Text.svelte"
|
||||||
export { default as heading } from "./Heading.svelte"
|
export { default as heading } from "./Heading.svelte"
|
||||||
export { default as input } from "./Input.svelte"
|
export { default as input } from "./Input.svelte"
|
||||||
export { default as select } from "./Select.svelte"
|
export { default as select } from "./Select.svelte"
|
||||||
|
export { default as textfield } from "./Textfield.svelte"
|
||||||
|
export { default as checkbox } from "./Checkbox.svelte"
|
||||||
|
export { default as radiobutton } from "./Radiobutton.svelte"
|
||||||
export { default as option } from "./Option.svelte"
|
export { default as option } from "./Option.svelte"
|
||||||
export { default as button } from "./Button.svelte"
|
export { default as button } from "./Button.svelte"
|
||||||
export { default as login } from "./Login.svelte"
|
export { default as login } from "./Login.svelte"
|
||||||
export { default as saveRecordButton } from "./Templates/saveRecordButton"
|
export { default as saveRecordButton } from "./Templates/saveRecordButton"
|
||||||
export { default as link } from "./Link.svelte"
|
export { default as link } from "./Link.svelte"
|
||||||
export { default as image } from "./Image.svelte"
|
export { default as image } from "./Image.svelte"
|
||||||
|
export { default as icon } from "./Icon.svelte"
|
||||||
|
export { default as Navigation } from "./Navigation.svelte"
|
||||||
|
|
65
yarn.lock
65
yarn.lock
|
@ -918,6 +918,27 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" ">= 8"
|
"@types/node" ">= 8"
|
||||||
|
|
||||||
|
"@rollup/plugin-json@^4.0.2":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.0.2.tgz#482185ee36ac7dd21c346e2dbcc22ffed0c6f2d6"
|
||||||
|
integrity sha512-t4zJMc98BdH42mBuzjhQA7dKh0t4vMJlUka6Fz0c+iO5IVnWaEMiYBy1uBj9ruHZzXBW23IPDGL9oCzBkQ9Udg==
|
||||||
|
dependencies:
|
||||||
|
"@rollup/pluginutils" "^3.0.4"
|
||||||
|
|
||||||
|
"@rollup/pluginutils@^3.0.4":
|
||||||
|
version "3.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.0.9.tgz#aa6adca2c45e5a1b950103a999e3cddfe49fd775"
|
||||||
|
integrity sha512-TLZavlfPAZYI7v33wQh4mTP6zojne14yok3DNSLcjoG/Hirxfkonn6icP5rrNWRn8nZsirJBFFpijVOJzkUHDg==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "0.0.39"
|
||||||
|
estree-walker "^1.0.1"
|
||||||
|
micromatch "^4.0.2"
|
||||||
|
|
||||||
|
"@types/estree@0.0.39":
|
||||||
|
version "0.0.39"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
|
||||||
|
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
|
||||||
|
|
||||||
"@types/node@>= 8":
|
"@types/node@>= 8":
|
||||||
version "13.5.3"
|
version "13.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.5.3.tgz#37f1f539b7535b9fb4ef77d59db1847a837b7f17"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.5.3.tgz#37f1f539b7535b9fb4ef77d59db1847a837b7f17"
|
||||||
|
@ -1216,6 +1237,13 @@ braces@^2.3.1:
|
||||||
split-string "^3.0.2"
|
split-string "^3.0.2"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
|
braces@^3.0.1:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||||
|
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||||
|
dependencies:
|
||||||
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
btoa-lite@^1.0.0:
|
btoa-lite@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337"
|
resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337"
|
||||||
|
@ -2065,6 +2093,11 @@ estree-walker@^0.6.1:
|
||||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
|
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
|
||||||
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
|
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
|
||||||
|
|
||||||
|
estree-walker@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
|
||||||
|
integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
|
||||||
|
|
||||||
esutils@^2.0.2:
|
esutils@^2.0.2:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||||
|
@ -2222,6 +2255,13 @@ fill-range@^4.0.0:
|
||||||
repeat-string "^1.6.1"
|
repeat-string "^1.6.1"
|
||||||
to-regex-range "^2.1.0"
|
to-regex-range "^2.1.0"
|
||||||
|
|
||||||
|
fill-range@^7.0.1:
|
||||||
|
version "7.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||||
|
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||||
|
dependencies:
|
||||||
|
to-regex-range "^5.0.1"
|
||||||
|
|
||||||
find-up@^1.0.0:
|
find-up@^1.0.0:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
|
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
|
||||||
|
@ -2930,6 +2970,11 @@ is-number@^3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
kind-of "^3.0.2"
|
kind-of "^3.0.2"
|
||||||
|
|
||||||
|
is-number@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||||
|
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||||
|
|
||||||
is-obj@^1.0.0:
|
is-obj@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
||||||
|
@ -3464,6 +3509,14 @@ micromatch@^3.1.10:
|
||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.2"
|
to-regex "^3.0.2"
|
||||||
|
|
||||||
|
micromatch@^4.0.2:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
|
||||||
|
integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
|
||||||
|
dependencies:
|
||||||
|
braces "^3.0.1"
|
||||||
|
picomatch "^2.0.5"
|
||||||
|
|
||||||
mime-db@1.43.0:
|
mime-db@1.43.0:
|
||||||
version "1.43.0"
|
version "1.43.0"
|
||||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
|
||||||
|
@ -4174,6 +4227,11 @@ performance-now@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||||
|
|
||||||
|
picomatch@^2.0.5:
|
||||||
|
version "2.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
||||||
|
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
|
||||||
|
|
||||||
pify@^2.0.0, pify@^2.3.0:
|
pify@^2.0.0, pify@^2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||||
|
@ -5141,6 +5199,13 @@ to-regex-range@^2.1.0:
|
||||||
is-number "^3.0.0"
|
is-number "^3.0.0"
|
||||||
repeat-string "^1.6.1"
|
repeat-string "^1.6.1"
|
||||||
|
|
||||||
|
to-regex-range@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||||
|
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
|
||||||
|
dependencies:
|
||||||
|
is-number "^7.0.0"
|
||||||
|
|
||||||
to-regex@^3.0.1, to-regex@^3.0.2:
|
to-regex@^3.0.1, to-regex@^3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
|
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
|
||||||
|
|
Loading…
Reference in New Issue