update picker to allow only popover
This commit is contained in:
parent
ac2389c445
commit
e88efe2d1a
|
@ -2,8 +2,9 @@
|
|||
import { createEventDispatcher } from "svelte"
|
||||
import FancyField from "./FancyField.svelte"
|
||||
import Icon from "../Icon/Icon.svelte"
|
||||
import Popover from "../Popover/Popover.svelte"
|
||||
import FancyFieldLabel from "./FancyFieldLabel.svelte"
|
||||
import StatusLight from "../StatusLight/StatusLight.svelte"
|
||||
import Picker from "../Form/Core/Picker.svelte"
|
||||
|
||||
export let label
|
||||
export let value
|
||||
|
@ -11,18 +12,30 @@
|
|||
export let error = null
|
||||
export let validate = null
|
||||
export let options = []
|
||||
export let isOptionEnabled = () => true
|
||||
export let getOptionLabel = option => extractProperty(option, "label")
|
||||
export let getOptionValue = option => extractProperty(option, "value")
|
||||
|
||||
export let getOptionSubtitle = option => extractProperty(option, "subtitle")
|
||||
export let getOptionColour = () => null
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let open = false
|
||||
let popover
|
||||
let wrapper
|
||||
|
||||
$: placeholder = !value
|
||||
$: selectedLabel = getSelectedLabel(value)
|
||||
$: fieldColour = getFieldAttribute(getOptionColour, value, options)
|
||||
|
||||
const getFieldAttribute = (getAttribute, value, options) => {
|
||||
// Wait for options to load if there is a value but no options
|
||||
if (!options?.length) {
|
||||
return ""
|
||||
}
|
||||
const index = options.findIndex(
|
||||
(option, idx) => getOptionValue(option, idx) === value
|
||||
)
|
||||
return index !== -1 ? getAttribute(options[index], index) : null
|
||||
}
|
||||
const extractProperty = (value, property) => {
|
||||
if (value && typeof value === "object") {
|
||||
return value[property]
|
||||
|
@ -64,44 +77,38 @@
|
|||
<FancyFieldLabel {placeholder}>{label}</FancyFieldLabel>
|
||||
{/if}
|
||||
|
||||
{#if fieldColour}
|
||||
<span class="align">
|
||||
<StatusLight square color={fieldColour} />
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
<div class="value" class:placeholder>
|
||||
{selectedLabel || ""}
|
||||
</div>
|
||||
|
||||
<div class="arrow">
|
||||
<div class="align">
|
||||
<Icon name="ChevronDown" />
|
||||
</div>
|
||||
</FancyField>
|
||||
|
||||
<Popover
|
||||
anchor={wrapper}
|
||||
align="left"
|
||||
portalTarget={document.documentElement}
|
||||
bind:this={popover}
|
||||
{open}
|
||||
on:close={() => (open = false)}
|
||||
useAnchorWidth={true}
|
||||
maxWidth={null}
|
||||
>
|
||||
<div class="popover-content">
|
||||
{#if options.length}
|
||||
{#each options as option, idx}
|
||||
<div
|
||||
class="popover-option"
|
||||
tabindex="0"
|
||||
on:click={() => onChange(getOptionValue(option, idx))}
|
||||
>
|
||||
<span class="option-text">
|
||||
{getOptionLabel(option, idx)}
|
||||
</span>
|
||||
{#if value === getOptionValue(option, idx)}
|
||||
<Icon name="Checkmark" />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</Popover>
|
||||
<Picker
|
||||
customAnchor={wrapper}
|
||||
onlyPopover={true}
|
||||
bind:open
|
||||
{error}
|
||||
{disabled}
|
||||
{options}
|
||||
{getOptionLabel}
|
||||
{getOptionValue}
|
||||
{getOptionSubtitle}
|
||||
{getOptionColour}
|
||||
{isOptionEnabled}
|
||||
isPlaceholder={value == null || value === ""}
|
||||
placeholderOption={placeholder === false ? null : placeholder}
|
||||
onSelectOption={onChange}
|
||||
isOptionSelected={option => option === value}
|
||||
/>
|
||||
|
||||
<style>
|
||||
.value {
|
||||
|
@ -118,30 +125,19 @@
|
|||
width: 0;
|
||||
transform: translateY(9px);
|
||||
}
|
||||
|
||||
.align {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
line-height: 17px;
|
||||
color: var(--spectrum-global-color-gray-900);
|
||||
transition: transform 130ms ease-out, opacity 130ms ease-out;
|
||||
transform: translateY(9px);
|
||||
}
|
||||
.value.placeholder {
|
||||
transform: translateY(0);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
margin-top: 0;
|
||||
}
|
||||
.popover-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
padding: 7px 0;
|
||||
}
|
||||
.popover-option {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 7px 16px;
|
||||
transition: background 130ms ease-out;
|
||||
font-size: 15px;
|
||||
}
|
||||
.popover-option:hover {
|
||||
background: var(--spectrum-global-color-gray-200);
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
export let getOptionIcon = () => null
|
||||
export let useOptionIconImage = false
|
||||
export let getOptionColour = () => null
|
||||
export let getOptionSubtitle = () => null
|
||||
export let open = false
|
||||
export let readonly = false
|
||||
export let quiet = false
|
||||
|
@ -39,8 +40,8 @@
|
|||
export let customPopoverHeight
|
||||
export let align = "left"
|
||||
export let footer = null
|
||||
export let tag = null
|
||||
|
||||
export let onlyPopover = false
|
||||
export let customAnchor = null
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let searchTerm = null
|
||||
|
@ -90,7 +91,8 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<button
|
||||
{#if !onlyPopover}
|
||||
<button
|
||||
{id}
|
||||
class="spectrum-Picker spectrum-Picker--sizeM"
|
||||
class:spectrum-Picker--quiet={quiet}
|
||||
|
@ -100,7 +102,7 @@
|
|||
aria-haspopup="listbox"
|
||||
on:click={onClick}
|
||||
bind:this={button}
|
||||
>
|
||||
>
|
||||
{#if fieldIcon}
|
||||
{#if !useOptionIconImage}x
|
||||
<span class="option-extra icon">
|
||||
|
@ -141,10 +143,10 @@
|
|||
>
|
||||
<use xlink:href="#spectrum-css-icon-Chevron100" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
</button>
|
||||
{/if}
|
||||
<Popover
|
||||
anchor={button}
|
||||
anchor={!onlyPopover ? button : customAnchor}
|
||||
align={align || "left"}
|
||||
bind:this={popover}
|
||||
{open}
|
||||
|
@ -218,6 +220,12 @@
|
|||
</span>
|
||||
{/if}
|
||||
<span class="spectrum-Menu-itemLabel">
|
||||
{#if getOptionSubtitle(option, idx)}
|
||||
<span class="subtitle-text"
|
||||
>{getOptionSubtitle(option, idx)}</span
|
||||
>
|
||||
{/if}
|
||||
|
||||
{getOptionLabel(option, idx)}
|
||||
</span>
|
||||
{#if option.tag}
|
||||
|
@ -252,6 +260,17 @@
|
|||
width: 100%;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.subtitle-text {
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
font-weight: 500;
|
||||
top: 10px;
|
||||
color: var(--spectrum-global-color-gray-600);
|
||||
display: block;
|
||||
margin-bottom: var(--spacing-s);
|
||||
}
|
||||
|
||||
.spectrum-Picker-label.auto-width {
|
||||
margin-right: var(--spacing-xs);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue