diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte
index aa0b26f6b7..784642787b 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte
@@ -13,6 +13,11 @@
import { fly } from "svelte/transition"
import { findComponentPath } from "@/helpers/components"
+ // Smallest possible 1x1 transparent GIF
+ const ghost = new Image(1, 1)
+ ghost.src =
+ "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="
+
let searchString
let searchRef
let selectedIndex
@@ -217,7 +222,8 @@
}
})
- const onDragStart = component => {
+ const onDragStart = (e, component) => {
+ e.dataTransfer.setDragImage(ghost, 0, 0)
previewStore.startDrag(component)
}
@@ -250,7 +256,7 @@
{#each category.children as component}
onDragStart(component.component)}
+ on:dragstart={e => onDragStart(e, component.component)}
on:dragend={onDragEnd}
class="component"
class:selected={selectedIndex === orderMap[component.component]}
@@ -308,7 +314,7 @@
}
.component:hover {
background: var(--spectrum-global-color-gray-300);
- cursor: pointer;
+ cursor: grab;
}
.component :global(.spectrum-Body) {
line-height: 1.2 !important;
diff --git a/packages/builder/src/stores/builder/app.ts b/packages/builder/src/stores/builder/app.ts
index 3c8ed4afc1..abebb5d9f1 100644
--- a/packages/builder/src/stores/builder/app.ts
+++ b/packages/builder/src/stores/builder/app.ts
@@ -39,7 +39,7 @@ interface AppMetaState {
appInstance: { _id: string } | null
initialised: boolean
hasAppPackage: boolean
- usedPlugins: Plugin[] | null
+ usedPlugins: Plugin[]
automations: AutomationSettings
routes: { [key: string]: any }
version?: string
@@ -76,7 +76,7 @@ export const INITIAL_APP_META_STATE: AppMetaState = {
appInstance: null,
initialised: false,
hasAppPackage: false,
- usedPlugins: null,
+ usedPlugins: [],
automations: {},
routes: {},
}
@@ -109,7 +109,7 @@ export class AppMetaStore extends BudiStore
{
appInstance: app.instance,
revertableVersion: app.revertableVersion,
upgradableVersion: app.upgradableVersion,
- usedPlugins: app.usedPlugins || null,
+ usedPlugins: app.usedPlugins || [],
icon: app.icon,
features: {
...INITIAL_APP_META_STATE.features,
diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts
index a8f52e2660..ad221cc67d 100644
--- a/packages/builder/src/stores/builder/components.ts
+++ b/packages/builder/src/stores/builder/components.ts
@@ -139,10 +139,6 @@ export class ComponentStore extends BudiStore {
/**
* Retrieve the component definition object
- * @param {string} componentType
- * @example
- * '@budibase/standard-components/container'
- * @returns {object}
*/
getDefinition(componentType: string) {
if (!componentType) {
@@ -151,10 +147,6 @@ export class ComponentStore extends BudiStore {
return get(this.store).components[componentType]
}
- /**
- *
- * @returns {object}
- */
getDefaultDatasource() {
// Ignore users table
const validTables = get(tables).list.filter(x => x._id !== "ta_users")
@@ -188,8 +180,6 @@ export class ComponentStore extends BudiStore {
/**
* Takes an enriched component instance and applies any required migration
* logic
- * @param {object} enrichedComponent
- * @returns {object} migrated Component
*/
migrateSettings(enrichedComponent: Component) {
const componentPrefix = "@budibase/standard-components"
@@ -230,22 +220,15 @@ export class ComponentStore extends BudiStore {
for (let setting of filterableTypes || []) {
const isLegacy = Array.isArray(enrichedComponent[setting.key])
if (isLegacy) {
- const processedSetting = utils.processSearchFilters(
+ enrichedComponent[setting.key] = utils.processSearchFilters(
enrichedComponent[setting.key]
)
- enrichedComponent[setting.key] = processedSetting
migrated = true
}
}
return migrated
}
- /**
- *
- * @param {object} component
- * @param {object} opts
- * @returns
- */
enrichEmptySettings(
component: Component,
opts: { screen?: Screen; parent?: Component; useDefaultValues?: boolean }
@@ -427,17 +410,10 @@ export class ComponentStore extends BudiStore {
}
}
- /**
- *
- * @param {string} componentName
- * @param {object} presetProps
- * @param {object} parent
- * @returns
- */
createInstance(
componentType: string,
- presetProps: any,
- parent: any
+ presetProps?: Record,
+ parent?: Component
): Component | null {
const screen = get(selectedScreen)
if (!screen) {
@@ -463,7 +439,7 @@ export class ComponentStore extends BudiStore {
_id: Helpers.uuid(),
_component: definition.component,
_styles: {
- normal: {},
+ normal: { ...presetProps?._styles?.normal },
hover: {},
active: {},
},
@@ -512,19 +488,11 @@ export class ComponentStore extends BudiStore {
}
}
- /**
- *
- * @param {string} componentName
- * @param {object} presetProps
- * @param {object} parent
- * @param {number} index
- * @returns
- */
async create(
componentType: string,
- presetProps: any,
- parent: Component,
- index: number
+ presetProps?: Record,
+ parent?: Component,
+ index?: number
) {
const state = get(this.store)
const componentInstance = this.createInstance(
@@ -611,13 +579,6 @@ export class ComponentStore extends BudiStore {
return componentInstance
}
- /**
- *
- * @param {function} patchFn
- * @param {string} componentId
- * @param {string} screenId
- * @returns
- */
async patch(
patchFn: (component: Component, screen: Screen) => any,
componentId?: string,
@@ -652,11 +613,6 @@ export class ComponentStore extends BudiStore {
await screenStore.patch(patchScreen, screenId)
}
- /**
- *
- * @param {object} component
- * @returns
- */
async delete(component: Component) {
if (!component) {
return
@@ -737,13 +693,6 @@ export class ComponentStore extends BudiStore {
})
}
- /**
- *
- * @param {object} targetComponent
- * @param {string} mode
- * @param {object} targetScreen
- * @returns
- */
async paste(
targetComponent: Component,
mode: string,
@@ -1101,6 +1050,7 @@ export class ComponentStore extends BudiStore {
async updateStyles(styles: Record, id: string) {
const patchFn = (component: Component) => {
+ delete component._placeholder
component._styles.normal = {
...component._styles.normal,
...styles,
@@ -1231,7 +1181,7 @@ export class ComponentStore extends BudiStore {
}
// Create new parent instance
- const newParentDefinition = this.createInstance(parentType, null, parent)
+ const newParentDefinition = this.createInstance(parentType)
if (!newParentDefinition) {
return
}
@@ -1267,10 +1217,6 @@ export class ComponentStore extends BudiStore {
/**
* Check if the components settings have been cached
- * @param {string} componentType
- * @example
- * '@budibase/standard-components/container'
- * @returns {boolean}
*/
isCached(componentType: string) {
const settings = get(this.store).settingsCache
@@ -1279,11 +1225,6 @@ export class ComponentStore extends BudiStore {
/**
* Cache component settings
- * @param {string} componentType
- * @param {object} definition
- * @example
- * '@budibase/standard-components/container'
- * @returns {array} the settings
*/
cacheSettings(componentType: string, definition: ComponentDefinition | null) {
let settings: ComponentSetting[] = []
@@ -1313,12 +1254,7 @@ export class ComponentStore extends BudiStore {
/**
* Retrieve an array of the component settings.
* These settings are cached because they cannot change at run time.
- *
* Searches a component's definition for a setting matching a certain predicate.
- * @param {string} componentType
- * @example
- * '@budibase/standard-components/container'
- * @returns {Array
diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte
new file mode 100644
index 0000000000..8a3da6f419
--- /dev/null
+++ b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte
@@ -0,0 +1,166 @@
+
diff --git a/packages/client/src/index.d.ts b/packages/client/src/index.d.ts
deleted file mode 100644
index 7e13670b33..0000000000
--- a/packages/client/src/index.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-interface Window {
- "##BUDIBASE_APP_ID##": string
- "##BUDIBASE_IN_BUILDER##": string
- MIGRATING_APP: boolean
-}
diff --git a/packages/client/src/index.js b/packages/client/src/index.js
deleted file mode 100644
index 8a48aa08e5..0000000000
--- a/packages/client/src/index.js
+++ /dev/null
@@ -1,138 +0,0 @@
-import ClientApp from "./components/ClientApp.svelte"
-import UpdatingApp from "./components/UpdatingApp.svelte"
-import {
- builderStore,
- appStore,
- blockStore,
- componentStore,
- environmentStore,
- dndStore,
- eventStore,
- hoverStore,
- stateStore,
-} from "./stores"
-import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js"
-import { get } from "svelte/store"
-import { initWebsocket } from "./websocket.js"
-
-// Provide svelte and svelte/internal as globals for custom components
-import * as svelte from "svelte"
-import * as internal from "svelte/internal"
-
-window.svelte_internal = internal
-window.svelte = svelte
-
-// Initialise spectrum icons
-loadSpectrumIcons()
-
-let app
-
-const loadBudibase = async () => {
- // Update builder store with any builder flags
- builderStore.set({
- ...get(builderStore),
- inBuilder: !!window["##BUDIBASE_IN_BUILDER##"],
- layout: window["##BUDIBASE_PREVIEW_LAYOUT##"],
- screen: window["##BUDIBASE_PREVIEW_SCREEN##"],
- selectedComponentId: window["##BUDIBASE_SELECTED_COMPONENT_ID##"],
- previewId: window["##BUDIBASE_PREVIEW_ID##"],
- theme: window["##BUDIBASE_PREVIEW_THEME##"],
- customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"],
- previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"],
- navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"],
- hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"],
- usedPlugins: window["##BUDIBASE_USED_PLUGINS##"],
- location: window["##BUDIBASE_LOCATION##"],
- snippets: window["##BUDIBASE_SNIPPETS##"],
- componentErrors: window["##BUDIBASE_COMPONENT_ERRORS##"],
- })
-
- // Set app ID - this window flag is set by both the preview and the real
- // server rendered app HTML
- appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"])
-
- // Set the flag used to determine if the app is being loaded via an iframe
- appStore.actions.setAppEmbedded(
- window["##BUDIBASE_APP_EMBEDDED##"] === "true"
- )
-
- if (window.MIGRATING_APP) {
- new UpdatingApp({
- target: window.document.body,
- })
- return
- }
-
- // Fetch environment info
- if (!get(environmentStore)?.loaded) {
- await environmentStore.actions.fetchEnvironment()
- }
-
- // Register handler for runtime events from the builder
- window.handleBuilderRuntimeEvent = (type, data) => {
- if (!window["##BUDIBASE_IN_BUILDER##"]) {
- return
- }
- if (type === "event-completed") {
- eventStore.actions.resolveEvent(data)
- } else if (type === "eject-block") {
- const block = blockStore.actions.getBlock(data)
- block?.eject()
- } else if (type === "dragging-new-component") {
- const { dragging, component } = data
- if (dragging) {
- const definition =
- componentStore.actions.getComponentDefinition(component)
- dndStore.actions.startDraggingNewComponent({ component, definition })
- } else {
- dndStore.actions.reset()
- }
- } else if (type === "request-context") {
- const { selectedComponentInstance, screenslotInstance } =
- get(componentStore)
- const instance = selectedComponentInstance || screenslotInstance
- const context = instance?.getDataContext()
- let stringifiedContext = null
- try {
- stringifiedContext = JSON.stringify(context)
- } catch (error) {
- // Ignore - invalid context
- }
- eventStore.actions.dispatchEvent("provide-context", {
- context: stringifiedContext,
- })
- } else if (type === "hover-component") {
- hoverStore.actions.hoverComponent(data, false)
- } else if (type === "builder-meta") {
- builderStore.actions.setMetadata(data)
- } else if (type === "builder-state") {
- const [[key, value]] = Object.entries(data)
- stateStore.actions.setValue(key, value)
- }
- }
-
- // Register any custom components
- if (window["##BUDIBASE_CUSTOM_COMPONENTS##"]) {
- window["##BUDIBASE_CUSTOM_COMPONENTS##"].forEach(component => {
- componentStore.actions.registerCustomComponent(component)
- })
- }
-
- // Make a callback available for custom component bundles to register
- // themselves at runtime
- window.registerCustomComponent =
- componentStore.actions.registerCustomComponent
-
- // Initialise websocket
- initWebsocket()
-
- // Create app if one hasn't been created yet
- if (!app) {
- app = new ClientApp({
- target: window.document.body,
- })
- }
-}
-
-// Attach to window so the HTML template can call this when it loads
-window.loadBudibase = loadBudibase
diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts
index 08330a60fa..e7d454e2f1 100644
--- a/packages/client/src/index.ts
+++ b/packages/client/src/index.ts
@@ -1,6 +1,83 @@
+import ClientApp from "./components/ClientApp.svelte"
+import UpdatingApp from "./components/UpdatingApp.svelte"
+import {
+ builderStore,
+ appStore,
+ blockStore,
+ componentStore,
+ environmentStore,
+ dndStore,
+ eventStore,
+ hoverStore,
+ stateStore,
+} from "@/stores"
+import { get } from "svelte/store"
+import { initWebsocket } from "@/websocket"
import { APIClient } from "@budibase/frontend-core"
-import type { ActionTypes } from "./constants"
+import type { ActionTypes } from "@/constants"
import { Readable } from "svelte/store"
+import {
+ Screen,
+ Layout,
+ Theme,
+ AppCustomTheme,
+ PreviewDevice,
+ AppNavigation,
+ Plugin,
+ Snippet,
+ UIComponentError,
+ CustomComponent,
+} from "@budibase/types"
+
+// Provide svelte and svelte/internal as globals for custom components
+import * as svelte from "svelte"
+// @ts-ignore
+import * as internal from "svelte/internal"
+window.svelte_internal = internal
+window.svelte = svelte
+
+// Initialise spectrum icons
+// eslint-disable-next-line local-rules/no-budibase-imports
+import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js"
+loadSpectrumIcons()
+
+// Extend global window scope
+declare global {
+ interface Window {
+ // Data from builder
+ "##BUDIBASE_APP_ID##"?: string
+ "##BUDIBASE_IN_BUILDER##"?: true
+ "##BUDIBASE_PREVIEW_LAYOUT##"?: Layout
+ "##BUDIBASE_PREVIEW_SCREEN##"?: Screen
+ "##BUDIBASE_SELECTED_COMPONENT_ID##"?: string
+ "##BUDIBASE_PREVIEW_ID##"?: number
+ "##BUDIBASE_PREVIEW_THEME##"?: Theme
+ "##BUDIBASE_PREVIEW_CUSTOM_THEME##"?: AppCustomTheme
+ "##BUDIBASE_PREVIEW_DEVICE##"?: PreviewDevice
+ "##BUDIBASE_APP_EMBEDDED##"?: string // This is a bool wrapped in a string
+ "##BUDIBASE_PREVIEW_NAVIGATION##"?: AppNavigation
+ "##BUDIBASE_HIDDEN_COMPONENT_IDS##"?: string[]
+ "##BUDIBASE_USED_PLUGINS##"?: Plugin[]
+ "##BUDIBASE_LOCATION##"?: {
+ protocol: string
+ hostname: string
+ port: string
+ }
+ "##BUDIBASE_SNIPPETS##"?: Snippet[]
+ "##BUDIBASE_COMPONENT_ERRORS##"?: Record[]
+ "##BUDIBASE_CUSTOM_COMPONENTS##"?: CustomComponent[]
+
+ // Other flags
+ MIGRATING_APP: boolean
+
+ // Client additions
+ handleBuilderRuntimeEvent: (type: string, data: any) => void
+ registerCustomComponent: typeof componentStore.actions.registerCustomComponent
+ loadBudibase: typeof loadBudibase
+ svelte: typeof svelte
+ svelte_internal: typeof internal
+ }
+}
export interface SDK {
API: APIClient
@@ -29,3 +106,119 @@ export type Component = Readable<{
}>
export type Context = Readable<{}>
+
+let app: ClientApp
+
+const loadBudibase = async () => {
+ // Update builder store with any builder flags
+ builderStore.set({
+ ...get(builderStore),
+ inBuilder: !!window["##BUDIBASE_IN_BUILDER##"],
+ layout: window["##BUDIBASE_PREVIEW_LAYOUT##"],
+ screen: window["##BUDIBASE_PREVIEW_SCREEN##"],
+ selectedComponentId: window["##BUDIBASE_SELECTED_COMPONENT_ID##"],
+ previewId: window["##BUDIBASE_PREVIEW_ID##"],
+ theme: window["##BUDIBASE_PREVIEW_THEME##"],
+ customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"],
+ previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"],
+ navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"],
+ hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"],
+ usedPlugins: window["##BUDIBASE_USED_PLUGINS##"],
+ location: window["##BUDIBASE_LOCATION##"],
+ snippets: window["##BUDIBASE_SNIPPETS##"],
+ componentErrors: window["##BUDIBASE_COMPONENT_ERRORS##"],
+ })
+
+ // Set app ID - this window flag is set by both the preview and the real
+ // server rendered app HTML
+ appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"])
+
+ // Set the flag used to determine if the app is being loaded via an iframe
+ appStore.actions.setAppEmbedded(
+ window["##BUDIBASE_APP_EMBEDDED##"] === "true"
+ )
+
+ if (window.MIGRATING_APP) {
+ new UpdatingApp({
+ target: window.document.body,
+ })
+ return
+ }
+
+ // Fetch environment info
+ if (!get(environmentStore)?.loaded) {
+ await environmentStore.actions.fetchEnvironment()
+ }
+
+ // Register handler for runtime events from the builder
+ window.handleBuilderRuntimeEvent = (type, data) => {
+ if (!window["##BUDIBASE_IN_BUILDER##"]) {
+ return
+ }
+ if (type === "event-completed") {
+ eventStore.actions.resolveEvent(data)
+ } else if (type === "eject-block") {
+ const block = blockStore.actions.getBlock(data)
+ block?.eject()
+ } else if (type === "dragging-new-component") {
+ const { dragging, component, componentId } = data
+ if (dragging) {
+ const definition =
+ componentStore.actions.getComponentDefinition(component)
+ dndStore.actions.startDraggingNewComponent({
+ component,
+ definition,
+ componentId,
+ })
+ } else {
+ dndStore.actions.reset()
+ }
+ } else if (type === "request-context") {
+ const { selectedComponentInstance, screenslotInstance } =
+ get(componentStore)
+ const instance = selectedComponentInstance || screenslotInstance
+ const context = instance?.getDataContext()
+ let stringifiedContext = null
+ try {
+ stringifiedContext = JSON.stringify(context)
+ } catch (error) {
+ // Ignore - invalid context
+ }
+ eventStore.actions.dispatchEvent("provide-context", {
+ context: stringifiedContext,
+ })
+ } else if (type === "hover-component") {
+ hoverStore.actions.hoverComponent(data, false)
+ } else if (type === "builder-meta") {
+ builderStore.actions.setMetadata(data)
+ } else if (type === "builder-state") {
+ const [[key, value]] = Object.entries(data)
+ stateStore.actions.setValue(key, value)
+ }
+ }
+
+ // Register any custom components
+ if (window["##BUDIBASE_CUSTOM_COMPONENTS##"]) {
+ window["##BUDIBASE_CUSTOM_COMPONENTS##"].forEach(component => {
+ componentStore.actions.registerCustomComponent(component)
+ })
+ }
+
+ // Make a callback available for custom component bundles to register
+ // themselves at runtime
+ window.registerCustomComponent =
+ componentStore.actions.registerCustomComponent
+
+ // Initialise websocket
+ initWebsocket()
+
+ // Create app if one hasn't been created yet
+ if (!app) {
+ app = new ClientApp({
+ target: window.document.body,
+ })
+ }
+}
+
+// Attach to window so the HTML template can call this when it loads
+window.loadBudibase = loadBudibase
diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js
index 43d4eeeed8..5cfb12c7d2 100644
--- a/packages/client/src/stores/dnd.js
+++ b/packages/client/src/stores/dnd.js
@@ -21,7 +21,11 @@ const createDndStore = () => {
})
}
- const startDraggingNewComponent = ({ component, definition }) => {
+ const startDraggingNewComponent = ({
+ component,
+ definition,
+ componentId,
+ }) => {
if (!component) {
return
}
@@ -38,6 +42,7 @@ const createDndStore = () => {
bounds: { height, width },
index: null,
newComponentType: component,
+ newComponentId: componentId,
},
})
}
@@ -82,6 +87,10 @@ export const dndParent = derivedMemo(dndStore, x => x.drop?.parent)
export const dndIndex = derivedMemo(dndStore, x => x.drop?.index)
export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds)
export const dndIsDragging = derivedMemo(dndStore, x => !!x.source)
+export const dndNewComponentId = derivedMemo(
+ dndStore,
+ x => x.source?.newComponentId
+)
export const dndIsNewComponent = derivedMemo(
dndStore,
x => x.source?.newComponentType != null
diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js
index f2b80ed732..268b0cc4bf 100644
--- a/packages/client/src/stores/index.js
+++ b/packages/client/src/stores/index.js
@@ -2,7 +2,7 @@ export { authStore } from "./auth"
export { appStore } from "./app"
export { notificationStore } from "./notification"
export { routeStore } from "./routes"
-export { screenStore } from "./screens"
+export { screenStore, isGridScreen } from "./screens"
export { builderStore } from "./builder"
export { dataSourceStore } from "./dataSource"
export { confirmationStore } from "./confirmation"
diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js
index a7277ca2b5..f85675e389 100644
--- a/packages/client/src/stores/screens.js
+++ b/packages/client/src/stores/screens.js
@@ -198,3 +198,7 @@ const createScreenStore = () => {
}
export const screenStore = createScreenStore()
+
+export const isGridScreen = derived(screenStore, $screenStore => {
+ return $screenStore.activeScreen?.props?.layout === "grid"
+})
diff --git a/packages/client/vite.config.mjs b/packages/client/vite.config.mjs
index 7c163181ae..9ef87d8ec8 100644
--- a/packages/client/vite.config.mjs
+++ b/packages/client/vite.config.mjs
@@ -20,7 +20,7 @@ export default defineConfig(({ mode }) => {
},
build: {
lib: {
- entry: "src/index.js",
+ entry: "src/index.ts",
formats: ["iife"],
outDir: "dist",
name: "budibase_client",
@@ -67,10 +67,6 @@ export default defineConfig(({ mode }) => {
find: "constants",
replacement: path.resolve("./src/constants"),
},
- {
- find: "@/constants",
- replacement: path.resolve("./src/constants"),
- },
{
find: "sdk",
replacement: path.resolve("./src/sdk"),
@@ -87,6 +83,10 @@ export default defineConfig(({ mode }) => {
find: "@budibase/bbui",
replacement: path.resolve("../bbui/src"),
},
+ {
+ find: "@",
+ replacement: path.resolve(__dirname, "src"),
+ },
],
},
}
diff --git a/packages/types/src/ui/components/index.ts b/packages/types/src/ui/components/index.ts
index 283ceb47da..85c7b1af84 100644
--- a/packages/types/src/ui/components/index.ts
+++ b/packages/types/src/ui/components/index.ts
@@ -2,6 +2,16 @@ export * from "./sidepanel"
export * from "./codeEditor"
export * from "./errors"
+export interface CustomComponent {
+ Component: any
+ schema: {
+ type: "component"
+ metadata: Record
+ schema: ComponentDefinition
+ }
+ version: string
+}
+
export interface ComponentDefinition {
component: string
name: string