1
0
Fork 0
mirror of synced 2024-05-17 02:42:53 +12:00
budibase/packages/bbui/src/Form/Core/EnvDropdown.svelte
2023-07-05 18:00:50 +01:00

277 lines
6.6 KiB
Svelte

<script>
import "@spectrum-css/textfield/dist/index-vars.css"
import { createEventDispatcher, onMount } from "svelte"
import clickOutside from "../../Actions/click_outside"
import Divider from "../../Divider/Divider.svelte"
export let value = null
export let placeholder = null
export let type = "text"
export let disabled = false
export let id = null
export let readonly = false
export let updateOnChange = true
export let align
export let autofocus = false
export let variables
export let showModal
export let environmentVariablesEnabled
export let handleUpgradePanel
const dispatch = createEventDispatcher()
let field
let focus = false
let iconFocused = false
let open = false
//eslint-disable-next-line
const STRIP_NAME_REGEX = /(\w+?)(?=\ })/g
// Strips the name out of the value which is {{ env.Variable }} resulting in an array like ["Variable"]
$: hbsValue = String(value)?.match(STRIP_NAME_REGEX) || []
const updateValue = newValue => {
if (readonly) {
return
}
if (type === "number") {
const float = parseFloat(newValue)
newValue = isNaN(float) ? null : float
}
dispatch("change", newValue)
}
const onFocus = () => {
if (readonly) {
return
}
focus = true
}
const onBlur = event => {
if (readonly) {
return
}
focus = false
updateValue(event.target.value)
}
const onInput = event => {
if (readonly || !updateOnChange) {
return
}
updateValue(event.target.value)
}
const handleOutsideClick = event => {
if (open) {
event.stopPropagation()
open = false
focus = false
iconFocused = false
dispatch("closed")
}
}
const handleVarSelect = variable => {
open = false
focus = false
iconFocused = false
updateValue(`{{ env.${variable} }}`)
}
onMount(() => {
focus = autofocus
if (focus) field.focus()
})
function removeVariable() {
updateValue("")
}
function openPopover() {
open = true
focus = true
iconFocused = true
}
</script>
<div class="spectrum-InputGroup">
<div
class:is-disabled={disabled || hbsValue.length}
class:is-focused={focus}
class="spectrum-Textfield"
>
<svg
class:close-color={hbsValue.length}
class:focused={iconFocused}
class="hoverable icon-position spectrum-Icon spectrum-Icon--sizeS spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true"
on:click={() => {
hbsValue.length ? removeVariable() : openPopover()
}}
>
<use
xlink:href={`#spectrum-icon-18-${!hbsValue.length ? "Key" : "Close"}`}
/>
</svg>
<input
bind:this={field}
disabled={hbsValue.length || disabled}
{readonly}
{id}
value={hbsValue.length ? `{{ ${hbsValue[0]} }}` : value}
placeholder={placeholder || ""}
on:click
on:blur
on:focus
on:input
on:keyup
on:blur={onBlur}
on:focus={onFocus}
on:input={onInput}
type={hbsValue.length ? "text" : type}
style={align ? `text-align: ${align};` : ""}
class="spectrum-Textfield-input"
inputmode={type === "number" ? "decimal" : "text"}
/>
</div>
{#if open}
<div
use:clickOutside={handleOutsideClick}
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
>
<ul class="spectrum-Menu" role="listbox">
{#if !environmentVariablesEnabled}
<div class="no-variables-text primary-text">
Upgrade your plan to get environment variables
</div>
{:else if variables.length}
<div style="max-height: 100px">
{#each variables as variable}
<li
class="spectrum-Menu-item"
role="option"
aria-selected="true"
tabindex="0"
on:click={() => handleVarSelect(variable.name)}
>
<span class="spectrum-Menu-itemLabel">
<div class="primary-text">
{variable.name}
<span />
</div>
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
</span>
</li>
{/each}
</div>
{:else}
<div class="no-variables-text primary-text">
You don't have any environment variables yet
</div>
{/if}
</ul>
<Divider noMargin />
{#if environmentVariablesEnabled}
<div on:click={() => showModal()} class="add-variable">
<svg
class="spectrum-Icon spectrum-Icon--sizeS "
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Add" />
</svg>
<div class="primary-text">Add Variable</div>
</div>
{:else}
<div on:click={() => handleUpgradePanel()} class="add-variable">
<svg
class="spectrum-Icon spectrum-Icon--sizeS "
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-ArrowUp" />
</svg>
<div class="primary-text">Upgrade plan</div>
</div>
{/if}
</div>
{/if}
</div>
<style>
.spectrum-Textfield {
width: 100%;
}
.icon-position {
position: absolute;
top: 25%;
right: 2%;
}
.hoverable:hover {
cursor: pointer;
color: var(--spectrum-global-color-blue-400);
}
.primary-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.spectrum-InputGroup {
min-width: 0;
width: 100%;
}
.spectrum-Popover {
max-height: 240px;
z-index: 999;
top: 100%;
}
.spectrum-Popover.spectrum-Popover--bottom.spectrum-Picker-popover.is-open {
width: 100%;
}
.no-variables-text {
padding: var(--spacing-m);
color: var(--spectrum-global-color-gray-600);
}
.add-variable {
display: flex;
padding: var(--spacing-m) 0 var(--spacing-m) var(--spacing-m);
align-items: center;
gap: var(--spacing-s);
cursor: pointer;
}
.focused {
color: var(--spectrum-global-color-blue-400);
}
.add-variable:hover {
background: var(--grey-1);
}
.close-color {
color: var(--spectrum-global-color-gray-900) !important;
}
.close-color:hover {
color: var(--spectrum-global-color-blue-400) !important;
}
</style>