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..d13d72b89f 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,13 +256,12 @@
{#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]}
on:click={() => addComponent(component.component)}
- on:mouseover={() => (selectedIndex = null)}
- on:focus
+ on:mouseenter={() => (selectedIndex = null)}
>
{component.name}
@@ -308,7 +313,6 @@
}
.component:hover {
background: var(--spectrum-global-color-gray-300);
- cursor: pointer;
}
.component :global(.spectrum-Body) {
line-height: 1.2 !important;
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte
index ba600c8eef..59548ada01 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte
@@ -189,8 +189,8 @@
} else if (type === "reload-plugin") {
await componentStore.refreshDefinitions()
} else if (type === "drop-new-component") {
- const { component, parent, index } = data
- await componentStore.create(component, null, parent, index)
+ const { component, parent, index, props } = data
+ await componentStore.create(component, props, parent, index)
} else if (type === "add-parent-component") {
const { componentId, parentType } = data
await componentStore.addParent(componentId, parentType)
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 b1198ca7b4..b3e897fa3c 100644
--- a/packages/builder/src/stores/builder/components.ts
+++ b/packages/builder/src/stores/builder/components.ts
@@ -11,6 +11,7 @@ import {
findComponentParent,
findAllMatchingComponents,
makeComponentUnique,
+ findComponentType,
} from "@/helpers/components"
import { getComponentFieldOptions } from "@/helpers/formFields"
import { selectedScreen } from "./screens"
@@ -139,10 +140,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 +148,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 +181,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 +221,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 }
@@ -280,14 +264,25 @@ export class ComponentStore extends BudiStore {
type: "table",
}
} else if (setting.type === "dataProvider") {
- // Pick closest data provider where required
+ let providerId
+
+ // Pick closest parent data provider if one exists
const path = findComponentPath(screen.props, treeId)
const providers = path.filter((component: Component) =>
component._component?.endsWith("/dataprovider")
)
- if (providers.length) {
- const id = providers[providers.length - 1]?._id
- component[setting.key] = `{{ literal ${safe(id)} }}`
+ providerId = providers[providers.length - 1]?._id
+
+ // If none in our direct path, select the first one the screen
+ if (!providerId) {
+ providerId = findComponentType(
+ screen.props,
+ "@budibase/standard-components/dataprovider"
+ )?._id
+ }
+
+ if (providerId) {
+ component[setting.key] = `{{ literal ${safe(providerId)} }}`
}
} else if (setting.type.startsWith("field/")) {
// Autofill form field names
@@ -316,6 +311,8 @@ export class ComponentStore extends BudiStore {
component[setting.key] = fieldOptions[0]
component.label = fieldOptions[0]
}
+ } else if (setting.type === "icon") {
+ component[setting.key] = "ri-star-fill"
} else if (useDefaultValues && setting.defaultValue !== undefined) {
// Use default value where required
component[setting.key] = setting.defaultValue
@@ -427,17 +424,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 +453,7 @@ export class ComponentStore extends BudiStore {
_id: Helpers.uuid(),
_component: definition.component,
_styles: {
- normal: {},
+ normal: { ...presetProps?._styles?.normal },
hover: {},
active: {},
},
@@ -512,19 +502,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 +593,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 +627,6 @@ export class ComponentStore extends BudiStore {
await screenStore.patch(patchScreen, screenId)
}
- /**
- *
- * @param {object} component
- * @returns
- */
async delete(component: Component) {
if (!component) {
return
@@ -737,13 +707,6 @@ export class ComponentStore extends BudiStore {
})
}
- /**
- *
- * @param {object} targetComponent
- * @param {string} mode
- * @param {object} targetScreen
- * @returns
- */
async paste(
targetComponent: Component,
mode: string,
@@ -1101,6 +1064,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 +1195,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 +1231,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 +1239,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 +1268,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