mirror of https://github.com/Budibase/budibase.git
committed by
GitHub
48 changed files with 1403 additions and 256 deletions
@ -0,0 +1,17 @@ |
|||
export const insertCodeMetadata = props => { |
|||
if (props._code && props._code.length > 0) { |
|||
props._codeMeta = codeMetaData(props._code) |
|||
} |
|||
|
|||
if (!props._children || props._children.length === 0) return |
|||
|
|||
for (let child of props._children) { |
|||
insertCodeMetadata(child) |
|||
} |
|||
} |
|||
|
|||
const codeMetaData = code => { |
|||
return { |
|||
dependsOnStore: RegExp(/(store.)/g).test(code), |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
<script> |
|||
import Button from "./Button.svelte" |
|||
import ButtonGroup from "./ButtonGroup.svelte" |
|||
import UIkit from "uikit" |
|||
|
|||
export let title="" |
|||
export let body="" |
|||
export let okText = "OK" |
|||
export let cancelText = "Cancel" |
|||
export let onOk = ()=> {} |
|||
export let onCancel = ()=> {} |
|||
|
|||
export const show = () => { |
|||
UIkit.modal(theModal).show() |
|||
} |
|||
|
|||
export const hide = () => { |
|||
UIkit.modal(theModal).hide() |
|||
} |
|||
|
|||
let theModal; |
|||
|
|||
const cancel = () => { |
|||
hide() |
|||
onCancel() |
|||
} |
|||
|
|||
const ok = () => { |
|||
hide() |
|||
onOk() |
|||
} |
|||
|
|||
</script> |
|||
|
|||
|
|||
<div id="my-id" uk-modal bind:this={theModal}> |
|||
<div class="uk-modal-dialog"> |
|||
<button class="uk-modal-close-default" type="button" uk-close></button> |
|||
<div class="uk-modal-header"> |
|||
<h2 class="uk-modal-title">{title}</h2> |
|||
</div> |
|||
<div class="uk-modal-body">{body}</div> |
|||
<div class="uk-modal-footer"> |
|||
<ButtonGroup> |
|||
<Button grouped color="primary" on:click={ok}> |
|||
{okText} |
|||
</Button> |
|||
<Button grouped color="secondary" on:click={cancel}> |
|||
{cancelText} |
|||
</Button> |
|||
</ButtonGroup> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
|
After Width: | Height: | Size: 454 B |
@ -0,0 +1,70 @@ |
|||
import { getStateOrValue } from "./getState" |
|||
import { setState, setStateFromBinding } from "./setState" |
|||
import { trimSlash } from "../common/trimSlash" |
|||
import { isBound } from "./isState" |
|||
import { attachChildren } from "../render/attachChildren" |
|||
|
|||
export const bbFactory = ({ |
|||
store, |
|||
getCurrentState, |
|||
frontendDefinition, |
|||
componentLibraries, |
|||
uiFunctions, |
|||
onScreenSlotRendered, |
|||
}) => { |
|||
const relativeUrl = url => |
|||
frontendDefinition.appRootPath |
|||
? frontendDefinition.appRootPath + "/" + trimSlash(url) |
|||
: url |
|||
|
|||
const apiCall = method => (url, body) => |
|||
fetch(relativeUrl(url), { |
|||
method: method, |
|||
headers: { |
|||
"Content-Type": "application/json", |
|||
}, |
|||
body: body && JSON.stringify(body), |
|||
}) |
|||
|
|||
const api = { |
|||
post: apiCall("POST"), |
|||
get: apiCall("GET"), |
|||
patch: apiCall("PATCH"), |
|||
delete: apiCall("DELETE"), |
|||
} |
|||
|
|||
const safeCallEvent = (event, context) => { |
|||
const isFunction = obj => |
|||
!!(obj && obj.constructor && obj.call && obj.apply) |
|||
|
|||
if (isFunction(event)) event(context) |
|||
} |
|||
|
|||
return (treeNode, setupState) => { |
|||
const attachParams = { |
|||
componentLibraries, |
|||
uiFunctions, |
|||
treeNode, |
|||
onScreenSlotRendered, |
|||
setupState, |
|||
getCurrentState, |
|||
} |
|||
|
|||
return { |
|||
attachChildren: attachChildren(attachParams), |
|||
context: treeNode.context, |
|||
props: treeNode.props, |
|||
call: safeCallEvent, |
|||
setStateFromBinding: (binding, value) => |
|||
setStateFromBinding(store, binding, value), |
|||
setState: (path, value) => setState(store, path, value), |
|||
getStateOrValue: (prop, currentContext) => |
|||
getStateOrValue(getCurrentState(), prop, currentContext), |
|||
store: store, |
|||
relativeUrl, |
|||
api, |
|||
isBound, |
|||
parent, |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,288 @@ |
|||
import { |
|||
isEventType, |
|||
eventHandlers, |
|||
EVENT_TYPE_MEMBER_NAME, |
|||
} from "./eventHandlers" |
|||
import { bbFactory } from "./bbComponentApi" |
|||
import { getState } from "./getState" |
|||
import { attachChildren } from "../render/attachChildren" |
|||
|
|||
import { |
|||
isBound, |
|||
takeStateFromStore, |
|||
takeStateFromContext, |
|||
takeStateFromEventParameters, |
|||
BB_STATE_FALLBACK, |
|||
BB_STATE_BINDINGPATH, |
|||
BB_STATE_BINDINGSOURCE, |
|||
} from "./isState" |
|||
|
|||
const doNothing = () => {} |
|||
doNothing.isPlaceholder = true |
|||
|
|||
const isMetaProp = propName => |
|||
propName === "_component" || |
|||
propName === "_children" || |
|||
propName === "_id" || |
|||
propName === "_style" || |
|||
propName === "_code" || |
|||
propName === "_codeMeta" |
|||
|
|||
export const createStateManager = ({ |
|||
store, |
|||
coreApi, |
|||
rootPath, |
|||
frontendDefinition, |
|||
componentLibraries, |
|||
uiFunctions, |
|||
onScreenSlotRendered, |
|||
}) => { |
|||
let handlerTypes = eventHandlers(store, coreApi, rootPath) |
|||
let currentState |
|||
|
|||
// any nodes that have props that are bound to the store
|
|||
let nodesBoundByProps = [] |
|||
|
|||
// any node whose children depend on code, that uses the store
|
|||
let nodesWithCodeBoundChildren = [] |
|||
|
|||
const getCurrentState = () => currentState |
|||
const registerBindings = _registerBindings( |
|||
nodesBoundByProps, |
|||
nodesWithCodeBoundChildren |
|||
) |
|||
const bb = bbFactory({ |
|||
store, |
|||
getCurrentState, |
|||
frontendDefinition, |
|||
componentLibraries, |
|||
uiFunctions, |
|||
onScreenSlotRendered, |
|||
}) |
|||
|
|||
const setup = _setup(handlerTypes, getCurrentState, registerBindings, bb) |
|||
|
|||
const unsubscribe = store.subscribe( |
|||
onStoreStateUpdated({ |
|||
setCurrentState: s => (currentState = s), |
|||
getCurrentState, |
|||
nodesWithCodeBoundChildren, |
|||
nodesBoundByProps, |
|||
uiFunctions, |
|||
componentLibraries, |
|||
onScreenSlotRendered, |
|||
setupState: setup, |
|||
}) |
|||
) |
|||
|
|||
return { |
|||
setup, |
|||
destroy: () => unsubscribe(), |
|||
getCurrentState, |
|||
store, |
|||
} |
|||
} |
|||
|
|||
const onStoreStateUpdated = ({ |
|||
setCurrentState, |
|||
getCurrentState, |
|||
nodesWithCodeBoundChildren, |
|||
nodesBoundByProps, |
|||
uiFunctions, |
|||
componentLibraries, |
|||
onScreenSlotRendered, |
|||
setupState, |
|||
}) => s => { |
|||
setCurrentState(s) |
|||
|
|||
// the original array gets changed by components' destroy()
|
|||
// so we make a clone and check if they are still in the original
|
|||
const nodesWithBoundChildren_clone = [...nodesWithCodeBoundChildren] |
|||
for (let node of nodesWithBoundChildren_clone) { |
|||
if (!nodesWithCodeBoundChildren.includes(node)) continue |
|||
attachChildren({ |
|||
uiFunctions, |
|||
componentLibraries, |
|||
treeNode: node, |
|||
onScreenSlotRendered, |
|||
setupState, |
|||
getCurrentState, |
|||
})(node.rootElement, { hydrate: true, force: true }) |
|||
} |
|||
|
|||
for (let node of nodesBoundByProps) { |
|||
setNodeState(s, node) |
|||
} |
|||
} |
|||
|
|||
const _registerBindings = (nodesBoundByProps, nodesWithCodeBoundChildren) => ( |
|||
node, |
|||
bindings |
|||
) => { |
|||
if (bindings.length > 0) { |
|||
node.bindings = bindings |
|||
nodesBoundByProps.push(node) |
|||
const onDestroy = () => { |
|||
nodesBoundByProps = nodesBoundByProps.filter(n => n === node) |
|||
node.onDestroy = node.onDestroy.filter(d => d === onDestroy) |
|||
} |
|||
node.onDestroy.push(onDestroy) |
|||
} |
|||
if ( |
|||
node.props._children && |
|||
node.props._children.filter(c => c._codeMeta && c._codeMeta.dependsOnStore) |
|||
.length > 0 |
|||
) { |
|||
nodesWithCodeBoundChildren.push(node) |
|||
const onDestroy = () => { |
|||
nodesWithCodeBoundChildren = nodesWithCodeBoundChildren.filter( |
|||
n => n === node |
|||
) |
|||
node.onDestroy = node.onDestroy.filter(d => d === onDestroy) |
|||
} |
|||
node.onDestroy.push(onDestroy) |
|||
} |
|||
} |
|||
|
|||
const setNodeState = (storeState, node) => { |
|||
if (!node.component) return |
|||
const newProps = { ...node.bindings.initialProps } |
|||
|
|||
for (let binding of node.bindings) { |
|||
const val = getState(storeState, binding.path, binding.fallback) |
|||
|
|||
if (val === undefined && newProps[binding.propName] !== undefined) { |
|||
delete newProps[binding.propName] |
|||
} |
|||
|
|||
if (val !== undefined) { |
|||
newProps[binding.propName] = val |
|||
} |
|||
} |
|||
|
|||
node.component.$set(newProps) |
|||
} |
|||
|
|||
const _setup = ( |
|||
handlerTypes, |
|||
getCurrentState, |
|||
registerBindings, |
|||
bb |
|||
) => node => { |
|||
const props = node.props |
|||
const context = node.context || {} |
|||
const initialProps = { ...props } |
|||
const storeBoundProps = [] |
|||
const currentStoreState = getCurrentState() |
|||
|
|||
for (let propName in props) { |
|||
if (isMetaProp(propName)) continue |
|||
|
|||
const val = props[propName] |
|||
|
|||
if (isBound(val) && takeStateFromStore(val)) { |
|||
const path = BindingPath(val) |
|||
const source = BindingSource(val) |
|||
const fallback = BindingFallback(val) |
|||
|
|||
storeBoundProps.push({ |
|||
path, |
|||
fallback, |
|||
propName, |
|||
source, |
|||
}) |
|||
|
|||
initialProps[propName] = !currentStoreState |
|||
? fallback |
|||
: getState( |
|||
currentStoreState, |
|||
BindingPath(val), |
|||
BindingFallback(val), |
|||
BindingSource(val) |
|||
) |
|||
} else if (isBound(val) && takeStateFromContext(val)) { |
|||
initialProps[propName] = !context |
|||
? val |
|||
: getState( |
|||
context, |
|||
BindingPath(val), |
|||
BindingFallback(val), |
|||
BindingSource(val) |
|||
) |
|||
} else if (isEventType(val)) { |
|||
const handlersInfos = [] |
|||
for (let e of val) { |
|||
const handlerInfo = { |
|||
handlerType: e[EVENT_TYPE_MEMBER_NAME], |
|||
parameters: e.parameters, |
|||
} |
|||
const resolvedParams = {} |
|||
for (let paramName in handlerInfo.parameters) { |
|||
const paramValue = handlerInfo.parameters[paramName] |
|||
if (!isBound(paramValue)) { |
|||
resolvedParams[paramName] = () => paramValue |
|||
continue |
|||
} else if (takeStateFromContext(paramValue)) { |
|||
const val = getState( |
|||
context, |
|||
paramValue[BB_STATE_BINDINGPATH], |
|||
paramValue[BB_STATE_FALLBACK] |
|||
) |
|||
resolvedParams[paramName] = () => val |
|||
} else if (takeStateFromStore(paramValue)) { |
|||
resolvedParams[paramName] = () => |
|||
getState( |
|||
getCurrentState(), |
|||
paramValue[BB_STATE_BINDINGPATH], |
|||
paramValue[BB_STATE_FALLBACK] |
|||
) |
|||
continue |
|||
} else if (takeStateFromEventParameters(paramValue)) { |
|||
resolvedParams[paramName] = eventContext => { |
|||
getState( |
|||
eventContext, |
|||
paramValue[BB_STATE_BINDINGPATH], |
|||
paramValue[BB_STATE_FALLBACK] |
|||
) |
|||
} |
|||
} |
|||
} |
|||
|
|||
handlerInfo.parameters = resolvedParams |
|||
handlersInfos.push(handlerInfo) |
|||
} |
|||
|
|||
if (handlersInfos.length === 0) initialProps[propName] = doNothing |
|||
else { |
|||
initialProps[propName] = async context => { |
|||
for (let handlerInfo of handlersInfos) { |
|||
const handler = makeHandler(handlerTypes, handlerInfo) |
|||
await handler(context) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
registerBindings(node, storeBoundProps) |
|||
|
|||
const setup = _setup(handlerTypes, getCurrentState, registerBindings, bb) |
|||
initialProps._bb = bb(node, setup) |
|||
|
|||
return initialProps |
|||
} |
|||
|
|||
const makeHandler = (handlerTypes, handlerInfo) => { |
|||
const handlerType = handlerTypes[handlerInfo.handlerType] |
|||
return context => { |
|||
const parameters = {} |
|||
for (let p in handlerInfo.parameters) { |
|||
parameters[p] = handlerInfo.parameters[p](context) |
|||
} |
|||
handlerType.execute(parameters) |
|||
} |
|||
} |
|||
|
|||
const BindingPath = prop => prop[BB_STATE_BINDINGPATH] |
|||
const BindingFallback = prop => prop[BB_STATE_FALLBACK] |
|||
const BindingSource = prop => prop[BB_STATE_BINDINGSOURCE] |
|||
@ -1,20 +1,189 @@ |
|||
{ |
|||
"_lib": "./dist/index.js", |
|||
"h1": { |
|||
"name": "H1", |
|||
"description": "An HTML H1 tag", |
|||
"_generators": {}, |
|||
"Body1": { |
|||
"name": "Body1", |
|||
"description": "Sets the font properties as Roboto Body 1", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Body2": { |
|||
"name": "Body2", |
|||
"description": "Sets the font properties as Roboto Body 2", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Button": { |
|||
"name": "Button", |
|||
"description": "A Material Design button with different variations. It renders as an anchor if href is passed to it.", |
|||
"props": { |
|||
"onClick": "event", |
|||
"variant": "string", |
|||
"colour": "string", |
|||
"size": "string", |
|||
"href": "string", |
|||
"icon": "string", |
|||
"trailingIcon": "bool", |
|||
"fullwidth": "bool", |
|||
"text": "string", |
|||
"className": "string" |
|||
"disabled": "bool" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"button": { |
|||
"name": "Button", |
|||
"description": "A button", |
|||
"Caption": { |
|||
"name": "Caption", |
|||
"description": "Sets the font properties as Roboto Caption", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Checkbox": { |
|||
"name": "Checkbox", |
|||
"description": "A Material Design checkbox. Supports aligning label before or after checkbox.", |
|||
"props": { |
|||
"onClick": "event", |
|||
"id": "string", |
|||
"label": "string", |
|||
"disabled": "bool", |
|||
"alignEnd": "bool", |
|||
"indeterminate": "bool", |
|||
"checked": "bool" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Datatable": { |
|||
"name": "Datatable", |
|||
"description": "A Material Design component to represent tabular data.", |
|||
"props": {}, |
|||
"tags": [] |
|||
}, |
|||
"H1": { |
|||
"name": "H1", |
|||
"description": "Sets the font properties as Roboto Headline1", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"H2": { |
|||
"name": "H2", |
|||
"description": "Sets the font properties as Roboto Headline2", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"H3": { |
|||
"name": "H3", |
|||
"description": "Sets the font properties as Roboto Headline3", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"H4": { |
|||
"name": "H4", |
|||
"description": "Sets the font properties as Roboto Headline4", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"H5": { |
|||
"name": "H5", |
|||
"description": "Sets the font properties as Roboto Headline5", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"H6": { |
|||
"name": "H6", |
|||
"description": "Sets the font properties as Roboto Headline6", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Label": { |
|||
"name": "Label", |
|||
"description": "A simple label component that displays its text in the standard Roboto Material Design font", |
|||
"props": { |
|||
"bold": "bool" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Overline": { |
|||
"name": "Overline", |
|||
"description": "Sets the font properties as Roboto Overline", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Radiobutton": { |
|||
"name": "Radiobutton", |
|||
"description": "A Material Design radiobutton. Supports aligning label before or after radiobutton.", |
|||
"props": { |
|||
"onClick": "event", |
|||
"id": "string", |
|||
"label": "string", |
|||
"names": "string", |
|||
"name": "string", |
|||
"checked": "bool", |
|||
"disabled": "bool", |
|||
"alignEnd": "bool" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Sub1": { |
|||
"name": "Sub1", |
|||
"description": "Sets the font properties as Roboto Subtitle1", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Sub2": { |
|||
"name": "Sub2", |
|||
"description": "Sets the font properties as Roboto Subtitle2", |
|||
"props": { |
|||
"text": "string" |
|||
}, |
|||
"tags": [] |
|||
}, |
|||
"Textfield": { |
|||
"name": "Textfield", |
|||
"description": "A Material Design textfield with multiple variants. Can also be converted to a text area / multine text field.", |
|||
"props": { |
|||
"raised": "bool" |
|||
"onChange": "event", |
|||
"label": "string", |
|||
"variant": "string", |
|||
"disabled": "bool", |
|||
"fullwidth": "bool", |
|||
"colour":"string", |
|||
"size":"string", |
|||
"type": "string", |
|||
"required": "bool", |
|||
"minLength": "number", |
|||
"maxLength": "number", |
|||
"helperText": "string", |
|||
"errorText": "string", |
|||
"placeholder": "string", |
|||
"icon": "string", |
|||
"trailingIcon": "bool", |
|||
"textarea": "bool", |
|||
"rows": "number", |
|||
"cols": "number", |
|||
"validation": "bool", |
|||
"persistent": "bool" |
|||
}, |
|||
"tags": [] |
|||
} |
|||
} |
|||
|
|||
|
|||
@ -1,12 +0,0 @@ |
|||
<script> |
|||
import "@material/button/mdc-button.scss" |
|||
export let raised = false |
|||
|
|||
let c = raised ? "mdc-button mdc-button--raised" : "mdc-button" |
|||
</script> |
|||
|
|||
<button class={c}> |
|||
<div class="mdc-button__ripple" /> |
|||
|
|||
<span class="mdc-button__label">Button</span> |
|||
</button> |
|||
@ -1,2 +1,2 @@ |
|||
import "./_index.scss" |
|||
export { default as button } from "./Button.svelte" |
|||
export { default as Button } from "./Button.svelte" |
|||
|
|||
@ -1,4 +1,4 @@ |
|||
import "./_style.scss"; |
|||
export { default as checkbox } from "./Checkbox.svelte"; |
|||
export { default as checkboxgroup } from "./CheckboxGroup.svelte"; |
|||
export { default as Checkbox } from "./Checkbox.svelte"; |
|||
export { default as Checkboxgroup } from "./CheckboxGroup.svelte"; |
|||
|
|||
|
|||
@ -0,0 +1,67 @@ |
|||
<script> |
|||
import { onMount, setContext } from "svelte" |
|||
import { MDCDataTable } from "@material/data-table" |
|||
import Row from "./DatatableRow.svelte" |
|||
import Cell from "./DatatableCell.svelte" |
|||
import { Button } from "../Button" |
|||
import ClassBuilder from "../ClassBuilder.js" |
|||
|
|||
const cb = new ClassBuilder("data-table") |
|||
setContext("BBMD:data-table:cb", cb) |
|||
|
|||
let datatable = null |
|||
let instance = null |
|||
|
|||
onMount(() => { |
|||
if (!!datatable) instance = new MDCDataTable(datatable) |
|||
return () => { |
|||
!!instance && instance.destroy() |
|||
instance = null |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<div bind:this={datatable} class={cb.build()}> |
|||
<table class={cb.elem`table`} aria-label="Material Design Datatable"> |
|||
<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> |
|||
</div> |
|||
@ -0,0 +1,23 @@ |
|||
<script> |
|||
import { getContext } from "svelte" |
|||
|
|||
export let isHeader = false |
|||
export let numeric = false |
|||
|
|||
const cb = getContext("BBMD:data-table:cb") |
|||
|
|||
let elementName = isHeader ? "header-cell" : "cell" |
|||
let modifiers = { numeric } |
|||
let props = { modifiers } |
|||
let cellClass = cb.build({ elementName, props }) |
|||
</script> |
|||
|
|||
{#if isHeader} |
|||
<th class={cellClass} role="columnheader" scope="col"> |
|||
<slot /> |
|||
</th> |
|||
{:else} |
|||
<td class={cellClass}> |
|||
<slot /> |
|||
</td> |
|||
{/if} |
|||
@ -0,0 +1,26 @@ |
|||
<script> |
|||
import { getContext } from "svelte"; |
|||
|
|||
export let onSelect = () => {}; |
|||
export let isHeader = false; |
|||
let row = null; |
|||
let selected = false; |
|||
|
|||
const cb = getContext("BBMD:data-table:cb"); |
|||
|
|||
let elementName = isHeader ? "header-row" : "row"; |
|||
let modifiers = {}; |
|||
|
|||
$: modifiers = { selected }; |
|||
$: props = { modifiers }; |
|||
$: rowClass = cb.build({ elementName, props }); |
|||
|
|||
function rowSelected() { |
|||
selected = !selected; |
|||
onSelect(); |
|||
} |
|||
</script> |
|||
|
|||
<tr bind:this={row} class={rowClass} on:click={rowSelected}> |
|||
<slot /> |
|||
</tr> |
|||
@ -0,0 +1 @@ |
|||
@import "@material/data-table/mdc-data-table"; |
|||
@ -0,0 +1,2 @@ |
|||
import "./_style.scss"; |
|||
export { default as Datatable } from "./Datatable.svelte"; |
|||
@ -1,8 +0,0 @@ |
|||
<script> |
|||
export let text = "" |
|||
export let className = "" |
|||
|
|||
export let _bb |
|||
</script> |
|||
|
|||
<h1 class={className}>{text}</h1> |
|||
@ -1,3 +1,3 @@ |
|||
import "./_style.scss"; |
|||
export { default as radiobutton } from "./Radiobutton.svelte"; |
|||
export { default as radiobuttongroup } from "./RadiobuttonGroup.svelte"; |
|||
export { default as Radiobutton } from "./Radiobutton.svelte"; |
|||
export { default as Radiobuttongroup } from "./RadiobuttonGroup.svelte"; |
|||
|
|||
@ -1,23 +1,25 @@ |
|||
import { |
|||
H1, |
|||
Overline, |
|||
button, |
|||
icon, |
|||
textfield, |
|||
checkbox, |
|||
checkboxgroup, |
|||
radiobutton, |
|||
radiobuttongroup, |
|||
Button, |
|||
Icon, |
|||
Textfield, |
|||
Checkbox, |
|||
Checkboxgroup, |
|||
Radiobutton, |
|||
Radiobuttongroup, |
|||
Datatable, |
|||
} from "@BBMD" |
|||
|
|||
export default { |
|||
H1, |
|||
Overline, |
|||
button, |
|||
icon, |
|||
textfield, |
|||
checkbox, |
|||
checkboxgroup, |
|||
radiobutton, |
|||
radiobuttongroup, |
|||
Button, |
|||
Icon, |
|||
Textfield, |
|||
Checkbox, |
|||
Checkboxgroup, |
|||
Radiobutton, |
|||
Radiobuttongroup, |
|||
Datatable, |
|||
} |
|||
|
|||
@ -1,2 +1,2 @@ |
|||
import "./_index.scss" |
|||
export { default as textfield } from "./Textfield.svelte" |
|||
export { default as Textfield } from "./Textfield.svelte" |
|||
@ -1,9 +1,11 @@ |
|||
import "@material/theme/mdc-theme.scss"; |
|||
|
|||
export { button } from "./Button" |
|||
export { default as icon } from "./Icon.svelte" |
|||
export { textfield } from "./Textfield" |
|||
export { Button } from "./Button" |
|||
export { default as Icon } from "./Common/Icon.svelte" |
|||
export { Textfield } from "./Textfield" |
|||
export * from "./Typography" |
|||
export { checkbox, checkboxgroup } from "./Checkbox" |
|||
export { radiobutton, radiobuttongroup } from "./Radiobutton" |
|||
export { Checkbox, Checkboxgroup } from "./Checkbox" |
|||
export { Radiobutton, Radiobuttongroup } from "./Radiobutton" |
|||
export { default as Label } from "./Common/Label.svelte" |
|||
export { Datatable } from "./Datatable" |
|||
|
|||
|
|||
@ -0,0 +1,92 @@ |
|||
const { readdir, stat, copyFile } = require("fs-extra") |
|||
const { constants } = require("fs") |
|||
const { join, basename } = require("path") |
|||
const serverConfig = require("../../../server/config")() |
|||
|
|||
const packagesFolder = ".." |
|||
|
|||
const jsFile = dir => join(dir, "index.js") |
|||
const generatorsFile = dir => join(dir, "generators.js") |
|||
const jsMapFile = dir => join(dir, "index.js.map") |
|||
const sourceJs = jsFile("dist") |
|||
const sourceJsMap = jsMapFile("dist") |
|||
const componentsFile = "components.json" |
|||
const sourceGenerators = generatorsFile("dist") |
|||
|
|||
const appPackages = join( |
|||
packagesFolder, |
|||
"server", |
|||
serverConfig.latestPackagesFolder |
|||
) |
|||
|
|||
const publicMain = appName => |
|||
join( |
|||
appPackages, |
|||
appName, |
|||
"public", |
|||
"main", |
|||
"lib", |
|||
"node_modules", |
|||
"@budibase", |
|||
"standard-components" |
|||
) |
|||
const publicUnauth = appName => |
|||
join( |
|||
appPackages, |
|||
appName, |
|||
"public", |
|||
"unauthenticated", |
|||
"lib", |
|||
"node_modules", |
|||
"@budibase", |
|||
"standard-components" |
|||
) |
|||
const nodeModulesDist = appName => |
|||
join( |
|||
appPackages, |
|||
appName, |
|||
"node_modules", |
|||
"@budibase", |
|||
"standard-components", |
|||
"dist" |
|||
) |
|||
const nodeModules = appName => |
|||
join(appPackages, appName, "node_modules", "@budibase", "standard-components") |
|||
|
|||
;(async () => { |
|||
const apps = await readdir(appPackages) |
|||
|
|||
const copySource = file => async toDir => { |
|||
const dest = join(toDir, basename(file)) |
|||
try { |
|||
await copyFile(file, dest, constants.COPYFILE_FICLONE) |
|||
console.log(`COPIED ${file} to ${dest}`) |
|||
} catch (e) { |
|||
console.log(`COPY FAILED ${file} to ${dest}: ${e}`) |
|||
} |
|||
} |
|||
|
|||
const copySourceJs = copySource(sourceJs) |
|||
const copySourceJsMap = copySource(sourceJsMap) |
|||
const copyGenerators = copySource(sourceGenerators) |
|||
const copyComponentsJson = copySource(componentsFile) |
|||
|
|||
for (let app of apps) { |
|||
if (app === ".data") continue |
|||
if (!(await stat(join(appPackages, app))).isDirectory()) continue |
|||
|
|||
await copySourceJs(nodeModulesDist(app)) |
|||
await copySourceJsMap(nodeModulesDist(app)) |
|||
await copyGenerators(nodeModulesDist(app)) |
|||
|
|||
await copyComponentsJson(nodeModules(app)) |
|||
|
|||
await copySourceJs(join(publicMain(app), "dist")) |
|||
await copySourceJsMap(join(publicMain(app), "dist")) |
|||
await copyGenerators(join(publicMain(app), "dist")) |
|||
|
|||
await copySourceJs(join(publicUnauth(app), "dist")) |
|||
await copySourceJsMap(join(publicUnauth(app), "dist")) |
|||
await copyGenerators(join(publicUnauth(app), "dist")) |
|||
} |
|||
})() |
|||
@ -0,0 +1,9 @@ |
|||
module.exports = props => { |
|||
if (props._codeMeta) { |
|||
delete props._codeMeta |
|||
} |
|||
|
|||
for (let child of props._children || []) { |
|||
module.exports(child) |
|||
} |
|||
} |
|||
Loading…
Reference in new issue