diff --git a/packages/bbui/src/ActionButton/ActionButton.svelte b/packages/bbui/src/ActionButton/ActionButton.svelte
index f24eb25ffb..b518ac3d92 100644
--- a/packages/bbui/src/ActionButton/ActionButton.svelte
+++ b/packages/bbui/src/ActionButton/ActionButton.svelte
@@ -1,8 +1,7 @@
{#each sections as section, idx (section.name)}
@@ -102,10 +93,11 @@
control={getComponentForSettingType(setting.type)}
label={setting.label}
key={setting.key}
- value={componentInstance[setting.key] ??
- componentInstance[setting.key]?.defaultValue}
+ value={componentInstance[setting.key]}
+ defaultValue={setting.defaultValue}
nested={setting.nested}
onChange={val => updateProp(setting.key, val)}
+ highlighted={$store.highlightedSettingKey === setting.key}
props={{
options: setting.options || [],
placeholder: setting.placeholder || null,
@@ -116,7 +108,6 @@
{componentBindings}
{componentInstance}
{componentDefinition}
- autofocus={isFocused(setting)}
/>
{/if}
{/each}
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte
index b16530bfe6..a5b7a08255 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte
@@ -6,7 +6,6 @@
import { createEventDispatcher, onMount } from "svelte"
export let value
- export let autofocus = false
const dispatch = createEventDispatcher()
const getValue = component => `{{ literal ${makePropSafe(component._id)} }}`
@@ -25,7 +24,6 @@
{#if value?.type === "query"}
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FieldSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FieldSelect.svelte
index edcc1ccf15..7d1741df17 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FieldSelect.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FieldSelect.svelte
@@ -10,7 +10,6 @@
export let componentInstance = {}
export let value = ""
export let placeholder
- export let autofocus = false
const dispatch = createEventDispatcher()
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
@@ -38,10 +37,4 @@
}
-
+
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte
index b30d442999..1f08c56ff5 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte
@@ -10,7 +10,6 @@
export let componentInstance
export let value
export let type
- export let autofocus = false
$: form = findClosestMatchingComponent(
$currentAsset?.props,
@@ -41,4 +40,4 @@
}
-
+
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/IconSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/IconSelect.svelte
index 821e44bf82..0aad0e844d 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/IconSelect.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/IconSelect/IconSelect.svelte
@@ -15,7 +15,6 @@
export let value = ""
export let maxIconsPerPage = 30
- export let autofocus = false
let searchTerm = ""
let selectedLetter = "A"
@@ -118,7 +117,7 @@
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/MultiFieldSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/MultiFieldSelect.svelte
index 9e3a91bc41..485fde64fa 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/MultiFieldSelect.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/MultiFieldSelect.svelte
@@ -10,7 +10,6 @@
export let componentInstance = {}
export let value = ""
export let placeholder
- export let autofocus
const dispatch = createEventDispatcher()
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
@@ -32,10 +31,4 @@
}
-
+
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte
index c2ead2eef9..3927e0b3a5 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/PropertyControl.svelte
@@ -4,8 +4,8 @@
readableToRuntimeBinding,
runtimeToReadableBinding,
} from "builderStore/dataBinding"
- import { setContext } from "svelte"
import { store } from "builderStore"
+ import { onDestroy } from "svelte"
export let label = ""
export let componentInstance = {}
@@ -13,15 +13,17 @@
export let key = ""
export let type = ""
export let value = null
+ export let defaultValue = null
export let props = {}
export let onChange = () => {}
export let bindings = []
export let componentBindings = []
export let nested = false
- export let autofocus = false
+ export let highlighted = false
+ $: nullishValue = value == null || value === ""
$: allBindings = getAllBindings(bindings, componentBindings, nested)
- $: safeValue = getSafeValue(value, props.defaultValue, allBindings)
+ $: safeValue = getSafeValue(value, defaultValue, allBindings)
$: tempValue = safeValue
$: replaceBindings = val => readableToRuntimeBinding(allBindings, val)
@@ -64,30 +66,18 @@
: enriched
}
- setContext("builderFocus", {
- clear: () => {
- if (!$store?.builderFocus) {
- return
- }
- store.update(state => {
- const updatedFocus = $store?.builderFocus?.filter(focus => {
- return (
- focus.location === "component_settings" &&
- focus.target !== componentInstance._id
- )
- })
- if (updatedFocus?.length > 0) {
- state.builderFocus = updatedFocus
- } else {
- delete state.builderFocus
- }
- return state
- })
- },
+ onDestroy(() => {
+ if (highlighted) {
+ store.actions.settings.highlight(null)
+ }
})
-
+
{#if type !== "boolean" && label}
{label}
@@ -107,7 +97,6 @@
{key}
{type}
{...props}
- {autofocus}
/>
@@ -119,6 +108,14 @@
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
+ transition: background 130ms ease-out, border-color 130ms ease-out;
+ border-left: 4px solid transparent;
+ margin: -6px calc(-1 * var(--spacing-xl));
+ padding: 6px var(--spacing-xl) 6px calc(var(--spacing-xl) - 4px);
+ }
+ .property-control.highlighted {
+ background: var(--spectrum-global-color-gray-300);
+ border-color: var(--spectrum-global-color-blue-400);
}
.label {
padding-bottom: var(--spectrum-global-dimension-size-65);
diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/URLSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/URLSelect.svelte
index 581f0e7fd2..dc2fa7ad89 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/URLSelect.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/URLSelect.svelte
@@ -4,7 +4,6 @@
export let value
export let bindings
- export let autofocus
$: urlOptions = $store.screens
.map(screen => screen.routing?.route)
@@ -17,5 +16,4 @@
on:change
options={urlOptions}
appendBindingsAsOptions={false}
- {autofocus}
/>
diff --git a/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte b/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte
index df3ba7f3d3..e0b46d8ed7 100644
--- a/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/ScreenSettingsSection.svelte
@@ -115,7 +115,6 @@
control={def.control}
label={def.label}
key={def.key}
- error="asdasds"
value={deepGet($currentAsset, def.key)}
onChange={val => setAssetProps(def.key, val, def.parser, def.validate)}
{bindings}
diff --git a/packages/client/manifest.json b/packages/client/manifest.json
index c2e0311297..6f0a55e5a9 100644
--- a/packages/client/manifest.json
+++ b/packages/client/manifest.json
@@ -274,7 +274,8 @@
{
"type": "text",
"label": "Text",
- "key": "text"
+ "key": "text",
+ "defaultValue": "New Button"
},
{
"type": "select",
@@ -1154,15 +1155,13 @@
{
"type": "text",
"label": "Text",
- "key": "text",
- "required": true
+ "key": "text"
},
{
"type": "url",
"label": "URL",
"key": "url",
- "placeholder": "/screen",
- "required": true
+ "placeholder": "/screen"
},
{
"type": "boolean",
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte
index a1550cf72f..c196e2ff64 100644
--- a/packages/client/src/components/Component.svelte
+++ b/packages/client/src/components/Component.svelte
@@ -23,6 +23,7 @@
import Manifest from "manifest.json"
import { getActiveConditions, reduceConditionActions } from "utils/conditions"
import Placeholder from "components/app/Placeholder.svelte"
+ import ComponentPlaceholder from "components/app/ComponentPlaceholder.svelte"
export let instance = {}
export let isLayout = false
@@ -81,6 +82,7 @@
let definition
let settingsDefinition
let settingsDefinitionMap
+ let missingRequiredSettings = false
// Set up initial state for each new component instance
$: initialise(instance)
@@ -99,9 +101,10 @@
// Derive definition properties which can all be optional, so need to be
// coerced to booleans
- $: editable = !!definition?.editable
$: hasChildren = !!definition?.hasChildren
$: showEmptyState = definition?.showEmptyState !== false
+ $: hasMissingRequiredSettings = missingRequiredSettings?.length > 0
+ $: editable = !!definition?.editable && !hasMissingRequiredSettings
// Interactive components can be selected, dragged and highlighted inside
// the builder preview
@@ -155,6 +158,7 @@
name,
editing,
type: instance._component,
+ missingRequiredSettings,
})
const initialise = instance => {
@@ -201,6 +205,27 @@
staticSettings = instanceSettings.staticSettings
dynamicSettings = instanceSettings.dynamicSettings
+ // Check if we have any missing required settings
+ missingRequiredSettings = settingsDefinition.filter(setting => {
+ let empty = instance[setting.key] == null || instance[setting.key] === ""
+ let missing = setting.required && empty
+
+ // Check if this setting depends on another, as it may not be required
+ if (setting.dependsOn) {
+ const dependsOnKey = setting.dependsOn.setting || setting.dependsOn
+ const dependsOnValue = setting.dependsOn.value
+ const realDependentValue = instance[dependsOnKey]
+ if (dependsOnValue == null && realDependentValue == null) {
+ return false
+ }
+ if (dependsOnValue !== realDependentValue) {
+ return false
+ }
+ }
+
+ return missing
+ })
+
// Force an initial enrichment of the new settings
enrichComponentSettings(get(context), settingsDefinitionMap, {
force: true,
@@ -414,17 +439,21 @@
data-id={id}
data-name={name}
>
-
- {#if children.length}
- {#each children as child (child._id)}
-
- {/each}
- {:else if emptyState}
-
- {:else if isBlock}
-
- {/if}
-
+ {#if hasMissingRequiredSettings}
+
+ {:else}
+
+ {#if children.length}
+ {#each children as child (child._id)}
+
+ {/each}
+ {:else if emptyState}
+
+ {:else if isBlock}
+
+ {/if}
+
+ {/if}
{/if}
diff --git a/packages/client/src/components/app/ComponentPlaceholder.svelte b/packages/client/src/components/app/ComponentPlaceholder.svelte
new file mode 100644
index 0000000000..13cc217ef0
--- /dev/null
+++ b/packages/client/src/components/app/ComponentPlaceholder.svelte
@@ -0,0 +1,44 @@
+
+
+{#if $builderStore.inBuilder && requiredSetting}
+
+
+
+ Add the {requiredSetting.label} setting to start using your
+ component -
+
+ {
+ builderStore.actions.highlightSetting(requiredSetting.key)
+ }}
+ >
+ Show me
+
+
+
+{/if}
+
+
diff --git a/packages/client/src/components/app/Link.svelte b/packages/client/src/components/app/Link.svelte
index 5ac8a4f9ec..79bf296208 100644
--- a/packages/client/src/components/app/Link.svelte
+++ b/packages/client/src/components/app/Link.svelte
@@ -1,6 +1,5 @@
{#if $builderStore.inBuilder}
-
- {#if componentInstance && focus_setting}
-
-
- Add the {focus_setting?.label} setting to start using your
- component
-
- {
- builderStore.actions.setFocus([
- {
- location: "component_settings",
- key: focus_setting.key,
- target: $component.id,
- },
- ])
- }}
- >
- Show me
-
-
- {:else}
- {text || $component.name || "Placeholder"}
- {/if}
+
+ {text || $component.name || "Placeholder"}
{/if}
@@ -69,18 +17,5 @@
div {
color: var(--spectrum-global-color-gray-600);
font-size: var(--font-size-s);
- padding: var(--spacing-xs);
- }
- :global(div.placeholder_wrap mark) {
- background-color: var(--spectrum-global-color-gray-400);
- padding: 0px 2px;
- border-radius: 2px;
- }
- :global(div.placeholder_wrap .showMe) {
- cursor: pointer;
- }
- :global(div.placeholder_wrap .showMe:hover) {
- text-decoration: underline;
- cursor: pointer;
}
diff --git a/packages/client/src/components/app/forms/Field.svelte b/packages/client/src/components/app/forms/Field.svelte
index dbdb21d559..9a91ea5b2d 100644
--- a/packages/client/src/components/app/forms/Field.svelte
+++ b/packages/client/src/components/app/forms/Field.svelte
@@ -76,9 +76,7 @@
{#if !formContext}
{:else if !fieldState}
- {#if $builderStore.inBuilder}
-
- {/if}
+
{:else if schemaType && schemaType !== type && type !== "options"}
{
}
store.update(state => ({ ...state, editMode: enabled }))
},
- setFocus: data => {
- window.parent.postMessage({ type: "builder-focus", data })
+ highlightSetting: setting => {
+ dispatchEvent("highlight-setting", { setting })
},
}
return {