input.js 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  1. /*!
  2. * All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. * See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
  4. * v1.0.0-beta.82
  5. */
  6. import { Component, Element, Event, h, Host, Method, Prop, State, Watch } from "@stencil/core";
  7. import { getElementDir, getElementProp, getSlotted, setRequestedIcon } from "../../utils/dom";
  8. import { CSS, INPUT_TYPE_ICONS, SLOTS, TEXT } from "./resources";
  9. import { connectLabel, disconnectLabel, getLabelText } from "../../utils/label";
  10. import { connectForm, disconnectForm, HiddenFormInputSlot, submitForm } from "../../utils/form";
  11. import { getDecimalSeparator, delocalizeNumberString, localizeNumberString } from "../../utils/locale";
  12. import { numberKeys } from "../../utils/key";
  13. import { isValidNumber, parseNumberString, sanitizeNumberString } from "../../utils/number";
  14. import { CSS_UTILITY, TEXT as COMMON_TEXT } from "../../utils/resources";
  15. import { decimalPlaces } from "../../utils/math";
  16. import { createObserver } from "../../utils/observers";
  17. import { updateHostInteraction } from "../../utils/interactive";
  18. /**
  19. * @slot action - A slot for positioning a button next to an input
  20. */
  21. export class Input {
  22. constructor() {
  23. //--------------------------------------------------------------------------
  24. //
  25. // Properties
  26. //
  27. //--------------------------------------------------------------------------
  28. /** specify the alignment of the value of the input */
  29. this.alignment = "start";
  30. /** should the input autofocus */
  31. this.autofocus = false;
  32. /** optionally display a clear button that displays when field has a value
  33. * shows by default for search, time, date
  34. * will not display for type="textarea" */
  35. this.clearable = false;
  36. /** is the input disabled */
  37. this.disabled = false;
  38. /** for number values, displays the locale's group separator */
  39. this.groupSeparator = false;
  40. /** when true, the component will not be visible */
  41. this.hidden = false;
  42. /**
  43. * string to override English loading text
  44. * @default "Loading"
  45. */
  46. this.intlLoading = COMMON_TEXT.loading;
  47. /** flip the icon in rtl */
  48. this.iconFlipRtl = false;
  49. /** specify if the input is in loading state */
  50. this.loading = false;
  51. /** BCP 47 language tag for desired language and country format */
  52. this.locale = document.documentElement.lang || "en";
  53. /**
  54. * Toggles locale formatting for numbers.
  55. * @internal
  56. */
  57. this.localeFormat = false;
  58. /** specify the placement of the number buttons */
  59. this.numberButtonType = "vertical";
  60. /** When true, a field cannot be modified. */
  61. this.readOnly = false;
  62. /** is the input required */
  63. this.required = false;
  64. /** specify the scale of the input, defaults to m */
  65. this.scale = "m";
  66. /** specify the status of the input field, determines message and icons */
  67. this.status = "idle";
  68. /** @internal adds inline styles for text input when slotted in calcite-inline-editable */
  69. this.editingEnabled = false;
  70. /**
  71. * specify the input type
  72. *
  73. * Note that the following types add type-specific icons by default: `date`, `email`, `password`, `search`, `tel`, `time`
  74. */
  75. this.type = "text";
  76. /** input value */
  77. this.value = "";
  78. /** keep track of the rendered child type */
  79. this.childElType = "input";
  80. this.previousValueOrigin = "initial";
  81. this.mutationObserver = createObserver("mutation", () => this.setDisabledAction());
  82. this.userChangedValue = false;
  83. //--------------------------------------------------------------------------
  84. //
  85. // Private Methods
  86. //
  87. //--------------------------------------------------------------------------
  88. this.keyDownHandler = (event) => {
  89. if (this.readOnly || this.disabled) {
  90. return;
  91. }
  92. if (this.isClearable && event.key === "Escape") {
  93. this.clearInputValue(event);
  94. event.preventDefault();
  95. }
  96. if (event.key === "Enter" && !event.defaultPrevented) {
  97. submitForm(this);
  98. }
  99. };
  100. this.clearInputValue = (nativeEvent) => {
  101. this.setValue({
  102. committing: true,
  103. nativeEvent,
  104. origin: "user",
  105. value: ""
  106. });
  107. };
  108. this.emitChangeIfUserModified = () => {
  109. if (this.previousValueOrigin === "user" && this.value !== this.previousEmittedValue) {
  110. this.calciteInputChange.emit();
  111. }
  112. this.previousEmittedValue = this.value;
  113. };
  114. this.inputBlurHandler = () => {
  115. this.calciteInputBlur.emit({
  116. element: this.childEl,
  117. value: this.value
  118. });
  119. this.emitChangeIfUserModified();
  120. };
  121. this.inputFocusHandler = (event) => {
  122. const slottedActionEl = getSlotted(this.el, "action");
  123. if (event.target !== slottedActionEl) {
  124. this.setFocus();
  125. }
  126. this.calciteInputFocus.emit({
  127. element: this.childEl,
  128. value: this.value
  129. });
  130. };
  131. this.inputInputHandler = (nativeEvent) => {
  132. if (this.disabled || this.readOnly) {
  133. return;
  134. }
  135. this.setValue({
  136. nativeEvent,
  137. origin: "user",
  138. value: nativeEvent.target.value
  139. });
  140. };
  141. this.inputKeyDownHandler = (event) => {
  142. if (this.disabled || this.readOnly) {
  143. return;
  144. }
  145. if (event.key === "Enter") {
  146. this.emitChangeIfUserModified();
  147. }
  148. };
  149. this.inputNumberInputHandler = (nativeEvent) => {
  150. if (this.disabled || this.readOnly) {
  151. return;
  152. }
  153. const value = nativeEvent.target.value;
  154. const delocalizedValue = delocalizeNumberString(value, this.locale);
  155. if (nativeEvent.inputType === "insertFromPaste") {
  156. if (!isValidNumber(delocalizedValue)) {
  157. nativeEvent.preventDefault();
  158. }
  159. this.setValue({
  160. nativeEvent,
  161. origin: "user",
  162. value: parseNumberString(delocalizedValue)
  163. });
  164. this.childNumberEl.value = this.localizedValue;
  165. }
  166. else {
  167. this.setValue({
  168. nativeEvent,
  169. origin: "user",
  170. value: delocalizedValue
  171. });
  172. }
  173. };
  174. this.inputNumberKeyDownHandler = (event) => {
  175. if (this.type !== "number" || this.disabled || this.readOnly) {
  176. return;
  177. }
  178. if (event.key === "ArrowUp") {
  179. /* prevent default behavior of moving cursor to the beginning of the input when holding down ArrowUp */
  180. event.preventDefault();
  181. this.nudgeNumberValue("up", event);
  182. return;
  183. }
  184. if (event.key === "ArrowDown") {
  185. this.nudgeNumberValue("down", event);
  186. return;
  187. }
  188. const supportedKeys = [
  189. ...numberKeys,
  190. "ArrowLeft",
  191. "ArrowRight",
  192. "Backspace",
  193. "Delete",
  194. "Enter",
  195. "Escape",
  196. "Tab"
  197. ];
  198. if (event.altKey || event.ctrlKey || event.metaKey) {
  199. return;
  200. }
  201. const isShiftTabEvent = event.shiftKey && event.key === "Tab";
  202. if (supportedKeys.includes(event.key) && (!event.shiftKey || isShiftTabEvent)) {
  203. if (event.key === "Enter") {
  204. this.emitChangeIfUserModified();
  205. }
  206. return;
  207. }
  208. const decimalSeparator = getDecimalSeparator(this.locale);
  209. if (event.key === decimalSeparator) {
  210. if (!this.value && !this.childNumberEl.value) {
  211. return;
  212. }
  213. if (this.value && this.childNumberEl.value.indexOf(decimalSeparator) === -1) {
  214. return;
  215. }
  216. }
  217. if (/[eE]/.test(event.key)) {
  218. if (!this.value && !this.childNumberEl.value) {
  219. return;
  220. }
  221. if (this.value && !/[eE]/.test(this.childNumberEl.value)) {
  222. return;
  223. }
  224. }
  225. if (event.key === "-") {
  226. if (!this.value && !this.childNumberEl.value) {
  227. return;
  228. }
  229. if (this.value && this.childNumberEl.value.split("-").length <= 2) {
  230. return;
  231. }
  232. }
  233. event.preventDefault();
  234. };
  235. this.nudgeNumberValue = (direction, nativeEvent) => {
  236. if ((nativeEvent instanceof KeyboardEvent && nativeEvent.repeat) || this.type !== "number") {
  237. return;
  238. }
  239. const inputMax = this.maxString ? parseFloat(this.maxString) : null;
  240. const inputMin = this.minString ? parseFloat(this.minString) : null;
  241. const valueNudgeDelayInMs = 100;
  242. this.incrementOrDecrementNumberValue(direction, inputMax, inputMin, nativeEvent);
  243. if (this.nudgeNumberValueIntervalId) {
  244. window.clearInterval(this.nudgeNumberValueIntervalId);
  245. }
  246. let firstValueNudge = true;
  247. this.nudgeNumberValueIntervalId = window.setInterval(() => {
  248. if (firstValueNudge) {
  249. firstValueNudge = false;
  250. return;
  251. }
  252. this.incrementOrDecrementNumberValue(direction, inputMax, inputMin, nativeEvent);
  253. }, valueNudgeDelayInMs);
  254. };
  255. this.numberButtonMouseUpAndMouseOutHandler = () => {
  256. window.clearInterval(this.nudgeNumberValueIntervalId);
  257. };
  258. this.numberButtonMouseDownHandler = (event) => {
  259. event.preventDefault();
  260. const direction = event.target.dataset.adjustment;
  261. this.nudgeNumberValue(direction, event);
  262. };
  263. this.setChildElRef = (el) => {
  264. this.childEl = el;
  265. };
  266. this.setChildNumberElRef = (el) => {
  267. this.childNumberEl = el;
  268. };
  269. this.setInputValue = (newInputValue) => {
  270. if (this.type === "text" && !this.childEl) {
  271. return;
  272. }
  273. if (this.type === "number" && !this.childNumberEl) {
  274. return;
  275. }
  276. this[`child${this.type === "number" ? "Number" : ""}El`].value = newInputValue;
  277. };
  278. this.setPreviousEmittedValue = (newPreviousEmittedValue) => {
  279. this.previousEmittedValue =
  280. this.type === "number"
  281. ? isValidNumber(newPreviousEmittedValue)
  282. ? newPreviousEmittedValue
  283. : ""
  284. : newPreviousEmittedValue;
  285. };
  286. this.setPreviousValue = (newPreviousValue) => {
  287. this.previousValue =
  288. this.type === "number"
  289. ? isValidNumber(newPreviousValue)
  290. ? newPreviousValue
  291. : ""
  292. : newPreviousValue;
  293. };
  294. this.setValue = ({ committing = false, nativeEvent, origin, previousValue, value }) => {
  295. const previousLocalizedValue = this.type === "number"
  296. ? localizeNumberString(this.previousValue, this.locale, this.groupSeparator)
  297. : "";
  298. const sanitizedValue = this.type === "number" ? sanitizeNumberString(value) : value;
  299. const newValue = this.type === "number" && value && !sanitizedValue
  300. ? isValidNumber(this.previousValue)
  301. ? this.previousValue
  302. : ""
  303. : sanitizedValue;
  304. const newLocalizedValue = this.type === "number"
  305. ? localizeNumberString(newValue, this.locale, this.groupSeparator)
  306. : "";
  307. this.setPreviousValue(previousValue || this.value);
  308. this.previousValueOrigin = origin;
  309. this.userChangedValue = origin === "user" && this.value !== newValue;
  310. this.value = newValue;
  311. if (this.type === "number") {
  312. this.localizedValue = newLocalizedValue;
  313. }
  314. if (origin === "direct") {
  315. this.setInputValue(this.type === "number" ? newLocalizedValue : newValue);
  316. }
  317. if (nativeEvent) {
  318. const calciteInputInputEvent = this.calciteInputInput.emit({
  319. element: this.childEl,
  320. nativeEvent,
  321. value: this.value
  322. });
  323. if (calciteInputInputEvent.defaultPrevented) {
  324. this.value = this.previousValue;
  325. this.localizedValue = previousLocalizedValue;
  326. }
  327. else if (committing) {
  328. this.emitChangeIfUserModified();
  329. }
  330. }
  331. };
  332. this.inputKeyUpHandler = () => {
  333. window.clearInterval(this.nudgeNumberValueIntervalId);
  334. };
  335. }
  336. disabledWatcher() {
  337. this.setDisabledAction();
  338. }
  339. /** watcher to update number-to-string for max */
  340. maxWatcher() {
  341. var _a;
  342. this.maxString = ((_a = this.max) === null || _a === void 0 ? void 0 : _a.toString()) || null;
  343. }
  344. /** watcher to update number-to-string for min */
  345. minWatcher() {
  346. var _a;
  347. this.minString = ((_a = this.min) === null || _a === void 0 ? void 0 : _a.toString()) || null;
  348. }
  349. valueWatcher(newValue, previousValue) {
  350. if (!this.userChangedValue) {
  351. this.setValue({
  352. origin: "direct",
  353. previousValue,
  354. value: newValue == null || newValue == ""
  355. ? ""
  356. : this.type === "number"
  357. ? isValidNumber(newValue)
  358. ? newValue
  359. : this.previousValue || ""
  360. : newValue
  361. });
  362. this.warnAboutInvalidNumberValue(newValue);
  363. }
  364. this.userChangedValue = false;
  365. }
  366. updateRequestedIcon() {
  367. this.requestedIcon = setRequestedIcon(INPUT_TYPE_ICONS, this.icon, this.type);
  368. }
  369. get isClearable() {
  370. return !this.isTextarea && (this.clearable || this.type === "search") && this.value.length > 0;
  371. }
  372. get isTextarea() {
  373. return this.childElType === "textarea";
  374. }
  375. //--------------------------------------------------------------------------
  376. //
  377. // Lifecycle
  378. //
  379. //--------------------------------------------------------------------------
  380. connectedCallback() {
  381. var _a;
  382. this.scale = getElementProp(this.el, "scale", this.scale);
  383. this.status = getElementProp(this.el, "status", this.status);
  384. this.inlineEditableEl = this.el.closest("calcite-inline-editable");
  385. if (this.inlineEditableEl) {
  386. this.editingEnabled = this.inlineEditableEl.editingEnabled || false;
  387. }
  388. this.setPreviousEmittedValue(this.value);
  389. this.setPreviousValue(this.value);
  390. if (this.type === "number") {
  391. this.warnAboutInvalidNumberValue(this.value);
  392. this.setValue({
  393. origin: "connected",
  394. value: isValidNumber(this.value) ? this.value : ""
  395. });
  396. }
  397. connectLabel(this);
  398. connectForm(this);
  399. (_a = this.mutationObserver) === null || _a === void 0 ? void 0 : _a.observe(this.el, { childList: true });
  400. this.setDisabledAction();
  401. }
  402. disconnectedCallback() {
  403. var _a;
  404. disconnectLabel(this);
  405. disconnectForm(this);
  406. (_a = this.mutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
  407. }
  408. componentWillLoad() {
  409. var _a, _b;
  410. this.childElType = this.type === "textarea" ? "textarea" : "input";
  411. this.maxString = (_a = this.max) === null || _a === void 0 ? void 0 : _a.toString();
  412. this.minString = (_b = this.min) === null || _b === void 0 ? void 0 : _b.toString();
  413. this.requestedIcon = setRequestedIcon(INPUT_TYPE_ICONS, this.icon, this.type);
  414. }
  415. componentShouldUpdate(newValue, oldValue, property) {
  416. if (this.type === "number" && property === "value" && newValue && !isValidNumber(newValue)) {
  417. this.setValue({
  418. origin: "reset",
  419. value: oldValue
  420. });
  421. return false;
  422. }
  423. return true;
  424. }
  425. componentDidRender() {
  426. updateHostInteraction(this);
  427. }
  428. //--------------------------------------------------------------------------
  429. //
  430. // Public Methods
  431. //
  432. //--------------------------------------------------------------------------
  433. /** Sets focus on the component. */
  434. async setFocus() {
  435. var _a, _b;
  436. if (this.type === "number") {
  437. (_a = this.childNumberEl) === null || _a === void 0 ? void 0 : _a.focus();
  438. }
  439. else {
  440. (_b = this.childEl) === null || _b === void 0 ? void 0 : _b.focus();
  441. }
  442. }
  443. onLabelClick() {
  444. this.setFocus();
  445. }
  446. incrementOrDecrementNumberValue(direction, inputMax, inputMin, nativeEvent) {
  447. const { value } = this;
  448. const inputStep = this.step === "any" ? 1 : Math.abs(this.step || 1);
  449. const inputVal = value && value !== "" ? parseFloat(value) : 0;
  450. const adjustment = direction === "up" ? 1 : -1;
  451. const nudgedValue = inputVal + inputStep * adjustment;
  452. const finalValue = (typeof inputMin === "number" && !isNaN(inputMin) && nudgedValue < inputMin) ||
  453. (typeof inputMax === "number" && !isNaN(inputMax) && nudgedValue > inputMax)
  454. ? inputVal
  455. : nudgedValue;
  456. const inputValPlaces = decimalPlaces(inputVal);
  457. const inputStepPlaces = decimalPlaces(inputStep);
  458. this.setValue({
  459. committing: true,
  460. nativeEvent,
  461. origin: "user",
  462. value: finalValue.toFixed(Math.max(inputValPlaces, inputStepPlaces))
  463. });
  464. }
  465. onFormReset() {
  466. this.setValue({
  467. origin: "reset",
  468. value: this.defaultValue
  469. });
  470. }
  471. syncHiddenFormInput(input) {
  472. var _a, _b, _c, _d;
  473. if (this.type === "number") {
  474. input.type = "number";
  475. input.min = (_b = (_a = this.min) === null || _a === void 0 ? void 0 : _a.toString(10)) !== null && _b !== void 0 ? _b : "";
  476. input.max = (_d = (_c = this.max) === null || _c === void 0 ? void 0 : _c.toString(10)) !== null && _d !== void 0 ? _d : "";
  477. }
  478. else if (this.type === "text") {
  479. input.type = "text";
  480. if (this.minLength != null) {
  481. input.minLength = this.minLength;
  482. }
  483. if (this.maxLength != null) {
  484. input.maxLength = this.maxLength;
  485. }
  486. }
  487. else if (this.type === "password") {
  488. input.type = "password";
  489. }
  490. }
  491. setDisabledAction() {
  492. const slottedActionEl = getSlotted(this.el, "action");
  493. if (!slottedActionEl) {
  494. return;
  495. }
  496. this.disabled
  497. ? slottedActionEl.setAttribute("disabled", "")
  498. : slottedActionEl.removeAttribute("disabled");
  499. }
  500. warnAboutInvalidNumberValue(value) {
  501. if (this.type === "number" && value && !isValidNumber(value)) {
  502. console.warn(`The specified value "${value}" cannot be parsed, or is out of range.`);
  503. }
  504. }
  505. // --------------------------------------------------------------------------
  506. //
  507. // Render Methods
  508. //
  509. // --------------------------------------------------------------------------
  510. render() {
  511. const dir = getElementDir(this.el);
  512. const loader = (h("div", { class: CSS.loader },
  513. h("calcite-progress", { label: this.intlLoading, type: "indeterminate" })));
  514. const inputClearButton = (h("button", { "aria-label": this.intlClear || TEXT.clear, class: CSS.clearButton, disabled: this.disabled || this.readOnly, onClick: this.clearInputValue, tabIndex: this.disabled ? -1 : 0, type: "button" },
  515. h("calcite-icon", { icon: "x", scale: "s" })));
  516. const iconEl = (h("calcite-icon", { class: CSS.inputIcon, flipRtl: this.iconFlipRtl, icon: this.requestedIcon, scale: "s" }));
  517. const isHorizontalNumberButton = this.numberButtonType === "horizontal";
  518. const numberButtonsHorizontalUp = (h("button", { class: {
  519. [CSS.numberButtonItem]: true,
  520. [CSS.buttonItemHorizontal]: isHorizontalNumberButton
  521. }, "data-adjustment": "up", disabled: this.disabled || this.readOnly, onMouseDown: this.numberButtonMouseDownHandler, onMouseOut: this.numberButtonMouseUpAndMouseOutHandler, onMouseUp: this.numberButtonMouseUpAndMouseOutHandler, tabIndex: -1, type: "button" },
  522. h("calcite-icon", { icon: "chevron-up", scale: "s" })));
  523. const numberButtonsHorizontalDown = (h("button", { class: {
  524. [CSS.numberButtonItem]: true,
  525. [CSS.buttonItemHorizontal]: isHorizontalNumberButton
  526. }, "data-adjustment": "down", disabled: this.disabled || this.readOnly, onMouseDown: this.numberButtonMouseDownHandler, onMouseOut: this.numberButtonMouseUpAndMouseOutHandler, onMouseUp: this.numberButtonMouseUpAndMouseOutHandler, tabIndex: -1, type: "button" },
  527. h("calcite-icon", { icon: "chevron-down", scale: "s" })));
  528. const numberButtonsVertical = (h("div", { class: CSS.numberButtonWrapper },
  529. numberButtonsHorizontalUp,
  530. numberButtonsHorizontalDown));
  531. const prefixText = h("div", { class: CSS.prefix }, this.prefixText);
  532. const suffixText = h("div", { class: CSS.suffix }, this.suffixText);
  533. const localeNumberInput = this.type === "number" ? (h("input", { "aria-label": getLabelText(this), autofocus: this.autofocus ? true : null, defaultValue: this.defaultValue, disabled: this.disabled ? true : null, enterKeyHint: this.el.enterKeyHint, inputMode: this.el.inputMode, key: "localized-input", maxLength: this.maxLength, minLength: this.minLength, name: undefined, onBlur: this.inputBlurHandler, onFocus: this.inputFocusHandler, onInput: this.inputNumberInputHandler, onKeyDown: this.inputNumberKeyDownHandler, onKeyUp: this.inputKeyUpHandler, placeholder: this.placeholder || "", readOnly: this.readOnly, ref: this.setChildNumberElRef, type: "text", value: this.localizedValue })) : null;
  534. const childEl = this.type !== "number"
  535. ? [
  536. h(this.childElType, { "aria-label": getLabelText(this), autofocus: this.autofocus ? true : null, class: {
  537. [CSS.editingEnabled]: this.editingEnabled,
  538. [CSS.inlineChild]: !!this.inlineEditableEl
  539. }, defaultValue: this.defaultValue, disabled: this.disabled ? true : null, enterKeyHint: this.el.enterKeyHint, inputMode: this.el.inputMode, max: this.maxString, maxLength: this.maxLength, min: this.minString, minLength: this.minLength, name: this.name, onBlur: this.inputBlurHandler, onFocus: this.inputFocusHandler, onInput: this.inputInputHandler, onKeyDown: this.inputKeyDownHandler, onKeyUp: this.inputKeyUpHandler, placeholder: this.placeholder || "", readOnly: this.readOnly, ref: this.setChildElRef, required: this.required ? true : null, step: this.step, tabIndex: this.disabled || (this.inlineEditableEl && !this.editingEnabled) ? -1 : null, type: this.type, value: this.value }),
  540. this.isTextarea ? (h("div", { class: CSS.resizeIconWrapper },
  541. h("calcite-icon", { icon: "chevron-down", scale: "s" }))) : null
  542. ]
  543. : null;
  544. return (h(Host, { onClick: this.inputFocusHandler, onKeyDown: this.keyDownHandler },
  545. h("div", { class: { [CSS.inputWrapper]: true, [CSS_UTILITY.rtl]: dir === "rtl" } },
  546. this.type === "number" && this.numberButtonType === "horizontal" && !this.readOnly
  547. ? numberButtonsHorizontalDown
  548. : null,
  549. this.prefixText ? prefixText : null,
  550. h("div", { class: CSS.wrapper },
  551. localeNumberInput,
  552. childEl,
  553. this.isClearable ? inputClearButton : null,
  554. this.requestedIcon ? iconEl : null,
  555. this.loading ? loader : null),
  556. h("div", { class: CSS.actionWrapper },
  557. h("slot", { name: SLOTS.action })),
  558. this.type === "number" && this.numberButtonType === "vertical" && !this.readOnly
  559. ? numberButtonsVertical
  560. : null,
  561. this.suffixText ? suffixText : null,
  562. this.type === "number" && this.numberButtonType === "horizontal" && !this.readOnly
  563. ? numberButtonsHorizontalUp
  564. : null,
  565. h(HiddenFormInputSlot, { component: this }))));
  566. }
  567. static get is() { return "calcite-input"; }
  568. static get encapsulation() { return "shadow"; }
  569. static get originalStyleUrls() { return {
  570. "$": ["input.scss"]
  571. }; }
  572. static get styleUrls() { return {
  573. "$": ["input.css"]
  574. }; }
  575. static get properties() { return {
  576. "alignment": {
  577. "type": "string",
  578. "mutable": false,
  579. "complexType": {
  580. "original": "Position",
  581. "resolved": "\"end\" | \"start\"",
  582. "references": {
  583. "Position": {
  584. "location": "import",
  585. "path": "../interfaces"
  586. }
  587. }
  588. },
  589. "required": false,
  590. "optional": false,
  591. "docs": {
  592. "tags": [],
  593. "text": "specify the alignment of the value of the input"
  594. },
  595. "attribute": "alignment",
  596. "reflect": true,
  597. "defaultValue": "\"start\""
  598. },
  599. "autofocus": {
  600. "type": "boolean",
  601. "mutable": false,
  602. "complexType": {
  603. "original": "boolean",
  604. "resolved": "boolean",
  605. "references": {}
  606. },
  607. "required": false,
  608. "optional": false,
  609. "docs": {
  610. "tags": [],
  611. "text": "should the input autofocus"
  612. },
  613. "attribute": "autofocus",
  614. "reflect": false,
  615. "defaultValue": "false"
  616. },
  617. "clearable": {
  618. "type": "boolean",
  619. "mutable": false,
  620. "complexType": {
  621. "original": "boolean",
  622. "resolved": "boolean",
  623. "references": {}
  624. },
  625. "required": false,
  626. "optional": false,
  627. "docs": {
  628. "tags": [],
  629. "text": "optionally display a clear button that displays when field has a value\nshows by default for search, time, date\nwill not display for type=\"textarea\""
  630. },
  631. "attribute": "clearable",
  632. "reflect": true,
  633. "defaultValue": "false"
  634. },
  635. "disabled": {
  636. "type": "boolean",
  637. "mutable": false,
  638. "complexType": {
  639. "original": "boolean",
  640. "resolved": "boolean",
  641. "references": {}
  642. },
  643. "required": false,
  644. "optional": false,
  645. "docs": {
  646. "tags": [],
  647. "text": "is the input disabled"
  648. },
  649. "attribute": "disabled",
  650. "reflect": true,
  651. "defaultValue": "false"
  652. },
  653. "groupSeparator": {
  654. "type": "boolean",
  655. "mutable": false,
  656. "complexType": {
  657. "original": "boolean",
  658. "resolved": "boolean",
  659. "references": {}
  660. },
  661. "required": false,
  662. "optional": false,
  663. "docs": {
  664. "tags": [],
  665. "text": "for number values, displays the locale's group separator"
  666. },
  667. "attribute": "group-separator",
  668. "reflect": false,
  669. "defaultValue": "false"
  670. },
  671. "hidden": {
  672. "type": "boolean",
  673. "mutable": false,
  674. "complexType": {
  675. "original": "boolean",
  676. "resolved": "boolean",
  677. "references": {}
  678. },
  679. "required": false,
  680. "optional": false,
  681. "docs": {
  682. "tags": [],
  683. "text": "when true, the component will not be visible"
  684. },
  685. "attribute": "hidden",
  686. "reflect": false,
  687. "defaultValue": "false"
  688. },
  689. "icon": {
  690. "type": "any",
  691. "mutable": false,
  692. "complexType": {
  693. "original": "string | boolean",
  694. "resolved": "boolean | string",
  695. "references": {}
  696. },
  697. "required": false,
  698. "optional": false,
  699. "docs": {
  700. "tags": [],
  701. "text": "when used as a boolean set to true, show a default recommended icon for certain\ninput types (tel, password, email, date, time, search). You can also pass a\ncalcite-ui-icon name to this prop to display a requested icon for any input type"
  702. },
  703. "attribute": "icon",
  704. "reflect": true
  705. },
  706. "intlClear": {
  707. "type": "string",
  708. "mutable": false,
  709. "complexType": {
  710. "original": "string",
  711. "resolved": "string",
  712. "references": {}
  713. },
  714. "required": false,
  715. "optional": true,
  716. "docs": {
  717. "tags": [],
  718. "text": "A text label that will appear on the clear button for screen readers."
  719. },
  720. "attribute": "intl-clear",
  721. "reflect": false
  722. },
  723. "intlLoading": {
  724. "type": "string",
  725. "mutable": false,
  726. "complexType": {
  727. "original": "string",
  728. "resolved": "string",
  729. "references": {}
  730. },
  731. "required": false,
  732. "optional": true,
  733. "docs": {
  734. "tags": [{
  735. "name": "default",
  736. "text": "\"Loading\""
  737. }],
  738. "text": "string to override English loading text"
  739. },
  740. "attribute": "intl-loading",
  741. "reflect": false,
  742. "defaultValue": "COMMON_TEXT.loading"
  743. },
  744. "iconFlipRtl": {
  745. "type": "boolean",
  746. "mutable": false,
  747. "complexType": {
  748. "original": "boolean",
  749. "resolved": "boolean",
  750. "references": {}
  751. },
  752. "required": false,
  753. "optional": false,
  754. "docs": {
  755. "tags": [],
  756. "text": "flip the icon in rtl"
  757. },
  758. "attribute": "icon-flip-rtl",
  759. "reflect": true,
  760. "defaultValue": "false"
  761. },
  762. "label": {
  763. "type": "string",
  764. "mutable": false,
  765. "complexType": {
  766. "original": "string",
  767. "resolved": "string",
  768. "references": {}
  769. },
  770. "required": false,
  771. "optional": true,
  772. "docs": {
  773. "tags": [],
  774. "text": "Applies to the aria-label attribute on the button or hyperlink"
  775. },
  776. "attribute": "label",
  777. "reflect": false
  778. },
  779. "loading": {
  780. "type": "boolean",
  781. "mutable": false,
  782. "complexType": {
  783. "original": "boolean",
  784. "resolved": "boolean",
  785. "references": {}
  786. },
  787. "required": false,
  788. "optional": false,
  789. "docs": {
  790. "tags": [],
  791. "text": "specify if the input is in loading state"
  792. },
  793. "attribute": "loading",
  794. "reflect": true,
  795. "defaultValue": "false"
  796. },
  797. "locale": {
  798. "type": "string",
  799. "mutable": false,
  800. "complexType": {
  801. "original": "string",
  802. "resolved": "string",
  803. "references": {}
  804. },
  805. "required": false,
  806. "optional": true,
  807. "docs": {
  808. "tags": [],
  809. "text": "BCP 47 language tag for desired language and country format"
  810. },
  811. "attribute": "locale",
  812. "reflect": false,
  813. "defaultValue": "document.documentElement.lang || \"en\""
  814. },
  815. "localeFormat": {
  816. "type": "boolean",
  817. "mutable": false,
  818. "complexType": {
  819. "original": "boolean",
  820. "resolved": "boolean",
  821. "references": {}
  822. },
  823. "required": false,
  824. "optional": false,
  825. "docs": {
  826. "tags": [{
  827. "name": "internal",
  828. "text": undefined
  829. }],
  830. "text": "Toggles locale formatting for numbers."
  831. },
  832. "attribute": "locale-format",
  833. "reflect": false,
  834. "defaultValue": "false"
  835. },
  836. "max": {
  837. "type": "number",
  838. "mutable": false,
  839. "complexType": {
  840. "original": "number",
  841. "resolved": "number",
  842. "references": {}
  843. },
  844. "required": false,
  845. "optional": true,
  846. "docs": {
  847. "tags": [],
  848. "text": "input max"
  849. },
  850. "attribute": "max",
  851. "reflect": true
  852. },
  853. "min": {
  854. "type": "number",
  855. "mutable": false,
  856. "complexType": {
  857. "original": "number",
  858. "resolved": "number",
  859. "references": {}
  860. },
  861. "required": false,
  862. "optional": true,
  863. "docs": {
  864. "tags": [],
  865. "text": "input min"
  866. },
  867. "attribute": "min",
  868. "reflect": true
  869. },
  870. "maxlength": {
  871. "type": "number",
  872. "mutable": false,
  873. "complexType": {
  874. "original": "number",
  875. "resolved": "number",
  876. "references": {}
  877. },
  878. "required": false,
  879. "optional": true,
  880. "docs": {
  881. "tags": [{
  882. "name": "deprecated",
  883. "text": "use maxLength instead"
  884. }],
  885. "text": "Maximum length of text input."
  886. },
  887. "attribute": "maxlength",
  888. "reflect": true
  889. },
  890. "maxLength": {
  891. "type": "number",
  892. "mutable": false,
  893. "complexType": {
  894. "original": "number",
  895. "resolved": "number",
  896. "references": {}
  897. },
  898. "required": false,
  899. "optional": true,
  900. "docs": {
  901. "tags": [],
  902. "text": "Maximum length of the input value"
  903. },
  904. "attribute": "max-length",
  905. "reflect": true
  906. },
  907. "minLength": {
  908. "type": "number",
  909. "mutable": false,
  910. "complexType": {
  911. "original": "number",
  912. "resolved": "number",
  913. "references": {}
  914. },
  915. "required": false,
  916. "optional": true,
  917. "docs": {
  918. "tags": [],
  919. "text": "Minimum length of the text input"
  920. },
  921. "attribute": "min-length",
  922. "reflect": true
  923. },
  924. "name": {
  925. "type": "string",
  926. "mutable": false,
  927. "complexType": {
  928. "original": "string",
  929. "resolved": "string",
  930. "references": {}
  931. },
  932. "required": false,
  933. "optional": false,
  934. "docs": {
  935. "tags": [],
  936. "text": "The name of the input"
  937. },
  938. "attribute": "name",
  939. "reflect": true
  940. },
  941. "numberButtonType": {
  942. "type": "string",
  943. "mutable": false,
  944. "complexType": {
  945. "original": "InputPlacement",
  946. "resolved": "\"horizontal\" | \"none\" | \"vertical\"",
  947. "references": {
  948. "InputPlacement": {
  949. "location": "import",
  950. "path": "./interfaces"
  951. }
  952. }
  953. },
  954. "required": false,
  955. "optional": true,
  956. "docs": {
  957. "tags": [],
  958. "text": "specify the placement of the number buttons"
  959. },
  960. "attribute": "number-button-type",
  961. "reflect": true,
  962. "defaultValue": "\"vertical\""
  963. },
  964. "placeholder": {
  965. "type": "string",
  966. "mutable": false,
  967. "complexType": {
  968. "original": "string",
  969. "resolved": "string",
  970. "references": {}
  971. },
  972. "required": false,
  973. "optional": false,
  974. "docs": {
  975. "tags": [],
  976. "text": "explicitly whitelist placeholder attribute"
  977. },
  978. "attribute": "placeholder",
  979. "reflect": false
  980. },
  981. "prefixText": {
  982. "type": "string",
  983. "mutable": false,
  984. "complexType": {
  985. "original": "string",
  986. "resolved": "string",
  987. "references": {}
  988. },
  989. "required": false,
  990. "optional": true,
  991. "docs": {
  992. "tags": [],
  993. "text": "optionally add prefix"
  994. },
  995. "attribute": "prefix-text",
  996. "reflect": false
  997. },
  998. "readOnly": {
  999. "type": "boolean",
  1000. "mutable": false,
  1001. "complexType": {
  1002. "original": "boolean",
  1003. "resolved": "boolean",
  1004. "references": {}
  1005. },
  1006. "required": false,
  1007. "optional": false,
  1008. "docs": {
  1009. "tags": [],
  1010. "text": "When true, a field cannot be modified."
  1011. },
  1012. "attribute": "read-only",
  1013. "reflect": false,
  1014. "defaultValue": "false"
  1015. },
  1016. "required": {
  1017. "type": "boolean",
  1018. "mutable": false,
  1019. "complexType": {
  1020. "original": "boolean",
  1021. "resolved": "boolean",
  1022. "references": {}
  1023. },
  1024. "required": false,
  1025. "optional": false,
  1026. "docs": {
  1027. "tags": [],
  1028. "text": "is the input required"
  1029. },
  1030. "attribute": "required",
  1031. "reflect": false,
  1032. "defaultValue": "false"
  1033. },
  1034. "scale": {
  1035. "type": "string",
  1036. "mutable": true,
  1037. "complexType": {
  1038. "original": "Scale",
  1039. "resolved": "\"l\" | \"m\" | \"s\"",
  1040. "references": {
  1041. "Scale": {
  1042. "location": "import",
  1043. "path": "../interfaces"
  1044. }
  1045. }
  1046. },
  1047. "required": false,
  1048. "optional": false,
  1049. "docs": {
  1050. "tags": [],
  1051. "text": "specify the scale of the input, defaults to m"
  1052. },
  1053. "attribute": "scale",
  1054. "reflect": true,
  1055. "defaultValue": "\"m\""
  1056. },
  1057. "status": {
  1058. "type": "string",
  1059. "mutable": true,
  1060. "complexType": {
  1061. "original": "Status",
  1062. "resolved": "\"idle\" | \"invalid\" | \"valid\"",
  1063. "references": {
  1064. "Status": {
  1065. "location": "import",
  1066. "path": "../interfaces"
  1067. }
  1068. }
  1069. },
  1070. "required": false,
  1071. "optional": false,
  1072. "docs": {
  1073. "tags": [],
  1074. "text": "specify the status of the input field, determines message and icons"
  1075. },
  1076. "attribute": "status",
  1077. "reflect": true,
  1078. "defaultValue": "\"idle\""
  1079. },
  1080. "step": {
  1081. "type": "any",
  1082. "mutable": false,
  1083. "complexType": {
  1084. "original": "number | \"any\"",
  1085. "resolved": "\"any\" | number",
  1086. "references": {}
  1087. },
  1088. "required": false,
  1089. "optional": true,
  1090. "docs": {
  1091. "tags": [],
  1092. "text": "input step"
  1093. },
  1094. "attribute": "step",
  1095. "reflect": true
  1096. },
  1097. "suffixText": {
  1098. "type": "string",
  1099. "mutable": false,
  1100. "complexType": {
  1101. "original": "string",
  1102. "resolved": "string",
  1103. "references": {}
  1104. },
  1105. "required": false,
  1106. "optional": true,
  1107. "docs": {
  1108. "tags": [],
  1109. "text": "optionally add suffix *"
  1110. },
  1111. "attribute": "suffix-text",
  1112. "reflect": false
  1113. },
  1114. "editingEnabled": {
  1115. "type": "boolean",
  1116. "mutable": true,
  1117. "complexType": {
  1118. "original": "boolean",
  1119. "resolved": "boolean",
  1120. "references": {}
  1121. },
  1122. "required": false,
  1123. "optional": false,
  1124. "docs": {
  1125. "tags": [{
  1126. "name": "internal",
  1127. "text": "adds inline styles for text input when slotted in calcite-inline-editable"
  1128. }],
  1129. "text": ""
  1130. },
  1131. "attribute": "editing-enabled",
  1132. "reflect": true,
  1133. "defaultValue": "false"
  1134. },
  1135. "type": {
  1136. "type": "string",
  1137. "mutable": false,
  1138. "complexType": {
  1139. "original": "| \"color\"\n | \"date\"\n | \"datetime-local\"\n | \"email\"\n | \"file\"\n | \"image\"\n | \"month\"\n | \"number\"\n | \"password\"\n | \"search\"\n | \"tel\"\n | \"text\"\n | \"textarea\"\n | \"time\"\n | \"url\"\n | \"week\"",
  1140. "resolved": "\"color\" | \"date\" | \"datetime-local\" | \"email\" | \"file\" | \"image\" | \"month\" | \"number\" | \"password\" | \"search\" | \"tel\" | \"text\" | \"textarea\" | \"time\" | \"url\" | \"week\"",
  1141. "references": {}
  1142. },
  1143. "required": false,
  1144. "optional": false,
  1145. "docs": {
  1146. "tags": [],
  1147. "text": "specify the input type\n\nNote that the following types add type-specific icons by default: `date`, `email`, `password`, `search`, `tel`, `time`"
  1148. },
  1149. "attribute": "type",
  1150. "reflect": true,
  1151. "defaultValue": "\"text\""
  1152. },
  1153. "value": {
  1154. "type": "string",
  1155. "mutable": true,
  1156. "complexType": {
  1157. "original": "string",
  1158. "resolved": "string",
  1159. "references": {}
  1160. },
  1161. "required": false,
  1162. "optional": false,
  1163. "docs": {
  1164. "tags": [],
  1165. "text": "input value"
  1166. },
  1167. "attribute": "value",
  1168. "reflect": false,
  1169. "defaultValue": "\"\""
  1170. }
  1171. }; }
  1172. static get states() { return {
  1173. "localizedValue": {}
  1174. }; }
  1175. static get events() { return [{
  1176. "method": "calciteInputFocus",
  1177. "name": "calciteInputFocus",
  1178. "bubbles": true,
  1179. "cancelable": true,
  1180. "composed": true,
  1181. "docs": {
  1182. "tags": [{
  1183. "name": "internal",
  1184. "text": undefined
  1185. }],
  1186. "text": ""
  1187. },
  1188. "complexType": {
  1189. "original": "any",
  1190. "resolved": "any",
  1191. "references": {}
  1192. }
  1193. }, {
  1194. "method": "calciteInputBlur",
  1195. "name": "calciteInputBlur",
  1196. "bubbles": true,
  1197. "cancelable": true,
  1198. "composed": true,
  1199. "docs": {
  1200. "tags": [{
  1201. "name": "internal",
  1202. "text": undefined
  1203. }],
  1204. "text": ""
  1205. },
  1206. "complexType": {
  1207. "original": "any",
  1208. "resolved": "any",
  1209. "references": {}
  1210. }
  1211. }, {
  1212. "method": "calciteInputInput",
  1213. "name": "calciteInputInput",
  1214. "bubbles": true,
  1215. "cancelable": true,
  1216. "composed": true,
  1217. "docs": {
  1218. "tags": [],
  1219. "text": "This event fires each time a new value is typed."
  1220. },
  1221. "complexType": {
  1222. "original": "any",
  1223. "resolved": "any",
  1224. "references": {}
  1225. }
  1226. }, {
  1227. "method": "calciteInputChange",
  1228. "name": "calciteInputChange",
  1229. "bubbles": true,
  1230. "cancelable": true,
  1231. "composed": true,
  1232. "docs": {
  1233. "tags": [],
  1234. "text": "This event fires each time a new value is typed and committed."
  1235. },
  1236. "complexType": {
  1237. "original": "void",
  1238. "resolved": "void",
  1239. "references": {}
  1240. }
  1241. }]; }
  1242. static get methods() { return {
  1243. "setFocus": {
  1244. "complexType": {
  1245. "signature": "() => Promise<void>",
  1246. "parameters": [],
  1247. "references": {
  1248. "Promise": {
  1249. "location": "global"
  1250. }
  1251. },
  1252. "return": "Promise<void>"
  1253. },
  1254. "docs": {
  1255. "text": "Sets focus on the component.",
  1256. "tags": []
  1257. }
  1258. }
  1259. }; }
  1260. static get elementRef() { return "el"; }
  1261. static get watchers() { return [{
  1262. "propName": "disabled",
  1263. "methodName": "disabledWatcher"
  1264. }, {
  1265. "propName": "max",
  1266. "methodName": "maxWatcher"
  1267. }, {
  1268. "propName": "min",
  1269. "methodName": "minWatcher"
  1270. }, {
  1271. "propName": "value",
  1272. "methodName": "valueWatcher"
  1273. }, {
  1274. "propName": "icon",
  1275. "methodName": "updateRequestedIcon"
  1276. }, {
  1277. "propName": "type",
  1278. "methodName": "updateRequestedIcon"
  1279. }]; }
  1280. }