budibase/packages/client/src/stores/builder.js

103 lines
3.0 KiB
JavaScript

import { writable, derived, get } from "svelte/store"
import Manifest from "manifest.json"
import { findComponentById, findComponentPathById } from "../utils/components"
import { pingEndUser } from "../api"
const dispatchEvent = (type, data = {}) => {
window.parent.postMessage({ type, data })
}
const createBuilderStore = () => {
const initialState = {
inBuilder: false,
layout: null,
screen: null,
selectedComponentId: null,
editMode: false,
previewId: null,
previewType: null,
selectedPath: [],
theme: null,
customTheme: null,
previewDevice: "desktop",
isDragging: false,
}
const writableStore = writable(initialState)
const derivedStore = derived(writableStore, $state => {
// Avoid any of this logic if we aren't in the builder preview
if (!$state.inBuilder) {
return $state
}
// Derive the selected component instance and definition
const { layout, screen, previewType, selectedComponentId } = $state
const asset = previewType === "layout" ? layout : screen
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 {
...$state,
selectedComponent: component,
selectedComponentDefinition: definition,
selectedComponentPath: path?.map(component => component._id),
}
})
const actions = {
selectComponent: id => {
if (id === get(writableStore).selectedComponentId) {
return
}
writableStore.update(state => ({ ...state, editMode: false }))
dispatchEvent("select-component", { id })
},
updateProp: (prop, value) => {
dispatchEvent("update-prop", { prop, value })
},
deleteComponent: id => {
dispatchEvent("delete-component", { id })
},
notifyLoaded: () => {
dispatchEvent("preview-loaded")
},
pingEndUser: () => {
pingEndUser()
},
setSelectedPath: path => {
writableStore.update(state => ({ ...state, selectedPath: path }))
},
moveComponent: (componentId, destinationComponentId, mode) => {
dispatchEvent("move-component", {
componentId,
destinationComponentId,
mode,
})
},
setDragging: dragging => {
if (dragging === get(writableStore).isDragging) {
return
}
writableStore.update(state => ({ ...state, isDragging: dragging }))
},
setEditMode: enabled => {
if (enabled === get(writableStore).editMode) {
return
}
writableStore.update(state => ({ ...state, editMode: enabled }))
},
}
return {
...writableStore,
set: state => writableStore.set({ ...initialState, ...state }),
subscribe: derivedStore.subscribe,
actions,
}
}
export const builderStore = createBuilderStore()