Refactoring and some styling updates

This commit is contained in:
Dean 2023-05-29 21:19:44 +01:00
parent 0730c15b14
commit e8c6185add
14 changed files with 341 additions and 211 deletions

View File

@ -56,6 +56,8 @@ export default function positionDropdown(element, opts) {
styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width
} else if (align === "right-outside") { } else if (align === "right-outside") {
styles.left = anchorBounds.right + offset styles.left = anchorBounds.right + offset
} else if (align === "left-outside") {
styles.left = anchorBounds.left - elementBounds.width - offset
} else { } else {
styles.left = anchorBounds.left styles.left = anchorBounds.left
} }

View File

@ -21,7 +21,6 @@
} }
export function hide() { export function hide() {
console.log("CLOSE")
if (!visible) { if (!visible) {
return return
} }

View File

@ -12,6 +12,7 @@
export let emphasized = false export let emphasized = false
export let onTop = false export let onTop = false
export let size = "M" export let size = "M"
export let beforeSwitch = null
let thisSelected = undefined let thisSelected = undefined
@ -28,9 +29,14 @@
thisSelected = selected thisSelected = selected
dispatch("select", thisSelected) dispatch("select", thisSelected)
} else if ($tab.title !== thisSelected) { } else if ($tab.title !== thisSelected) {
thisSelected = $tab.title if (typeof beforeSwitch == "function") {
selected = $tab.title const proceed = beforeSwitch($tab.title)
dispatch("select", thisSelected) if (proceed) {
thisSelected = $tab.title
selected = $tab.title
dispatch("select", thisSelected)
}
}
} }
if ($tab.title !== thisSelected) { if ($tab.title !== thisSelected) {
tab.update(state => { tab.update(state => {

View File

@ -519,7 +519,7 @@ export const makeStateBinding = key => {
readableBinding: `State.${key}`, readableBinding: `State.${key}`,
category: "State", category: "State",
icon: "AutomatedSegment", icon: "AutomatedSegment",
display: { name: key }, //no type display: { name: key },
} }
} }

View File

@ -69,6 +69,7 @@ const INITIAL_FRONTEND_STATE = {
customTheme: {}, customTheme: {},
previewDevice: "desktop", previewDevice: "desktop",
highlightedSettingKey: null, highlightedSettingKey: null,
propertyFocus: null,
builderSidePanel: false, builderSidePanel: false,
// URL params // URL params
@ -1319,6 +1320,12 @@ export const getFrontendStore = () => {
highlightedSettingKey: key, highlightedSettingKey: key,
})) }))
}, },
propertyFocus: key => {
store.update(state => ({
...state,
propertyFocus: key,
}))
},
}, },
dnd: { dnd: {
start: component => { start: component => {

View File

@ -37,7 +37,6 @@
import { TriggerStepID, ActionStepID } from "constants/backend/automations" import { TriggerStepID, ActionStepID } from "constants/backend/automations"
import { onMount } from "svelte" import { onMount } from "svelte"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import CodeEditor from "components/common/CodeEditor/CodeEditor.svelte"
export let block export let block
export let testData export let testData
@ -235,18 +234,19 @@
? `steps[${idx - loopBlockCount}].${name}` ? `steps[${idx - loopBlockCount}].${name}`
: `steps.${idx - loopBlockCount}.${name}` : `steps.${idx - loopBlockCount}.${name}`
const runtime = idx === 0 ? `trigger.${name}` : runtimeName const runtime = idx === 0 ? `trigger.${name}` : runtimeName
const categoryName =
idx === 0
? "Trigger outputs"
: isLoopBlock
? "Loop Outputs"
: `Step ${idx - loopBlockCount} outputs`
return { return {
readableBinding: runtime, readableBinding: runtime,
runtimeBinding: runtime, runtimeBinding: runtime,
type: value.type, type: value.type,
description: value.description, description: value.description,
icon: bindingIcon, icon: bindingIcon,
category: category: categoryName,
idx === 0
? "Trigger outputs"
: isLoopBlock
? "Loop Outputs"
: `Step ${idx - loopBlockCount} outputs`,
display: { display: {
type: value.type, type: value.type,
name: name, name: name,

View File

@ -69,13 +69,15 @@
to: opts.end || editor.state.doc.length, to: opts.end || editor.state.doc.length,
insert: opts.value, insert: opts.value,
}, },
selection: { selection: opts.cursor
anchor: opts.start + opts.value.length, ? {
}, anchor: opts.start + opts.value.length,
}
: undefined,
}) })
} }
// For handlebars only. Demo // For handlebars only.
const bindStyle = new MatchDecorator({ const bindStyle = new MatchDecorator({
regexp: /{{[.\[\]\"#-\w\s\/]*}}/g, regexp: /{{[.\[\]\"#-\w\s\/]*}}/g,
decoration: match => { decoration: match => {
@ -117,7 +119,7 @@
...completionKeymap, ...completionKeymap,
indentWithTab, indentWithTab,
] ]
return buildKeymap return baseMap
} }
const buildBaseExtensions = () => { const buildBaseExtensions = () => {
@ -167,8 +169,6 @@
complete.push(foldGutter()) complete.push(foldGutter())
complete.push( complete.push(
EditorView.inputHandler.of((view, from, to, insert) => { EditorView.inputHandler.of((view, from, to, insert) => {
console.log({ view, from, to, insert })
if (insert === "$") { if (insert === "$") {
let { text } = view.state.doc.lineAt(from) let { text } = view.state.doc.lineAt(from)

View File

@ -1,26 +1,14 @@
import { EditorView } from "@codemirror/view" import { EditorView } from "@codemirror/view"
// import { insertCompletionText } from "@codemirror/autocomplete"
import { getManifest } from "@budibase/string-templates" import { getManifest } from "@budibase/string-templates"
import sanitizeHtml from "sanitize-html" import sanitizeHtml from "sanitize-html"
import { groupBy } from "lodash" import { groupBy } from "lodash"
// Really just Javascript and Text
export const EditorModes = { export const EditorModes = {
JS: { JS: {
name: "javascript", name: "javascript",
json: false, json: false,
match: /\$$/, match: /\$$/,
}, },
JSON: {
name: "javascript",
json: true,
},
XML: {
name: "xml",
},
SQL: {
name: "sql",
},
Handlebars: { Handlebars: {
name: "handlebars", name: "handlebars",
base: "text/html", base: "text/html",
@ -31,7 +19,6 @@ export const EditorModes = {
}, },
} }
// Get a generalised approach to constants in the dataBindings file?
export const SECTIONS = { export const SECTIONS = {
HB_HELPER: { HB_HELPER: {
name: "Helper", name: "Helper",
@ -108,7 +95,7 @@ export const getDefaultTheme = opts => {
color: "var(--ink)", color: "var(--ink)",
}, },
"& .binding-wrap": { "& .binding-wrap": {
color: "chartreuse", color: "var(--spectrum-global-color-blue-700)",
}, },
}, },
{ dark } { dark }
@ -209,20 +196,15 @@ export const jsAutocomplete = baseCompletions => {
let jsBinding = context.matchBefore(/\$\(\"[\s\w]*/) let jsBinding = context.matchBefore(/\$\(\"[\s\w]*/)
let options = baseCompletions || [] let options = baseCompletions || []
if (!jsBinding) { if (jsBinding) {
console.log("leaving")
return { return {
from: context.pos, from: jsBinding.from + 3,
filter: true, filter: true,
options, options,
} }
} }
return { return null
from: jsBinding.from + 3,
filter: true,
options,
}
} }
return coreCompletion return coreCompletion
@ -305,30 +287,27 @@ export const insertBinding = (view, from, to, text, mode) => {
} }
export const bindingsToCompletions = (bindings, mode) => { export const bindingsToCompletions = (bindings, mode) => {
// REFACTOR OUT
const bindingByCategory = groupBy(bindings, "category") const bindingByCategory = groupBy(bindings, "category")
const categoryToIcon = bindings?.reduce((acc, ele) => { const categoryMeta = bindings?.reduce((acc, ele) => {
if (ele.icon) { acc[ele.category] = acc[ele.category] || {}
acc[ele.category] = acc[ele.category] || ele.icon
}
return acc
}, {})
// REFACTOR OUT
const categoryToRank = bindings?.reduce((acc, ele) => {
if (ele.icon) { if (ele.icon) {
acc[ele.category] = acc[ele.category] || ele.display.rank acc[ele.category]["icon"] = acc[ele.category]["icon"] || ele.icon
}
if (ele.display?.rank) {
acc[ele.category]["rank"] = acc[ele.category]["rank"] || ele.display.rank
} }
return acc return acc
}, {}) }, {})
const completions = Object.keys(bindingByCategory).reduce((comps, catKey) => { const completions = Object.keys(bindingByCategory).reduce((comps, catKey) => {
// REFACTOR OUT const { icon, rank } = categoryMeta[catKey] || {}
const bindindSectionHeader = buildSectionHeader( const bindindSectionHeader = buildSectionHeader(
bindingByCategory.type, bindingByCategory.type,
catKey, catKey,
categoryToIcon[catKey] || "", icon || "",
categoryToRank[catKey] || 1 typeof rank == "number" ? rank : 1
) )
return [ return [

View File

@ -1,17 +1,13 @@
<script> <script>
import groupBy from "lodash/fp/groupBy"
import { import {
Search,
Input,
DrawerContent, DrawerContent,
Tabs, Tabs,
Tab, Tab,
Body, Body,
Layout,
Button, Button,
ActionButton, ActionButton,
Heading,
Icon, Icon,
Popover,
} from "@budibase/bbui" } from "@budibase/bbui"
import { createEventDispatcher, onMount } from "svelte" import { createEventDispatcher, onMount } from "svelte"
import { import {
@ -23,7 +19,7 @@
readableToRuntimeBinding, readableToRuntimeBinding,
runtimeToReadableBinding, runtimeToReadableBinding,
} from "builderStore/dataBinding" } from "builderStore/dataBinding"
import { handlebarsCompletions } from "constants/completions" import { store } from "builderStore"
import { convertToJS } from "@budibase/string-templates" import { convertToJS } from "@budibase/string-templates"
import { admin } from "stores/portal" import { admin } from "stores/portal"
import CodeEditor from "../CodeEditor/CodeEditor.svelte" import CodeEditor from "../CodeEditor/CodeEditor.svelte"
@ -37,7 +33,6 @@
jsInsert, jsInsert,
} from "../CodeEditor" } from "../CodeEditor"
import { getContext } from "svelte" import { getContext } from "svelte"
import BindingPicker from "./BindingPicker.svelte" import BindingPicker from "./BindingPicker.svelte"
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
@ -55,57 +50,19 @@
const drawerActions = getContext("drawer-actions") const drawerActions = getContext("drawer-actions")
const bindingDrawerActions = getContext("binding-drawer-actions") const bindingDrawerActions = getContext("binding-drawer-actions")
let helpers = handlebarsCompletions()
let getCaretPosition let getCaretPosition
let insertAtPos let insertAtPos
let search = ""
let initialValueJS = typeof value === "string" && value?.startsWith("{{ js ") let initialValueJS = typeof value === "string" && value?.startsWith("{{ js ")
let mode = initialValueJS ? "JavaScript" : "Text" let mode = initialValueJS ? "JavaScript" : "Text"
let jsValue = initialValueJS ? value : null let jsValue = initialValueJS ? value : null
let hbsValue = initialValueJS ? null : value let hbsValue = initialValueJS ? null : value
let sidebar = true let sidebar = true
let selectedCategory = null let targetMode = null
let popover
let popoverAnchor
let hoverTarget
$: usingJS = mode === "JavaScript" $: usingJS = mode === "JavaScript"
$: searchRgx = new RegExp(search, "ig")
$: categories = Object.entries(groupBy("category", bindings))
$: editorMode = mode == "JavaScript" ? EditorModes.JS : EditorModes.Handlebars $: editorMode = mode == "JavaScript" ? EditorModes.JS : EditorModes.Handlebars
$: bindingCompletions = bindingsToCompletions(bindings, editorMode) $: bindingCompletions = bindingsToCompletions(bindings, editorMode)
$: bindingIcons = bindings?.reduce((acc, ele) => {
if (ele.icon) {
acc[ele.category] = acc[ele.category] || ele.icon
}
return acc
}, {})
$: categoryIcons = { ...bindingIcons, Helpers: "MagicWand" }
$: filteredCategories = categories
.map(([name, categoryBindings]) => ({
name,
bindings: categoryBindings?.filter(binding => {
return binding.readableBinding.match(searchRgx)
}),
}))
.filter(category => {
return (
category.bindings?.length > 0 &&
(!selectedCategory ? true : selectedCategory === category.name)
)
})
$: filteredHelpers = helpers?.filter(helper => {
return helper.label.match(searchRgx) || helper.description.match(searchRgx)
})
$: categoryNames = getCategoryNames(categories)
const updateValue = val => { const updateValue = val => {
valid = isValid(readableToRuntimeBinding(bindings, val)) valid = isValid(readableToRuntimeBinding(bindings, val))
if (valid) { if (valid) {
@ -113,14 +70,6 @@
} }
} }
const getCategoryNames = categories => {
let names = [...categories.map(cat => cat[0])]
if (allowHelpers) {
names.push("Helpers")
}
return names
}
// Adds a JS/HBS helper to the expression // Adds a JS/HBS helper to the expression
const onSelectHelper = (helper, js) => { const onSelectHelper = (helper, js) => {
const pos = getCaretPosition() const pos = getCaretPosition()
@ -163,6 +112,18 @@
updateValue(jsValue) updateValue(jsValue)
} }
const switchMode = () => {
if (targetMode == "Text") {
jsValue = null
updateValue(jsValue)
} else {
hbsValue = null
updateValue(hbsValue)
}
mode = targetMode + ""
targetMode = null
}
const convert = () => { const convert = () => {
const runtime = readableToRuntimeBinding(bindings, hbsValue) const runtime = readableToRuntimeBinding(bindings, hbsValue)
const runtimeJs = encodeJSBinding(convertToJS(runtime)) const runtimeJs = encodeJSBinding(convertToJS(runtime))
@ -177,84 +138,108 @@
}) })
</script> </script>
<DrawerContent> <span class="binding-drawer">
<div class="main"> <DrawerContent>
<Tabs selected={mode} on:select={onChangeMode}> <div class="main">
<Tab title="Text"> <Tabs
<div class="main-content" class:binding-panel={sidebar}> selected={mode}
<div class="editor"> on:select={onChangeMode}
<CodeEditor beforeSwitch={selectedMode => {
value={hbsValue} if (selectedMode == mode) {
on:change={onChangeHBSValue} return true
bind:getCaretPosition }
bind:insertAtPos
completions={[
hbAutocomplete([
...bindingCompletions,
...getHelperCompletions(),
]),
]}
placeholder="Add text, or click the objects on the left to add them to the textbox."
/>
<div class="binding-footer">
<div class="messaging">
{#if !valid}
<p class="syntax-error">
Current Handlebars syntax is invalid, please check the guide
<a href="https://handlebarsjs.com/guide/">here</a>
for more details.
</p>
{/if}
</div>
<div class="actions">
{#if $admin.isDev && allowJS}
<ActionButton secondary>Convert To JS</ActionButton>
{/if}
<ActionButton
secondary
icon={sidebar ? "RailRightClose" : "RailRightOpen"}
on:click={() => {
sidebar = !sidebar
}}
/>
</div>
</div>
</div>
{#if sidebar} //Get the current mode value
<div class="binding-picker"> const currentEditorValue = mode === "JavaScript" ? jsValue : hbsValue
<BindingPicker if (currentEditorValue) {
{bindings} targetMode = selectedMode
{allowHelpers} return false
addHelper={onSelectHelper} }
addBinding={onSelectBinding} return true
mode={editorMode} }}
/> >
</div> <Tab title="Text">
{/if}
</div>
</Tab>
{#if allowJS}
<Tab title="JavaScript">
<div class="main-content" class:binding-panel={sidebar}> <div class="main-content" class:binding-panel={sidebar}>
<div class="editor"> <div class="editor">
<CodeEditor <div class="overlay-wrap">
value={decodeJSBinding(jsValue)} {#if targetMode}
on:change={onChangeJSValue} <div class="mode-overlay">
completions={[ <div class="prompt-body">
jsAutocomplete([ <Heading size="S">
...bindingCompletions, {`Switch to ${targetMode}?`}
...getHelperCompletions(), </Heading>
]), <Body>This will discard anything in your text</Body>
]} <div class="switch-actions">
mode={EditorModes.JS} <Button
bind:getCaretPosition secondary
bind:insertAtPos size="S"
/> on:click={() => {
<Body size="S"> targetMode = null
JavaScript expressions are executed as functions, so ensure that }}
your expression returns a value. >
</Body> No - keep text
</Button>
<Button cta size="S" on:click={switchMode}>
Yes - discard text
</Button>
</div>
</div>
</div>
{/if}
<CodeEditor
value={hbsValue}
on:change={onChangeHBSValue}
bind:getCaretPosition
bind:insertAtPos
completions={[
hbAutocomplete([
...bindingCompletions,
...getHelperCompletions(),
]),
]}
placeholder=""
/>
</div>
<div class="binding-footer">
<div class="messaging">
{#if !valid}
<div class="syntax-error">
Current Handlebars syntax is invalid, please check the
guide
<a href="https://handlebarsjs.com/guide/">here</a>
for more details.
</div>
{:else}
<Icon name="FlashOn" />
<div class="messaging-wrap">
<div>
Add available bindings by typing $ or use the menu on
the right
</div>
</div>
{/if}
</div>
<div class="actions">
{#if $admin.isDev && allowJS}
<ActionButton
secondary
on:click={() => {
convert()
targetMode = null
}}
>
Convert To JS
</ActionButton>
{/if}
<ActionButton
secondary
icon={sidebar ? "RailRightClose" : "RailRightOpen"}
on:click={() => {
sidebar = !sidebar
}}
/>
</div>
</div>
</div> </div>
{#if sidebar} {#if sidebar}
@ -270,32 +255,130 @@
{/if} {/if}
</div> </div>
</Tab> </Tab>
{/if} {#if allowJS}
<div class="drawer-actions"> <Tab title="JavaScript">
<Button <div class="main-content" class:binding-panel={sidebar}>
secondary <div class="editor">
quiet <div class="overlay-wrap">
on:click={() => { {#if targetMode}
console.log(drawerActions) <div class="mode-overlay">
drawerActions.hide() <div class="prompt-body">
}} <Heading size="S">
> {`Switch to ${targetMode}?`}
Cancel </Heading>
</Button> <Body>This will discard anything in your text</Body>
<Button <div class="switch-actions">
cta <Button
on:click={() => { secondary
bindingDrawerActions.save() size="S"
}} on:click={() => {
> targetMode = null
Save }}
</Button> >
</div> No - keep text
</Tabs> </Button>
</div> <Button cta size="S" on:click={switchMode}>
</DrawerContent> Yes - discard text
</Button>
</div>
</div>
</div>
{/if}
<CodeEditor
value={decodeJSBinding(jsValue)}
on:change={onChangeJSValue}
completions={[
jsAutocomplete([
...bindingCompletions,
...getHelperCompletions(),
]),
]}
mode={EditorModes.JS}
bind:getCaretPosition
bind:insertAtPos
/>
</div>
<div class="binding-footer">
<div class="messaging">
<Icon name="FlashOn" />
<div class="messaging-wrap">
<div>
Add available bindings by typing $ or use the menu on
the right
</div>
</div>
</div>
<div class="actions">
<ActionButton
secondary
icon={sidebar ? "RailRightClose" : "RailRightOpen"}
on:click={() => {
sidebar = !sidebar
}}
/>
</div>
</div>
</div>
{#if sidebar}
<div class="binding-picker">
<BindingPicker
{bindings}
{allowHelpers}
addHelper={onSelectHelper}
addBinding={onSelectBinding}
mode={editorMode}
/>
</div>
{/if}
</div>
</Tab>
{/if}
<div class="drawer-actions">
<Button
secondary
quiet
on:click={() => {
store.actions.settings.propertyFocus(null)
drawerActions.hide()
}}
>
Cancel
</Button>
<Button
cta
on:click={() => {
bindingDrawerActions.save()
}}
>
Save
</Button>
</div>
</Tabs>
</div>
</DrawerContent>
</span>
<style> <style>
.messaging {
display: flex;
align-items: center;
gap: var(--spacing-m);
min-width: 0;
flex: 1;
}
.messaging-wrap {
overflow: hidden;
}
.messaging-wrap > div {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.binding-drawer :global(.drawer-contents) {
height: unset;
}
.main :global(textarea) { .main :global(textarea) {
min-height: 202px !important; min-height: 202px !important;
} }
@ -323,7 +406,6 @@
} }
.syntax-error { .syntax-error {
padding-top: var(--spacing-m);
color: var(--red); color: var(--red);
font-size: 12px; font-size: 12px;
} }
@ -354,5 +436,36 @@
.editor { .editor {
padding: var(--spacing-xl); padding: var(--spacing-xl);
padding-bottom: 0px; padding-bottom: 0px;
min-width: 0;
}
.overlay-wrap {
position: relative;
}
.mode-overlay {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: var(
--spectrum-textfield-m-background-color,
var(--spectrum-global-color-gray-50)
);
border-radius: var(--border-radius-s);
}
.prompt-body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--spacing-l);
}
.prompt-body .switch-actions {
display: flex;
gap: var(--spacing-l);
} }
</style> </style>

View File

@ -45,7 +45,6 @@
(!selectedCategory ? true : selectedCategory === category.name) (!selectedCategory ? true : selectedCategory === category.name)
) )
}) })
$: console.log(filteredCategories)
$: filteredHelpers = helpers?.filter(helper => { $: filteredHelpers = helpers?.filter(helper => {
return helper.label.match(searchRgx) || helper.description.match(searchRgx) return helper.label.match(searchRgx) || helper.description.match(searchRgx)
}) })

View File

@ -4,6 +4,9 @@
readableToRuntimeBinding, readableToRuntimeBinding,
runtimeToReadableBinding, runtimeToReadableBinding,
} from "builderStore/dataBinding" } from "builderStore/dataBinding"
import { store } from "builderStore"
import ClientBindingPanel from "components/common/bindings/ClientBindingPanel.svelte" import ClientBindingPanel from "components/common/bindings/ClientBindingPanel.svelte"
import { createEventDispatcher, setContext } from "svelte" import { createEventDispatcher, setContext } from "svelte"
import { isJSBinding } from "@budibase/string-templates" import { isJSBinding } from "@budibase/string-templates"
@ -20,6 +23,7 @@
export let allowHelpers = true export let allowHelpers = true
export let updateOnChange = true export let updateOnChange = true
export let drawerLeft export let drawerLeft
export let key
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
let bindingDrawer let bindingDrawer
@ -32,6 +36,7 @@
const saveBinding = () => { const saveBinding = () => {
onChange(tempValue) onChange(tempValue)
store.actions.settings.propertyFocus(null)
onBlur() onBlur()
bindingDrawer.hide() bindingDrawer.hide()
} }
@ -62,7 +67,13 @@
{updateOnChange} {updateOnChange}
/> />
{#if !disabled} {#if !disabled}
<div class="icon" on:click={bindingDrawer.show}> <div
class="icon"
on:click={() => {
store.actions.settings.propertyFocus(key)
bindingDrawer.show()
}}
>
<Icon size="S" name="FlashOn" /> <Icon size="S" name="FlashOn" />
</div> </div>
{/if} {/if}

View File

@ -21,6 +21,7 @@
export let componentBindings = [] export let componentBindings = []
export let nested = false export let nested = false
export let highlighted = false export let highlighted = false
export let propertyFocus = false
export let info = null export let info = null
$: nullishValue = value == null || value === "" $: nullishValue = value == null || value === ""
@ -72,6 +73,10 @@
if (highlighted) { if (highlighted) {
store.actions.settings.highlight(null) store.actions.settings.highlight(null)
} }
// To fix focus 'affect' when property is target of a drawer other actions in the builder.
if (propertyFocus) {
store.actions.settings.propertyFocus(null)
}
}) })
</script> </script>
@ -79,6 +84,7 @@
class="property-control" class="property-control"
class:wide={!label || labelHidden} class:wide={!label || labelHidden}
class:highlighted={highlighted && nullishValue} class:highlighted={highlighted && nullishValue}
class:property-focus={propertyFocus}
> >
{#if label && !labelHidden} {#if label && !labelHidden}
<div class="label"> <div class="label">
@ -125,6 +131,14 @@
background: var(--spectrum-global-color-gray-300); background: var(--spectrum-global-color-gray-300);
border-color: var(--spectrum-global-color-static-red-600); border-color: var(--spectrum-global-color-static-red-600);
} }
.property-control.property-focus :global(input) {
border-color: var(
--spectrum-textfield-m-border-color-down,
var(--spectrum-alias-border-color-mouse-focus)
);
}
.label { .label {
margin-top: 16px; margin-top: 16px;
transform: translateY(-50%); transform: translateY(-50%);

View File

@ -107,7 +107,6 @@
(inCodeEditor || ["input", "textarea"].indexOf(activeTag) !== -1) && (inCodeEditor || ["input", "textarea"].indexOf(activeTag) !== -1) &&
e.key !== "Escape" e.key !== "Escape"
) { ) {
console.log("KEY PRESS")
return return
} }
// Key events are always for the selected component // Key events are always for the selected component

View File

@ -140,6 +140,7 @@
nested={setting.nested} nested={setting.nested}
onChange={val => updateSetting(setting, val)} onChange={val => updateSetting(setting, val)}
highlighted={$store.highlightedSettingKey === setting.key} highlighted={$store.highlightedSettingKey === setting.key}
propertyFocus={$store.propertyFocus === setting.key}
info={setting.info} info={setting.info}
props={{ props={{
// Generic settings // Generic settings