Merge pull request #115 from mjashanks/master
New Components, Bug fixes... including PR #114
This commit is contained in:
commit
a5ad52d822
38 changed files with 729 additions and 259 deletions
|
@ -55,7 +55,7 @@
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
background: white;
|
background: white;
|
||||||
padding: 0px 15px;
|
padding: 0px 15px 0 1.8rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -104,7 +104,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding: 8px 10px;
|
padding: 8px 10px 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-logo:hover {
|
.home-logo:hover {
|
||||||
|
|
|
@ -4,22 +4,29 @@ import { pipe } from "../common/core"
|
||||||
const self = n => n
|
const self = n => n
|
||||||
const join_with = delimiter => a => a.join(delimiter)
|
const join_with = delimiter => a => a.join(delimiter)
|
||||||
const empty_string_to_unset = s => (s.length ? s : "0")
|
const empty_string_to_unset = s => (s.length ? s : "0")
|
||||||
const add_suffix = suffix => s => s + suffix
|
const add_suffix_if_number = suffix => s => {
|
||||||
|
try {
|
||||||
|
if (isNaN(s) || isNaN(parseFloat(s))) return s
|
||||||
|
} catch (_) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return s + suffix
|
||||||
|
}
|
||||||
|
|
||||||
export const make_margin = values =>
|
export const make_margin = values =>
|
||||||
pipe(values, [
|
pipe(values, [
|
||||||
map(empty_string_to_unset),
|
map(empty_string_to_unset),
|
||||||
map(add_suffix("px")),
|
map(add_suffix_if_number("px")),
|
||||||
join_with(" "),
|
join_with(" "),
|
||||||
])
|
])
|
||||||
|
|
||||||
const css_map = {
|
const css_map = {
|
||||||
templaterows: {
|
templaterows: {
|
||||||
name: "grid-template-columns",
|
name: "grid-template-rows",
|
||||||
generate: self,
|
generate: self,
|
||||||
},
|
},
|
||||||
templatecolumns: {
|
templatecolumns: {
|
||||||
name: "grid-template-rows",
|
name: "grid-template-columns",
|
||||||
generate: self,
|
generate: self,
|
||||||
},
|
},
|
||||||
gridarea: {
|
gridarea: {
|
||||||
|
@ -58,6 +65,14 @@ const css_map = {
|
||||||
name: "z-index",
|
name: "z-index",
|
||||||
generate: self,
|
generate: self,
|
||||||
},
|
},
|
||||||
|
height: {
|
||||||
|
name: "height",
|
||||||
|
generate: self,
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
name: "width",
|
||||||
|
generate: self,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generate_rule = ([name, values]) =>
|
export const generate_rule = ([name, values]) =>
|
||||||
|
@ -97,10 +112,11 @@ const apply_class = (id, name, styles) => `.${name}-${id} {\n${styles}\n}`
|
||||||
|
|
||||||
export const generate_screen_css = component_array => {
|
export const generate_screen_css = component_array => {
|
||||||
let styles = ""
|
let styles = ""
|
||||||
|
let emptyStyles = { layout: {}, position: {} }
|
||||||
|
|
||||||
for (let i = 0; i < component_array.length; i += 1) {
|
for (let i = 0; i < component_array.length; i += 1) {
|
||||||
const { _styles, _id, _children } = component_array[i]
|
const { _styles, _id, _children } = component_array[i]
|
||||||
const { layout, position } = generate_css(_styles)
|
const { layout, position } = generate_css(_styles || emptyStyles)
|
||||||
|
|
||||||
styles += apply_class(_id, "pos", position) + "\n"
|
styles += apply_class(_id, "pos", position) + "\n"
|
||||||
styles += apply_class(_id, "lay", layout) + "\n"
|
styles += apply_class(_id, "lay", layout) + "\n"
|
||||||
|
|
|
@ -721,9 +721,27 @@ const getContainerComponent = components =>
|
||||||
*/
|
*/
|
||||||
const addChildComponent = store => (componentToAdd, presetName) => {
|
const addChildComponent = store => (componentToAdd, presetName) => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
|
function findSlot(component_array) {
|
||||||
|
for (let i = 0; i < component_array.length; i += 1) {
|
||||||
|
if (component_array[i]._component === "##builtin/screenslot")
|
||||||
|
return true
|
||||||
|
if (component_array[i]._children) findSlot(component_array[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
componentToAdd.startsWith("##") &&
|
||||||
|
findSlot(state.pages[state.currentPageName].props._children)
|
||||||
|
) {
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
const component = componentToAdd.startsWith("##")
|
const component = componentToAdd.startsWith("##")
|
||||||
? getBuiltin(componentToAdd)
|
? getBuiltin(componentToAdd)
|
||||||
: state.components.find(({ name }) => name === componentToAdd)
|
: state.components.find(({ name }) => name === componentToAdd)
|
||||||
|
|
||||||
const presetProps = presetName ? component.presets[presetName] : {}
|
const presetProps = presetName ? component.presets[presetName] : {}
|
||||||
const newComponent = createProps(component, presetProps)
|
const newComponent = createProps(component, presetProps)
|
||||||
|
|
||||||
|
@ -731,7 +749,9 @@ const addChildComponent = store => (componentToAdd, presetName) => {
|
||||||
newComponent.props
|
newComponent.props
|
||||||
)
|
)
|
||||||
|
|
||||||
_savePage(state)
|
state.currentFrontEndType === "page"
|
||||||
|
? _savePage(state)
|
||||||
|
: _saveScreenApi(state.currentPreviewItem, state)
|
||||||
|
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
|
@ -749,7 +769,7 @@ const addTemplatedComponent = store => props => {
|
||||||
props
|
props
|
||||||
)
|
)
|
||||||
|
|
||||||
_savePage(state)
|
_saveCurrentPreviewItem(state)
|
||||||
|
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
|
@ -792,9 +812,7 @@ const setComponentStyle = store => (type, name, value) => {
|
||||||
])
|
])
|
||||||
|
|
||||||
// save without messing with the store
|
// save without messing with the store
|
||||||
s.currentFrontEndType === "page"
|
_saveCurrentPreviewItem(s)
|
||||||
? _savePage(s)
|
|
||||||
: _saveScreenApi(s.currentPreviewItem, s)
|
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -843,9 +861,7 @@ const deleteComponent = store => component => {
|
||||||
parent._children = parent._children.filter(c => c !== component)
|
parent._children = parent._children.filter(c => c !== component)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.currentFrontEndType === "page"
|
_saveCurrentPreviewItem(s)
|
||||||
? _savePage(s)
|
|
||||||
: _saveScreenApi(s.currentPreviewItem, s)
|
|
||||||
|
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
|
@ -864,9 +880,7 @@ const moveUpComponent = store => component => {
|
||||||
parent._children = newChildren
|
parent._children = newChildren
|
||||||
}
|
}
|
||||||
s.currentComponentInfo = component
|
s.currentComponentInfo = component
|
||||||
s.currentFrontEndType === "page"
|
_saveCurrentPreviewItem(s)
|
||||||
? _savePage(s)
|
|
||||||
: _saveScreenApi(s.currentPreviewItem, s)
|
|
||||||
|
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
|
@ -885,9 +899,7 @@ const moveDownComponent = store => component => {
|
||||||
parent._children = newChildren
|
parent._children = newChildren
|
||||||
}
|
}
|
||||||
s.currentComponentInfo = component
|
s.currentComponentInfo = component
|
||||||
s.currentFrontEndType === "page"
|
_saveCurrentPreviewItem(s)
|
||||||
? _savePage(s)
|
|
||||||
: _saveScreenApi(s.currentPreviewItem, s)
|
|
||||||
|
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
|
@ -902,9 +914,7 @@ const copyComponent = store => component => {
|
||||||
})
|
})
|
||||||
parent._children = [...parent._children, copiedComponent]
|
parent._children = [...parent._children, copiedComponent]
|
||||||
s.curren
|
s.curren
|
||||||
s.currentFrontEndType === "page"
|
_saveCurrentPreviewItem(s)
|
||||||
? _savePage(s)
|
|
||||||
: _saveScreenApi(s.currentPreviewItem, s)
|
|
||||||
s.currentComponentInfo = copiedComponent
|
s.currentComponentInfo = copiedComponent
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
|
@ -913,7 +923,7 @@ const copyComponent = store => component => {
|
||||||
const getParent = (rootProps, child) => {
|
const getParent = (rootProps, child) => {
|
||||||
let parent
|
let parent
|
||||||
walkProps(rootProps, (p, breakWalk) => {
|
walkProps(rootProps, (p, breakWalk) => {
|
||||||
if (p._children.includes(child)) {
|
if (p._children && p._children.includes(child)) {
|
||||||
parent = p
|
parent = p
|
||||||
breakWalk()
|
breakWalk()
|
||||||
}
|
}
|
||||||
|
@ -934,3 +944,8 @@ const walkProps = (props, action, cancelToken = null) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _saveCurrentPreviewItem = s =>
|
||||||
|
s.currentFrontEndType === "page"
|
||||||
|
? _savePage(s)
|
||||||
|
: _saveScreenApi(s.currentPreviewItem, s)
|
||||||
|
|
8
packages/builder/src/common/Icons/Add.svelte
Normal file
8
packages/builder/src/common/Icons/Add.svelte
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="100%"
|
||||||
|
height="100%">
|
||||||
|
<path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path fill="currentColor" d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 213 B |
|
@ -1,10 +1,10 @@
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="100%"
|
||||||
height="24">
|
height="100%">
|
||||||
<path fill="none" d="M0 0h24v24H0z" />
|
<path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z" />
|
d="M12 15l-4.243-4.243 1.415-1.414L12 12.172l2.828-2.829 1.415 1.414z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 246 B After Width: | Height: | Size: 254 B |
10
packages/builder/src/common/Icons/Check.svelte
Normal file
10
packages/builder/src/common/Icons/Check.svelte
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="100%"
|
||||||
|
height="100%">
|
||||||
|
<path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 254 B |
12
packages/builder/src/common/Icons/Grid.svelte
Normal file
12
packages/builder/src/common/Icons/Grid.svelte
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="100%"
|
||||||
|
height="100%">
|
||||||
|
<path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M14 10v4h-4v-4h4zm2 0h5v4h-5v-4zm-2 11h-4v-5h4v5zm2 0v-5h5v4a1 1 0 0 1-1
|
||||||
|
1h-4zM14 3v5h-4V3h4zm2 0h4a1 1 0 0 1 1 1v4h-5V3zm-8 7v4H3v-4h5zm0 11H4a1 1 0
|
||||||
|
0 1-1-1v-4h5v5zM8 3v5H3V4a1 1 0 0 1 1-1h4z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 388 B |
12
packages/builder/src/common/Icons/Shape.svelte
Normal file
12
packages/builder/src/common/Icons/Shape.svelte
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="100%"
|
||||||
|
height="100%">
|
||||||
|
<path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M5 8a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm14 0a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0
|
||||||
|
14a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM5 22a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM9
|
||||||
|
4h6v2H9V4zm0 14h6v2H9v-2zM4 9h2v6H4V9zm14 0h2v6h-2V9z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 387 B |
|
@ -11,3 +11,7 @@ export { default as XCircleIcon } from "./XCircle.svelte"
|
||||||
export { default as ChevronUpIcon } from "./ChevronUp.svelte"
|
export { default as ChevronUpIcon } from "./ChevronUp.svelte"
|
||||||
export { default as ChevronDownIcon } from "./ChevronDown.svelte"
|
export { default as ChevronDownIcon } from "./ChevronDown.svelte"
|
||||||
export { default as CopyIcon } from "./Copy.svelte"
|
export { default as CopyIcon } from "./Copy.svelte"
|
||||||
|
export { default as CheckIcon } from "./Check.svelte"
|
||||||
|
export { default as GridIcon } from "./Grid.svelte"
|
||||||
|
export { default as ShapeIcon } from "./Shape.svelte"
|
||||||
|
export { default as AddIcon } from "./Add.svelte"
|
||||||
|
|
|
@ -60,6 +60,12 @@
|
||||||
store.addTemplatedComponent(instance.props)
|
store.addTemplatedComponent(instance.props)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generate_components_list(components) {
|
||||||
|
return $store.currentFrontEndType === "page"
|
||||||
|
? $store.builtins.concat(components)
|
||||||
|
: components
|
||||||
|
}
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
const newComponentLibraries = []
|
const newComponentLibraries = []
|
||||||
|
|
||||||
|
@ -110,7 +116,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{#if componentLibrary}
|
{#if componentLibrary}
|
||||||
{#each $store.builtins.concat(componentLibrary.components) as component}
|
{#each generate_components_list(componentLibrary.components) as component}
|
||||||
<div class="component-container">
|
<div class="component-container">
|
||||||
<div
|
<div
|
||||||
class="component"
|
class="component"
|
||||||
|
@ -139,7 +145,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if component.presets}
|
{#if component.presets || templatesByComponent[component.name]}
|
||||||
<Button
|
<Button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
selectedComponent = selectedComponent ? null : component.name
|
selectedComponent = selectedComponent ? null : component.name
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
import ConfirmDialog from "../common/ConfirmDialog.svelte"
|
import ConfirmDialog from "../common/ConfirmDialog.svelte"
|
||||||
import { pipe } from "../common/core"
|
import { pipe } from "../common/core"
|
||||||
import { store } from "../builderStore"
|
import { store } from "../builderStore"
|
||||||
import { ArrowDownIcon } from "../common/Icons/"
|
import { ArrowDownIcon, ShapeIcon } from "../common/Icons/"
|
||||||
|
|
||||||
export let screens = []
|
export let screens = []
|
||||||
|
|
||||||
|
@ -25,9 +25,12 @@
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
const lastPartOfName = c =>
|
const lastPartOfName = c => {
|
||||||
c &&
|
if (!c) return ""
|
||||||
last(c.name ? c.name.split("/") : c._component.split("/"))
|
const name = c.name ? c.name : c._component ? c._component : c
|
||||||
|
return last(name.split("/"))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const isComponentSelected = (current, comp) => current === comp
|
const isComponentSelected = (current, comp) => current === comp
|
||||||
|
|
||||||
|
@ -47,7 +50,6 @@
|
||||||
componentToDelete = component
|
componentToDelete = component
|
||||||
confirmDeleteDialog.show()
|
confirmDeleteDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -55,17 +57,21 @@
|
||||||
{#each _screens as screen}
|
{#each _screens as screen}
|
||||||
<div
|
<div
|
||||||
class="hierarchy-item component"
|
class="hierarchy-item component"
|
||||||
class:selected={$store.currentPreviewItem.name === screen.title}
|
class:selected={$store.currentComponentInfo._id === screen.component.props._id}
|
||||||
on:click|stopPropagation={() => store.setCurrentScreen(screen.title)}>
|
on:click|stopPropagation={() => store.setCurrentScreen(screen.title)}>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
class="icon"
|
class="icon"
|
||||||
style="transform: rotate({$store.currentPreviewItem.name === screen.title ? 0 : -90}deg);">
|
class:rotate={$store.currentPreviewItem.name !== screen.title}>
|
||||||
{#if screen.component.props._children.length}
|
{#if screen.component.props._children.length}
|
||||||
<ArrowDownIcon />
|
<ArrowDownIcon />
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<span class="icon">
|
||||||
|
<ShapeIcon />
|
||||||
|
</span>
|
||||||
|
|
||||||
<span class="title">{screen.title}</span>
|
<span class="title">{screen.title}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -77,7 +83,7 @@
|
||||||
onDeleteComponent={confirmDeleteComponent}
|
onDeleteComponent={confirmDeleteComponent}
|
||||||
onMoveUpComponent={store.moveUpComponent}
|
onMoveUpComponent={store.moveUpComponent}
|
||||||
onMoveDownComponent={store.moveDownComponent}
|
onMoveDownComponent={store.moveDownComponent}
|
||||||
onCopyComponent={store.copyComponent}/>
|
onCopyComponent={store.copyComponent} />
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
|
@ -86,28 +92,29 @@
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
bind:this={confirmDeleteDialog}
|
bind:this={confirmDeleteDialog}
|
||||||
title="Confirm Delete"
|
title="Confirm Delete"
|
||||||
body={`Are you sure you wish to delete this '${lastPartOfName(componentToDelete._component)}' component`}
|
body={`Are you sure you wish to delete this '${lastPartOfName(componentToDelete)}' component`}
|
||||||
okText="Delete Component"
|
okText="Delete Component"
|
||||||
onOk={() => store.deleteComponent(componentToDelete)}/>
|
onOk={() => store.deleteComponent(componentToDelete)} />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.root {
|
.root {
|
||||||
font-weight: 500;
|
font-weight: 400;
|
||||||
font-size: 0.9rem;
|
font-size: 0.8rem;
|
||||||
color: #828fa5;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hierarchy-item {
|
.hierarchy-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 11px 7px;
|
padding: 0 7px 0 3px;
|
||||||
|
height: 35px;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
border-radius: 5px;
|
border-radius: 0 5px 5px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hierarchy-item:hover {
|
.hierarchy-item:hover {
|
||||||
/* color: var(--secondary); */
|
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,12 +125,27 @@
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
width: 24px;
|
width: 20px;
|
||||||
height: 24px;
|
margin-top: 2px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon:nth-of-type(2) {
|
||||||
|
width: 14px;
|
||||||
|
margin: 0 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(svg) {
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate :global(svg) {
|
||||||
|
transform: rotate(-90deg);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
import { last } from "lodash/fp"
|
import { last } from "lodash/fp"
|
||||||
import { pipe } from "../common/core"
|
import { pipe } from "../common/core"
|
||||||
import { XCircleIcon, ChevronUpIcon, ChevronDownIcon, CopyIcon } from "../common/Icons"
|
import {
|
||||||
|
XCircleIcon,
|
||||||
|
ChevronUpIcon,
|
||||||
|
ChevronDownIcon,
|
||||||
|
CopyIcon,
|
||||||
|
} from "../common/Icons"
|
||||||
|
|
||||||
export let components = []
|
export let components = []
|
||||||
export let currentComponent
|
export let currentComponent
|
||||||
|
@ -12,9 +17,8 @@
|
||||||
export let onMoveDownComponent
|
export let onMoveDownComponent
|
||||||
export let onCopyComponent
|
export let onCopyComponent
|
||||||
|
|
||||||
|
|
||||||
const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
|
const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
|
||||||
const get_name = s => !s ? "" : last(s.split("/"))
|
const get_name = s => (!s ? "" : last(s.split("/")))
|
||||||
|
|
||||||
const get_capitalised_name = name =>
|
const get_capitalised_name = name =>
|
||||||
pipe(
|
pipe(
|
||||||
|
@ -22,13 +26,12 @@
|
||||||
[get_name, capitalise]
|
[get_name, capitalise]
|
||||||
)
|
)
|
||||||
|
|
||||||
const moveDownComponent = component => {
|
const moveDownComponent = component => {
|
||||||
const c = component
|
const c = component
|
||||||
return () => {
|
return () => {
|
||||||
return onMoveDownComponent(c)
|
return onMoveDownComponent(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -37,25 +40,25 @@
|
||||||
<div
|
<div
|
||||||
class="item"
|
class="item"
|
||||||
class:selected={currentComponent === component}
|
class:selected={currentComponent === component}
|
||||||
style="padding-left: {level * 20 + 67}px">
|
style="padding-left: {level * 20 + 15}px">
|
||||||
<div>{get_capitalised_name(component._component)}</div>
|
<div>{get_capitalised_name(component._component)}</div>
|
||||||
<div class="reorder-buttons">
|
<div class="reorder-buttons">
|
||||||
{#if index > 0}
|
{#if index > 0}
|
||||||
<button on:click|stopPropagation={() => onMoveUpComponent(component)}>
|
<button
|
||||||
<ChevronUpIcon />
|
on:click|stopPropagation={() => onMoveUpComponent(component)}>
|
||||||
</button>
|
<ChevronUpIcon />
|
||||||
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if index < (components.length - 1)}
|
{#if index < components.length - 1}
|
||||||
<button on:click|stopPropagation={moveDownComponent(component)}>
|
<button on:click|stopPropagation={moveDownComponent(component)}>
|
||||||
<ChevronDownIcon />
|
<ChevronDownIcon />
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<button on:click|stopPropagation={() => onCopyComponent(component)}>
|
<button on:click|stopPropagation={() => onCopyComponent(component)}>
|
||||||
<CopyIcon />
|
<CopyIcon />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button on:click|stopPropagation={() => onDeleteComponent(component)}>
|
||||||
on:click|stopPropagation={() => onDeleteComponent(component)}>
|
|
||||||
<XCircleIcon />
|
<XCircleIcon />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -82,18 +85,16 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto auto auto;
|
grid-template-columns: 1fr auto auto auto;
|
||||||
padding: 0px 5px 0px 67px;
|
padding: 0px 5px 0px 15px;
|
||||||
margin: auto 0px;
|
margin: auto 0px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
height: 43px;
|
height: 35px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item button {
|
.item button {
|
||||||
|
@ -110,7 +111,7 @@
|
||||||
}
|
}
|
||||||
.item:hover button {
|
.item:hover button {
|
||||||
border-style: none;
|
border-style: none;
|
||||||
background: rgba(0,0,0,0);
|
background: rgba(0, 0, 0, 0);
|
||||||
display: block;
|
display: block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -122,6 +123,7 @@
|
||||||
.selected {
|
.selected {
|
||||||
color: var(--button-text);
|
color: var(--button-text);
|
||||||
background: var(--background-button) !important;
|
background: var(--background-button) !important;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reorder-buttons {
|
.reorder-buttons {
|
||||||
|
@ -135,5 +137,4 @@
|
||||||
height: 17px;
|
height: 17px;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
padding: ["Padding", tbrl, "small"],
|
padding: ["Padding", tbrl, "small"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: size = {
|
||||||
|
height: ["Height", single],
|
||||||
|
width: ["Width", single],
|
||||||
|
}
|
||||||
|
|
||||||
$: zindex = {
|
$: zindex = {
|
||||||
zindex: ["Z-Index", single],
|
zindex: ["Z-Index", single],
|
||||||
}
|
}
|
||||||
|
@ -82,6 +87,22 @@
|
||||||
onStyleChanged={_value => onStyleChanged('position', key, _value)}
|
onStyleChanged={_value => onStyleChanged('position', key, _value)}
|
||||||
values={layout[key] || newValue(meta.length)}
|
values={layout[key] || newValue(meta.length)}
|
||||||
{meta}
|
{meta}
|
||||||
|
{size}
|
||||||
|
type="text" />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4>Size</h4>
|
||||||
|
<div class="layout-layer">
|
||||||
|
{#each Object.entries(size) as [key, [name, meta, size]] (component._id + key)}
|
||||||
|
<div class="grid">
|
||||||
|
<h5>{name}:</h5>
|
||||||
|
<InputGroup
|
||||||
|
onStyleChanged={_value => onStyleChanged('position', key, _value)}
|
||||||
|
values={layout[key] || newValue(meta.length)}
|
||||||
|
type="text"
|
||||||
|
{meta}
|
||||||
{size} />
|
{size} />
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
146
packages/builder/src/userInterface/MasterLayout.svelte
Normal file
146
packages/builder/src/userInterface/MasterLayout.svelte
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
<script>
|
||||||
|
// import { tick } from "svelte"
|
||||||
|
import ComponentsHierarchyChildren from "./ComponentsHierarchyChildren.svelte"
|
||||||
|
|
||||||
|
import { last, sortBy, map, trimCharsStart, trimChars, join } from "lodash/fp"
|
||||||
|
import ConfirmDialog from "../common/ConfirmDialog.svelte"
|
||||||
|
import { pipe } from "../common/core"
|
||||||
|
import { store } from "../builderStore"
|
||||||
|
import { ArrowDownIcon, GridIcon } from "../common/Icons/"
|
||||||
|
|
||||||
|
export let layout
|
||||||
|
|
||||||
|
let confirmDeleteDialog
|
||||||
|
let componentToDelete = ""
|
||||||
|
|
||||||
|
const joinPath = join("/")
|
||||||
|
|
||||||
|
const normalizedName = name =>
|
||||||
|
pipe(
|
||||||
|
name,
|
||||||
|
[
|
||||||
|
trimCharsStart("./"),
|
||||||
|
trimCharsStart("~/"),
|
||||||
|
trimCharsStart("../"),
|
||||||
|
trimChars(" "),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
const lastPartOfName = c =>
|
||||||
|
c && last(c.name ? c.name.split("/") : c._component.split("/"))
|
||||||
|
|
||||||
|
const isComponentSelected = (current, comp) => current === comp
|
||||||
|
|
||||||
|
const isFolderSelected = (current, folder) => isInSubfolder(current, folder)
|
||||||
|
|
||||||
|
$: _layout = pipe(
|
||||||
|
layout,
|
||||||
|
[c => ({ component: c, title: lastPartOfName(c) })]
|
||||||
|
)
|
||||||
|
|
||||||
|
const isScreenSelected = component =>
|
||||||
|
component.component &&
|
||||||
|
$store.currentPreviewItem &&
|
||||||
|
component.component.name === $store.currentPreviewItem.name
|
||||||
|
|
||||||
|
const confirmDeleteComponent = async component => {
|
||||||
|
console.log(component)
|
||||||
|
componentToDelete = component
|
||||||
|
// await tick()
|
||||||
|
confirmDeleteDialog.show()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="root">
|
||||||
|
<div
|
||||||
|
class="hierarchy-item component"
|
||||||
|
class:selected={$store.currentComponentInfo._id === _layout.component.props._id}
|
||||||
|
on:click|stopPropagation={() => store.setScreenType('page')}>
|
||||||
|
|
||||||
|
<span
|
||||||
|
class="icon"
|
||||||
|
class:rotate={$store.currentPreviewItem.name !== _layout.title}>
|
||||||
|
{#if _layout.component.props._children.length}
|
||||||
|
<ArrowDownIcon />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="icon">
|
||||||
|
<GridIcon />
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="title">Master Layout</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if $store.currentPreviewItem.name === _layout.title && _layout.component.props._children}
|
||||||
|
<ComponentsHierarchyChildren
|
||||||
|
components={_layout.component.props._children}
|
||||||
|
currentComponent={$store.currentComponentInfo}
|
||||||
|
onSelect={store.selectComponent}
|
||||||
|
onDeleteComponent={confirmDeleteComponent}
|
||||||
|
onMoveUpComponent={store.moveUpComponent}
|
||||||
|
onMoveDownComponent={store.moveDownComponent}
|
||||||
|
onCopyComponent={store.copyComponent} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
bind:this={confirmDeleteDialog}
|
||||||
|
title="Confirm Delete"
|
||||||
|
body={`Are you sure you wish to delete this '${lastPartOfName(componentToDelete)}' component`}
|
||||||
|
okText="Delete Component"
|
||||||
|
onOk={() => store.deleteComponent(componentToDelete)} />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.root {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hierarchy-item {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 7px 0 3px;
|
||||||
|
height: 35px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-radius: 0 5px 5px 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hierarchy-item:hover {
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
color: var(--button-text);
|
||||||
|
background: var(--background-button) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
transition: 0.2s;
|
||||||
|
width: 20px;
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon:nth-of-type(2) {
|
||||||
|
width: 14px;
|
||||||
|
margin: 0 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(svg) {
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate :global(svg) {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { store } from "../builderStore"
|
import { store } from "../builderStore"
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
|
import { CheckIcon } from "../common/Icons"
|
||||||
|
|
||||||
const getPage = (s, name) => {
|
const getPage = (s, name) => {
|
||||||
const props = s.pages[name]
|
const props = s.pages[name]
|
||||||
|
@ -22,19 +23,23 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<select
|
<ul>
|
||||||
id="page"
|
|
||||||
name="select"
|
|
||||||
on:change={({ target }) => store.setCurrentPage(target.value)}>
|
|
||||||
|
|
||||||
{#each pages as { title, id }}
|
{#each pages as { title, id }}
|
||||||
<option value={id}>Page: {title}</option>
|
<li>
|
||||||
{/each}
|
<span class="icon">
|
||||||
|
{#if id === $store.currentPageName}
|
||||||
|
<CheckIcon />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
|
||||||
</select>
|
<button
|
||||||
<span class="arrow">
|
class:active={id === $store.currentPageName}
|
||||||
{@html getIcon('chevron-down', '24')}
|
on:click={() => store.setCurrentPage(id)}>
|
||||||
</span>
|
{title}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -44,37 +49,36 @@
|
||||||
color: var(--secondary50);
|
color: var(--secondary50);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
padding-left: 1.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
ul {
|
||||||
display: block;
|
|
||||||
font-size: 16px;
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #444;
|
|
||||||
line-height: 1.3;
|
|
||||||
padding: 1em 2.6em 0.9em 1.4em;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: none;
|
padding: 0;
|
||||||
border-radius: 0.5em;
|
list-style: none;
|
||||||
-moz-appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
background-color: #fafafa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.arrow {
|
li {
|
||||||
position: absolute;
|
margin: 0.5rem 0;
|
||||||
right: 10px;
|
}
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
button {
|
||||||
margin: auto;
|
margin: 0 0 0 6px;
|
||||||
width: 30px;
|
padding: 0;
|
||||||
height: 30px;
|
border: none;
|
||||||
pointer-events: none;
|
font-family: Roboto;
|
||||||
color: var(--primary100);
|
font-size: 0.8rem;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
width: 14px;
|
||||||
|
color: #333;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import ComponentsHierarchy from "./ComponentsHierarchy.svelte"
|
import ComponentsHierarchy from "./ComponentsHierarchy.svelte"
|
||||||
import ComponentsHierarchyChildren from "./ComponentsHierarchyChildren.svelte"
|
import ComponentsHierarchyChildren from "./ComponentsHierarchyChildren.svelte"
|
||||||
|
import MasterLayout from "./MasterLayout.svelte"
|
||||||
import PagesList from "./PagesList.svelte"
|
import PagesList from "./PagesList.svelte"
|
||||||
import { store } from "../builderStore"
|
import { store } from "../builderStore"
|
||||||
import IconButton from "../common/IconButton.svelte"
|
import IconButton from "../common/IconButton.svelte"
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
import ComponentsPaneSwitcher from "./ComponentsPaneSwitcher.svelte"
|
import ComponentsPaneSwitcher from "./ComponentsPaneSwitcher.svelte"
|
||||||
import ConfirmDialog from "../common/ConfirmDialog.svelte"
|
import ConfirmDialog from "../common/ConfirmDialog.svelte"
|
||||||
import { last } from "lodash/fp"
|
import { last } from "lodash/fp"
|
||||||
|
import { AddIcon } from "../common/Icons"
|
||||||
|
|
||||||
let newComponentPicker
|
let newComponentPicker
|
||||||
let confirmDeleteDialog
|
let confirmDeleteDialog
|
||||||
|
@ -31,8 +33,7 @@
|
||||||
confirmDeleteDialog.show()
|
confirmDeleteDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastPartOfName = c => c ? last(c.split("/")) : ""
|
const lastPartOfName = c => (c ? last(c.split("/")) : "")
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -40,63 +41,32 @@
|
||||||
<div class="ui-nav">
|
<div class="ui-nav">
|
||||||
|
|
||||||
<div class="pages-list-container">
|
<div class="pages-list-container">
|
||||||
<div class="nav-group-header">
|
<div class="nav-header">
|
||||||
|
|
||||||
<span class="navigator-title">Navigator</span>
|
<span class="navigator-title">Navigator</span>
|
||||||
|
<span class="components-nav-header">Pages</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="nav-items-container">
|
<div class="nav-items-container">
|
||||||
<PagesList />
|
<PagesList />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="components-list-container">
|
<div class="border-line" />
|
||||||
|
|
||||||
<div class="nav-group-header">
|
|
||||||
|
|
||||||
<span
|
|
||||||
on:click={() => store.setScreenType('page')}
|
|
||||||
class="components-nav-header"
|
|
||||||
class:active={$store.currentFrontEndType === 'page'}>
|
|
||||||
Page
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="nav-items-container">
|
|
||||||
{#if $store.currentFrontEndType === 'page'}
|
|
||||||
<ComponentsHierarchyChildren
|
|
||||||
components={$store.currentPreviewItem.props._children}
|
|
||||||
currentComponent={$store.currentComponentInfo}
|
|
||||||
onDeleteComponent={confirmDeleteComponent}
|
|
||||||
onSelect={store.selectComponent}
|
|
||||||
onMoveUpComponent={store.moveUpComponent}
|
|
||||||
onMoveDownComponent={store.moveDownComponent}
|
|
||||||
onCopyComponent={store.copyComponent}
|
|
||||||
level={-2} />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="components-list-container">
|
<div class="components-list-container">
|
||||||
|
|
||||||
<div class="nav-group-header">
|
<div class="nav-group-header">
|
||||||
|
<span class="components-nav-header" style="margin-top: 0;">
|
||||||
<span
|
|
||||||
on:click={() => store.setScreenType('screen')}
|
|
||||||
class="components-nav-header"
|
|
||||||
class:active={$store.currentFrontEndType === 'screen'}>
|
|
||||||
Screens
|
Screens
|
||||||
</span>
|
</span>
|
||||||
|
<div>
|
||||||
{#if $store.currentFrontEndType === 'screen'}
|
<button on:click={newComponent}>
|
||||||
<div>
|
<AddIcon />
|
||||||
<button on:click={newComponent}>+</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-items-container">
|
<div class="nav-items-container">
|
||||||
{#if $store.currentFrontEndType === 'screen'}
|
<MasterLayout layout={$store.pages[$store.currentPageName]} />
|
||||||
<ComponentsHierarchy screens={$store.screens} />
|
<ComponentsHierarchy screens={$store.screens} />
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -120,9 +90,9 @@
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
bind:this={confirmDeleteDialog}
|
bind:this={confirmDeleteDialog}
|
||||||
title="Confirm Delete"
|
title="Confirm Delete"
|
||||||
body={`Are you sure you wish to delete this '${lastPartOfName(componentToDelete._component)}' component`}
|
body={`Are you sure you wish to delete this '${lastPartOfName(componentToDelete)}' component`}
|
||||||
okText="Delete Component"
|
okText="Delete Component"
|
||||||
onOk={() => store.deleteComponent(componentToDelete)}/>
|
onOk={() => store.deleteComponent(componentToDelete)} />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
button {
|
button {
|
||||||
|
@ -130,19 +100,12 @@
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: var(--background-button);
|
width: 20px;
|
||||||
|
|
||||||
width: 1.8rem;
|
|
||||||
height: 1.8rem;
|
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding: 0;
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--button-text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
|
@ -157,7 +120,7 @@
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
background-color: var(--secondary5);
|
background-color: var(--secondary5);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0 1.5rem 0rem 1.5rem;
|
padding: 0 1.5rem 0rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-pane {
|
.preview-pane {
|
||||||
|
@ -179,6 +142,8 @@
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
color: #999;
|
color: #999;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header {
|
.nav-group-header {
|
||||||
|
@ -186,13 +151,20 @@
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
padding: 0 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-items-container {
|
.nav-items-container {
|
||||||
padding: 1rem 0rem 0rem 0rem;
|
padding: 1rem 0rem 0rem 0rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header {
|
.nav-group-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 2rem 0 0 0;
|
padding: 1.5rem 0 0 1.8rem;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -228,9 +200,12 @@
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #999;
|
color: #999;
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
.border-line {
|
||||||
color: #333;
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
width: calc(100% + 1.5rem);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -77,6 +77,10 @@ export const makePropsSafe = (componentDefinition, props) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!props._styles) {
|
||||||
|
props._styles = { layout: {}, position: {} }
|
||||||
|
}
|
||||||
|
|
||||||
return props
|
return props
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
{
|
{
|
||||||
"_lib": "./dist/index.js",
|
"_lib": "./dist/index.js",
|
||||||
|
"_templates": {
|
||||||
|
"indexDatatable": {
|
||||||
|
"description": "Datatable based on an Index",
|
||||||
|
"component": "Datatable"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Body1": {
|
"Body1": {
|
||||||
"name": "Body1",
|
"name": "Body1",
|
||||||
"description": "Sets the font properties as Roboto Body 1",
|
"description": "Sets the font properties as Roboto Body 1",
|
||||||
|
@ -61,6 +67,26 @@
|
||||||
"props": {},
|
"props": {},
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
|
"DatatableHead": {
|
||||||
|
"name": "DatatableHead",
|
||||||
|
"description": "Material Design <thead>.",
|
||||||
|
"props": {}
|
||||||
|
},
|
||||||
|
"DatatableCell": {
|
||||||
|
"name": "DatatableCell",
|
||||||
|
"description": "Material Design <td>.",
|
||||||
|
"props": {}
|
||||||
|
},
|
||||||
|
"DatatableBody": {
|
||||||
|
"name": "DatatableBody",
|
||||||
|
"description": "Material Design <tbody>.",
|
||||||
|
"props": {}
|
||||||
|
},
|
||||||
|
"DatatableRow": {
|
||||||
|
"name": "DatatableRow",
|
||||||
|
"description": "Material Design <tr>.",
|
||||||
|
"props": {}
|
||||||
|
},
|
||||||
"H1": {
|
"H1": {
|
||||||
"name": "H1",
|
"name": "H1",
|
||||||
"description": "Sets the font properties as Roboto Headline1",
|
"description": "Sets the font properties as Roboto Headline1",
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@budibase/client": "^0.0.16",
|
"@budibase/client": "^0.0.16",
|
||||||
|
"@budibase/standard-components": "^0.0.16",
|
||||||
"@material/button": "^4.0.0",
|
"@material/button": "^4.0.0",
|
||||||
"@nx-js/compiler-util": "^2.0.0",
|
"@nx-js/compiler-util": "^2.0.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
|
|
@ -6,14 +6,27 @@
|
||||||
import { Button } from "../Button"
|
import { Button } from "../Button"
|
||||||
import ClassBuilder from "../ClassBuilder.js"
|
import ClassBuilder from "../ClassBuilder.js"
|
||||||
|
|
||||||
|
export let _bb
|
||||||
|
|
||||||
const cb = new ClassBuilder("data-table")
|
const cb = new ClassBuilder("data-table")
|
||||||
setContext("BBMD:data-table:cb", cb)
|
setContext("BBMD:data-table:cb", cb)
|
||||||
|
|
||||||
let datatable = null
|
let datatable = null
|
||||||
let instance = null
|
let instance = null
|
||||||
|
let tableElement
|
||||||
|
let initialied = false
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if(tableElement && datatable && !initialied) {
|
||||||
|
const children = _bb.attachChildren(tableElement)
|
||||||
|
if(children.length > 0) {
|
||||||
|
instance = new MDCDataTable(datatable)
|
||||||
|
initialied = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (!!datatable) instance = new MDCDataTable(datatable)
|
|
||||||
return () => {
|
return () => {
|
||||||
!!instance && instance.destroy()
|
!!instance && instance.destroy()
|
||||||
instance = null
|
instance = null
|
||||||
|
@ -22,46 +35,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={datatable} class={cb.build()}>
|
<div bind:this={datatable} class={cb.build()}>
|
||||||
<table class={cb.elem`table`} aria-label="Material Design Datatable">
|
<table class={cb.elem`table`} aria-label="Material Design Datatable" bind:this={tableElement}>
|
||||||
<thead>
|
|
||||||
<Row isHeader>
|
|
||||||
<Cell isHeader>Id</Cell>
|
|
||||||
<Cell isHeader>First Name</Cell>
|
|
||||||
<Cell isHeader>Second Name</Cell>
|
|
||||||
<Cell isHeader>Gender</Cell>
|
|
||||||
<Cell isHeader>Address</Cell>
|
|
||||||
<Cell isHeader>Actions</Cell>
|
|
||||||
</Row>
|
|
||||||
</thead>
|
|
||||||
<tbody class={cb.elem`content`}>
|
|
||||||
<Row>
|
|
||||||
<Cell>123456</Cell>
|
|
||||||
<Cell>Conor</Cell>
|
|
||||||
<Cell>McKeown</Cell>
|
|
||||||
<Cell>Male</Cell>
|
|
||||||
<Cell>1 Cool Street</Cell>
|
|
||||||
<Cell>
|
|
||||||
<Button
|
|
||||||
text="Select"
|
|
||||||
variant="unelevated"
|
|
||||||
colour="secondary"
|
|
||||||
size="small" />
|
|
||||||
</Cell>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Cell>789101</Cell>
|
|
||||||
<Cell>Joe</Cell>
|
|
||||||
<Cell>Bloggs</Cell>
|
|
||||||
<Cell>Male</Cell>
|
|
||||||
<Cell>2 Cool Street</Cell>
|
|
||||||
<Cell>
|
|
||||||
<Button
|
|
||||||
text="Select"
|
|
||||||
variant="unelevated"
|
|
||||||
colour="secondary"
|
|
||||||
size="small" />
|
|
||||||
</Cell>
|
|
||||||
</Row>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
import ClassBuilder from "../ClassBuilder.js"
|
||||||
|
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
const cb = getContext("BBMD:data-table:cb")
|
||||||
|
|
||||||
|
let tbody
|
||||||
|
|
||||||
|
$: tbody && _bb.attachChildren(tbody)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<tbody bind:this={tbody} class={cb.elem`content`}></tbody>
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
export let isHeader = false
|
export let isHeader = false
|
||||||
export let numeric = false
|
export let numeric = false
|
||||||
|
export let _bb
|
||||||
|
|
||||||
const cb = getContext("BBMD:data-table:cb")
|
const cb = getContext("BBMD:data-table:cb")
|
||||||
|
|
||||||
|
@ -10,14 +11,18 @@
|
||||||
let modifiers = { numeric }
|
let modifiers = { numeric }
|
||||||
let props = { modifiers }
|
let props = { modifiers }
|
||||||
let cellClass = cb.build({ elementName, props })
|
let cellClass = cb.build({ elementName, props })
|
||||||
|
let element
|
||||||
|
|
||||||
|
$: element && _bb.attachChildren(element)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if isHeader}
|
{#if isHeader}
|
||||||
<th class={cellClass} role="columnheader" scope="col">
|
<th class={cellClass} role="columnheader" scope="col" bind:this={element}>
|
||||||
<slot />
|
<slot />
|
||||||
</th>
|
</th>
|
||||||
{:else}
|
{:else}
|
||||||
<td class={cellClass}>
|
<td class={cellClass} bind:this={element}>
|
||||||
<slot />
|
<slot />
|
||||||
</td>
|
</td>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
let thead
|
||||||
|
|
||||||
|
$: thead && _bb.attachChildren(thead)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<thead bind:this={thead} class=className></thead>
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
export let onSelect = () => {};
|
export let onSelect = () => {};
|
||||||
export let isHeader = false;
|
export let isHeader = false;
|
||||||
|
|
||||||
|
export let _bb
|
||||||
|
|
||||||
let row = null;
|
let row = null;
|
||||||
let selected = false;
|
let selected = false;
|
||||||
|
|
||||||
|
@ -14,6 +17,7 @@
|
||||||
$: modifiers = { selected };
|
$: modifiers = { selected };
|
||||||
$: props = { modifiers };
|
$: props = { modifiers };
|
||||||
$: rowClass = cb.build({ elementName, props });
|
$: rowClass = cb.build({ elementName, props });
|
||||||
|
$: row && _bb.attachChildren(row)
|
||||||
|
|
||||||
function rowSelected() {
|
function rowSelected() {
|
||||||
selected = !selected;
|
selected = !selected;
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
import "./_style.scss";
|
import "./_style.scss"
|
||||||
export { default as Datatable } from "./Datatable.svelte";
|
export { default as Datatable } from "./Datatable.svelte"
|
||||||
|
export { default as DatatableCell } from "./DatatableCell.svelte"
|
||||||
|
export { default as DatatableHead } from "./DatatableHead.svelte"
|
||||||
|
export { default as DatatableBody } from "./DatatableBody.svelte"
|
||||||
|
export { default as DatatableRow } from "./DatatableRow.svelte"
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
export default ({ indexes, helpers }) =>
|
||||||
|
indexes.map(i => ({
|
||||||
|
name: `Table based on index: ${i.name} `,
|
||||||
|
props: tableProps(i, helpers.indexSchema(i)),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const tableProps = (index, indexSchema) => ({
|
||||||
|
_component: "@budibase/materialdesign-components/Datatable",
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_component: "@budibase/materialdesign-components/DatatableHead",
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_component: "@budibase/materialdesign-components/DatatableRow",
|
||||||
|
isHeader: true,
|
||||||
|
_children: columnHeaders(indexSchema),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_component: "@budibase/materialdesign-components/DatatableBody",
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_code: rowCode(index),
|
||||||
|
_component: "@budibase/materialdesign-components/DatatableRow",
|
||||||
|
_children: dataCells(index, indexSchema),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const columnHeaders = indexSchema =>
|
||||||
|
indexSchema.map(col => ({
|
||||||
|
_component: "@budibase/materialdesign-components/DatatableCell",
|
||||||
|
isHeader: true,
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/text",
|
||||||
|
type: "none",
|
||||||
|
text: col.name,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
|
||||||
|
const dataCells = (index, indexSchema) =>
|
||||||
|
indexSchema.map(col => ({
|
||||||
|
_component: "@budibase/materialdesign-components/DatatableCell",
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_component: "@budibase/standard-components/text",
|
||||||
|
type: "none",
|
||||||
|
text: {
|
||||||
|
"##bbstate": `${dataItem(index)}.${col.name}`,
|
||||||
|
"##bbstatefallback": "",
|
||||||
|
"##bbsource": "context",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
|
||||||
|
const dataItem = index => `${index.name}_item`
|
||||||
|
const dataCollection = index => `store.${index.name}`
|
||||||
|
const rowCode = index =>
|
||||||
|
`
|
||||||
|
if (!${dataCollection(index)}) return
|
||||||
|
|
||||||
|
for (let ${dataItem(index)} of ${dataCollection(index)})
|
||||||
|
render( { ${dataItem(index)}) }`
|
|
@ -12,6 +12,7 @@
|
||||||
Radiobutton,
|
Radiobutton,
|
||||||
Radiobuttongroup,
|
Radiobuttongroup,
|
||||||
Datatable,
|
Datatable,
|
||||||
|
CustomersIndexTable,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
let currentComponent
|
let currentComponent
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
Radiobutton,
|
Radiobutton,
|
||||||
Radiobuttongroup,
|
Radiobuttongroup,
|
||||||
Datatable,
|
Datatable,
|
||||||
|
CustomersIndexTable
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,23 +2,24 @@ import { createApp } from "@budibase/client/src/createApp"
|
||||||
import components from "./testComponents"
|
import components from "./testComponents"
|
||||||
import packageJson from "../../package.json"
|
import packageJson from "../../package.json"
|
||||||
import { rootComponent } from "./rootComponent"
|
import { rootComponent } from "./rootComponent"
|
||||||
|
import * as standardcomponents from "@budibase/standard-components/src/index"
|
||||||
|
|
||||||
export default async props => {
|
export default async props => {
|
||||||
delete components._lib
|
delete components._lib
|
||||||
const componentLibraries = {}
|
const componentLibraries = {}
|
||||||
componentLibraries[packageJson.name] = components
|
componentLibraries[packageJson.name] = components
|
||||||
componentLibraries["testcomponents"] = {
|
componentLibraries["testcomponents"] = {
|
||||||
rootComponent: rootComponent(window)
|
rootComponent: rootComponent(window),
|
||||||
}
|
}
|
||||||
|
componentLibraries["@budibase/standard-components"] = standardcomponents
|
||||||
const appDef = { hierarchy: {}, actions: {} }
|
const appDef = { hierarchy: {}, actions: {} }
|
||||||
const user = { name: "yeo", permissions: [] }
|
const user = { name: "yeo", permissions: [] }
|
||||||
const { initialisePage } = createApp(
|
const { initialisePage } = createApp(
|
||||||
window.document,
|
|
||||||
componentLibraries,
|
componentLibraries,
|
||||||
{ appRootPath: "" },
|
{ appRootPath: "" },
|
||||||
appDef,
|
appDef,
|
||||||
user,
|
user,
|
||||||
{},
|
{}
|
||||||
[]
|
|
||||||
)
|
)
|
||||||
return initialisePage
|
return initialisePage
|
||||||
}
|
}
|
|
@ -1,3 +1,24 @@
|
||||||
|
import indexDatatable from "../Templates/indexDatatable"
|
||||||
|
|
||||||
|
const templateOptions = {
|
||||||
|
indexes: [
|
||||||
|
{
|
||||||
|
name: "customers",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
helpers: {
|
||||||
|
indexSchema: index => {
|
||||||
|
const field = name => ({ name })
|
||||||
|
if (index.name === "customers")
|
||||||
|
return [
|
||||||
|
field("id"),
|
||||||
|
field("surname"),
|
||||||
|
field("forname"),
|
||||||
|
field("address"),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export const props = {
|
export const props = {
|
||||||
H1: {
|
H1: {
|
||||||
|
@ -80,4 +101,6 @@ export const props = {
|
||||||
_component: "@budibase/materialdesign-components/Datatable",
|
_component: "@budibase/materialdesign-components/Datatable",
|
||||||
_children: [],
|
_children: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
CustomersIndexTable: indexDatatable(templateOptions)[0].props,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,3 @@
|
||||||
import {
|
import * as components from "@BBMD"
|
||||||
H1,
|
|
||||||
Overline,
|
|
||||||
Button,
|
|
||||||
Icon,
|
|
||||||
Textfield,
|
|
||||||
Checkbox,
|
|
||||||
Checkboxgroup,
|
|
||||||
Radiobutton,
|
|
||||||
Radiobuttongroup,
|
|
||||||
Datatable,
|
|
||||||
} from "@BBMD"
|
|
||||||
|
|
||||||
export default {
|
export default components
|
||||||
H1,
|
|
||||||
Overline,
|
|
||||||
Button,
|
|
||||||
Icon,
|
|
||||||
Textfield,
|
|
||||||
Checkbox,
|
|
||||||
Checkboxgroup,
|
|
||||||
Radiobutton,
|
|
||||||
Radiobuttongroup,
|
|
||||||
Datatable,
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import "@material/theme/mdc-theme.scss";
|
import "@material/theme/mdc-theme.scss"
|
||||||
|
|
||||||
export { Button } from "./Button"
|
export { Button } from "./Button"
|
||||||
export { default as Icon } from "./Common/Icon.svelte"
|
export { default as Icon } from "./Common/Icon.svelte"
|
||||||
|
@ -7,5 +7,11 @@ export * from "./Typography"
|
||||||
export { Checkbox, Checkboxgroup } from "./Checkbox"
|
export { Checkbox, Checkboxgroup } from "./Checkbox"
|
||||||
export { Radiobutton, Radiobuttongroup } from "./Radiobutton"
|
export { Radiobutton, Radiobuttongroup } from "./Radiobutton"
|
||||||
export { default as Label } from "./Common/Label.svelte"
|
export { default as Label } from "./Common/Label.svelte"
|
||||||
export { Datatable } from "./Datatable"
|
export {
|
||||||
|
Datatable,
|
||||||
|
DatatableHead,
|
||||||
|
DatatableBody,
|
||||||
|
DatatableCell,
|
||||||
|
DatatableRow,
|
||||||
|
} from "./Datatable"
|
||||||
|
export { default as indexDatatable } from "./Templates/indexDatatable"
|
||||||
|
|
|
@ -137,6 +137,24 @@
|
||||||
},
|
},
|
||||||
"tags": ["div", "container"]
|
"tags": ["div", "container"]
|
||||||
},
|
},
|
||||||
|
"link": {
|
||||||
|
"description": "an HTML anchor <a> tag",
|
||||||
|
"props": {
|
||||||
|
"url": "string",
|
||||||
|
"openInNewTab": "bool",
|
||||||
|
"text": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"description": "an HTML <img> tag",
|
||||||
|
"props": {
|
||||||
|
"url": "string",
|
||||||
|
"className": "string",
|
||||||
|
"description": "string",
|
||||||
|
"height": "string",
|
||||||
|
"width": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"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",
|
||||||
|
@ -178,5 +196,19 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tags": []
|
"tags": []
|
||||||
|
},
|
||||||
|
"thead": {
|
||||||
|
"name": "TableHead",
|
||||||
|
"description": "an HTML <thead> tab",
|
||||||
|
"props" : {
|
||||||
|
"className":"string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tbody": {
|
||||||
|
"name": "TableBody",
|
||||||
|
"description": "an HTML <tbody> tab",
|
||||||
|
"props" : {
|
||||||
|
"className":"string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
19
packages/standard-components/src/Image.svelte
Normal file
19
packages/standard-components/src/Image.svelte
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import { buildStyle } from "./buildStyle"
|
||||||
|
|
||||||
|
export let className = "";
|
||||||
|
export let url = "";
|
||||||
|
export let description = ""
|
||||||
|
export let height
|
||||||
|
export let width
|
||||||
|
|
||||||
|
$: style = buildStyle({height, width})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<img class={className}
|
||||||
|
style={style}
|
||||||
|
src={url}
|
||||||
|
alt={description} >
|
18
packages/standard-components/src/Link.svelte
Normal file
18
packages/standard-components/src/Link.svelte
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export let url = ""
|
||||||
|
export let text = ""
|
||||||
|
export let openInNewTab = false
|
||||||
|
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
let anchorElement
|
||||||
|
|
||||||
|
$: anchorElement && !text && _bb.attachChildren(anchorElement)
|
||||||
|
$: target = openInNewTab ? "_blank" : "_self"
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<a href={url} bind:this={anchorElement} target={target}>{text}</a>
|
||||||
|
|
||||||
|
|
12
packages/standard-components/src/TableBody.svelte
Normal file
12
packages/standard-components/src/TableBody.svelte
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export let className=""
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
let thead
|
||||||
|
|
||||||
|
$: _bb.attachChildren(thead)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<tbody bind:this={thead} class=className></tbody>
|
12
packages/standard-components/src/TableHead.svelte
Normal file
12
packages/standard-components/src/TableHead.svelte
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export let className=""
|
||||||
|
export let _bb
|
||||||
|
|
||||||
|
let thead
|
||||||
|
|
||||||
|
$: _bb.attachChildren(thead)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<thead bind:this={thead} class=className></thead>
|
|
@ -29,7 +29,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if isTag("none")}
|
{#if isTag("none")}
|
||||||
{text}
|
<span>{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>")}
|
||||||
|
|
|
@ -7,3 +7,5 @@ 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 image } from "./Image.svelte"
|
||||||
|
|
Loading…
Reference in a new issue