Type BindingSidePanel
This commit is contained in:
parent
5fb2a6ea2c
commit
894cfba0e0
|
@ -27,7 +27,7 @@ export type UpdateHandler = (
|
||||||
|
|
||||||
interface Opts {
|
interface Opts {
|
||||||
anchor?: HTMLElement
|
anchor?: HTMLElement
|
||||||
align: PopoverAlignment
|
align: PopoverAlignment | `${PopoverAlignment}`
|
||||||
maxHeight?: number
|
maxHeight?: number
|
||||||
maxWidth?: number
|
maxWidth?: number
|
||||||
minWidth?: number
|
minWidth?: number
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
import { PopoverAlignment } from "../constants"
|
import { PopoverAlignment } from "../constants"
|
||||||
|
|
||||||
export let anchor: HTMLElement
|
export let anchor: HTMLElement
|
||||||
export let align: PopoverAlignment = PopoverAlignment.Right
|
export let align: PopoverAlignment | `${PopoverAlignment}` =
|
||||||
|
PopoverAlignment.Right
|
||||||
export let portalTarget: string | undefined = undefined
|
export let portalTarget: string | undefined = undefined
|
||||||
export let minWidth: number | undefined = undefined
|
export let minWidth: number | undefined = undefined
|
||||||
export let maxWidth: number | undefined = undefined
|
export let maxWidth: number | undefined = undefined
|
||||||
|
|
|
@ -421,7 +421,7 @@
|
||||||
{context}
|
{context}
|
||||||
addHelper={onSelectHelper}
|
addHelper={onSelectHelper}
|
||||||
addBinding={onSelectBinding}
|
addBinding={onSelectBinding}
|
||||||
mode={editorMode}
|
{mode}
|
||||||
/>
|
/>
|
||||||
{:else if sidePanel === SidePanel.Evaluation}
|
{:else if sidePanel === SidePanel.Evaluation}
|
||||||
<EvaluationSidePanel
|
<EvaluationSidePanel
|
||||||
|
|
|
@ -1,32 +1,40 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import groupBy from "lodash/fp/groupBy"
|
import groupBy from "lodash/fp/groupBy"
|
||||||
import { convertToJS } from "@budibase/string-templates"
|
import { convertToJS } from "@budibase/string-templates"
|
||||||
import { Input, Layout, Icon, Popover } from "@budibase/bbui"
|
import { Input, Layout, Icon, Popover } from "@budibase/bbui"
|
||||||
import { handlebarsCompletions } from "@/constants/completions"
|
import { handlebarsCompletions } from "@/constants/completions"
|
||||||
|
import { BindingMode, EnrichedBinding, Helper } from "@budibase/types"
|
||||||
|
|
||||||
export let addHelper
|
export let addHelper: (helper: Helper, js?: boolean) => void
|
||||||
export let addBinding
|
export let addBinding: (binding: EnrichedBinding) => void
|
||||||
export let bindings
|
export let bindings: EnrichedBinding[]
|
||||||
export let mode
|
export let mode: BindingMode
|
||||||
export let allowHelpers
|
export let allowHelpers: boolean
|
||||||
export let context = null
|
export let context = null
|
||||||
|
|
||||||
let search = ""
|
let search = ""
|
||||||
let searching = false
|
let searching = false
|
||||||
let popover
|
let popover: Popover
|
||||||
let popoverAnchor
|
let popoverAnchor: HTMLElement | null
|
||||||
let hoverTarget
|
let hoverTarget: {
|
||||||
|
helper: boolean
|
||||||
|
code: string
|
||||||
|
description?: string
|
||||||
|
} | null
|
||||||
let helpers = handlebarsCompletions()
|
let helpers = handlebarsCompletions()
|
||||||
let selectedCategory
|
let selectedCategory: string | null
|
||||||
let hideTimeout
|
let hideTimeout: ReturnType<typeof setTimeout> | null
|
||||||
|
|
||||||
$: bindingIcons = bindings?.reduce((acc, ele) => {
|
$: bindingIcons = bindings?.reduce<Record<string, string>>((acc, ele) => {
|
||||||
if (ele.icon) {
|
if (ele.icon) {
|
||||||
acc[ele.category] = acc[ele.category] || ele.icon
|
acc[ele.category] = acc[ele.category] || ele.icon
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
$: categoryIcons = { ...bindingIcons, Helpers: "MagicWand" }
|
$: categoryIcons = {
|
||||||
|
...bindingIcons,
|
||||||
|
Helpers: "MagicWand",
|
||||||
|
} as Record<string, string>
|
||||||
$: categories = Object.entries(groupBy("category", bindings))
|
$: categories = Object.entries(groupBy("category", bindings))
|
||||||
$: categoryNames = getCategoryNames(categories)
|
$: categoryNames = getCategoryNames(categories)
|
||||||
$: searchRgx = new RegExp(search, "ig")
|
$: searchRgx = new RegExp(search, "ig")
|
||||||
|
@ -48,11 +56,11 @@
|
||||||
(!search ||
|
(!search ||
|
||||||
helper.label.match(searchRgx) ||
|
helper.label.match(searchRgx) ||
|
||||||
helper.description.match(searchRgx)) &&
|
helper.description.match(searchRgx)) &&
|
||||||
(mode.name !== "javascript" || helper.allowsJs)
|
(mode !== BindingMode.JavaScript || helper.allowsJs)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const getHelperExample = (helper, js) => {
|
const getHelperExample = (helper: Helper, js: boolean) => {
|
||||||
let example = helper.example || ""
|
let example = helper.example || ""
|
||||||
if (js) {
|
if (js) {
|
||||||
example = convertToJS(example).split("\n")[0].split("= ")[1]
|
example = convertToJS(example).split("\n")[0].split("= ")[1]
|
||||||
|
@ -63,15 +71,18 @@
|
||||||
return example || ""
|
return example || ""
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCategoryNames = categories => {
|
const getCategoryNames = (categories: [string, EnrichedBinding[]][]) => {
|
||||||
let names = [...categories.map(cat => cat[0])]
|
const names = [...categories.map(cat => cat[0])]
|
||||||
if (allowHelpers) {
|
if (allowHelpers) {
|
||||||
names.push("Helpers")
|
names.push("Helpers")
|
||||||
}
|
}
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
const showBindingPopover = (binding, target) => {
|
const showBindingPopover = (
|
||||||
|
binding: EnrichedBinding,
|
||||||
|
target: HTMLElement
|
||||||
|
) => {
|
||||||
if (!context || !binding.value || binding.value === "") {
|
if (!context || !binding.value || binding.value === "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -84,7 +95,7 @@
|
||||||
popover.show()
|
popover.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
const showHelperPopover = (helper, target) => {
|
const showHelperPopover = (helper: any, target: HTMLElement) => {
|
||||||
stopHidingPopover()
|
stopHidingPopover()
|
||||||
if (!helper.displayText && helper.description) {
|
if (!helper.displayText && helper.description) {
|
||||||
return
|
return
|
||||||
|
@ -93,7 +104,7 @@
|
||||||
hoverTarget = {
|
hoverTarget = {
|
||||||
helper: true,
|
helper: true,
|
||||||
description: helper.description,
|
description: helper.description,
|
||||||
code: getHelperExample(helper, mode.name === "javascript"),
|
code: getHelperExample(helper, mode === BindingMode.JavaScript),
|
||||||
}
|
}
|
||||||
popover.show()
|
popover.show()
|
||||||
}
|
}
|
||||||
|
@ -119,37 +130,39 @@
|
||||||
search = ""
|
search = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
const stopSearching = e => {
|
const stopSearching = (e: Event) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
searching = false
|
searching = false
|
||||||
search = ""
|
search = ""
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Popover
|
{#if popoverAnchor && hoverTarget}
|
||||||
align="left-outside"
|
<Popover
|
||||||
bind:this={popover}
|
align="left-outside"
|
||||||
anchor={popoverAnchor}
|
bind:this={popover}
|
||||||
minWidth={0}
|
anchor={popoverAnchor}
|
||||||
maxWidth={480}
|
minWidth={0}
|
||||||
maxHeight={480}
|
maxWidth={480}
|
||||||
dismissible={false}
|
maxHeight={480}
|
||||||
on:mouseenter={stopHidingPopover}
|
dismissible={false}
|
||||||
on:mouseleave={hidePopover}
|
on:mouseenter={stopHidingPopover}
|
||||||
>
|
on:mouseleave={hidePopover}
|
||||||
<div class="binding-popover" class:helper={hoverTarget.helper}>
|
>
|
||||||
{#if hoverTarget.description}
|
<div class="binding-popover" class:helper={hoverTarget.helper}>
|
||||||
<div>
|
{#if hoverTarget.description}
|
||||||
|
<div>
|
||||||
|
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
||||||
|
{@html hoverTarget.description}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if hoverTarget.code}
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
||||||
{@html hoverTarget.description}
|
<pre>{@html hoverTarget.code}</pre>
|
||||||
</div>
|
{/if}
|
||||||
{/if}
|
</div>
|
||||||
{#if hoverTarget.code}
|
</Popover>
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
{/if}
|
||||||
<pre>{@html hoverTarget.code}</pre>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||||
|
@ -173,7 +186,7 @@
|
||||||
<div class="search-input">
|
<div class="search-input">
|
||||||
<Input
|
<Input
|
||||||
placeholder="Search for bindings"
|
placeholder="Search for bindings"
|
||||||
autocomplete="off"
|
autocomplete={false}
|
||||||
bind:value={search}
|
bind:value={search}
|
||||||
autofocus
|
autofocus
|
||||||
/>
|
/>
|
||||||
|
@ -230,7 +243,8 @@
|
||||||
{#each category.bindings as binding}
|
{#each category.bindings as binding}
|
||||||
<li
|
<li
|
||||||
class="binding"
|
class="binding"
|
||||||
on:mouseenter={e => showBindingPopover(binding, e.target)}
|
on:mouseenter={e =>
|
||||||
|
showBindingPopover(binding, e.currentTarget)}
|
||||||
on:mouseleave={hidePopover}
|
on:mouseleave={hidePopover}
|
||||||
on:click={() => addBinding(binding)}
|
on:click={() => addBinding(binding)}
|
||||||
>
|
>
|
||||||
|
@ -266,7 +280,8 @@
|
||||||
class="binding"
|
class="binding"
|
||||||
on:mouseenter={e => showHelperPopover(helper, e.target)}
|
on:mouseenter={e => showHelperPopover(helper, e.target)}
|
||||||
on:mouseleave={hidePopover}
|
on:mouseleave={hidePopover}
|
||||||
on:click={() => addHelper(helper, mode.name === "javascript")}
|
on:click={() =>
|
||||||
|
addHelper(helper, mode === BindingMode.JavaScript)}
|
||||||
>
|
>
|
||||||
<span class="binding__label">{helper.displayText}</span>
|
<span class="binding__label">{helper.displayText}</span>
|
||||||
<span class="binding__typeWrap">
|
<span class="binding__typeWrap">
|
||||||
|
|
|
@ -1,7 +1,19 @@
|
||||||
export interface EnrichedBinding {
|
export interface EnrichedBinding {
|
||||||
|
value: string
|
||||||
|
valueHTML: string
|
||||||
runtimeBinding: string
|
runtimeBinding: string
|
||||||
readableBinding: string
|
readableBinding: string
|
||||||
type?: null | string
|
type?: null | string
|
||||||
|
icon?: string
|
||||||
|
category: string
|
||||||
|
display?: { name: string; type: string }
|
||||||
|
fieldSchema?: {
|
||||||
|
name: string
|
||||||
|
tableId: string
|
||||||
|
type: string
|
||||||
|
subtype?: string
|
||||||
|
prefixKeys?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum BindingMode {
|
export enum BindingMode {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export interface Helper {
|
export interface Helper {
|
||||||
|
displayText: string
|
||||||
example: string
|
example: string
|
||||||
description: string
|
description: string
|
||||||
args: any[]
|
args: any[]
|
||||||
|
|
Loading…
Reference in New Issue