115 lines
3.3 KiB
Plaintext
115 lines
3.3 KiB
Plaintext
component PinInput {
|
|
props {
|
|
size = "default"
|
|
color = "primary"
|
|
label = "Verification code"
|
|
name = "pin"
|
|
value = ""
|
|
length = 4
|
|
pattern = "[0-9]"
|
|
type = "text"
|
|
inputMode = "numeric"
|
|
placeholder = "○"
|
|
autocomplete = "one-time-code"
|
|
masked = false
|
|
disabled = false
|
|
readonly = false
|
|
required = false
|
|
autoFocus = false
|
|
autoSubmit = false
|
|
allowPaste = true
|
|
clearable = true
|
|
clearLabel = "Clear code"
|
|
separator = ""
|
|
groupSize = 0
|
|
helpText = ""
|
|
invalid = false
|
|
validationMessage = ""
|
|
class = ""
|
|
@event input = function
|
|
@event change = function
|
|
@event complete = function
|
|
@event paste = function
|
|
@event clear = function
|
|
@event error = function
|
|
}
|
|
|
|
functions {
|
|
function inputIndexes() {
|
|
return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].slice(
|
|
0,
|
|
Math.max(1, Math.min(12, Number(length)))
|
|
)
|
|
}
|
|
}
|
|
|
|
view {
|
|
<fieldset
|
|
{...attrs}
|
|
class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--pin-input {invalid ? 'wire-next--invalid' : ''} {disabled ? 'wire-next--disabled' : ''} {class}"
|
|
data-wrn-pin-input
|
|
data-length="{length}"
|
|
data-pattern="{pattern}"
|
|
data-allow-paste="{allowPaste ? 'true' : 'false'}"
|
|
data-auto-submit="{autoSubmit ? 'true' : 'false'}"
|
|
data-value="{value}"
|
|
disabled="{disabled}"
|
|
aria-describedby="{validationMessage ? `${name}-validation` : helpText ? `${name}-help` : ''}"
|
|
>
|
|
<div class="wire-next__pin-heading">
|
|
<legend>{label}</legend>
|
|
<button
|
|
type="button"
|
|
class="wire-next__pin-clear"
|
|
data-pin-clear
|
|
aria-label="{clearLabel}"
|
|
title="{clearLabel}"
|
|
style="{clearable && value ? '' : 'display: none'}"
|
|
>
|
|
<span class="icon-[lucide--rotate-ccw]" aria-hidden="true"></span>
|
|
<span>{clearLabel}</span>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="wire-next__pin-cells" role="group" aria-label="{label}">
|
|
{#each inputIndexes() as index}
|
|
<input
|
|
data-pin-cell
|
|
data-pin-index="{index}"
|
|
id="{name}-{index}"
|
|
type="{masked ? 'password' : type}"
|
|
inputmode="{inputMode}"
|
|
maxlength="1"
|
|
value="{value[index] || ''}"
|
|
placeholder="{placeholder}"
|
|
autocomplete="{index === 0 ? autocomplete : 'off'}"
|
|
aria-label="{label} digit {index + 1} of {length}"
|
|
aria-required="{required ? 'true' : 'false'}"
|
|
readonly="{readonly}"
|
|
disabled="{disabled}"
|
|
autofocus="{autoFocus && index === 0}"
|
|
/>
|
|
{#if separator && groupSize !== 0 && (index + 1) % groupSize === 0 && index + 1 !== length}
|
|
<span class="wire-next__pin-separator" aria-hidden="true">{separator}</span>
|
|
{/if}
|
|
{/each}
|
|
</div>
|
|
|
|
<input
|
|
type="hidden"
|
|
name="{name}"
|
|
value="{value}"
|
|
required="{required}"
|
|
data-pin-value
|
|
/>
|
|
|
|
{#if helpText && !validationMessage}<small id="{name}-help">{helpText}</small>{/if}
|
|
<small
|
|
id="{name}-validation"
|
|
class="wire-next__validation"
|
|
data-error="{name}"
|
|
>{validationMessage}</small>
|
|
</fieldset>
|
|
}
|
|
}
|