144 lines
3.6 KiB
Svelte
144 lines
3.6 KiB
Svelte
<script>
|
|
import { Icon, Popover, Layout } from "@budibase/bbui"
|
|
import { store } from "builderStore"
|
|
import { cloneDeep } from "lodash/fp"
|
|
import { createEventDispatcher } from "svelte"
|
|
import ComponentSettingsSection from "../../../../pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte"
|
|
import { getContext } from "svelte"
|
|
|
|
export let anchor
|
|
export let componentInstance
|
|
export let componentBindings
|
|
export let bindings
|
|
export let parseSettings
|
|
export let disabled
|
|
|
|
const draggable = getContext("draggable")
|
|
const dispatch = createEventDispatcher()
|
|
|
|
let popover
|
|
let drawers = []
|
|
let open = false
|
|
|
|
// Auto hide the component when another item is selected
|
|
$: if (open && $draggable.selected !== componentInstance._id) {
|
|
popover.hide()
|
|
}
|
|
|
|
// Open automatically if the component is marked as selected
|
|
$: if (!open && $draggable.selected === componentInstance._id && popover) {
|
|
popover.show()
|
|
open = true
|
|
}
|
|
|
|
$: componentDef = store.actions.components.getDefinition(
|
|
componentInstance._component
|
|
)
|
|
$: parsedComponentDef = processComponentDefinitionSettings(componentDef)
|
|
|
|
const processComponentDefinitionSettings = componentDef => {
|
|
if (!componentDef) {
|
|
return {}
|
|
}
|
|
const clone = cloneDeep(componentDef)
|
|
|
|
if (typeof parseSettings === "function") {
|
|
clone.settings = parseSettings(clone.settings)
|
|
}
|
|
|
|
return clone
|
|
}
|
|
|
|
const updateSetting = async (setting, value) => {
|
|
const nestedComponentInstance = cloneDeep(componentInstance)
|
|
|
|
const patchFn = store.actions.components.updateComponentSetting(
|
|
setting.key,
|
|
value
|
|
)
|
|
patchFn(nestedComponentInstance)
|
|
|
|
dispatch("change", nestedComponentInstance)
|
|
}
|
|
|
|
const customPositionHandler = (anchorBounds, eleBounds, cfg) => {
|
|
let { left, top } = cfg
|
|
let percentageOffset = 30
|
|
// left-outside
|
|
left = anchorBounds.left - eleBounds.width - 18
|
|
|
|
// shift up from the anchor, if space allows
|
|
let offsetPos = Math.floor(eleBounds.height / 100) * percentageOffset
|
|
let defaultTop = anchorBounds.top - offsetPos
|
|
|
|
if (window.innerHeight - defaultTop < eleBounds.height) {
|
|
top = window.innerHeight - eleBounds.height - 5
|
|
} else {
|
|
top = anchorBounds.top - offsetPos
|
|
}
|
|
|
|
return { ...cfg, left, top }
|
|
}
|
|
</script>
|
|
|
|
<Icon
|
|
name="Settings"
|
|
hoverable
|
|
size="S"
|
|
on:click={() => {
|
|
if (!open) {
|
|
popover.show()
|
|
open = true
|
|
}
|
|
}}
|
|
/>
|
|
|
|
<Popover
|
|
bind:this={popover}
|
|
on:open={() => {
|
|
drawers = []
|
|
$draggable.actions.select(componentInstance._id)
|
|
}}
|
|
on:close={() => {
|
|
open = false
|
|
if ($draggable.selected === componentInstance._id) {
|
|
$draggable.actions.select()
|
|
}
|
|
}}
|
|
{anchor}
|
|
align="left-outside"
|
|
showPopover={drawers.length === 0}
|
|
clickOutsideOverride={drawers.length > 0}
|
|
maxHeight={600}
|
|
handlePostionUpdate={customPositionHandler}
|
|
>
|
|
<span class="popover-wrap">
|
|
<Layout noPadding noGap>
|
|
<slot name="header" />
|
|
<ComponentSettingsSection
|
|
includeHidden
|
|
{componentInstance}
|
|
componentDefinition={parsedComponentDef}
|
|
isScreen={false}
|
|
onUpdateSetting={updateSetting}
|
|
showSectionTitle={false}
|
|
showInstanceName={false}
|
|
{bindings}
|
|
{componentBindings}
|
|
on:drawerShow={e => {
|
|
drawers = [...drawers, e.detail]
|
|
}}
|
|
on:drawerHide={() => {
|
|
drawers = drawers.slice(0, -1)
|
|
}}
|
|
/>
|
|
</Layout>
|
|
</span>
|
|
</Popover>
|
|
|
|
<style>
|
|
.popover-wrap {
|
|
background-color: var(--spectrum-alias-background-color-primary);
|
|
}
|
|
</style>
|