148 lines
4.0 KiB
JavaScript
148 lines
4.0 KiB
JavaScript
import { get, writable, derived } from "svelte/store"
|
|
import Manifest from "manifest.json"
|
|
import { findComponentById, findComponentPathById } from "../utils/components"
|
|
import { devToolsStore } from "./devTools"
|
|
import { screenStore } from "./screens"
|
|
import { builderStore } from "./builder"
|
|
import Router from "../components/Router.svelte"
|
|
import * as AppComponents from "../components/app/index.js"
|
|
|
|
const budibasePrefix = "@budibase/standard-components/"
|
|
|
|
const createComponentStore = () => {
|
|
const store = writable({})
|
|
|
|
const derivedStore = derived(
|
|
[store, builderStore, devToolsStore, screenStore],
|
|
([$store, $builderState, $devToolsState, $screenState]) => {
|
|
// Avoid any of this logic if we aren't in the builder preview
|
|
if (!$builderState.inBuilder && !$devToolsState.visible) {
|
|
return {}
|
|
}
|
|
|
|
// Derive the selected component instance and definition
|
|
let asset
|
|
const { screen, selectedComponentId } = $builderState
|
|
if ($builderState.inBuilder) {
|
|
asset = screen
|
|
} else {
|
|
asset = $screenState.activeScreen
|
|
}
|
|
const component = findComponentById(asset?.props, selectedComponentId)
|
|
const prefix = "@budibase/standard-components/"
|
|
const type = component?._component?.replace(prefix, "")
|
|
const definition = type ? Manifest[type] : null
|
|
|
|
// Derive the selected component path
|
|
const path =
|
|
findComponentPathById(asset?.props, selectedComponentId) || []
|
|
|
|
return {
|
|
customComponentManifest: $store.customComponentManifest,
|
|
selectedComponentInstance: $store[selectedComponentId],
|
|
selectedComponent: component,
|
|
selectedComponentDefinition: definition,
|
|
selectedComponentPath: path?.map(component => component._id),
|
|
mountedComponents: Object.keys($store).length,
|
|
currentAsset: asset,
|
|
}
|
|
}
|
|
)
|
|
|
|
const registerInstance = (id, instance) => {
|
|
store.update(state => ({
|
|
...state,
|
|
[id]: instance,
|
|
}))
|
|
}
|
|
|
|
const unregisterInstance = id => {
|
|
store.update(state => {
|
|
delete state[id]
|
|
return state
|
|
})
|
|
}
|
|
|
|
const isComponentRegistered = id => {
|
|
return get(store)[id] != null
|
|
}
|
|
|
|
const getComponentById = id => {
|
|
const asset = get(derivedStore).currentAsset
|
|
return findComponentById(asset?.props, id)
|
|
}
|
|
|
|
const getComponentDefinition = type => {
|
|
if (!type) {
|
|
return null
|
|
}
|
|
|
|
// Screenslot is an edge case
|
|
if (type === "screenslot") {
|
|
type = `${budibasePrefix}${type}`
|
|
}
|
|
|
|
// Handle built-in components
|
|
if (type.startsWith(budibasePrefix)) {
|
|
type = type.replace(budibasePrefix, "")
|
|
return type ? Manifest[type] : null
|
|
}
|
|
|
|
// Handle custom components
|
|
const { customComponentManifest } = get(store)
|
|
return customComponentManifest?.[type]?.schema?.schema
|
|
}
|
|
|
|
const getComponentConstructor = type => {
|
|
if (!type) {
|
|
return null
|
|
}
|
|
if (type === "screenslot") {
|
|
return Router
|
|
}
|
|
|
|
// Handle budibase components
|
|
if (type.startsWith(budibasePrefix)) {
|
|
const split = type.split("/")
|
|
const name = split[split.length - 1]
|
|
return AppComponents[name]
|
|
}
|
|
|
|
// Handle custom components
|
|
const { customComponentManifest } = get(store)
|
|
return customComponentManifest?.[type]?.Component
|
|
}
|
|
|
|
const registerCustomComponent = ({ Component, schema }) => {
|
|
if (!Component || !schema?.schema?.name) {
|
|
return
|
|
}
|
|
store.update(state => {
|
|
if (!state.customComponentManifest) {
|
|
state.customComponentManifest = {}
|
|
}
|
|
const componentName = `plugin/${schema.schema.name}/1.0.0`
|
|
state.customComponentManifest[componentName] = {
|
|
schema,
|
|
Component,
|
|
}
|
|
return state
|
|
})
|
|
}
|
|
|
|
return {
|
|
...derivedStore,
|
|
actions: {
|
|
registerInstance,
|
|
unregisterInstance,
|
|
isComponentRegistered,
|
|
getComponentById,
|
|
getComponentDefinition,
|
|
getComponentConstructor,
|
|
registerCustomComponent,
|
|
},
|
|
}
|
|
}
|
|
|
|
export const componentStore = createComponentStore()
|