JezK
Edit File: sc-price-input.cjs.entry.js.map
{"file":"sc-price-input.entry.cjs.js","mappings":";;;;;;;;;AAAA,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAC/C,2BAAe,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCC8GA,eAAO,CAAC,UAAE;;;;oCAIV,eAAO,CAAC,UAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","names":[],"sources":["src/components/ui/price-input/sc-price-input.css?tag=sc-price-input&encapsulation=shadow","src/components/ui/price-input/sc-price-input.tsx"],"sourcesContent":[":host {\n display: block;\n}\n","import { Component, Prop, Event, EventEmitter, h, Method, Watch, Element } from '@stencil/core';\nimport { getCurrencySymbol } from '../../../functions/price';\nimport { FormSubmitController } from '../../../functions/form-data';\nimport { isZeroDecimal, maybeConvertAmount } from '../../../functions/currency';\nimport { sprintf, __ } from '@wordpress/i18n';\n\n/**\n * @part base - The elements base wrapper.\n * @part input - The html input element.\n * @part base - The elements base wrapper.\n * @part prefix - Used to prepend an icon or element to the input.\n * @part suffix - Used to prepend an icon or element to the input.\n * @part help-text - Help text that describes how to use the input.\n */\n@Component({\n tag: 'sc-price-input',\n styleUrl: 'sc-price-input.css',\n shadow: true,\n})\nexport class ScPriceInput {\n @Element() el: HTMLScPriceInputElement;\n private input: HTMLScInputElement;\n\n private formController: any;\n\n /** The input's size. */\n @Prop({ reflect: true }) size: 'small' | 'medium' | 'large' = 'medium';\n\n /** The input's name attribute. */\n @Prop() name: string;\n\n /** The input's value attribute. */\n @Prop({ mutable: true }) value = '';\n\n /** Draws a pill-style input with rounded edges. */\n @Prop({ reflect: true }) pill = false;\n\n /** The input's label. */\n @Prop() label: string;\n\n /** Should we show the label */\n @Prop() showLabel: boolean = true;\n\n /** The input's help text. */\n @Prop() help: string = '';\n\n /** Adds a clear button when the input is populated. */\n @Prop() clearable = false;\n\n /** The input's placeholder text. */\n @Prop() placeholder: string;\n\n /** Disables the input. */\n @Prop({ reflect: true }) disabled: boolean = false;\n\n /** Makes the input readonly. */\n @Prop({ reflect: true }) readonly: boolean = false;\n\n /** The minimum length of input that will be considered valid. */\n @Prop() minlength: number;\n\n /** The maximum length of input that will be considered valid. */\n @Prop() maxlength: number;\n\n /** The input's maximum value. */\n @Prop({ reflect: true }) max: number;\n\n /** The input's minimum value. */\n @Prop({ reflect: true }) min: number;\n\n /** Makes the input a required field. */\n @Prop({ reflect: true }) required = false;\n\n /**\n * This will be true when the control is in an invalid state. Validity is determined by props such as `type`,\n * `required`, `minlength`, `maxlength`, and `pattern` using the browser's constraint validation API.\n */\n @Prop({ mutable: true, reflect: true }) invalid = false;\n\n /** The input's autofocus attribute. */\n @Prop() autofocus: boolean;\n\n /** Inputs focus */\n @Prop({ mutable: true, reflect: true }) hasFocus: boolean;\n\n /** 3 letter currency code for input */\n @Prop({ reflect: true }) currencyCode: string;\n\n /** Show the currency code with the input */\n @Prop() showCode: boolean;\n\n /** Emitted when the control's value changes. */\n @Event({ composed: true })\n scChange: EventEmitter<void>;\n\n /** Emitted when the control's value changes. */\n @Event({ composed: true })\n scInput: EventEmitter<void>;\n\n /** Emitted when the control gains focus. */\n @Event() scFocus: EventEmitter<void>;\n\n /** Emitted when the control loses focus. */\n @Event() scBlur: EventEmitter<void>;\n\n @Method()\n async reportValidity() {\n const input = this.input.shadowRoot.querySelector('input');\n input.setCustomValidity('');\n if (this.min && this.value && parseFloat(this.value) < this.min) {\n this.invalid = true;\n input.setCustomValidity(sprintf(__('Must be %d or more.', 'surecart'), maybeConvertAmount(this.min, this.currencyCode).toString()));\n }\n if (this.max && this.value && parseFloat(this.value) > this.max) {\n this.invalid = true;\n input.setCustomValidity(sprintf(__('Must be %d or less.', 'surecart'), maybeConvertAmount(this.max, this.currencyCode).toString()));\n }\n return input.reportValidity();\n }\n\n /** Sets focus on the input. */\n @Method()\n async triggerFocus(options?: FocusOptions) {\n return this.input.triggerFocus(options);\n }\n\n /** Sets a custom validation message. If `message` is not empty, the field will be considered invalid. */\n @Method()\n async setCustomValidity(message: string) {\n this.input.setCustomValidity(message);\n }\n\n /** Removes focus from the input. */\n @Method()\n async triggerBlur() {\n return this.input.blur();\n }\n\n @Watch('hasFocus')\n handleFocusChange() {\n this.hasFocus ? this.input?.focus?.() : this.input?.blur?.();\n }\n\n handleChange() {\n this.updateValue();\n this.scChange.emit();\n }\n\n handleInput() {\n this.updateValue();\n this.scInput.emit();\n }\n\n updateValue() {\n // This fixes issues on mobile Safari where a decimal point is added to the end of the input value\n // does not have an input value.\n const parsed = parseFloat(this.input.value);\n if (isNaN(parsed)) {\n this.value = '';\n return;\n }\n const val = isZeroDecimal(this.currencyCode) ? parsed : (parsed * 100).toFixed(2);\n this.value = val.toString();\n this.setCustomValidity('');\n }\n\n componentDidLoad() {\n this.handleFocusChange();\n this.formController = new FormSubmitController(this.el).addFormData();\n document.addEventListener('wheel', () => {\n this.input.triggerBlur();\n });\n }\n\n disconnectedCallback() {\n this.formController?.removeFormData();\n }\n\n getFormattedValue() {\n if (!this.value) return '';\n\n const parsedAmount = parseFloat(this.value);\n if (isNaN(parsedAmount)) return '';\n\n return maybeConvertAmount(parsedAmount, this.currencyCode).toString();\n }\n\n render() {\n return (\n <sc-input\n exportparts=\"base, input, form-control, label, help-text, prefix, suffix\"\n size={this.size}\n label={this.label}\n showLabel={this.showLabel}\n help={this.help}\n ref={el => (this.input = el as HTMLScInputElement)}\n type=\"text\" // we cannot use number because it's basically the worst. https://stackoverflow.blog/2022/12/26/why-the-number-input-is-the-worst-input/\n name={this.name}\n disabled={this.disabled}\n readonly={this.readonly}\n required={this.required}\n placeholder={this.placeholder}\n minlength={this.minlength}\n maxlength={this.maxlength}\n min={!!this.min ? this.min / 100 : 0.0}\n step={0.01}\n max={!!this.max ? this.max / 100 : null}\n // TODO: Test These below\n autofocus={this.autofocus}\n inputmode={'decimal'}\n onScChange={() => this.handleChange()}\n onScInput={() => this.handleInput()}\n onScBlur={() => this.scBlur.emit()}\n onScFocus={() => this.scFocus.emit()}\n pattern=\"^\\d*(\\.\\d{0,2})?$\" // This prevents more than two decimal places\n value={this.getFormattedValue()}\n >\n <span style={{ opacity: '0.5' }} slot=\"prefix\">\n {getCurrencySymbol(this.currencyCode)}\n </span>\n\n <span slot=\"suffix\">\n <slot name=\"suffix\">{this.showCode && this?.currencyCode && <span style={{ opacity: '0.5' }}>{this.currencyCode.toUpperCase()}</span>}</slot>\n </span>\n </sc-input>\n );\n }\n}\n"],"version":3}