UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

547 lines (546 loc) • 43.8 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */ import { C as CSS_UTILITY, c as customElement } from "../../chunks/runtime.js"; import { live } from "lit/directives/live.js"; import { keyed } from "lit/directives/keyed.js"; import { css, html, nothing } from "lit"; import { createRef, ref } from "lit/directives/ref.js"; import { LitElement, createEvent, stringOrBoolean, safeClassMap } from "@arcgis/lumina"; import { useWatchAttributes, useDirection } from "@arcgis/lumina/controllers"; import { b as setRequestedIcon, j as isPrimaryPointerButton } from "../../chunks/dom.js"; import { n as numberKeys } from "../../chunks/key.js"; import { c as connectLabel, d as disconnectLabel, g as getLabelText } from "../../chunks/label.js"; import { i as isValidNumber, B as BigDecimal, n as numberStringFormatter, p as parseNumberString, s as sanitizeNumberString, a as addLocalizedTrailingDecimalZeros } from "../../chunks/locale.js"; import { g as getIconScale } from "../../chunks/component.js"; import { I as InternalLabel } from "../../chunks/InternalLabel.js"; import { V as Validation } from "../../chunks/Validation.js"; import { u as useT9n } from "../../chunks/useT9n.js"; import { u as useSetFocus } from "../../chunks/useSetFocus.js"; import { u as useInteractive } from "../../chunks/useInteractive.js"; import { u as useForm } from "../../chunks/useForm.js"; const CSS = { loader: "loader", clearButton: "clear-button", editingEnabled: "editing-enabled", inlineChild: "inline-child", inputIcon: "icon", prefix: "prefix", suffix: "suffix", numberButtonWrapper: "number-button-wrapper", buttonItemHorizontal: "number-button-item--horizontal", wrapper: "element-wrapper", inputWrapper: "wrapper", actionWrapper: "action-wrapper", numberButtonItem: "number-button-item", hasSuffix: "has-suffix", hasPrefix: "has-prefix" }; const IDS = { validationMessage: "inputValidationMessage" }; const INPUT_TYPE_ICONS = { tel: "phone", password: "lock", email: "email-address", date: "calendar", time: "clock", search: "search" }; const SLOTS = { action: "action" }; const DIRECTION = { up: "up", down: "down" }; const ICONS = { chevronUp: "chevron-up", chevronDown: "chevron-down", close: "x" }; const NUDGE_DELAY_IN_MS = 150; const styles = css`:host([disabled]){cursor:default;-webkit-user-select:none;user-select:none;opacity:var(--calcite-opacity-disabled)}:host([disabled]) *,:host([disabled]) ::slotted(*){pointer-events:none}:host{display:block}:host([scale=s]) input,:host([scale=s]) .prefix,:host([scale=s]) .suffix{block-size:1.5rem;font-size:var(--calcite-font-size-relative-sm);line-height:var(--calcite-font-line-height-sm)}:host([scale=s]) input{padding-inline:var(--calcite-spacing-sm)}:host([scale=s]) .has-prefix input{padding-inline-start:var(--calcite-spacing-xxs)}:host([scale=s]) .prefix{padding-inline:var(--calcite-spacing-sm) var(--calcite-spacing-xxs)}:host([scale=s]) .has-suffix input{padding-inline-end:var(--calcite-spacing-xxs)}:host([scale=s]) .suffix{padding-inline:var(--calcite-spacing-xxs) var(--calcite-spacing-sm)}:host([scale=s]) input[type=file]{min-block-size:1.5rem}:host([scale=s]) .number-button-wrapper,:host([scale=s]) .action-wrapper{block-size:1.5rem}:host([scale=s]) .clear-button{min-block-size:1.5rem;min-inline-size:1.5rem}:host([scale=m]) input,:host([scale=m]) .prefix,:host([scale=m]) .suffix{block-size:2rem;font-size:var(--calcite-font-size-relative-base);line-height:var(--calcite-font-line-height-base)}:host([scale=m]) input{padding-inline:var(--calcite-spacing-md)}:host([scale=m]) .has-prefix input{padding-inline-start:var(--calcite-spacing-xs)}:host([scale=m]) .prefix{padding-inline:var(--calcite-spacing-md) var(--calcite-spacing-xs)}:host([scale=m]) .has-suffix input{padding-inline-end:var(--calcite-spacing-xs)}:host([scale=m]) .suffix{padding-inline:var(--calcite-spacing-xs) var(--calcite-spacing-md)}:host([scale=m]) input[type=file]{min-block-size:2rem}:host([scale=m]) .number-button-wrapper,:host([scale=m]) .action-wrapper{block-size:2rem}:host([scale=m]) .clear-button{min-block-size:2rem;min-inline-size:2rem}:host([scale=l]) input,:host([scale=l]) .prefix,:host([scale=l]) .suffix{block-size:2.75rem;font-size:var(--calcite-font-size-relative-md);line-height:var(--calcite-font-line-height-md)}:host([scale=l]) input{padding-inline:var(--calcite-spacing-lg)}:host([scale=l]) .has-prefix input{padding-inline-start:var(--calcite-spacing-sm)}:host([scale=l]) .prefix{padding-inline:var(--calcite-spacing-lg) var(--calcite-spacing-sm)}:host([scale=l]) .has-suffix input{padding-inline-end:var(--calcite-spacing-sm)}:host([scale=l]) .suffix{padding-inline:var(--calcite-spacing-sm) var(--calcite-spacing-lg)}:host([scale=l]) input[type=file]{min-block-size:2.75rem}:host([scale=l]) .number-button-wrapper,:host([scale=l]) .action-wrapper{block-size:2.75rem}:host([scale=l]) .clear-button{min-block-size:2.75rem;min-inline-size:2.75rem}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}.interaction-container{display:contents}input{position:relative;margin:0;box-sizing:border-box;display:flex;max-block-size:100%;inline-size:100%;max-inline-size:100%;flex:1 1 0%;text-overflow:ellipsis;border-width:1px;border-style:solid;font-family:inherit;font-weight:var(--calcite-font-weight-normal);border-color:var(--calcite-input-border-color, var(--calcite-color-border-input));background-color:var(--calcite-input-background-color, var(--calcite-color-foreground-1));color:var(--calcite-input-text-color, var(--calcite-color-text-1));transition:var(--calcite-animation-timing),block-size 0,outline-offset 0s;-webkit-appearance:none}input:placeholder-shown{text-overflow:ellipsis}input{border-start-start-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp));border-start-end-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp));border-end-start-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp));border-end-end-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp))}.has-prefix input{border-start-start-radius:0;border-end-start-radius:0}:host(:not([status=invalid])) .has-prefix input{border-inline-start-width:0}:host(:not([status=invalid])) .has-suffix input{border-inline-end-width:0}.has-suffix input,.element-wrapper:has(.clear-button) input,:host([number-button-type=vertical][type=number]) input,:host([number-button-type=horizontal]) .has-suffix .suffix,:host([number-button-type=vertical][type=number]) .has-suffix .suffix,:host([number-button-type=vertical][type=number]) .clear-button,:host([number-button-type=horizontal][type=number]) .clear-button{border-start-end-radius:0;border-end-end-radius:0}:host([number-button-type=horizontal]) input{border-start-start-radius:0;border-start-end-radius:0;border-end-start-radius:0;border-end-end-radius:0}.has-prefix .prefix:first-child,:host([number-button-type=horizontal]) .number-button-item[data-adjustment=down]{border-start-start-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp));border-end-start-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp))}.has-suffix .suffix,:host([number-button-type=vertical][type=number][read-only]) .has-suffix .suffix,:host([clearable]) .clear-button,:host([number-button-type=horizontal]) .number-button-item[data-adjustment=up]{border-end-end-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp));border-start-end-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp))}:host([clearable]) .has-suffix .clear-button{border-end-end-radius:0;border-start-end-radius:0}:host([number-button-type=vertical]) .number-button-item[data-adjustment=down]{border-block-start-width:0px;border-end-end-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp))}:host([number-button-type=vertical]) .number-button-item[data-adjustment=up]{border-start-end-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp))}input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input:focus{border-color:var(--calcite-color-brand);color:var(--calcite-input-text-color, var(--calcite-color-text-1))}input[readonly]{font-weight:var(--calcite-font-weight-medium);background-color:var(--calcite-input-background-color, var(--calcite-color-background))}input[readonly]:focus{color:var(--calcite-input-text-color, var(--calcite-color-text-1))}:host([read-only]) .prefix,:host([read-only]) .suffix{background-color:var(--calcite-input-background-color, var(--calcite-color-background))}input{outline-color:transparent}input:focus{outline:var(--calcite-border-width-md) solid var(--calcite-color-focus, var(--calcite-ui-focus-color, var(--calcite-color-brand)));outline-offset:calc(calc(-1 * var(--calcite-spacing-base)) * calc(1 - (2*clamp(0,var(--calcite-offset-invert-focus),1))))}:host([status=invalid]) input{border-color:var(--calcite-color-status-danger)}:host([status=invalid]) input:focus{outline:var(--calcite-border-width-md) solid var(--calcite-color-status-danger);outline-offset:calc(calc(-1 * var(--calcite-spacing-base)) * calc(1 - (2*clamp(0,var(--calcite-offset-invert-focus),1))))}:host([scale=s]) .icon{inset-inline-start:.5rem}:host([scale=m]) .icon{inset-inline-start:.75rem}:host([scale=l]) .icon{inset-inline-start:1rem}:host([icon][scale=s]) input{padding-inline-start:2rem}:host([icon][scale=m]) input{padding-inline-start:2.5rem}:host([icon][scale=l]) input{padding-inline-start:3.5rem}.element-wrapper{position:relative;order:3;display:inline-flex;flex:1 1 0%;align-items:center;isolation:isolate}.icon{pointer-events:none;position:absolute;display:block;transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out;color:var(--calcite-input-icon-color, var(--calcite-color-text-3));z-index:var(--calcite-z-index)}input[type=text]::-ms-clear,input[type=text]::-ms-reveal{display:none;block-size:0px;inline-size:0px}input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration,input[type=date]::-webkit-clear-button,input[type=time]::-webkit-clear-button{display:none}.clear-button{pointer-events:initial;order:4;margin:0;box-sizing:border-box;display:flex;min-block-size:100%;cursor:pointer;align-items:center;justify-content:center;align-self:stretch;border-width:1px;border-style:solid;outline-color:transparent;transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out;border-color:var(--calcite-input-border-color, var(--calcite-color-border-input));background-color:var(--calcite-input-actions-background-color, var(--calcite-color-foreground-1));border-inline-start-width:0px}.clear-button calcite-icon{transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out;color:var(--calcite-input-actions-icon-color, var(--calcite-color-text-3))}.clear-button:hover{background-color:var(--calcite-input-actions-background-color-hover, var(--calcite-color-foreground-2))}.clear-button:hover calcite-icon{color:var(--calcite-input-actions-icon-color-hover, var(--calcite-color-text-1))}.clear-button:active{background-color:var(--calcite-input-actions-background-color-press, var(--calcite-color-foreground-3))}.clear-button:active calcite-icon{color:var(--calcite-input-actions-icon-color-press, var(--calcite-color-text-1))}.clear-button:focus{outline:var(--calcite-border-width-md) solid var(--calcite-color-focus, var(--calcite-ui-focus-color, var(--calcite-color-brand)));outline-offset:calc(calc(-1 * var(--calcite-spacing-base)) * calc(1 - (2*clamp(0,var(--calcite-offset-invert-focus),1))))}.clear-button:disabled{opacity:var(--calcite-opacity-disabled)}.has-suffix .clear-button{border-inline-end-width:0}.loader{inset-block-start:1px;inset-inline:1px;pointer-events:none;position:absolute;display:block;--calcite-progress-background-color: var(--calcite-input-loading-background-color);--calcite-progress-fill-color: var(--calcite-input-loading-fill-color)}.action-wrapper{order:7;display:flex}.prefix,.suffix{box-sizing:border-box;display:flex;block-size:auto;min-block-size:100%;-webkit-user-select:none;user-select:none;align-content:center;align-items:center;overflow-wrap:break-word;border-width:1px;border-style:solid;line-height:1;font-weight:var(--calcite-font-weight-regular);border-color:var(--calcite-input-border-color, var(--calcite-color-border-input))}.prefix{order:2;border-inline-end-width:0px;inline-size:var(--calcite-input-prefix-size, auto);background-color:var(--calcite-input-background-color, var(--calcite-color-foreground-1));color:var(--calcite-input-prefix-text-color, var(--calcite-color-text-2))}.suffix{order:5;border-inline-start-width:0px;inline-size:var(--calcite-input-suffix-size, auto);background-color:var(--calcite-input-background-color, var(--calcite-color-foreground-1));color:var(--calcite-input-suffix-text-color, var(--calcite-color-text-2))}:host([alignment=start]) input{text-align:start}:host([alignment=end]) input{text-align:end}input[type=number]{-moz-appearance:textfield}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;-moz-appearance:textfield;margin:0}.number-button-wrapper{pointer-events:none;order:6;box-sizing:border-box;display:flex;flex-direction:column;transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out}:host([number-button-type=vertical]) .wrapper{flex-direction:row;display:flex}:host([number-button-type=vertical]) input{order:2}:host([number-button-type=horizontal]) .calcite--rtl .number-button-item[data-adjustment=down] calcite-icon{transform:rotate(-90deg)}:host([number-button-type=horizontal]) .calcite--rtl .number-button-item[data-adjustment=up] calcite-icon{transform:rotate(-90deg)}.number-button-item.number-button-item--horizontal{border-color:var(--calcite-input-border-color, var(--calcite-color-border-input));order:1;max-block-size:100%;min-block-size:100%;align-self:stretch;border-width:1px;border-style:solid}.number-button-item.number-button-item--horizontal[data-adjustment=down] calcite-icon,.number-button-item.number-button-item--horizontal[data-adjustment=up] calcite-icon{transform:rotate(90deg)}.number-button-item.number-button-item--horizontal[data-adjustment=down]{border-inline-end-width:0px}.number-button-item.number-button-item--horizontal[data-adjustment=up]{border-inline-start-width:0px;order:5}.number-button-item{max-block-size:50%;min-block-size:50%;pointer-events:initial;margin:0;box-sizing:border-box;display:flex;cursor:pointer;align-items:center;align-self:center;border-width:1px;border-style:solid;background-color:var(--calcite-color-foreground-1);padding-block:0px;padding-inline:.5rem;transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out;border-color:var(--calcite-input-border-color, var(--calcite-color-border-input));background-color:var(--calcite-input-actions-background-color, var(--calcite-color-foreground-1));border-inline-start-width:0px}.number-button-item calcite-icon{pointer-events:none;transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out;color:var(--calcite-input-actions-icon-color, var(--calcite-color-text-3))}.number-button-item:hover{background-color:var(--calcite-input-actions-background-color-hover, var(--calcite-color-foreground-2))}.number-button-item:hover calcite-icon{color:var(--calcite-input-actions-icon-color-hover, var(--calcite-color-text-1))}.number-button-item:active{background-color:var(--calcite-input-actions-background-color-press, var(--calcite-color-foreground-3))}.number-button-item:active calcite-icon{color:var(--calcite-input-actions-icon-color-press, var(--calcite-color-text-1))}.number-button-item:disabled{pointer-events:none}.wrapper{position:relative;display:flex;flex-direction:row;align-items:center;border-radius:var(--calcite-input-corner-radius, var(--calcite-corner-radius-sharp));box-shadow:var(--calcite-input-shadow, var(--calcite-shadow-none))}input[type=date]::-webkit-input-placeholder{visibility:hidden!important}:host([type=color]) input{padding:.25rem}:host([type=file]) input{cursor:pointer;border-width:1px;border-style:dashed;background-color:var(--calcite-color-foreground-1);text-align:center;border-color:var(--calcite-input-border-color, var(--calcite-color-border-input));block-size:initial}:host([type=file][scale=s]) input{padding-block:1px;padding-inline:.5rem}:host([type=file][scale=m]) input{padding-block:.25rem;padding-inline:.75rem}:host([type=file][scale=l]) input{padding-block:.5rem;padding-inline:1rem}:host(.no-bottom-border) input{border-block-end-width:0px}:host(.border-top-color-one) input{border-block-start-color:var(--calcite-color-border-1)}input.inline-child{background-color:transparent;transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out}input.inline-child .editing-enabled{background-color:inherit}input.inline-child:not(.editing-enabled){display:flex;cursor:pointer;text-overflow:ellipsis;border-color:transparent;padding-inline-start:0}:host([type=datetime-local]) .element-wrapper{inline-size:100%}:host([type=datetime-local]) .element-wrapper input{display:inline-block;min-inline-size:0}.internal-label-alignment--center{align-items:center}.internal-label-alignment--end{align-items:end}.internal-label--container{display:flex;justify-content:space-between;color:var(--calcite-color-text-1)}.internal-label-required--indicator{font-weight:var(--calcite-font-weight-medium);color:var(--calcite-color-status-danger);padding-inline:var(--calcite-spacing-base)}.internal-label-required--indicator:hover{cursor:help}.internal-label--text{line-height:1}:host([scale=s]) .internal-label-spacing--bottom{margin-block-end:var(--calcite-spacing-xxs)}:host([scale=s]) .internal-label-spacing-inline--end{margin-inline-end:var(--calcite-spacing-sm)}:host([scale=s]) .internal-label-spacing-inline--start{margin-inline-start:var(--calcite-spacing-sm)}:host([scale=s]) .internal-label--text{font-size:var(--calcite-font-size--2)}:host([scale=m]) .internal-label-spacing--bottom{margin-block-end:var(--calcite-spacing-sm)}:host([scale=m]) .internal-label-spacing-inline--end{margin-inline-end:var(--calcite-spacing-sm)}:host([scale=m]) .internal-label-spacing-inline--start{margin-inline-start:var(--calcite-spacing-sm)}:host([scale=m]) .internal-label--text{font-size:var(--calcite-font-size--1)}:host([scale=l]) .internal-label-spacing--bottom{margin-block-end:var(--calcite-spacing-sm)}:host([scale=l]) .internal-label-spacing-inline--end{margin-inline-end:var(--calcite-spacing-md)}:host([scale=l]) .internal-label-spacing-inline--start{margin-inline-start:var(--calcite-spacing-md)}:host([scale=l]) .internal-label--text{font-size:var(--calcite-font-size-0)}.validation-container{display:flex;flex-direction:column;align-items:flex-start;align-self:stretch}:host([scale=m]) .validation-container,:host([scale=l]) .validation-container{padding-block-start:.5rem}:host([scale=s]) .validation-container{padding-block-start:.25rem}::slotted(input[slot=hidden-form-input]){margin:0!important;opacity:0!important;outline:none!important;padding:0!important;position:absolute!important;inset:0!important;transform:none!important;-webkit-appearance:none!important;z-index:-1!important}:host([hidden]){display:none}[hidden]{display:none}::placeholder{font-weight:var(--calcite-font-weight-normal);color:var(--calcite-input-placeholder-text-color, var(--calcite-color-text-3))}`; class Input extends LitElement { constructor() { super(); this.actionWrapperRef = createRef(); this.attributeWatch = useWatchAttributes(["autofocus", "enterkeyhint", "inputmode", "spellcheck"], this.handleGlobalAttributesChanged); this.childRef = createRef(); this.childNumberRef = createRef(); this.direction = useDirection(); this.formSupport = useForm({ inputType: "text" })(this); this.inputWrapperRef = createRef(); this.previousValueOrigin = "initial"; this.userChangedValue = false; this._value = ""; this.messages = useT9n({ blocking: true }); this.focusSetter = useSetFocus()(this); this.interactiveContainer = useInteractive(this); this.slottedActionElDisabledInternally = false; this.alignment = "start"; this.clearable = false; this.disabled = false; this.editingEnabled = false; this.groupSeparator = false; this.iconFlipRtl = false; this.loading = false; this.localeFormat = false; this.multiple = false; this.numberButtonType = "vertical"; this.readOnly = false; this.required = false; this.scale = "m"; this.status = "idle"; this.type = "text"; this.validity = { valid: false, badInput: false, customError: false, patternMismatch: false, rangeOverflow: false, rangeUnderflow: false, stepMismatch: false, tooLong: false, tooShort: false, typeMismatch: false, valueMissing: false }; this.calciteInputChange = createEvent({ cancelable: false }); this.calciteInputInput = createEvent(); this.calciteInternalInputBlur = createEvent({ cancelable: false }); this.calciteInternalInputFocus = createEvent({ cancelable: false }); this.listen("click", this.clickHandler); this.listen("keydown", this.keyDownHandler); } static { this.properties = { displayedValue: [16, {}, { state: true }], slottedActionElDisabledInternally: [16, {}, { state: true }], accept: 1, alignment: [3, {}, { reflect: true }], autocomplete: 1, clearable: [7, {}, { reflect: true, type: Boolean }], disabled: [7, {}, { reflect: true, type: Boolean }], editingEnabled: [7, {}, { reflect: true, type: Boolean }], files: [0, {}, { attribute: false }], form: [3, {}, { reflect: true }], groupSeparator: [7, {}, { reflect: true, type: Boolean }], icon: [3, { converter: stringOrBoolean, type: String }, { reflect: true }], iconFlipRtl: [7, {}, { reflect: true, type: Boolean }], label: 1, labelText: 1, loading: [7, {}, { reflect: true, type: Boolean }], localeFormat: [5, {}, { type: Boolean }], max: [11, {}, { reflect: true, type: Number }], maxLength: [11, {}, { reflect: true, type: Number }], messageOverrides: [0, {}, { attribute: false }], min: [11, {}, { reflect: true, type: Number }], minLength: [11, {}, { reflect: true, type: Number }], multiple: [5, {}, { type: Boolean }], name: [3, {}, { reflect: true }], numberButtonType: [3, {}, { reflect: true }], numberingSystem: [3, {}, { reflect: true }], pattern: 1, placeholder: 1, prefixText: 1, readOnly: [7, {}, { reflect: true, type: Boolean }], required: [7, {}, { reflect: true, type: Boolean }], scale: [3, {}, { reflect: true }], status: [3, {}, { reflect: true }], step: [3, {}, { reflect: true }], suffixText: 1, type: [3, {}, { reflect: true }], validationIcon: [3, { converter: stringOrBoolean, type: String }, { reflect: true }], validationMessage: 1, validity: [0, {}, { attribute: false }], value: 1 }; } static { this.formAssociated = true; } static { this.styles = styles; } get isClearable() { return (this.clearable || this.type === "search") && this.value?.length > 0; } get value() { return this._value; } set value(value) { const oldValue = this._value; if (value !== oldValue) { this._value = value; this.valueWatcher(value, oldValue); if (value && this._value === "") { this.setValue({ origin: "reset", value: oldValue }); } } } async selectText() { const selectTarget = this.type === "number" ? this.childNumberRef : this.childRef; selectTarget.value?.select(); } async setFocus(options) { return this.focusSetter(() => this.type === "number" ? this.childNumberRef.value : this.childRef.value, options); } connectedCallback() { super.connectedCallback(); this.inlineEditableEl = this.el.closest("calcite-inline-editable"); if (this.inlineEditableEl) { this.editingEnabled = this.inlineEditableEl.editingEnabled || false; } connectLabel(this); } async load() { this.maxString = this.max?.toString(); this.minString = this.min?.toString(); this.requestedIcon = setRequestedIcon(INPUT_TYPE_ICONS, this.icon, this.type); this.setPreviousEmittedValue(this.value); this.setPreviousValue(this.value); if (this.type === "number") { if (this.value === "Infinity" || this.value === "-Infinity") { this.displayedValue = this.value; this.previousEmittedValue = this.value; } else { this.warnAboutInvalidNumberValue(this.value); this.setValue({ origin: "connected", value: isValidNumber(this.value) ? this.value : "" }); } } } willUpdate(changes) { if (changes.has("max")) { this.maxString = this.max?.toString() || null; } if (changes.has("min")) { this.minString = this.min?.toString() || null; } if (changes.has("icon") || changes.has("type") && (this.hasUpdated || this.type !== "text")) { this.requestedIcon = setRequestedIcon(INPUT_TYPE_ICONS, this.icon, this.type); } if (changes.has("readOnly")) { this.stopNudging(); } if (changes.has("type") && (this.hasUpdated || this.type !== "text")) { this.formSupport.overrideInputType(this.type); } } disconnectedCallback() { super.disconnectedCallback(); disconnectLabel(this); this.stopNudging(); } stopNudging() { window.clearInterval(this.nudgeNumberValueIntervalId); } handleGlobalAttributesChanged() { this.requestUpdate(); } valueWatcher(newValue, previousValue) { if (!this.userChangedValue) { if (this.type === "number" && (newValue === "Infinity" || newValue === "-Infinity")) { this.displayedValue = newValue; this.previousEmittedValue = newValue; return; } this.setValue({ origin: "direct", previousValue, value: newValue == null || newValue == "" ? "" : this.type === "number" ? isValidNumber(newValue) ? newValue : this.previousValue || "" : newValue }); this.warnAboutInvalidNumberValue(newValue); } this.userChangedValue = false; } keyDownHandler(event) { if (this.readOnly || this.disabled || event.defaultPrevented) { return; } if (this.isClearable && event.key === "Escape") { this.clearInputValue(event); event.preventDefault(); } if (event.key === "Enter" && this.formSupport.active) { event.preventDefault(); this.formSupport.requestSubmit(); } } onLabelClick() { this.setFocus(); } incrementOrDecrementNumberValue(direction, inputMax, inputMin, nativeEvent) { const { value } = this; if (value === "Infinity" || value === "-Infinity") { return; } const adjustment = direction === "up" ? 1 : -1; const inputStep = this.step === "any" ? 1 : Math.abs(this.step || 1); const inputVal = new BigDecimal(value !== "" ? value : "0"); const nudgedValue = inputVal.add(`${inputStep * adjustment}`); const nudgedValueBelowInputMin = () => typeof inputMin === "number" && !isNaN(inputMin) && nudgedValue.subtract(`${inputMin}`).isNegative; const nudgedValueAboveInputMax = () => typeof inputMax === "number" && !isNaN(inputMax) && !nudgedValue.subtract(`${inputMax}`).isNegative; const finalValue = nudgedValueBelowInputMin() ? `${inputMin}` : nudgedValueAboveInputMax() ? `${inputMax}` : nudgedValue.toString(); this.setValue({ committing: true, nativeEvent, origin: "user", value: finalValue }); } clearInputValue(nativeEvent) { this.setValue({ committing: true, nativeEvent, origin: "user", value: "" }); } emitChangeIfUserModified() { if (this.previousValueOrigin === "user" && this.value !== this.previousEmittedValue) { this.calciteInputChange.emit(); this.setPreviousEmittedValue(this.value); } } inputBlurHandler() { this.stopNudging(); this.calciteInternalInputBlur.emit(); this.emitChangeIfUserModified(); } clickHandler(event) { if (this.disabled) { return; } const composedPath = event.composedPath(); if (!composedPath.includes(this.inputWrapperRef.value) || composedPath.includes(this.actionWrapperRef.value)) { return; } this.setFocus(); } inputFocusHandler() { this.calciteInternalInputFocus.emit(); } inputInputHandler(nativeEvent) { if (this.disabled || this.readOnly) { return; } if (this.type === "file") { this.files = this.childRef.value.files; } this.setValue({ nativeEvent, origin: "user", value: nativeEvent.target.value }); } inputKeyDownHandler(event) { if (this.disabled || this.readOnly) { return; } if (event.key === "Enter") { this.emitChangeIfUserModified(); } } inputNumberInputHandler(nativeEvent) { if (this.disabled || this.readOnly) { return; } if (this.value === "Infinity" || this.value === "-Infinity") { return; } const value = nativeEvent.target.value; numberStringFormatter.numberFormatOptions = { locale: this.messages._lang, numberingSystem: this.numberingSystem, useGrouping: this.groupSeparator }; const delocalizedValue = numberStringFormatter.delocalize(value); if (nativeEvent.inputType === "insertFromPaste") { if (!isValidNumber(delocalizedValue)) { nativeEvent.preventDefault(); } this.setValue({ nativeEvent, origin: "user", value: parseNumberString(delocalizedValue) }); this.childNumberRef.value.value = this.displayedValue; } else { this.setValue({ nativeEvent, origin: "user", value: delocalizedValue }); } } inputNumberKeyDownHandler(event) { if (this.type !== "number" || this.disabled || this.readOnly) { return; } if (this.value === "Infinity" || this.value === "-Infinity") { event.preventDefault(); if (event.key === "Backspace" || event.key === "Delete") { this.clearInputValue(event); } return; } if (event.key === "ArrowUp") { event.preventDefault(); this.nudgeNumberValue("up", event); return; } if (event.key === "ArrowDown") { this.nudgeNumberValue("down", event); return; } const supportedKeys = [ ...numberKeys, "ArrowLeft", "ArrowRight", "Backspace", "Delete", "Enter", "Escape", "Tab" ]; if (event.altKey || event.ctrlKey || event.metaKey) { return; } const isShiftTabEvent = event.shiftKey && event.key === "Tab"; if (supportedKeys.includes(event.key) || isShiftTabEvent) { if (event.key === "Enter") { this.emitChangeIfUserModified(); } return; } numberStringFormatter.numberFormatOptions = { locale: this.messages._lang, numberingSystem: this.numberingSystem, useGrouping: this.groupSeparator }; if (event.key === numberStringFormatter.decimal) { if (!this.value && !this.childNumberRef.value.value) { return; } if (this.value && this.childNumberRef.value.value.indexOf(numberStringFormatter.decimal) === -1) { return; } } if (/[eE]/.test(event.key)) { if (!this.value && !this.childNumberRef.value.value) { return; } if (this.value && !/[eE]/.test(this.childNumberRef.value.value)) { return; } } if (event.key === "-") { if (!this.value && !this.childNumberRef.value.value) { return; } if (this.value && this.childNumberRef.value.value.split("-").length <= 2) { return; } } event.preventDefault(); } nudgeNumberValue(direction, nativeEvent) { if (nativeEvent instanceof KeyboardEvent && nativeEvent.repeat || this.type !== "number") { return; } const inputMax = this.maxString ? parseFloat(this.maxString) : null; const inputMin = this.minString ? parseFloat(this.minString) : null; this.incrementOrDecrementNumberValue(direction, inputMax, inputMin, nativeEvent); if (this.nudgeNumberValueIntervalId) { this.stopNudging(); } let firstValueNudge = true; this.nudgeNumberValueIntervalId = window.setInterval(() => { if (firstValueNudge) { firstValueNudge = false; return; } this.incrementOrDecrementNumberValue(direction, inputMax, inputMin, nativeEvent); }, NUDGE_DELAY_IN_MS); } numberButtonPointerUpAndOutHandler() { this.stopNudging(); } numberButtonPointerDownHandler(event) { if (!isPrimaryPointerButton(event)) { return; } event.preventDefault(); const direction = event.target.dataset.adjustment; if (!this.disabled) { this.nudgeNumberValue(direction, event); } } setInputValue(newInputValue) { const target = this.type === "number" ? this.childNumberRef : this.childRef; if (target.value) { target.value.value = newInputValue; } } setPreviousEmittedValue(value) { this.previousEmittedValue = this.normalizeValue(value); } normalizeValue(value) { return this.type === "number" ? isValidNumber(value) ? value : "" : value; } setPreviousValue(value) { this.previousValue = this.normalizeValue(value); } setValue({ committing = false, nativeEvent, origin, previousValue, value }) { this.setPreviousValue(previousValue ?? this.value); this.previousValueOrigin = origin; if (this.type === "number") { numberStringFormatter.numberFormatOptions = { locale: this.messages._lang, numberingSystem: this.numberingSystem, useGrouping: this.groupSeparator, signDisplay: "never" }; const isValueDeleted = this.previousValue?.length > value.length || this.value?.length > value.length; const hasTrailingDecimalSeparator = value.charAt(value.length - 1) === "."; const sanitizedValue = hasTrailingDecimalSeparator && isValueDeleted ? value : sanitizeNumberString(value); const newValue = value && !sanitizedValue ? isValidNumber(this.previousValue) ? this.previousValue : "" : sanitizedValue; let newLocalizedValue = numberStringFormatter.localize(newValue); if (origin !== "connected" && !hasTrailingDecimalSeparator) { newLocalizedValue = addLocalizedTrailingDecimalZeros(newLocalizedValue, newValue, numberStringFormatter); } this.displayedValue = hasTrailingDecimalSeparator && isValueDeleted ? `${newLocalizedValue}${numberStringFormatter.decimal}` : newLocalizedValue; this.userChangedValue = origin === "user" && this.value !== newValue; this.value = ["-", "."].includes(newValue) ? "" : newValue; } else { this.userChangedValue = origin === "user" && this.value !== value; this.value = value; } if (origin === "direct") { this.setInputValue(value); this.previousEmittedValue = value; } if (nativeEvent) { const calciteInputInputEvent = this.calciteInputInput.emit(); if (calciteInputInputEvent.defaultPrevented) { this.value = this.previousValue; this.displayedValue = this.type === "number" ? numberStringFormatter.localize(this.previousValue) : this.previousValue; } else if (committing) { this.emitChangeIfUserModified(); } } } inputKeyUpHandler() { this.stopNudging(); } warnAboutInvalidNumberValue(value) { if (this.type === "number" && value && !isValidNumber(value)) { console.warn(`The specified value "${value}" cannot be parsed, or is out of range.`); } } render() { const dir = this.direction; const loader = html`<div class=${safeClassMap(CSS.loader)}><calcite-progress .label=${this.messages.loading} type=indeterminate></calcite-progress></div>`; const inputClearButton = html`<button .ariaLabel=${this.messages.clear} class=${safeClassMap(CSS.clearButton)} .disabled=${this.disabled || this.readOnly} @click=${this.clearInputValue} tabindex=-1 title=${this.messages.clear ?? nothing} type=button><calcite-icon .icon=${ICONS.close} .scale=${getIconScale(this.scale)}></calcite-icon></button>`; const iconEl = html`<calcite-icon class=${safeClassMap(CSS.inputIcon)} .flipRtl=${this.iconFlipRtl} .icon=${this.requestedIcon} .scale=${getIconScale(this.scale)}></calcite-icon>`; const isHorizontalNumberButton = this.numberButtonType === "horizontal"; const numberButtonsHorizontalUp = html`<button aria-hidden=true class=${safeClassMap({ [CSS.numberButtonItem]: true, [CSS.buttonItemHorizontal]: isHorizontalNumberButton })} data-adjustment=${DIRECTION.up} data-testid=number-button-up .disabled=${this.disabled || this.readOnly} @pointerdown=${this.numberButtonPointerDownHandler} @pointerout=${this.numberButtonPointerUpAndOutHandler} @pointerup=${this.numberButtonPointerUpAndOutHandler} tabindex=-1 type=button><calcite-icon .icon=${ICONS.chevronUp} .scale=${getIconScale(this.scale)}></calcite-icon></button>`; const numberButtonsHorizontalDown = html`<button aria-hidden=true class=${safeClassMap({ [CSS.numberButtonItem]: true, [CSS.buttonItemHorizontal]: isHorizontalNumberButton })} data-adjustment=${DIRECTION.down} data-testid=number-button-down .disabled=${this.disabled || this.readOnly} @pointerdown=${this.numberButtonPointerDownHandler} @pointerout=${this.numberButtonPointerUpAndOutHandler} @pointerup=${this.numberButtonPointerUpAndOutHandler} tabindex=-1 type=button><calcite-icon .icon=${ICONS.chevronDown} .scale=${getIconScale(this.scale)}></calcite-icon></button>`; const numberButtonsVertical = html`<div class=${safeClassMap(CSS.numberButtonWrapper)}>${numberButtonsHorizontalUp}${numberButtonsHorizontalDown}</div>`; const prefixText = html`<div class=${safeClassMap(CSS.prefix)}>${this.prefixText}</div>`; const suffixText = html`<div class=${safeClassMap(CSS.suffix)}>${this.suffixText}</div>`; const autofocus = this.el.autofocus; const enterKeyHint = this.el.enterKeyHint; const inputMode = this.el.inputMode; const localeNumberInput = this.type === "number" ? keyed("localized-input", html`<input accept=${this.accept ?? nothing} aria-errormessage=${IDS.validationMessage} .ariaInvalid=${this.status === "invalid"} .ariaLabel=${getLabelText(this)} autocomplete=${this.autocomplete ?? nothing} .autofocus=${autofocus} value=${this.defaultValue ?? nothing} .disabled=${this.disabled ? true : null} enterkeyhint=${enterKeyHint ?? nothing} inputmode=${inputMode ?? nothing} maxlength=${this.maxLength ?? nothing} minlength=${this.minLength ?? nothing} .multiple=${this.multiple} name=${nothing} @blur=${this.inputBlurHandler} @focus=${this.inputFocusHandler} @input=${this.inputNumberInputHandler} @keydown=${this.inputNumberKeyDownHandler} @keyup=${this.inputKeyUpHandler} pattern=${this.pattern ?? nothing} placeholder=${(this.placeholder || "") ?? nothing} .readOnly=${this.readOnly} .required=${this.required} type=text .value=${live(this.displayedValue ?? "")} ${ref(this.childNumberRef)}>`) : null; const childEl = this.type !== "number" ? html`<input accept=${this.accept ?? nothing} aria-errormessage=${IDS.validationMessage} .ariaInvalid=${this.status === "invalid"} .ariaLabel=${getLabelText(this)} autocomplete=${this.autocomplete ?? nothing} .autofocus=${autofocus} class=${safeClassMap({ [CSS.editingEnabled]: this.editingEnabled, [CSS.inlineChild]: !!this.inlineEditableEl })} value=${this.defaultValue ?? nothing} .disabled=${this.disabled ? true : null} enterkeyhint=${enterKeyHint ?? nothing} inputmode=${inputMode ?? nothing} max=${this.maxString ?? nothing} maxlength=${this.maxLength ?? nothing} min=${this.minString ?? nothing} minlength=${this.minLength ?? nothing} .multiple=${this.multiple} name=${this.name ?? nothing} @blur=${this.inputBlurHandler} @focus=${this.inputFocusHandler} @input=${this.inputInputHandler} @keydown=${this.inputKeyDownHandler} @keyup=${this.inputKeyUpHandler} pattern=${this.pattern ?? nothing} placeholder=${(this.placeholder || "") ?? nothing} .readOnly=${this.readOnly} .required=${this.required ? true : null} spellcheck=${this.el.spellcheck ?? nothing} step=${this.step ?? nothing} tabindex=${(this.disabled || this.inlineEditableEl && !this.editingEnabled ? -1 : null) ?? nothing} type=${this.type ?? nothing} .value=${live(this.value ?? "")} ${ref( this.childRef /* using unknown to workaround Lumina dynamic ref type issue */ )}>` : null; return this.interactiveContainer({ disabled: this.disabled, children: html`${this.labelText && InternalLabel({ labelText: this.labelText, onClick: this.onLabelClick, required: this.required, tooltipText: this.messages.required }) || ""}<div class=${safeClassMap({ [CSS.inputWrapper]: true, [CSS_UTILITY.rtl]: dir === "rtl", [CSS.hasSuffix]: this.suffixText, [CSS.hasPrefix]: this.prefixText })} ${ref(this.inputWrapperRef)}>${this.type === "number" && this.numberButtonType === "horizontal" && !this.readOnly ? numberButtonsHorizontalDown : null}${this.prefixText ? prefixText : null}<div class=${safeClassMap(CSS.wrapper)}>${localeNumberInput}${childEl}${this.isClearable ? inputClearButton : null}${this.requestedIcon ? iconEl : null}${this.loading ? loader : null}</div><div class=${safeClassMap(CSS.actionWrapper)} ${ref(this.actionWrapperRef)}><slot name=${SLOTS.action}></slot></div>${this.type === "number" && this.numberButtonType === "vertical" && !this.readOnly ? numberButtonsVertical : null}${this.suffixText ? suffixText : null}${this.type === "number" && this.numberButtonType === "horizontal" && !this.readOnly ? numberButtonsHorizontalUp : null}</div>${this.validationMessage && this.status === "invalid" ? Validation({ icon: this.validationIcon, id: IDS.validationMessage, message: this.validationMessage, scale: this.scale, status: this.status }) : null}` }); } } customElement("calcite-input", Input); export { Input };