diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js
index 31b8dcff22..8cac56df66 100644
--- a/packages/builder/src/builderStore/store/frontend.js
+++ b/packages/builder/src/builderStore/store/frontend.js
@@ -479,7 +479,7 @@ export const getFrontendStore = () => {
// Try to extract a nav component from the master screen
const nav = findChildComponentType(
state.pages.main,
- "@budibase/standard-components/Navigation"
+ "@budibase/standard-components/navigation"
)
if (nav) {
let newLink
diff --git a/packages/builder/src/components/userInterface/EventsEditor/EventEditorModal.svelte b/packages/builder/src/components/userInterface/EventsEditor/EventEditorModal.svelte
index 56485a2b6e..27e91cd29e 100644
--- a/packages/builder/src/components/userInterface/EventsEditor/EventEditorModal.svelte
+++ b/packages/builder/src/components/userInterface/EventsEditor/EventEditorModal.svelte
@@ -1,11 +1,11 @@
{#each screens as screen (screen._id)}
-
+
+
+
{/each}
+
+
diff --git a/packages/client/src/old/createApp.js b/packages/client/src/old/createApp.js
deleted file mode 100644
index f276b8d441..0000000000
--- a/packages/client/src/old/createApp.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { attachChildren } from "./render/attachChildren"
-import { createTreeNode } from "./render/prepareRenderComponent"
-import { screenRouter } from "./render/screenRouter"
-import { createStateManager } from "./state/stateManager"
-import { getAppId } from "@budibase/component-sdk"
-
-export const createApp = ({
- componentLibraries,
- frontendDefinition,
- window,
-}) => {
- let routeTo
- let currentUrl
- let screenStateManager
-
- const onScreenSlotRendered = screenSlotNode => {
- const onScreenSelected = (screen, url) => {
- const stateManager = createStateManager({
- componentLibraries,
- onScreenSlotRendered: () => {},
- routeTo,
- })
- const getAttachChildrenParams = attachChildrenParams(stateManager)
- screenSlotNode.props._children = [screen.props]
- const initialiseChildParams = getAttachChildrenParams(screenSlotNode)
- attachChildren(initialiseChildParams)(screenSlotNode.rootElement, {
- hydrate: true,
- force: true,
- })
- if (screenStateManager) screenStateManager.destroy()
- screenStateManager = stateManager
- currentUrl = url
- }
-
- routeTo = screenRouter({
- screens: frontendDefinition.screens,
- onScreenSelected,
- window,
- })
- const fallbackPath = window.location.pathname.replace(getAppId(), "")
- routeTo(currentUrl || fallbackPath)
- }
-
- const attachChildrenParams = stateManager => {
- const getInitialiseParams = treeNode => ({
- componentLibraries,
- treeNode,
- onScreenSlotRendered,
- setupState: stateManager.setup,
- })
-
- return getInitialiseParams
- }
-
- let rootTreeNode
- const pageStateManager = createStateManager({
- componentLibraries,
- onScreenSlotRendered,
- // seems weird, but the routeTo variable may not be available at this point
- routeTo: url => routeTo(url),
- })
-
- const initialisePage = (page, target, urlPath) => {
- currentUrl = urlPath
-
- rootTreeNode = createTreeNode()
- rootTreeNode.props = {
- _children: [page.props],
- }
- const getInitialiseParams = attachChildrenParams(pageStateManager)
- const initChildParams = getInitialiseParams(rootTreeNode)
-
- attachChildren(initChildParams)(target, {
- hydrate: true,
- force: true,
- })
-
- return rootTreeNode
- }
-
- return {
- initialisePage,
- screenStore: () => screenStateManager.store,
- pageStore: () => pageStateManager.store,
- routeTo: () => routeTo,
- rootNode: () => rootTreeNode,
- }
-}
diff --git a/packages/client/src/old/index.js.old b/packages/client/src/old/index.js.old
deleted file mode 100644
index 5c46c1f6b9..0000000000
--- a/packages/client/src/old/index.js.old
+++ /dev/null
@@ -1,59 +0,0 @@
-import { createApp } from "./createApp"
-import { builtins, builtinLibName } from "./render/builtinComponents"
-import { getAppId } from "@budibase/component-sdk"
-
-/**
- * create a web application from static budibase definition files.
- * @param {object} opts - configuration options for budibase client libary
- */
-export const loadBudibase = async opts => {
- const _window = (opts && opts.window) || window
- // const _localStorage = (opts && opts.localStorage) || localStorage
- const appId = getAppId(window.document.cookie)
- const frontendDefinition = _window["##BUDIBASE_FRONTEND_DEFINITION##"]
-
- const user = {}
-
- const componentLibraryModules = (opts && opts.componentLibraries) || {}
-
- const libraries = frontendDefinition.libraries || []
-
- for (let library of libraries) {
- // fetch the JavaScript for the component libraries from the server
- componentLibraryModules[library] = await import(
- `/componentlibrary?library=${encodeURI(library)}&appId=${appId}`
- )
- }
-
- componentLibraryModules[builtinLibName] = builtins(_window)
-
- const {
- initialisePage,
- screenStore,
- pageStore,
- routeTo,
- rootNode,
- } = createApp({
- componentLibraries: componentLibraryModules,
- frontendDefinition,
- user,
- window: _window,
- })
-
- const route = _window.location
- ? _window.location.pathname.replace(`${appId}/`, "").replace(appId, "")
- : ""
-
- initialisePage(frontendDefinition.page, _window.document.body, route)
-
- return {
- screenStore,
- pageStore,
- routeTo,
- rootNode,
- }
-}
-
-if (window) {
- window.loadBudibase = loadBudibase
-}
diff --git a/packages/client/src/old/render/attachChildren.js b/packages/client/src/old/render/attachChildren.js
deleted file mode 100644
index ee6f313c33..0000000000
--- a/packages/client/src/old/render/attachChildren.js
+++ /dev/null
@@ -1,138 +0,0 @@
-import { prepareRenderComponent } from "./prepareRenderComponent"
-import { isScreenSlot } from "./builtinComponents"
-import deepEqual from "deep-equal"
-import appStore from "../state/store"
-
-export const attachChildren = initialiseOpts => (htmlElement, options) => {
- const {
- componentLibraries,
- treeNode,
- onScreenSlotRendered,
- setupState,
- } = initialiseOpts
-
- const anchor = options && options.anchor ? options.anchor : null
- const force = options ? options.force : false
- const hydrate = options ? options.hydrate : true
- const context = options && options.context
-
- if (!force && treeNode.children.length > 0) return treeNode.children
-
- for (let childNode of treeNode.children) {
- childNode.destroy()
- }
-
- if (!htmlElement) return
-
- if (hydrate) {
- while (htmlElement.firstChild) {
- htmlElement.removeChild(htmlElement.firstChild)
- }
- }
-
- const contextStoreKeys = []
-
- // create new context if supplied
- if (context) {
- let childIndex = 0
- // if context is an array, map to new structure
- const contextArray = Array.isArray(context) ? context : [context]
- for (let ctx of contextArray) {
- const key = appStore.create(
- ctx,
- treeNode.props._id,
- childIndex,
- treeNode.contextStoreKey
- )
- contextStoreKeys.push(key)
- childIndex++
- }
- }
-
- const childNodes = []
-
- const createChildNodes = contextStoreKey => {
- for (let childProps of treeNode.props._children) {
- const { componentName, libName } = splitName(childProps._component)
-
- if (!componentName || !libName) return
-
- const ComponentConstructor = componentLibraries[libName][componentName]
-
- const childNode = prepareRenderComponent({
- props: childProps,
- parentNode: treeNode,
- ComponentConstructor,
- htmlElement,
- anchor,
- // in same context as parent, unless a new one was supplied
- contextStoreKey,
- })
-
- childNodes.push(childNode)
- }
- }
-
- if (context) {
- // if new context(s) is supplied, then create nodes
- // with keys to new context stores
- for (let contextStoreKey of contextStoreKeys) {
- createChildNodes(contextStoreKey)
- }
- } else {
- // otherwise, use same context store as parent
- // which maybe undefined (therfor using the root state)
- createChildNodes(treeNode.contextStoreKey)
- }
-
- // if everything is equal, then don't re-render
- if (areTreeNodesEqual(treeNode.children, childNodes)) return treeNode.children
-
- for (let node of childNodes) {
- const initialProps = setupState(node)
- node.render(initialProps)
- }
-
- const screenSlot = childNodes.find(n => isScreenSlot(n.props._component))
-
- if (onScreenSlotRendered && screenSlot) {
- // assuming there is only ever one screen slot
- onScreenSlotRendered(screenSlot)
- }
-
- treeNode.children = childNodes
-
- return childNodes
-}
-
-const splitName = fullname => {
- const nameParts = fullname.split("/")
-
- const componentName = nameParts[nameParts.length - 1]
-
- const libName = fullname.substring(
- 0,
- fullname.length - componentName.length - 1
- )
-
- return { libName, componentName }
-}
-
-const areTreeNodesEqual = (children1, children2) => {
- if (children1.length !== children2.length) return false
- if (children1 === children2) return true
-
- let isEqual = false
- for (let i = 0; i < children1.length; i++) {
- // same context and same children, then nothing has changed
- isEqual =
- deepEqual(children1[i].context, children2[i].context) &&
- areTreeNodesEqual(children1[i].children, children2[i].children)
- if (!isEqual) return false
- if (isScreenSlot(children1[i].parentNode.props._component)) {
- isEqual = deepEqual(children1[i].props, children2[i].props)
- }
- if (!isEqual) return false
- }
- return true
-}
diff --git a/packages/client/src/old/render/builtinComponents.js b/packages/client/src/old/render/builtinComponents.js
deleted file mode 100644
index f5343234f4..0000000000
--- a/packages/client/src/old/render/builtinComponents.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { screenSlotComponent } from "./screenSlotComponent"
-
-export const builtinLibName = "##builtin"
-
-export const isScreenSlot = componentName =>
- componentName === "##builtin/screenslot"
-
-export const builtins = window => ({
- screenslot: screenSlotComponent(window),
-})
diff --git a/packages/client/src/old/render/prepareRenderComponent.js b/packages/client/src/old/render/prepareRenderComponent.js
deleted file mode 100644
index 5d0d34d003..0000000000
--- a/packages/client/src/old/render/prepareRenderComponent.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import renderTemplateString from "../state/renderTemplateString"
-import appStore from "../state/store"
-import hasBinding from "../state/hasBinding"
-
-export const prepareRenderComponent = ({
- ComponentConstructor,
- htmlElement,
- anchor,
- props,
- parentNode,
- contextStoreKey,
-}) => {
- const thisNode = createTreeNode()
- thisNode.parentNode = parentNode
- thisNode.props = props
- thisNode.contextStoreKey = contextStoreKey
-
- // the treeNode is first created (above), and then this
- // render method is add. The treeNode is returned, and
- // render is called later (in attachChildren)
- thisNode.render = initialProps => {
- thisNode.component = new ComponentConstructor({
- target: htmlElement,
- props: initialProps,
- hydrate: false,
- anchor,
- })
-
- // finds the root element of the component, which was created by the contructor above
- // we use this later to attach a className to. This is how styles
- // are applied by the builder
- thisNode.rootElement = htmlElement.children[htmlElement.children.length - 1]
-
- let [componentName] = props._component.match(/[a-z]*$/)
- if (props._id && thisNode.rootElement) {
- thisNode.rootElement.classList.add(`${componentName}-${props._id}`)
- }
-
- // make this node listen to the store
- if (thisNode.stateBound) {
- const unsubscribe = appStore.subscribe(state => {
- const storeBoundProps = Object.keys(initialProps._bb.props).filter(p =>
- hasBinding(initialProps._bb.props[p])
- )
- if (storeBoundProps.length > 0) {
- const toSet = {}
- for (let prop of storeBoundProps) {
- const propValue = initialProps._bb.props[prop]
- toSet[prop] = renderTemplateString(propValue, state)
- }
- thisNode.component.$set(toSet)
- }
- }, thisNode.contextStoreKey)
- thisNode.unsubscribe = unsubscribe
- }
- }
-
- return thisNode
-}
-
-export const createTreeNode = () => ({
- context: {},
- props: {},
- rootElement: null,
- parentNode: null,
- children: [],
- bindings: [],
- component: null,
- unsubscribe: () => {},
- render: () => {},
- get destroy() {
- const node = this
- return () => {
- if (node.children) {
- // destroy children first - from leaf nodes up
- for (let child of node.children) {
- child.destroy()
- }
- }
- if (node.unsubscribe) node.unsubscribe()
- if (node.component && node.component.$destroy) node.component.$destroy()
- for (let onDestroyItem of node.onDestroy) {
- onDestroyItem()
- }
- }
- },
- onDestroy: [],
-})
diff --git a/packages/client/src/old/render/screenRouter.js b/packages/client/src/old/render/screenRouter.js
deleted file mode 100644
index 78dc75b3c4..0000000000
--- a/packages/client/src/old/render/screenRouter.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import regexparam from "regexparam"
-import appStore from "../state/store"
-import { getAppId } from "@budibase/component-sdk"
-
-export const screenRouter = ({ screens, onScreenSelected, window }) => {
- function sanitize(url) {
- if (!url) return url
- return url
- .split("/")
- .map(part => {
- // if parameter, then use as is
- if (part.startsWith(":")) return part
- return encodeURIComponent(part)
- })
- .join("/")
- .toLowerCase()
- }
-
- const isRunningLocally = () => {
- const hostname = (window.location && window.location.hostname) || ""
- return (
- hostname === "localhost" ||
- hostname === "127.0.0.1" ||
- hostname.startsWith("192.168")
- )
- }
-
- const makeRootedPath = url => {
- if (isRunningLocally()) {
- const appId = getAppId()
- if (url) {
- url = sanitize(url)
- if (!url.startsWith("/")) {
- url = `/${url}`
- }
- if (url.startsWith(`/${appId}`)) {
- return url
- }
- return `/${appId}${url}`
- }
- return `/${appId}`
- }
- return sanitize(url)
- }
-
- const routes = screens.map(s => makeRootedPath(s.routing?.route))
- let fallback = routes.findIndex(([p]) => p === makeRootedPath("*"))
- if (fallback < 0) fallback = 0
-
- let current
-
- function route(url) {
- const _url = makeRootedPath(url.state || url)
- current = routes.findIndex(
- p =>
- p !== makeRootedPath("*") &&
- new RegExp("^" + p.toLowerCase() + "$").test(_url.toLowerCase())
- )
-
- const params = {}
-
- if (current === -1) {
- routes.forEach((p, i) => {
- // ignore home - which matched everything
- if (p === makeRootedPath("*")) return
- const pm = regexparam(p)
- const matches = pm.pattern.exec(_url)
-
- if (!matches) return
-
- let j = 0
- while (j < pm.keys.length) {
- params[pm.keys[j]] = matches[++j] || null
- }
-
- current = i
- })
- }
-
- appStore.update(state => {
- state["##routeParams"] = params
- return state
- })
-
- const screenIndex = current !== -1 ? current : fallback
-
- try {
- !url.state && history.pushState(_url, null, _url)
- } catch (_) {
- // ignoring an exception here as the builder runs an iframe, which does not like this
- }
-
- onScreenSelected(screens[screenIndex], _url)
- }
-
- function click(e) {
- const x = e.target.closest("a")
- const y = x && x.getAttribute("href")
-
- if (
- e.ctrlKey ||
- e.metaKey ||
- e.altKey ||
- e.shiftKey ||
- e.button ||
- e.defaultPrevented
- )
- return
-
- const target = (x && x.target) || "_self"
- if (!y || target !== "_self" || x.host !== location.host) return
-
- e.preventDefault()
- route(y)
- }
-
- addEventListener("popstate", route)
- addEventListener("pushstate", route)
- addEventListener("click", click)
-
- return route
-}
diff --git a/packages/client/src/old/render/screenSlotComponent.js b/packages/client/src/old/render/screenSlotComponent.js
deleted file mode 100644
index 6ec133474a..0000000000
--- a/packages/client/src/old/render/screenSlotComponent.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export const screenSlotComponent = window => {
- return function(opts) {
- const node = window.document.createElement("DIV")
- const $set = props => {
- props._bb.attachChildren(node)
- }
- const $destroy = () => {
- if (opts.target && node) opts.target.removeChild(node)
- }
- this.$set = $set
- this.$destroy = $destroy
- opts.target.appendChild(node)
- }
-}
diff --git a/packages/client/src/old/state/bbComponentApi.js b/packages/client/src/old/state/bbComponentApi.js
deleted file mode 100644
index 554d1d1df7..0000000000
--- a/packages/client/src/old/state/bbComponentApi.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import setBindableComponentProp from "./setBindableComponentProp"
-import { attachChildren } from "../render/attachChildren"
-import store from "./store"
-
-export const bbFactory = ({
- componentLibraries,
- onScreenSlotRendered,
- runEventActions,
-}) => {
- return (treeNode, setupState) => {
- const attachParams = {
- componentLibraries,
- treeNode,
- onScreenSlotRendered,
- setupState,
- }
-
- return {
- attachChildren: attachChildren(attachParams),
- props: treeNode.props,
- call: async eventName =>
- eventName &&
- (await runEventActions(
- treeNode.props[eventName],
- store.getState(treeNode.contextStoreKey)
- )),
- setBinding: setBindableComponentProp(treeNode),
- parent,
- store: store.getStore(treeNode.contextStoreKey),
- // these parameters are populated by screenRouter
- routeParams: () => store.getState()["##routeParams"],
- }
- }
-}
diff --git a/packages/client/src/old/state/eventHandlers.js b/packages/client/src/old/state/eventHandlers.js
deleted file mode 100644
index 39aecd388c..0000000000
--- a/packages/client/src/old/state/eventHandlers.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import renderTemplateString from "./renderTemplateString"
-import { updateRow, saveRow, deleteRow } from "@budibase/component-sdk"
-
-export const EVENT_TYPE_MEMBER_NAME = "##eventHandlerType"
-
-export const eventHandlers = routeTo => {
- const handlers = {
- "Navigate To": param => routeTo(param && param.url),
- "Update Row": updateRow,
- "Save Row": saveRow,
- "Delete Row": deleteRow,
- }
-
- // when an event is called, this is what gets run
- const runEventActions = async (actions, state) => {
- if (!actions) return
- // calls event handlers sequentially
- for (let action of actions) {
- const handler = handlers[action[EVENT_TYPE_MEMBER_NAME]]
- const parameters = createParameters(action.parameters, state)
- if (handler) {
- await handler(parameters, state)
- }
- }
- }
-
- return runEventActions
-}
-
-// this will take a parameters obj, iterate all keys, and do a mustache render
-// for every string. It will work recursively if it encounnters an {}
-const createParameters = (parameterTemplateObj, state) => {
- const parameters = {}
- for (let key in parameterTemplateObj) {
- if (typeof parameterTemplateObj[key] === "string") {
- parameters[key] = renderTemplateString(parameterTemplateObj[key], state)
- } else if (typeof parameterTemplateObj[key] === "object") {
- parameters[key] = createParameters(parameterTemplateObj[key], state)
- }
- }
- return parameters
-}
diff --git a/packages/client/src/old/state/getSetContext.js b/packages/client/src/old/state/getSetContext.js
deleted file mode 100644
index 58dbb22d2c..0000000000
--- a/packages/client/src/old/state/getSetContext.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export const setContext = treeNode => (key, value) =>
- (treeNode.context[key] = value)
-
-export const getContext = treeNode => key => {
- if (treeNode.context && treeNode.context[key] !== undefined)
- return treeNode.context[key]
-
- if (!treeNode.context.$parent) return
-
- return getContext(treeNode.parentNode)(key)
-}
diff --git a/packages/client/src/old/state/hasBinding.js b/packages/client/src/old/state/hasBinding.js
deleted file mode 100644
index ac6ae79074..0000000000
--- a/packages/client/src/old/state/hasBinding.js
+++ /dev/null
@@ -1 +0,0 @@
-export default value => typeof value === "string" && value.includes("{{")
diff --git a/packages/client/src/old/state/renderTemplateString.js b/packages/client/src/old/state/renderTemplateString.js
deleted file mode 100644
index e2d8eba859..0000000000
--- a/packages/client/src/old/state/renderTemplateString.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import mustache from "mustache"
-
-// this is a much more liberal version of mustache's escape function
-// ...just ignoring < and > to prevent tags from user input
-// original version here https://github.com/janl/mustache.js/blob/4b7908f5c9fec469a11cfaed2f2bed23c84e1c5c/mustache.js#L78
-
-const entityMap = {
- "<": "<",
- ">": ">",
-}
-
-mustache.escape = text =>
- String(text).replace(/[&<>"'`=/]/g, function fromEntityMap(s) {
- return entityMap[s] || s
- })
-
-export default mustache.render
diff --git a/packages/client/src/old/state/setBindableComponentProp.js b/packages/client/src/old/state/setBindableComponentProp.js
deleted file mode 100644
index 4fe9191fc4..0000000000
--- a/packages/client/src/old/state/setBindableComponentProp.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import appStore from "./store"
-
-export default treeNode => (propName, value) => {
- if (!propName || propName.length === 0) return
- if (!treeNode) return
- const componentId = treeNode.props._id
-
- appStore.update(state => {
- state[componentId] = state[componentId] || {}
- state[componentId][propName] = value
- return state
- }, treeNode.contextStoreKey)
-}
diff --git a/packages/client/src/old/state/stateManager.js b/packages/client/src/old/state/stateManager.js
deleted file mode 100644
index b753d2f346..0000000000
--- a/packages/client/src/old/state/stateManager.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import { eventHandlers } from "./eventHandlers"
-import { bbFactory } from "./bbComponentApi"
-import renderTemplateString from "./renderTemplateString"
-import appStore from "./store"
-import hasBinding from "./hasBinding"
-
-const doNothing = () => {}
-doNothing.isPlaceholder = true
-
-const isMetaProp = propName =>
- propName === "_component" ||
- propName === "_children" ||
- propName === "_id" ||
- propName === "_style" ||
- propName === "_code" ||
- propName === "_codeMeta" ||
- propName === "_styles"
-
-export const createStateManager = ({
- componentLibraries,
- onScreenSlotRendered,
- routeTo,
-}) => {
- let runEventActions = eventHandlers(routeTo)
-
- const bb = bbFactory({
- componentLibraries,
- onScreenSlotRendered,
- runEventActions,
- })
-
- const setup = _setup(bb)
-
- return {
- setup,
- destroy: () => {},
- }
-}
-
-const _setup = bb => node => {
- const props = node.props
- const initialProps = { ...props }
-
- for (let propName in props) {
- if (isMetaProp(propName)) continue
-
- const propValue = props[propName]
-
- const isBound = hasBinding(propValue)
-
- if (isBound) {
- const state = appStore.getState(node.contextStoreKey)
- initialProps[propName] = renderTemplateString(propValue, state)
-
- if (!node.stateBound) {
- node.stateBound = true
- }
- }
- }
-
- const setup = _setup(bb)
- initialProps._bb = bb(node, setup)
-
- return initialProps
-}
diff --git a/packages/client/src/old/state/store.js b/packages/client/src/old/state/store.js
deleted file mode 100644
index cf284ec08e..0000000000
--- a/packages/client/src/old/state/store.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import { writable } from "svelte/store"
-
-// we assume that the reference to this state object
-// will remain for the life of the application
-const rootState = {}
-const rootStore = writable(rootState)
-const contextStores = {}
-
-// contextProviderId is the component id that provides the data for the context
-const contextStoreKey = (dataProviderId, childIndex) =>
- `${dataProviderId}${childIndex >= 0 ? ":" + childIndex : ""}`
-
-// creates a store for a datacontext (e.g. each item in a list component)
-// overrides store if already exists
-const create = (data, dataProviderId, childIndex, parentContextStoreId) => {
- const key = contextStoreKey(dataProviderId, childIndex)
- const state = { data }
-
- // add reference to parent state object,
- // so we can use bindings like state.parent.parent
- // (if no parent, then parent is rootState )
- state.parent = parentContextStoreId
- ? contextStores[parentContextStoreId].state
- : rootState
-
- contextStores[key] = {
- store: writable(state),
- subscriberCount: 0,
- state,
- parentContextStoreId,
- }
-
- return key
-}
-
-const subscribe = (subscription, storeKey) => {
- if (!storeKey) {
- return rootStore.subscribe(subscription)
- }
- const contextStore = contextStores[storeKey]
-
- // we are subscribing to multiple stores,
- // we dont want to run our listener for every subscription, the first time
- // as this could repeatedly run $set on the same component
- // ... which already has its initial properties set properly
- const ignoreFirstSubscription = () => {
- let hasRunOnce = false
- return () => {
- if (hasRunOnce) subscription(contextStore.state)
- hasRunOnce = true
- }
- }
-
- const unsubscribes = [rootStore.subscribe(ignoreFirstSubscription())]
-
- // we subscribe to all stores in the hierarchy
- const ancestorSubscribe = ctxStore => {
- // unsubscribe func returned by svelte store
- const svelteUnsub = ctxStore.store.subscribe(ignoreFirstSubscription())
-
- // we wrap the svelte unsubscribe, so we can
- // cleanup stores when they are no longer subscribed to
- const unsub = () => {
- ctxStore.subscriberCount = contextStore.subscriberCount - 1
- // when no subscribers left, we delete the store
- if (ctxStore.subscriberCount === 0) {
- delete ctxStore[storeKey]
- }
- svelteUnsub()
- }
- unsubscribes.push(unsub)
- if (ctxStore.parentContextStoreId) {
- ancestorSubscribe(contextStores[ctxStore.parentContextStoreId])
- }
- }
-
- ancestorSubscribe(contextStore)
-
- // our final unsubscribe function calls unsubscribe on all stores
- return () => unsubscribes.forEach(u => u())
-}
-
-const findStore = (dataProviderId, childIndex) =>
- dataProviderId
- ? contextStores[contextStoreKey(dataProviderId, childIndex)].store
- : rootStore
-
-const update = (updatefunc, dataProviderId, childIndex) =>
- findStore(dataProviderId, childIndex).update(updatefunc)
-
-const set = (value, dataProviderId, childIndex) =>
- findStore(dataProviderId, childIndex).set(value)
-
-const getState = contextStoreKey =>
- contextStoreKey ? contextStores[contextStoreKey].state : rootState
-
-const getStore = contextStoreKey =>
- contextStoreKey ? contextStores[contextStoreKey].store : rootStore
-
-export default {
- subscribe,
- update,
- set,
- getState,
- create,
- contextStoreKey,
- getStore,
-}
diff --git a/packages/server/src/constants/pages.js b/packages/server/src/constants/pages.js
index 5fe74d6123..e017885b49 100644
--- a/packages/server/src/constants/pages.js
+++ b/packages/server/src/constants/pages.js
@@ -39,7 +39,7 @@ const MAIN = {
_children: [
{
_id: "49e0e519-9e5e-4127-885a-ee6a0a49e2c1",
- _component: "@budibase/standard-components/Navigation",
+ _component: "@budibase/standard-components/navigation",
_styles: {
normal: {
"max-width": "1400px",
diff --git a/packages/standard-components/components.json b/packages/standard-components/components.json
index 7eddadb68e..180652688f 100644
--- a/packages/standard-components/components.json
+++ b/packages/standard-components/components.json
@@ -13,7 +13,7 @@
"embed": "string"
}
},
- "Navigation": {
+ "navigation": {
"name": "Navigation",
"description": "A basic header navigation component",
"children": true,
diff --git a/packages/standard-components/src/index.js b/packages/standard-components/src/index.js
index 51f53956fa..f578dc8f6f 100644
--- a/packages/standard-components/src/index.js
+++ b/packages/standard-components/src/index.js
@@ -10,7 +10,7 @@ export { default as button } from "./Button.svelte"
export { default as login } from "./Login.svelte"
export { default as link } from "./Link.svelte"
export { default as image } from "./Image.svelte"
-export { default as Navigation } from "./Navigation.svelte"
+export { default as navigation } from "./Navigation.svelte"
export { default as datagrid } from "./grid/Component.svelte"
export { default as dataform } from "./DataForm.svelte"
export { default as dataformwide } from "./DataFormWide.svelte"