Files
WPS3Media/ui/components/SettingsPanelOption.svelte

153 lines
3.8 KiB
Svelte
Raw Permalink Normal View History

<script>
import {getContext, hasContext} from "svelte";
import {writable} from "svelte/store";
import {slide} from "svelte/transition";
import {defined_settings, validationErrors} from "../js/stores";
import PanelRow from "./PanelRow.svelte";
import ToggleSwitch from "./ToggleSwitch.svelte";
import DefinedInWPConfig from "./DefinedInWPConfig.svelte";
import SettingNotifications from "./SettingNotifications.svelte";
export let heading = "";
export let description = "";
export let placeholder = "";
export let nested = false;
export let first = false; // of nested items
// Toggle and Text may both be used at same time.
export let toggleName = "";
export let toggle = false;
export let textName = "";
export let text = "";
export let alwaysShowText = false;
export let definedSettings = defined_settings;
/**
* Optional validator function.
*
* @param {string} textValue
*
* @return {string} Empty if no error
*/
export let validator = ( textValue ) => "";
// Parent page may want to be locked.
let settingsLocked = writable( false );
let textDirty = false;
if ( hasContext( "settingsLocked" ) ) {
settingsLocked = getContext( "settingsLocked" );
}
$: locked = $settingsLocked;
$: toggleDisabled = $definedSettings.includes( toggleName ) || locked;
$: textDisabled = $definedSettings.includes( textName ) || locked;
$: input = ((toggleName && toggle) || !toggleName || alwaysShowText) && textName;
$: headingName = input ? textName + "-heading" : toggleName;
/**
* Validate the text if validator function supplied.
*
* @param {string} text
* @param {bool} toggle
*
* @return {string}
*/
function validateText( text, toggle ) {
let message = "";
if ( validator !== undefined && toggle && !textDisabled ) {
message = validator( text );
}
validationErrors.update( _validationErrors => {
if ( _validationErrors.has( textName ) && message === "" ) {
_validationErrors.delete( textName );
} else if ( message !== "" ) {
_validationErrors.set( textName, message );
}
return _validationErrors;
} );
return message;
}
function onTextInput() {
textDirty = true;
}
$: validationError = validateText( text, toggle );
/**
* If appropriate, clicking the header toggles to toggle switch.
*/
function headingClickHandler() {
if ( toggleName && !toggleDisabled ) {
toggle = !toggle;
}
}
</script>
<div class="setting" class:nested class:first>
<PanelRow class="option">
{#if toggleName}
<ToggleSwitch name={toggleName} bind:checked={toggle} disabled={toggleDisabled}>
{heading}
</ToggleSwitch>
<!-- TODO: Fix a11y. -->
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<h4 id={headingName} on:click={headingClickHandler} class="toggler" class:toggleDisabled>{heading}</h4>
{:else}
<h4 id={headingName}>{heading}</h4>
{/if}
<DefinedInWPConfig defined={$definedSettings.includes( toggleName ) || (input && $definedSettings.includes( textName ))}/>
</PanelRow>
<PanelRow class="desc">
<p>{@html description}</p>
</PanelRow>
{#if input}
<PanelRow class="input">
<input
type="text"
id={textName}
name={textName}
bind:value={text}
on:input={onTextInput}
minlength="1"
size="10"
{placeholder}
disabled={textDisabled}
class:disabled={textDisabled}
aria-labelledby={headingName}
>
<label for={textName}>
{heading}
</label>
</PanelRow>
{#if validationError && textDirty}
<p class="input-error" transition:slide>{validationError}</p>
{/if}
{/if}
{#if toggleName}
<SettingNotifications settingKey={toggleName}/>
{/if}
{#if textName}
<SettingNotifications settingKey={textName}/>
{/if}
<slot/>
</div>
<style>
.toggler:not(.toggleDisabled) {
cursor: pointer;
}
</style>