update picker to allow only popover

This commit is contained in:
Peter Clement 2023-08-29 14:41:34 +01:00
parent ac2389c445
commit e88efe2d1a
2 changed files with 116 additions and 101 deletions

View File

@ -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>

View File

@ -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,61 +91,62 @@
}
</script>
<button
{id}
class="spectrum-Picker spectrum-Picker--sizeM"
class:spectrum-Picker--quiet={quiet}
{disabled}
class:is-invalid={!!error}
class:is-open={open}
aria-haspopup="listbox"
on:click={onClick}
bind:this={button}
>
{#if fieldIcon}
{#if !useOptionIconImage}x
<span class="option-extra icon">
<Icon size="S" name={fieldIcon} />
</span>
{:else}
<span class="option-extra icon field-icon">
<img src={fieldIcon} alt="icon" width="15" height="15" />
{#if !onlyPopover}
<button
{id}
class="spectrum-Picker spectrum-Picker--sizeM"
class:spectrum-Picker--quiet={quiet}
{disabled}
class:is-invalid={!!error}
class:is-open={open}
aria-haspopup="listbox"
on:click={onClick}
bind:this={button}
>
{#if fieldIcon}
{#if !useOptionIconImage}x
<span class="option-extra icon">
<Icon size="S" name={fieldIcon} />
</span>
{:else}
<span class="option-extra icon field-icon">
<img src={fieldIcon} alt="icon" width="15" height="15" />
</span>
{/if}
{/if}
{#if fieldColour}
<span class="option-extra">
<StatusLight square color={fieldColour} />
</span>
{/if}
{/if}
{#if fieldColour}
<span class="option-extra">
<StatusLight square color={fieldColour} />
<span
class="spectrum-Picker-label"
class:is-placeholder={isPlaceholder}
class:auto-width={autoWidth}
>
{fieldText}
</span>
{/if}
<span
class="spectrum-Picker-label"
class:is-placeholder={isPlaceholder}
class:auto-width={autoWidth}
>
{fieldText}
</span>
{#if error}
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Picker-validationIcon"
focusable="false"
aria-hidden="true"
aria-label="Folder"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Picker-validationIcon"
class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
focusable="false"
aria-hidden="true"
aria-label="Folder"
>
<use xlink:href="#spectrum-icon-18-Alert" />
<use xlink:href="#spectrum-css-icon-Chevron100" />
</svg>
{/if}
<svg
class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
focusable="false"
aria-hidden="true"
>
<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);
}