further popover changes / ts updates

This commit is contained in:
Peter Clement 2025-01-17 10:10:52 +00:00
parent 7cb422f806
commit 3cdcc44cbe
4 changed files with 134 additions and 94 deletions

View File

@ -1,17 +1,17 @@
<script lang="ts"> <script>
import Field from "./Field.svelte" import Field from "./Field.svelte"
import Combobox from "./Core/Combobox.svelte" import Combobox from "./Core/Combobox.svelte"
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
export let value: string | null = null export let value = null
export let label: string | undefined = undefined export let label = undefined
export let disabled: boolean = false export let disabled = false
export let readonly: boolean = false export let readonly = false
export let labelPosition: string = "above" export let labelPosition = "above"
export let error: string | null = null export let error = null
export let placeholder: string = "Choose an option or type" export let placeholder = "Choose an option or type"
export let options: any[] = [] export let options = []
export let helpText: string | null = null export let helpText = null
export let getOptionLabel = option => extractProperty(option, "label") export let getOptionLabel = option => extractProperty(option, "label")
export let getOptionValue = option => extractProperty(option, "value") export let getOptionValue = option => extractProperty(option, "value")
@ -30,6 +30,7 @@
<Field {helpText} {label} {labelPosition} {error}> <Field {helpText} {label} {labelPosition} {error}>
<Combobox <Combobox
{error}
{disabled} {disabled}
{value} {value}
{options} {options}

View File

@ -1,4 +1,4 @@
<script lang="ts"> <script>
import "@spectrum-css/inputgroup/dist/index-vars.css" import "@spectrum-css/inputgroup/dist/index-vars.css"
import "@spectrum-css/popover/dist/index-vars.css" import "@spectrum-css/popover/dist/index-vars.css"
import "@spectrum-css/menu/dist/index-vars.css" import "@spectrum-css/menu/dist/index-vars.css"
@ -6,12 +6,12 @@
import clickOutside from "../../Actions/click_outside" import clickOutside from "../../Actions/click_outside"
import Popover from "../../Popover/Popover.svelte" import Popover from "../../Popover/Popover.svelte"
export let value: string | null = null export let value = null
export let id: string | null = null export let id = null
export let placeholder: string = "Choose an option or type" export let placeholder = "Choose an option or type"
export let disabled: boolean = false export let disabled = false
export let readonly: boolean = false export let readonly = false
export let options: any[] = [] export let options = []
export let getOptionLabel = option => option export let getOptionLabel = option => option
export let getOptionValue = option => option export let getOptionValue = option => option

View File

