Tidy up logic for showing and hiding popovers for bindings and helpers
This commit is contained in:
parent
7a278234b5
commit
ca3f464523
|
@ -117,7 +117,7 @@
|
||||||
const indentWithTabCustom = {
|
const indentWithTabCustom = {
|
||||||
key: "Tab",
|
key: "Tab",
|
||||||
run: view => {
|
run: view => {
|
||||||
if (completionStatus(view.state) == "active") {
|
if (completionStatus(view.state) === "active") {
|
||||||
acceptCompletion(view)
|
acceptCompletion(view)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildKeymap = () => {
|
const buildKeymap = () => {
|
||||||
const baseMap = [
|
return [
|
||||||
...closeBracketsKeymap,
|
...closeBracketsKeymap,
|
||||||
...defaultKeymap,
|
...defaultKeymap,
|
||||||
...historyKeymap,
|
...historyKeymap,
|
||||||
|
@ -139,7 +139,6 @@
|
||||||
...completionKeymap,
|
...completionKeymap,
|
||||||
indentWithTabCustom,
|
indentWithTabCustom,
|
||||||
]
|
]
|
||||||
return baseMap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildBaseExtensions = () => {
|
const buildBaseExtensions = () => {
|
||||||
|
@ -215,7 +214,7 @@
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode.name == "javascript") {
|
if (mode.name === "javascript") {
|
||||||
complete.push(javascript())
|
complete.push(javascript())
|
||||||
complete.push(highlightWhitespace())
|
complete.push(highlightWhitespace())
|
||||||
complete.push(lineNumbers())
|
complete.push(lineNumbers())
|
||||||
|
@ -321,4 +320,19 @@
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.code-editor :global(.binding__example) {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: pre;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
max-height: 480px;
|
||||||
|
}
|
||||||
|
.code-editor :global(.binding__example span) {
|
||||||
|
overflow: hidden !important;
|
||||||
|
text-overflow: ellipsis !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -255,6 +255,11 @@ export const buildBindingInfoNode = (completion, binding) => {
|
||||||
const ele = document.createElement("div")
|
const ele = document.createElement("div")
|
||||||
ele.classList.add("info-bubble")
|
ele.classList.add("info-bubble")
|
||||||
|
|
||||||
|
if (binding.valueHTML) {
|
||||||
|
ele.innerHTML = `<div class="binding__example">${binding.valueHTML}</div>`
|
||||||
|
return ele
|
||||||
|
}
|
||||||
|
|
||||||
const exampleNodeHtml = binding.readableBinding
|
const exampleNodeHtml = binding.readableBinding
|
||||||
? `<div class="binding__example">{{ ${binding.readableBinding} }}</div>`
|
? `<div class="binding__example">{{ ${binding.readableBinding} }}</div>`
|
||||||
: ""
|
: ""
|
||||||
|
|
|
@ -62,16 +62,45 @@
|
||||||
let targetMode = null
|
let targetMode = null
|
||||||
let expressionResult
|
let expressionResult
|
||||||
|
|
||||||
|
$: enrichedBindings = enrichBindings(bindings, context)
|
||||||
$: usingJS = mode === "JavaScript"
|
$: usingJS = mode === "JavaScript"
|
||||||
$: editorMode =
|
$: editorMode =
|
||||||
mode === "JavaScript" ? EditorModes.JS : EditorModes.Handlebars
|
mode === "JavaScript" ? EditorModes.JS : EditorModes.Handlebars
|
||||||
$: bindingCompletions = bindingsToCompletions(bindings, editorMode)
|
$: bindingCompletions = bindingsToCompletions(enrichedBindings, editorMode)
|
||||||
$: runtimeExpression = readableToRuntimeBinding(bindings, value)
|
$: runtimeExpression = readableToRuntimeBinding(enrichedBindings, value)
|
||||||
$: expressionResult = processStringSync(runtimeExpression || "", context)
|
$: expressionResult = processStringSync(runtimeExpression || "", context)
|
||||||
$: bindingHelpers = new BindingHelpers(getCaretPosition, insertAtPos)
|
$: bindingHelpers = new BindingHelpers(getCaretPosition, insertAtPos)
|
||||||
|
|
||||||
|
const getBindingValue = (binding, context) => {
|
||||||
|
const hbs = `{{ literal ${binding.runtimeBinding} }}`
|
||||||
|
const res = processStringSync(hbs, context)
|
||||||
|
return JSON.stringify(res, null, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
const highlightJSON = json => {
|
||||||
|
return formatHighlight(json, {
|
||||||
|
keyColor: "#e06c75",
|
||||||
|
numberColor: "#e5c07b",
|
||||||
|
stringColor: "#98c379",
|
||||||
|
trueColor: "#d19a66",
|
||||||
|
falseColor: "#d19a66",
|
||||||
|
nullColor: "#c678dd",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const enrichBindings = (bindings, context) => {
|
||||||
|
return bindings.map(binding => {
|
||||||
|
const value = getBindingValue(binding, context)
|
||||||
|
return {
|
||||||
|
...binding,
|
||||||
|
value,
|
||||||
|
valueHTML: highlightJSON(value),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const updateValue = val => {
|
const updateValue = val => {
|
||||||
const runtimeExpression = readableToRuntimeBinding(bindings, val)
|
const runtimeExpression = readableToRuntimeBinding(enrichedBindings, val)
|
||||||
valid = isValid(runtimeExpression)
|
valid = isValid(runtimeExpression)
|
||||||
if (valid) {
|
if (valid) {
|
||||||
dispatch("change", val)
|
dispatch("change", val)
|
||||||
|
@ -116,9 +145,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const convert = () => {
|
const convert = () => {
|
||||||
const runtime = readableToRuntimeBinding(bindings, hbsValue)
|
const runtime = readableToRuntimeBinding(enrichedBindings, hbsValue)
|
||||||
const runtimeJs = encodeJSBinding(convertToJS(runtime))
|
const runtimeJs = encodeJSBinding(convertToJS(runtime))
|
||||||
jsValue = runtimeToReadableBinding(bindings, runtimeJs)
|
jsValue = runtimeToReadableBinding(enrichedBindings, runtimeJs)
|
||||||
hbsValue = null
|
hbsValue = null
|
||||||
mode = "JavaScript"
|
mode = "JavaScript"
|
||||||
onSelectBinding("", { forceJS: true })
|
onSelectBinding("", { forceJS: true })
|
||||||
|
@ -143,7 +172,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
valid = isValid(readableToRuntimeBinding(bindings, value))
|
valid = isValid(readableToRuntimeBinding(enrichedBindings, value))
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -261,7 +290,7 @@
|
||||||
{#if sidebar}
|
{#if sidebar}
|
||||||
<div class="binding-picker">
|
<div class="binding-picker">
|
||||||
<BindingPicker
|
<BindingPicker
|
||||||
{bindings}
|
bindings={enrichedBindings}
|
||||||
{allowHelpers}
|
{allowHelpers}
|
||||||
{context}
|
{context}
|
||||||
addHelper={onSelectHelper}
|
addHelper={onSelectHelper}
|
||||||
|
@ -348,7 +377,7 @@
|
||||||
{#if sidebar}
|
{#if sidebar}
|
||||||
<div class="binding-picker">
|
<div class="binding-picker">
|
||||||
<BindingPicker
|
<BindingPicker
|
||||||
{bindings}
|
bindings={enrichedBindings}
|
||||||
{allowHelpers}
|
{allowHelpers}
|
||||||
{context}
|
{context}
|
||||||
addHelper={onSelectHelper}
|
addHelper={onSelectHelper}
|
||||||
|
|
|
@ -71,36 +71,26 @@
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
const getBindingValue = binding => {
|
const showBindingPopover = (binding, target) => {
|
||||||
const hbs = `{{ literal ${binding.runtimeBinding} }}`
|
stopHidingPopover()
|
||||||
const res = processStringSync(hbs, context)
|
popoverAnchor = target
|
||||||
return JSON.stringify(res, null, 2)
|
hoverTarget = {
|
||||||
|
code: binding.valueHTML,
|
||||||
|
}
|
||||||
|
popover.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
const highlight = json => {
|
const showHelperPopover = (helper, target) => {
|
||||||
return formatHighlight(json, {
|
stopHidingPopover()
|
||||||
keyColor: "#e06c75",
|
if (!helper.displayText && helper.description) {
|
||||||
numberColor: "#e5c07b",
|
return
|
||||||
stringColor: "#98c379",
|
|
||||||
trueColor: "#d19a66",
|
|
||||||
falseColor: "#d19a66",
|
|
||||||
nullColor: "#c678dd",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const showPopover = (target, binding) => {
|
|
||||||
if (hideTimeout) {
|
|
||||||
clearTimeout(hideTimeout)
|
|
||||||
hideTimeout = null
|
|
||||||
}
|
}
|
||||||
let val = getBindingValue(binding)
|
popoverAnchor = target
|
||||||
if (val !== "") {
|
hoverTarget = {
|
||||||
popoverAnchor = target
|
description: helper.description,
|
||||||
hoverTarget = {
|
code: getHelperExample(helper, mode.name === "javascript"),
|
||||||
code: val,
|
|
||||||
}
|
|
||||||
popover.show()
|
|
||||||
}
|
}
|
||||||
|
popover.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
const hidePopover = () => {
|
const hidePopover = () => {
|
||||||
|
@ -112,7 +102,7 @@
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
const stopHiding = () => {
|
const stopHidingPopover = () => {
|
||||||
if (hideTimeout) {
|
if (hideTimeout) {
|
||||||
clearTimeout(hideTimeout)
|
clearTimeout(hideTimeout)
|
||||||
hideTimeout = null
|
hideTimeout = null
|
||||||
|
@ -126,9 +116,10 @@
|
||||||
anchor={popoverAnchor}
|
anchor={popoverAnchor}
|
||||||
minWidth={0}
|
minWidth={0}
|
||||||
maxWidth={480}
|
maxWidth={480}
|
||||||
maxHeight={300}
|
maxHeight={480}
|
||||||
dismissible={false}
|
dismissible={false}
|
||||||
on:mouseenter={stopHiding}
|
on:mouseenter={stopHidingPopover}
|
||||||
|
on:mouseleave={hidePopover}
|
||||||
>
|
>
|
||||||
<div class="helper">
|
<div class="helper">
|
||||||
<Layout gap="S">
|
<Layout gap="S">
|
||||||
|
@ -139,10 +130,8 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if hoverTarget.code}
|
{#if hoverTarget.code}
|
||||||
<pre>
|
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
<pre>{@html hoverTarget.code}</pre>
|
||||||
{@html highlight(hoverTarget.code)}
|
|
||||||
</pre>
|
|
||||||
{/if}
|
{/if}
|
||||||
</Layout>
|
</Layout>
|
||||||
</div>
|
</div>
|
||||||
|
@ -212,10 +201,8 @@
|
||||||
{#each category.bindings as binding}
|
{#each category.bindings as binding}
|
||||||
<li
|
<li
|
||||||
class="binding"
|
class="binding"
|
||||||
on:mouseenter={e => showPopover(e.target, binding)}
|
on:mouseenter={e => showBindingPopover(binding, e.target)}
|
||||||
on:mouseleave={hidePopover}
|
on:mouseleave={hidePopover}
|
||||||
on:focus={() => {}}
|
|
||||||
on:blur={() => {}}
|
|
||||||
on:click={() => addBinding(binding)}
|
on:click={() => addBinding(binding)}
|
||||||
>
|
>
|
||||||
<span class="binding__label">
|
<span class="binding__label">
|
||||||
|
@ -227,7 +214,6 @@
|
||||||
{binding.readableBinding}
|
{binding.readableBinding}
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{#if binding.display?.type || binding.fieldSchema?.type}
|
{#if binding.display?.type || binding.fieldSchema?.type}
|
||||||
<span class="binding__typeWrap">
|
<span class="binding__typeWrap">
|
||||||
<span class="binding__type">
|
<span class="binding__type">
|
||||||
|
@ -250,26 +236,9 @@
|
||||||
{#each filteredHelpers as helper}
|
{#each filteredHelpers as helper}
|
||||||
<li
|
<li
|
||||||
class="binding"
|
class="binding"
|
||||||
|
on:mouseenter={e => showHelperPopover(helper, e.target)}
|
||||||
|
on:mouseleave={hidePopover}
|
||||||
on:click={() => addHelper(helper, mode.name === "javascript")}
|
on:click={() => addHelper(helper, mode.name === "javascript")}
|
||||||
on:mouseenter={e => {
|
|
||||||
popoverAnchor = e.target
|
|
||||||
if (!helper.displayText && helper.description) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
hoverTarget = {
|
|
||||||
description: helper.description,
|
|
||||||
code: getHelperExample(helper, mode.name === "javascript"),
|
|
||||||
}
|
|
||||||
popover.show()
|
|
||||||
e.stopPropagation()
|
|
||||||
}}
|
|
||||||
on:mouseleave={() => {
|
|
||||||
popover.hide()
|
|
||||||
popoverAnchor = null
|
|
||||||
hoverTarget = null
|
|
||||||
}}
|
|
||||||
on:focus={() => {}}
|
|
||||||
on:blur={() => {}}
|
|
||||||
>
|
>
|
||||||
<span class="binding__label">{helper.displayText}</span>
|
<span class="binding__label">{helper.displayText}</span>
|
||||||
<span class="binding__typeWrap">
|
<span class="binding__typeWrap">
|
||||||
|
@ -287,16 +256,16 @@
|
||||||
<style>
|
<style>
|
||||||
.search :global(input) {
|
.search :global(input) {
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0px;
|
border-radius: 0;
|
||||||
background: none;
|
background: none;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
padding: var(--spacing-m) var(--spacing-l);
|
padding: var(--spacing-m) var(--spacing-l);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-top: 0px;
|
border-top: 0;
|
||||||
border-bottom: var(--border-light);
|
border-bottom: var(--border-light);
|
||||||
border-left: 2px solid transparent;
|
border-left: 2px solid transparent;
|
||||||
border-right: 2px solid transparent;
|
border-right: 2px solid transparent;
|
||||||
|
@ -316,17 +285,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.category-list {
|
ul.category-list {
|
||||||
padding: 0px var(--spacing-l);
|
padding: 0 var(--spacing-l);
|
||||||
padding-bottom: var(--spacing-l);
|
padding-bottom: var(--spacing-l);
|
||||||
}
|
}
|
||||||
.sub-section {
|
.sub-section {
|
||||||
padding: var(--spacing-l);
|
padding: var(--spacing-l);
|
||||||
padding-top: 0px;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
.sub-section-back {
|
.sub-section-back {
|
||||||
padding: var(--spacing-l);
|
padding: var(--spacing-l);
|
||||||
padding-top: var(--spacing-xl);
|
padding-top: var(--spacing-xl);
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
.cat-heading {
|
.cat-heading {
|
||||||
margin-bottom: var(--spacing-l);
|
margin-bottom: var(--spacing-l);
|
||||||
|
|
Loading…
Reference in New Issue