@ -1,23 +1,26 @@
<script> <script lang="ts">
import { import {
default as AbsTooltip, default as AbsTooltip,
TooltipPosition, TooltipPosition,
TooltipType, TooltipType,
} from "../Tooltip/AbsTooltip.svelte" } from "../Tooltip/AbsTooltip.svelte"
export let name = "Add" type TooltipPositionType =
export let hidden = false (typeof TooltipPosition)[keyof typeof TooltipPosition]
export let size = "M"
export let hoverable = false export let name: string = "Add"
export let disabled = false export let hidden: boolean = false
export let color export let size: string = "M"
export let hoverColor export let hoverable: boolean = false
export let tooltip export let disabled: boolean = false
export let tooltipPosition = TooltipPosition.Bottom export let color: string | undefined = undefined
export let tooltipType = TooltipType.Default export let hoverColor: string | undefined = undefined
export let tooltipColor export let tooltip: string | undefined = undefined
export let tooltipWrap = true export let tooltipPosition: TooltipPositionType = TooltipPosition.Bottom
export let newStyles = false export let tooltipType: TooltipPositionType = TooltipType.Default
export let tooltipColor: string | undefined = undefined
export let tooltipWrap: boolean = true
export let newStyles: boolean = false
</script> </script>
<AbsTooltip <AbsTooltip

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { ActionButton, Modal, ModalContent, Combobox } from "@budibase/bbui" import { ActionButton, Popover, Divider, Icon, Select } from "@budibase/bbui"
import { getAllStateVariables } from "@/dataBinding" import { getAllStateVariables } from "@/dataBinding"
import { import {
componentStore, componentStore,
@ -11,25 +11,33 @@
findHBSBlocks, findHBSBlocks,
isJSBinding, isJSBinding,
} from "@budibase/string-templates" } from "@budibase/string-templates"
import { onMount } from "svelte"
type ComponentUsingState = { type ComponentUsingState = {
id: string id: string
name: string name: string
settings: string[] settings: string[]
}[] }
let modal: Modal
let selectedKey: string | null = null
let componentsUsingState: ComponentUsingState = []
let componentsUpdatingState: ComponentUsingState = []
const keyOptions = getAllStateVariables() const keyOptions = getAllStateVariables()
let popoverAnchor: any
let popover: any
let selectedKey: string | null
let componentsUsingState: ComponentUsingState[] = []
let componentsUpdatingState: ComponentUsingState[] = []
onMount(() => {
if (selectedKey) {
searchComponents(selectedKey)
}
})
function findComponentsUpdatingState( function findComponentsUpdatingState(
component: any, component: any,
stateKey: string stateKey: string
): ComponentUsingState { ): ComponentUsingState[] {
let foundComponents: ComponentUsingState = [] let foundComponents: ComponentUsingState[] = []
const eventHandlerProps = ["onClick", "onChange"] const eventHandlerProps = ["onClick", "onChange"]
@ -66,12 +74,8 @@
function findComponentsUsingState( function findComponentsUsingState(
component: any, component: any,
stateKey: string stateKey: string
): Array<{ id: string; name: string; settings: string[] }> { ): ComponentUsingState[] {
let componentsUsingState: Array<{ let componentsUsingState: ComponentUsingState[] = []
id: string
name: string
settings: string[]
}> = []
const { _children, ...componentSettings } = component const { _children, ...componentSettings } = component
let settingsWithState: string[] = [] let settingsWithState: string[] = []
@ -114,61 +118,83 @@
return componentsUsingState return componentsUsingState
} }
function searchComponents(stateKey: string) {
if (!stateKey || !$selectedScreen?.props) {
return
}
componentsUsingState = findComponentsUsingState(
$selectedScreen.props,
stateKey
)
componentsUpdatingState = findComponentsUpdatingState(
$selectedScreen.props,
stateKey
)
}
function handleStateKeySelect(event: CustomEvent) { function handleStateKeySelect(event: CustomEvent) {
selectedKey = event.detail selectedKey = event.detail
if (!selectedKey) { if (!selectedKey) {
throw new Error("No state key selected") throw new Error("No state key selected")
} }
if ($selectedScreen?.props) { searchComponents(selectedKey)
componentsUsingState = findComponentsUsingState(
$selectedScreen.props,
selectedKey
)
componentsUpdatingState = findComponentsUpdatingState(
$selectedScreen.props,
selectedKey
)
}
} }
function onClickComponentLink(component: { function onClickComponentLink(component: ComponentUsingState) {
id: string
name: string
settings: string[]
}) {
componentStore.select(component.id) componentStore.select(component.id)
component.settings.forEach(setting => { component.settings.forEach(setting => {
builderStore.highlightSetting(setting) builderStore.highlightSetting(setting)
}) })
popover.hide()
} }
</script> </script>
<ActionButton on:click={modal.show}>State</ActionButton> <div bind:this={popoverAnchor}>
<ActionButton on:click={popover.show}>State</ActionButton>
</div>
<Popover bind:this={popover} anchor={popoverAnchor} align="right">
<div class="state-panel">
<div class="split-title">
<div>State</div>
<div>
<Icon size="S" hoverable name="Close" on:click={popover.hide} />
</div>
</div>
<div>
Showing state variables for {$selectedScreen?.routing?.route.split(
"/"
)[1]}:
</div>
<div class="section">
<Select
value={selectedKey}
placeholder="Type here..."
options={keyOptions}
on:change={handleStateKeySelect}
/>
</div>
<Divider />
<div class="section">state inspector here</div>
<Divider />
<Modal bind:this={modal}>
<ModalContent title="State" showConfirmButton={false} cancelText="Close">
<Combobox
value={selectedKey}
options={keyOptions}
on:change={handleStateKeySelect}
/>
{#if componentsUsingState.length > 0} {#if componentsUsingState.length > 0}
<div class="components-list"> <div class="section">
<h4>Components using this state:</h4> <span class="text">Updates:</span>
{#each componentsUsingState as component} {#each componentsUsingState as component, i}
<button <button
class="component-link" class="component-link"
on:click={() => onClickComponentLink(component)} on:click={() => onClickComponentLink(component)}
> >
{component.name} ({component.settings.join(", ")}) {component.name}{i < componentsUsingState.length - 1 ? ", " : ""}
</button> </button>
{/each} {/each}
</div> </div>
{/if} {/if}
{#if componentsUpdatingState.length > 0} {#if componentsUpdatingState.length > 0}
<div class="components-list"> <div class="section">
<h4>Components updating this state:</h4> <span class="text">Updated by:</span>
{#each componentsUpdatingState as component} {#each componentsUpdatingState as component, i}
<button <button
class="component-link" class="component-link"
on:click={() => on:click={() =>
@ -178,38 +204,48 @@
settings: component.settings, settings: component.settings,
})} })}
> >
{component.name} (via {component.settings.join(", ")}) {component.name}{i < componentsUpdatingState.length - 1 ? ", " : ""}
</button> </button>
{/each} {/each}
</div> </div>
{/if} {/if}
</ModalContent> </div>
</Modal> </Popover>
<style> <style>
.components-list { .state-panel {
margin-top: var(--spacing-m); background-color: var(--spectrum-alias-background-color-primary);
max-width: 300px;
min-width: 300px;
padding: var(--spacing-m); padding: var(--spacing-m);
background-color: var(--spectrum-global-color-gray-50); display: flex;
flex-direction: column;
gap: var(--spacing-m);
} }
.components-list h4 { .section {
margin: 0 0 var(--spacing-s) 0; gap: var(--spacing-s);
font-size: 14px; }
.text {
color: var(--spectrum-global-color-gray-700);
font-size: var(--spectrum-global-dimension-font-size-75);
} }
.component-link { .component-link {
display: block; display: inline;
width: 100%;
text-align: left;
padding: var(--spacing-xs) var(--spacing-s);
margin: 2px 0;
border: none; border: none;
background: none; background: none;
color: var(--spectrum-global-color-blue-700); text-decoration: underline;
color: var(--spectrum-global-color-white);
cursor: pointer; cursor: pointer;
font-size: 12px; font-size: var(--spectrum-global-dimension-font-size-75);
padding: 0;
} }
.component-link:hover { .component-link:hover {
background-color: var(--spectrum-global-color-gray-200); text-decoration: underline;
border-radius: 4px; }
.split-title {
display: flex;
justify-content: space-between;
align-items: center;
} }
</style> </style>